write first version of user system
This commit is contained in:
308
src/engine.cpp
308
src/engine.cpp
@ -1,9 +1,11 @@
|
|||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "basic_defs.h"
|
#include "basic_defs.h"
|
||||||
|
#include "data.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
const hash_t add_user_hash = 1294763820278197867ull; // SplitMix64Hash(std::string_view("add_user"));
|
const hash_t add_user_hash = 1294763820278197867ull; // SplitMix64Hash(std::string_view("add_user"));
|
||||||
const hash_t login_hash = 2711532776857333909ull; // SplitMix64Hash(std::string_view("login"));
|
const hash_t login_hash = 2711532776857333909ull; // SplitMix64Hash(std::string_view("login"));
|
||||||
@ -39,7 +41,7 @@ std::string TicketSystemEngine::Execute(const std::string &command) {
|
|||||||
// LOG->debug("clean_hash: {}", clean_hash);
|
// LOG->debug("clean_hash: {}", clean_hash);
|
||||||
// LOG->debug("exit_hash: {}", exit_hash);
|
// LOG->debug("exit_hash: {}", exit_hash);
|
||||||
char command_name[20];
|
char command_name[20];
|
||||||
sscanf(command.c_str(), "%s", command_name);
|
sscanf(command.c_str(), "%*s %s", command_name);
|
||||||
hash_t command_name_hash = SplitMix64Hash(std::string_view(command_name));
|
hash_t command_name_hash = SplitMix64Hash(std::string_view(command_name));
|
||||||
switch (command_name_hash) {
|
switch (command_name_hash) {
|
||||||
case add_user_hash:
|
case add_user_hash:
|
||||||
@ -90,20 +92,303 @@ std::string TicketSystemEngine::Execute(const std::string &command) {
|
|||||||
case exit_hash:
|
case exit_hash:
|
||||||
LOG->debug("match exit");
|
LOG->debug("match exit");
|
||||||
PrepareExit();
|
PrepareExit();
|
||||||
return std::move(Exit());
|
return std::move(Exit(command));
|
||||||
}
|
}
|
||||||
throw std::invalid_argument("Invalid command.");
|
throw std::invalid_argument("Invalid command.");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TicketSystemEngine::AddUser(const std::string &command) { return "AddUser"; }
|
std::string TicketSystemEngine::AddUser(const std::string &command) {
|
||||||
|
command_id_t command_id;
|
||||||
|
sscanf(command.c_str(), "[%llu]", &command_id);
|
||||||
|
LOG->debug("command id: {}", command_id);
|
||||||
|
LOG->debug("command: {}", command);
|
||||||
|
std::stringstream command_stream(command), response_stream;
|
||||||
|
std::string token, cur_username, username, password, name, mailAddr;
|
||||||
|
uint8_t privilege;
|
||||||
|
command_stream >> token >> token;
|
||||||
|
while (command_stream >> token) {
|
||||||
|
switch (token[1]) {
|
||||||
|
case 'c': {
|
||||||
|
command_stream >> cur_username;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u': {
|
||||||
|
command_stream >> username;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'p': {
|
||||||
|
command_stream >> password;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'n': {
|
||||||
|
command_stream >> name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'm': {
|
||||||
|
command_stream >> mailAddr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'g': {
|
||||||
|
int tmp;
|
||||||
|
command_stream >> tmp;
|
||||||
|
privilege = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument("arg parse fatal error in add_user");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (user_data.size() == 0) {
|
||||||
|
// special case, no need to check current user's privilege
|
||||||
|
FullUserData dat;
|
||||||
|
dat.privilege = 10;
|
||||||
|
strcpy(dat.username, username.c_str());
|
||||||
|
dat.password_hash = SplitMix64Hash(password);
|
||||||
|
strcpy(dat.name, name.c_str());
|
||||||
|
strcpy(dat.mailAddr, mailAddr.c_str());
|
||||||
|
user_data.Put(SplitMix64Hash(username), dat);
|
||||||
|
LOG->debug("stored user_name hash: {}", SplitMix64Hash(username));
|
||||||
|
LOG->debug("stored user_name: {}", dat.username);
|
||||||
|
LOG->debug("stored password hash: {}", dat.password_hash);
|
||||||
|
LOG->debug("stored name: {}", dat.name);
|
||||||
|
LOG->debug("stored mailAddr: {}", dat.mailAddr);
|
||||||
|
LOG->debug("stored privilege: {}", dat.privilege);
|
||||||
|
response_stream << '[' << command_id << "] 0";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
hash_t current_user_username_hash = SplitMix64Hash(cur_username);
|
||||||
|
if (online_users.find(current_user_username_hash) == online_users.end()) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
if (privilege >= online_users[current_user_username_hash]) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
hash_t new_user_username_hash = SplitMix64Hash(username);
|
||||||
|
if (user_data.HasKey(new_user_username_hash)) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
FullUserData dat;
|
||||||
|
dat.privilege = privilege;
|
||||||
|
strcpy(dat.username, username.c_str());
|
||||||
|
dat.password_hash = SplitMix64Hash(password);
|
||||||
|
strcpy(dat.name, name.c_str());
|
||||||
|
strcpy(dat.mailAddr, mailAddr.c_str());
|
||||||
|
user_data.Put(new_user_username_hash, dat);
|
||||||
|
LOG->debug("stored user_name hash: {}", new_user_username_hash);
|
||||||
|
LOG->debug("stored user_name: {}", dat.username);
|
||||||
|
LOG->debug("stored password hash: {}", dat.password_hash);
|
||||||
|
LOG->debug("stored name: {}", dat.name);
|
||||||
|
LOG->debug("stored mailAddr: {}", dat.mailAddr);
|
||||||
|
LOG->debug("stored privilege: {}", dat.privilege);
|
||||||
|
response_stream << '[' << command_id << "] 0";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::string TicketSystemEngine::LoginUser(const std::string &command) { return "LoginUser"; }
|
std::string TicketSystemEngine::LoginUser(const std::string &command) {
|
||||||
|
command_id_t command_id;
|
||||||
|
sscanf(command.c_str(), "[%llu]", &command_id);
|
||||||
|
LOG->debug("command id: {}", command_id);
|
||||||
|
std::stringstream command_stream(command), response_stream;
|
||||||
|
std::string token, user_name, password;
|
||||||
|
command_stream >> token >> token;
|
||||||
|
while (command_stream >> token) {
|
||||||
|
switch (token[1]) {
|
||||||
|
case 'u': {
|
||||||
|
command_stream >> user_name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'p': {
|
||||||
|
command_stream >> password;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument("arg parse fatal error in login");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hash_t user_name_hash = SplitMix64Hash(user_name);
|
||||||
|
hash_t password_hash = SplitMix64Hash(password);
|
||||||
|
if (online_users.find(user_name_hash) != online_users.end()) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
FullUserData dat;
|
||||||
|
try {
|
||||||
|
user_data.Get(user_name_hash, dat);
|
||||||
|
if (dat.password_hash != password_hash) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
} catch (std::runtime_error &e) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
online_users[user_name_hash] = dat.privilege;
|
||||||
|
response_stream << '[' << command_id << "] 0";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::string TicketSystemEngine::LogoutUser(const std::string &command) { return "LogoutUser"; }
|
std::string TicketSystemEngine::LogoutUser(const std::string &command) {
|
||||||
|
command_id_t command_id;
|
||||||
|
sscanf(command.c_str(), "[%llu]", &command_id);
|
||||||
|
LOG->debug("command id: {}", command_id);
|
||||||
|
std::stringstream command_stream(command), response_stream;
|
||||||
|
std::string token, user_name;
|
||||||
|
command_stream >> token >> token;
|
||||||
|
while (command_stream >> token) {
|
||||||
|
switch (token[1]) {
|
||||||
|
case 'u': {
|
||||||
|
command_stream >> user_name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument("arg parse fatal error in logout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hash_t user_name_hash = SplitMix64Hash(user_name);
|
||||||
|
if (online_users.find(user_name_hash) == online_users.end()) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
online_users.erase(user_name_hash);
|
||||||
|
response_stream << '[' << command_id << "] 0";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::string TicketSystemEngine::QueryProfile(const std::string &command) { return "QueryProfile"; }
|
std::string TicketSystemEngine::QueryProfile(const std::string &command) {
|
||||||
|
command_id_t command_id;
|
||||||
|
sscanf(command.c_str(), "[%llu]", &command_id);
|
||||||
|
LOG->debug("command id: {}", command_id);
|
||||||
|
std::stringstream command_stream(command), response_stream;
|
||||||
|
std::string token, current_user_name, user_name;
|
||||||
|
command_stream >> token >> token;
|
||||||
|
while (command_stream >> token) {
|
||||||
|
switch (token[1]) {
|
||||||
|
case 'c': {
|
||||||
|
command_stream >> current_user_name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u': {
|
||||||
|
command_stream >> user_name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument("arg parse fatal error in query_profile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hash_t current_user_name_hash = SplitMix64Hash(current_user_name);
|
||||||
|
hash_t user_name_hash = SplitMix64Hash(user_name);
|
||||||
|
if (online_users.find(current_user_name_hash) == online_users.end()) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
FullUserData dat;
|
||||||
|
LOG->debug("user_name_hash: {}", user_name_hash);
|
||||||
|
LOG->debug("mailAddr: {}", dat.mailAddr);
|
||||||
|
if (current_user_name_hash != user_name_hash) {
|
||||||
|
try {
|
||||||
|
user_data.Get(user_name_hash, dat);
|
||||||
|
if (online_users[current_user_name_hash] <= dat.privilege) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
} catch (std::runtime_error &e) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
user_data.Get(user_name_hash, dat);
|
||||||
|
}
|
||||||
|
LOG->debug("mailAddr: {}", dat.mailAddr);
|
||||||
|
response_stream << '[' << command_id << "] " << dat.username << ' ' << dat.name << ' ' << dat.mailAddr << ' '
|
||||||
|
<< static_cast<int>(dat.privilege);
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::string TicketSystemEngine::ModifyProfile(const std::string &command) { return "ModifyProfile"; }
|
std::string TicketSystemEngine::ModifyProfile(const std::string &command) {
|
||||||
|
command_id_t command_id;
|
||||||
|
sscanf(command.c_str(), "[%llu]", &command_id);
|
||||||
|
LOG->debug("command id: {}", command_id);
|
||||||
|
std::stringstream command_stream(command), response_stream;
|
||||||
|
std::string token, current_user_name, user_name, password, name, mailAddr;
|
||||||
|
uint8_t privilege = 11;
|
||||||
|
command_stream >> token >> token;
|
||||||
|
while (command_stream >> token) {
|
||||||
|
switch (token[1]) {
|
||||||
|
case 'c': {
|
||||||
|
command_stream >> current_user_name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u': {
|
||||||
|
command_stream >> user_name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'p': {
|
||||||
|
command_stream >> password;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'n': {
|
||||||
|
command_stream >> name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'm': {
|
||||||
|
command_stream >> mailAddr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'g': {
|
||||||
|
int tmp;
|
||||||
|
command_stream >> tmp;
|
||||||
|
privilege = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument("arg parse fatal error in add_user");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hash_t current_user_name_hash = SplitMix64Hash(current_user_name);
|
||||||
|
hash_t user_name_hash = SplitMix64Hash(user_name);
|
||||||
|
if (online_users.find(current_user_name_hash) == online_users.end()) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
FullUserData dat;
|
||||||
|
if (current_user_name_hash != user_name_hash) {
|
||||||
|
try {
|
||||||
|
user_data.Get(user_name_hash, dat);
|
||||||
|
if (online_users[current_user_name_hash] <= dat.privilege) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
} catch (std::runtime_error &e) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
user_data.Get(user_name_hash, dat);
|
||||||
|
}
|
||||||
|
if (privilege != 11 && privilege >= online_users[current_user_name_hash]) {
|
||||||
|
response_stream << '[' << command_id << "] -1";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
if (privilege != 11) {
|
||||||
|
dat.privilege = privilege;
|
||||||
|
}
|
||||||
|
if (password != "") {
|
||||||
|
dat.password_hash = SplitMix64Hash(password);
|
||||||
|
}
|
||||||
|
if (name != "") {
|
||||||
|
strcpy(dat.name, name.c_str());
|
||||||
|
}
|
||||||
|
if (mailAddr != "") {
|
||||||
|
strcpy(dat.mailAddr, mailAddr.c_str());
|
||||||
|
}
|
||||||
|
user_data.Put(user_name_hash, dat);
|
||||||
|
response_stream << '[' << command_id << "] " << dat.username << ' ' << dat.name << ' ' << dat.mailAddr << ' '
|
||||||
|
<< static_cast<int>(dat.privilege);
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::string TicketSystemEngine::AddTrain(const std::string &command) { return "AddTrain"; }
|
std::string TicketSystemEngine::AddTrain(const std::string &command) { return "AddTrain"; }
|
||||||
|
|
||||||
@ -125,6 +410,13 @@ std::string TicketSystemEngine::QueryTicket(const std::string &command) { return
|
|||||||
|
|
||||||
std::string TicketSystemEngine::Clean() { return "Clean"; }
|
std::string TicketSystemEngine::Clean() { return "Clean"; }
|
||||||
|
|
||||||
std::string TicketSystemEngine::Exit() { return "bye"; }
|
std::string TicketSystemEngine::Exit(const std::string &command) {
|
||||||
|
command_id_t command_id;
|
||||||
|
sscanf(command.c_str(), "[%llu]", &command_id);
|
||||||
|
LOG->debug("command id: {}", command_id);
|
||||||
|
std::stringstream response_stream;
|
||||||
|
response_stream << '[' << command_id << "] bye";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
void TicketSystemEngine::PrepareExit() { LOG->info("Preparing exit"); }
|
void TicketSystemEngine::PrepareExit() { LOG->info("Preparing exit"); }
|
@ -16,5 +16,8 @@ constexpr bool global_log_enabled = false;
|
|||||||
constexpr bool global_log_enabled = true;
|
constexpr bool global_log_enabled = true;
|
||||||
#endif
|
#endif
|
||||||
extern const bool optimize_enabled;
|
extern const bool optimize_enabled;
|
||||||
#define LOG if constexpr (global_log_enabled) if (logger_ptr) logger_ptr
|
#define LOG \
|
||||||
|
if constexpr (global_log_enabled) \
|
||||||
|
if (logger_ptr) logger_ptr
|
||||||
|
typedef unsigned long long command_id_t;
|
||||||
#endif
|
#endif
|
@ -1,4 +1,12 @@
|
|||||||
#ifndef DATA_H
|
#ifndef DATA_H
|
||||||
#define DATA_H
|
#define DATA_H
|
||||||
|
#include <cstdint>
|
||||||
|
#include "utils.h"
|
||||||
|
struct FullUserData {
|
||||||
|
char username[21];
|
||||||
|
hash_t password_hash;
|
||||||
|
char name[21];
|
||||||
|
char mailAddr[31];
|
||||||
|
uint8_t privilege;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
@ -7,17 +7,23 @@
|
|||||||
#include "dataguard/snapshot.h"
|
#include "dataguard/snapshot.h"
|
||||||
#endif
|
#endif
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "data.h"
|
||||||
|
#include "storage/disk_map.hpp"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
class TicketSystemEngine {
|
class TicketSystemEngine {
|
||||||
#ifdef ENABLE_ADVANCED_FEATURE
|
#ifdef ENABLE_ADVANCED_FEATURE
|
||||||
SnapShotManager snapshot_manager;
|
SnapShotManager snapshot_manager;
|
||||||
#endif
|
#endif
|
||||||
std::string data_directory;
|
std::string data_directory;
|
||||||
std::map<hash_t, bool> online_users;
|
std::map<hash_t, uint8_t> online_users;
|
||||||
|
DiskMap<hash_t, FullUserData> user_data;
|
||||||
void PrepareExit();
|
void PrepareExit();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline TicketSystemEngine(std::string data_directory) : data_directory(data_directory) {}
|
inline TicketSystemEngine(std::string data_directory)
|
||||||
|
: data_directory(data_directory),
|
||||||
|
user_data("user_data.idx", data_directory + "/user_data.idx", "user_data.val",
|
||||||
|
data_directory + "/user_data.val") {}
|
||||||
std::string Execute(const std::string &command);
|
std::string Execute(const std::string &command);
|
||||||
|
|
||||||
// 用户相关函数
|
// 用户相关函数
|
||||||
@ -42,6 +48,6 @@ class TicketSystemEngine {
|
|||||||
std::string QueryTransfer(const std::string &command);
|
std::string QueryTransfer(const std::string &command);
|
||||||
std::string QueryTicket(const std::string &command);
|
std::string QueryTicket(const std::string &command);
|
||||||
std::string Clean();
|
std::string Clean();
|
||||||
std::string Exit();
|
std::string Exit(const std::string &command);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
58
src/main.cpp
58
src/main.cpp
@ -1,4 +1,5 @@
|
|||||||
#include <sockpp/tcp_acceptor.h>
|
#include <sockpp/tcp_acceptor.h>
|
||||||
|
#include <exception>
|
||||||
#include "basic_defs.h"
|
#include "basic_defs.h"
|
||||||
#include "dataguard/dataguard.h"
|
#include "dataguard/dataguard.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
@ -17,7 +18,7 @@ const bool optimize_enabled = false;
|
|||||||
// const bool global_log_enabled = true;
|
// const bool global_log_enabled = true;
|
||||||
// #endif
|
// #endif
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
argparse::ArgumentParser program("core-cli", main_version + "-" + build_version);
|
argparse::ArgumentParser program("zts-core", main_version + "-" + build_version);
|
||||||
argparse::ArgumentParser fsck_command("fsck");
|
argparse::ArgumentParser fsck_command("fsck");
|
||||||
fsck_command.add_description("Check and fix data");
|
fsck_command.add_description("Check and fix data");
|
||||||
program.add_subparser(fsck_command);
|
program.add_subparser(fsck_command);
|
||||||
@ -29,6 +30,9 @@ int main(int argc, char *argv[]) {
|
|||||||
.default_value(std::string("127.0.0.1"))
|
.default_value(std::string("127.0.0.1"))
|
||||||
.nargs(1, 1);
|
.nargs(1, 1);
|
||||||
program.add_subparser(server_command);
|
program.add_subparser(server_command);
|
||||||
|
argparse::ArgumentParser snapshot_command("snapshot");
|
||||||
|
snapshot_command.add_description("Manage snapshots");
|
||||||
|
program.add_subparser(snapshot_command);
|
||||||
program.add_argument("-d", "--directory").help("Directory to serve").default_value(std::string(".")).nargs(1, 1);
|
program.add_argument("-d", "--directory").help("Directory to serve").default_value(std::string(".")).nargs(1, 1);
|
||||||
auto &group = program.add_mutually_exclusive_group();
|
auto &group = program.add_mutually_exclusive_group();
|
||||||
group.add_argument("-c", "--consolelog").help("Enable console log").default_value(false).implicit_value(true);
|
group.add_argument("-c", "--consolelog").help("Enable console log").default_value(false).implicit_value(true);
|
||||||
@ -81,29 +85,37 @@ int main(int argc, char *argv[]) {
|
|||||||
LOG->info("Data directory: {}", data_directory);
|
LOG->info("Data directory: {}", data_directory);
|
||||||
bool is_server = program.is_subcommand_used("server");
|
bool is_server = program.is_subcommand_used("server");
|
||||||
LOG->info("Server mode: {}", is_server);
|
LOG->info("Server mode: {}", is_server);
|
||||||
if (is_server) {
|
try {
|
||||||
auto port = server_command.get<int>("--port");
|
if (is_server) {
|
||||||
auto address = server_command.get<std::string>("--address");
|
auto port = server_command.get<int>("--port");
|
||||||
LOG->info("Server port: {}", port);
|
auto address = server_command.get<std::string>("--address");
|
||||||
LOG->info("Server address: {}", address);
|
LOG->info("Server port: {}", port);
|
||||||
LOG->info("Starting server");
|
LOG->info("Server address: {}", address);
|
||||||
sockpp::tcp_acceptor acceptor(sockpp::inet_address(address, port));
|
LOG->info("Starting server");
|
||||||
if (!acceptor) {
|
sockpp::tcp_acceptor acceptor(sockpp::inet_address(address, port));
|
||||||
LOG->error("Error creating acceptor: {}", acceptor.last_error_str());
|
if (!acceptor) {
|
||||||
return 1;
|
LOG->error("Error creating acceptor: {}", acceptor.last_error_str());
|
||||||
} else
|
return 1;
|
||||||
LOG->info("successfully bind to address {} port {}", address, port);
|
} else
|
||||||
throw std::runtime_error("Server mode not implemented");
|
LOG->info("successfully bind to address {} port {}", address, port);
|
||||||
} else {
|
throw std::runtime_error("Server mode not implemented");
|
||||||
std::ios::sync_with_stdio(false);
|
} else {
|
||||||
std::cin.tie(nullptr);
|
std::ios::sync_with_stdio(false);
|
||||||
std::cout.tie(nullptr);
|
std::cin.tie(nullptr);
|
||||||
TicketSystemEngine engine(data_directory);
|
std::cout.tie(nullptr);
|
||||||
std::string cmd;
|
TicketSystemEngine engine(data_directory);
|
||||||
while (std::getline(std::cin, cmd)) {
|
std::string cmd;
|
||||||
std::cout << engine.Execute(cmd) << '\n';
|
while (std::getline(std::cin, cmd)) {
|
||||||
std::cout.flush();
|
std::cout << engine.Execute(cmd) << '\n';
|
||||||
|
std::cout.flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
LOG->error("Exception: {}", e.what());
|
||||||
|
return 1;
|
||||||
|
} catch (...) {
|
||||||
|
LOG->error("Unknown exception");
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -53,7 +53,7 @@ class DiskMap : public DataDriverBase {
|
|||||||
res.push_back({data_file_identifier, data_file_path, data_disk_manager});
|
res.push_back({data_file_identifier, data_file_path, data_disk_manager});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
void LockDownForCheckOut() override {
|
virtual void LockDownForCheckOut() override {
|
||||||
delete indexer;
|
delete indexer;
|
||||||
delete index_bpm;
|
delete index_bpm;
|
||||||
delete index_disk_manager;
|
delete index_disk_manager;
|
||||||
@ -67,6 +67,7 @@ class DiskMap : public DataDriverBase {
|
|||||||
data_bpm = nullptr;
|
data_bpm = nullptr;
|
||||||
data_disk_manager = nullptr;
|
data_disk_manager = nullptr;
|
||||||
}
|
}
|
||||||
|
bool HasKey(const Key &key) { return indexer->Get(key) != kInvalidValueIndex; }
|
||||||
Value Get(const Key &key) {
|
Value Get(const Key &key) {
|
||||||
size_t data_id;
|
size_t data_id;
|
||||||
if ((data_id = indexer->Get(key)) == kInvalidValueIndex) throw std::runtime_error("Key not found");
|
if ((data_id = indexer->Get(key)) == kInvalidValueIndex) throw std::runtime_error("Key not found");
|
||||||
@ -74,6 +75,12 @@ class DiskMap : public DataDriverBase {
|
|||||||
data_storage->read(res, data_id);
|
data_storage->read(res, data_id);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
void Get(const Key &key, Value &res) {
|
||||||
|
size_t data_id;
|
||||||
|
if ((data_id = indexer->Get(key)) == kInvalidValueIndex) throw std::runtime_error("Key not found");
|
||||||
|
data_storage->read(res, data_id);
|
||||||
|
}
|
||||||
|
size_t size() { return indexer->Size(); }
|
||||||
bool Remove(const Key &key) {
|
bool Remove(const Key &key) {
|
||||||
b_plus_tree_value_index_t data_id;
|
b_plus_tree_value_index_t data_id;
|
||||||
bool remove_success = indexer->Remove(key, &data_id);
|
bool remove_success = indexer->Remove(key, &data_id);
|
||||||
@ -92,7 +99,7 @@ class DiskMap : public DataDriverBase {
|
|||||||
indexer->Put(key, data_id);
|
indexer->Put(key, data_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void Flush() {
|
virtual void Flush() override {
|
||||||
if (indexer == nullptr) return;
|
if (indexer == nullptr) return;
|
||||||
indexer->Flush();
|
indexer->Flush();
|
||||||
data_storage->Flush();
|
data_storage->Flush();
|
||||||
|
@ -21,3 +21,4 @@ add_executable(bpt_advanced_test bpt_advanced_test.cpp)
|
|||||||
target_link_libraries(bpt_advanced_test storage GTest::gtest_main spdlog::spdlog)
|
target_link_libraries(bpt_advanced_test storage GTest::gtest_main spdlog::spdlog)
|
||||||
add_executable(snapshot_test snapshot_test.cpp)
|
add_executable(snapshot_test snapshot_test.cpp)
|
||||||
target_link_libraries(snapshot_test storage dataguard GTest::gtest_main spdlog::spdlog)
|
target_link_libraries(snapshot_test storage dataguard GTest::gtest_main spdlog::spdlog)
|
||||||
|
add_executable(hash_collision_test hash_collision_test.cpp)
|
@ -1,13 +1,13 @@
|
|||||||
add_test(NAME basic_1 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_1 --skip-check --ignore-first-dependency)
|
add_test(NAME basic_1 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_1 --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME basic_2 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_2 --skip-check --ignore-first-dependency)
|
add_test(NAME basic_2 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_2 --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME basic_3 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_3 --skip-check --ignore-first-dependency)
|
add_test(NAME basic_3 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_3 --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME basic_4 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_4 --skip-check --ignore-first-dependency)
|
add_test(NAME basic_4 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_4 --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME basic_5 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_5 --skip-check --ignore-first-dependency)
|
add_test(NAME basic_5 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_5 --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME basic_6 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_6 --skip-check --ignore-first-dependency)
|
add_test(NAME basic_6 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_6 --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME basic_extra COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_extra --skip-check --ignore-first-dependency)
|
add_test(NAME basic_extra COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_extra --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME pressure_1_easy COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_1_easy --skip-check --ignore-first-dependency)
|
add_test(NAME pressure_1_easy COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_1_easy --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME pressure_2_easy COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_2_easy --skip-check --ignore-first-dependency)
|
add_test(NAME pressure_2_easy COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_2_easy --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME pressure_3_easy COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_3_easy --skip-check --ignore-first-dependency)
|
add_test(NAME pressure_3_easy COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_3_easy --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME pressure_1_hard COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_1_hard --skip-check --ignore-first-dependency)
|
add_test(NAME pressure_1_hard COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_1_hard --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME pressure_2_hard COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_2_hard --skip-check --ignore-first-dependency)
|
add_test(NAME pressure_2_hard COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_2_hard --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||||
add_test(NAME pressure_3_hard COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_3_hard --skip-check --ignore-first-dependency)
|
add_test(NAME pressure_3_hard COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_3_hard --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
17
test/hash_collision_test.cpp
Normal file
17
test/hash_collision_test.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "../src/include/utils.h"
|
||||||
|
std::unordered_map<hash_t, std::string> storage;
|
||||||
|
int main() {
|
||||||
|
std::string token;
|
||||||
|
while (std::cin >> token) {
|
||||||
|
hash_t hsh = SplitMix64Hash(token);
|
||||||
|
if (storage.find(hsh) == storage.end()) {
|
||||||
|
storage[hsh] = token;
|
||||||
|
} else if (storage[hsh] != token) {
|
||||||
|
std::cerr << "Collision detected: " << storage[hsh] << " " << token << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
@ -115,7 +115,7 @@ def RunTestGroup(name):
|
|||||||
if not enable_tested_program_logging:
|
if not enable_tested_program_logging:
|
||||||
command = f'ulimit -t {time_limit} && ulimit -m {memory_limit} && ulimit -f {disk_limit} && ulimit -n {file_number_limit} && {path_to_exec_file} < {input_file} > {output_file} 2> {stderr_file}'
|
command = f'ulimit -t {time_limit} && ulimit -m {memory_limit} && ulimit -f {disk_limit} && ulimit -n {file_number_limit} && {path_to_exec_file} < {input_file} > {output_file} 2> {stderr_file}'
|
||||||
else:
|
else:
|
||||||
command = f'ulimit -t {time_limit} && ulimit -m {memory_limit} && ulimit -f {disk_limit} && ulimit -n {file_number_limit} && {path_to_exec_file} -l {log_file} < {input_file} > {output_file} 2> {stderr_file}'
|
command = f'ulimit -t {time_limit} && ulimit -m {memory_limit} && ulimit -f {disk_limit} && ulimit -n {file_number_limit} && {path_to_exec_file} -l {log_file} --level debug < {input_file} > {output_file} 2> {stderr_file}'
|
||||||
print("the test command is: ", command)
|
print("the test command is: ", command)
|
||||||
process = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=playground_dir)
|
process = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=playground_dir)
|
||||||
# Check the exit status of the command
|
# Check the exit status of the command
|
||||||
|
Reference in New Issue
Block a user