From 22db1a45d6a6da8e05233814ed0ff6ef6b17cd3c Mon Sep 17 00:00:00 2001 From: suxunbin Date: Fri, 19 Oct 2018 20:32:52 +0800 Subject: [PATCH 1/3] Use system.db to optimize ghttp --- Main/gbuild.cpp | 119 ++++++- Main/ghttp.cpp | 800 +++++++++++++++++++++++++++++++----------- Main/ginit.cpp | 49 ++- Main/shutdown.cpp | 13 +- data/system/system.nt | 1 + docs/USAGE.md | 7 +- scripts/test.sh | 5 +- 7 files changed, 769 insertions(+), 225 deletions(-) diff --git a/Main/gbuild.cpp b/Main/gbuild.cpp index e56d930..aa02899 100644 --- a/Main/gbuild.cpp +++ b/Main/gbuild.cpp @@ -1,9 +1,9 @@ /*============================================================================= # Filename: gbuild.cpp -# Author: Bookug Lobert -# Mail: 1181955272@qq.com -# Last Modified: 2015-10-24 19:27 -# Description: firstly written by liyouhuan, modified by zengli +# Author: Bookug Lobert suxunbin +# Mail: 1181955272@qq.com suxunbin@pku.edu.cn +# Last Modified: 2018-10-19 20:30 +# Description: firstly written by liyouhuan, modified by zengli and suxunbin TODO: add -h/--help for help message =============================================================================*/ @@ -11,6 +11,7 @@ TODO: add -h/--help for help message #include "../Database/Database.h" using namespace std; +#define SYSTEM_PATH "data/system/system.nt" //[0]./gbuild [1]data_folder_path [2]rdf_file_path int @@ -44,15 +45,39 @@ main(int argc, char * argv[]) return -1; } + //check if the db_name is system + if (_db_path == "system") + { + cout<< "Your database's name can not be system."< \"already_built\"." + "<" + _db_path + "> ." + + "<" + _db_path + "> \"" + time + "\".}"; + ResultSet _rs; + FILE* ofp = stdout; + string msg; + int ret = system_db.query(sparql, _rs, ofp); + if (ret <= -100) // select query + { + if (ret == -100) + msg = _rs.to_str(); + else //query error + msg = "query failed"; + } + else //update query + { + if (ret >= 0) + msg = "update num : " + Util::int2string(ret); + else //update error + msg = "update failed."; + if (ret != -100) + cout << msg << endl; + } + return 0; + } + else //if isbuilt is true, update built_time of the database + { + string sparql = "DELETE {<" + _db_path + "> ?t .}" + + "WHERE{<" + _db_path + "> ?t .}"; + ResultSet _rs; + FILE* ofp = stdout; + string msg; + int ret = system_db.query(sparql, _rs, ofp); + if (ret <= -100) // select query + { + if (ret == -100) + msg = _rs.to_str(); + else //query error + msg = "query failed"; + } + else //update query + { + if (ret >= 0) + msg = "update num : " + Util::int2string(ret); + else //update error + msg = "update failed."; + if (ret != -100) + cout << msg << endl; + } + cout << "delete successfully" << endl; + } + string time = Util::get_date_time(); + string sparql = "INSERT DATA {<" + _db_path + "> \"" + time + "\".}"; + ResultSet _rs; + FILE* ofp = stdout; + string msg; + int ret = system_db.query(sparql, _rs, ofp); + if (ret <= -100) // select query + { + if (ret == -100) + msg = _rs.to_str(); + else //query error + msg = "query failed"; + } + else //update query + { + if (ret >= 0) + msg = "update num : " + Util::int2string(ret); + else //update error + msg = "update failed."; + if (ret != -100) + cout << msg << endl; + } + cout << "insert successfully" << endl; return 0; } diff --git a/Main/ghttp.cpp b/Main/ghttp.cpp index 37e8ce1..ff29dd8 100644 --- a/Main/ghttp.cpp +++ b/Main/ghttp.cpp @@ -2,8 +2,8 @@ # Filename: ghttp.cpp # Author: Bookug Lobert # Mail: zengli-bookug@pku.edu.cn -# Last Modified: 2017-06-15 15:09 -# Description: created by lvxin, improved by lijing +# Last Modified: 2018-10-19 20:27 +# Description: created by lvxin, improved by lijing and suxunbin =============================================================================*/ //SPARQL Endpoint: log files in logs/endpoint/ @@ -97,7 +97,7 @@ bool drop_handler(const HttpServer& server, const shared_ptr& response, const shared_ptr& request); -void checkall_thread(const shared_ptr& response, const shared_ptr& request); +bool checkall_thread(const shared_ptr& response, const shared_ptr& request); //============================================================================= @@ -114,9 +114,50 @@ pthread_rwlock_t users_map_lock; Database *system_database; std::map databases; -//std::set already_build; -std::map already_build; +//database information +struct DBInfo{ + private: + std::string db_name; + std::string creator; + std::string built_time; + public: + pthread_rwlock_t db_lock; + + DBInfo(){ + pthread_rwlock_init(&db_lock, NULL); + } + DBInfo(string _db_name, string _creator, string _time){ + db_name = _db_name; + creator = _creator; + built_time = _time; + pthread_rwlock_init(&db_lock, NULL); + } + DBInfo(string _db_name){ + db_name = _db_name; + pthread_rwlock_init(&db_lock, NULL); + } + ~DBInfo(){ + pthread_rwlock_destroy(&db_lock); + } + std::string getName(){ + return db_name; + } + std::string getCreator(){ + return creator; + } + void setCreator(string _creator){ + creator = _creator; + } + std::string getTime(){ + return built_time; + } + void setTime(string _time){ + built_time = _time; + } +}; + +//user information struct User{ private: std::string username; @@ -220,7 +261,7 @@ struct User{ }; //struct User root = User(ROOT_USERNAME, ROOT_PASSWORD); - +std::map already_build; std::map users; //struct User root = User(ROOT_USERNAME, ROOT_PASSWORD); //users.insert(pair(ROOT_USERNAME, &root)); @@ -582,6 +623,20 @@ int initialize(int argc, char *argv[]) //users.insert(pair(ROOT_USERNAME, &root)); //load system.db when initialize + if(!boost::filesystem::exists("system.db")) + { + cout << "Can not find system.db."<setCreator("root"); + already_build.insert(pair("system", temp_db)); + std::map::iterator it_already_build = already_build.find("system"); + if(pthread_rwlock_trywrlock(&(it_already_build->second->db_lock)) != 0) + { + cout << "Unable to load the database system.db due to loss of lock."<load(); if(!flag) @@ -592,9 +647,9 @@ int initialize(int argc, char *argv[]) return -1; } databases.insert(pair("system", system_database)); - - - //check databases that already built in the directory + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); + + /*//check databases that already built in the directory DIR * dir; struct dirent * ptr; dir = opendir("."); //open a directory @@ -621,11 +676,11 @@ int initialize(int argc, char *argv[]) } } } - closedir(dir);//close the pointer of the directory + closedir(dir);//close the pointer of the directory*/ //insert user from system.db to user map DB2Map(); - + HttpServer server; string db_name; if(argc == 1) @@ -676,7 +731,7 @@ int initialize(int argc, char *argv[]) //string success = db_name; - cout << "Database systetm.db loaded successfully."< response, shared_ptr request) + server.resource["^/%3[F|f]operation%3[D|d]monitor%26db_name%3[D|d](.*)%26username%3[D|d](.*)%26password%3[D|d](.*)$"]["GET"]=[&server](shared_ptr response, shared_ptr request) { //server.resource["^/monitor$"]["GET"]=[&server](shared_ptr response, shared_ptr request) { monitor_handler(server, response, request); @@ -883,7 +938,7 @@ int initialize(int argc, char *argv[]) //NOTICE:this may not be visited by browser directly if the browser does not do URL encode automatically! //In programming language, do URL encode first and then call server, then all is ok - server.resource["^/?operation=monitor&db_name=(.*)$"]["GET"]=[&server](shared_ptr response, shared_ptr request) + server.resource["^/?operation=monitor&db_name=(.*)&username=(.*)&password=(.*)$"]["GET"]=[&server](shared_ptr response, shared_ptr request) { //server.resource["^/monitor$"]["GET"]=[&server](shared_ptr response, shared_ptr request) { monitor_handler(server, response, request); @@ -906,22 +961,24 @@ int initialize(int argc, char *argv[]) // } // }; - server.resource["^/%3[F|f]operation%3[D|d]stop$"]["GET"]=[&server](shared_ptr response, shared_ptr request) + server.resource["^/%3[F|f]operation%3[D|d]stop%26username%3[D|d](.*)%26password%3[D|d](.*)$"]["GET"]=[&server](shared_ptr response, shared_ptr request) { - stop_handler(server, response, request); - exit(0); + bool flag = stop_handler(server, response, request); + if(flag) + exit(0); }; - server.resource["^/?operation=stop$"]["GET"]=[&server](shared_ptr response, shared_ptr request) + server.resource["^/?operation=stop&username=(.*)&password=(.*)$"]["GET"]=[&server](shared_ptr response, shared_ptr request) { - stop_handler(server, response, request); - exit(0); + bool flag = stop_handler(server, response, request); + if(flag) + exit(0); }; - server.resource["^/%3[F|f]operation%3[D|d]checkpoint%26db_name%3[D|d](.*)$"]["GET"]=[&server](shared_ptr response, shared_ptr request) + server.resource["^/%3[F|f]operation%3[D|d]checkpoint%26db_name%3[D|d](.*)%26username%3[D|d](.*)%26password%3[D|d](.*)$"]["GET"]=[&server](shared_ptr response, shared_ptr request) { checkpoint_handler(server, response, request); }; - server.resource["^/?operation=checkpoint&db_name=(.*)$"]["GET"]=[&server](shared_ptr response, shared_ptr request) + server.resource["^/?operation=checkpoint&db_name=(.*)&username=(.*)&password=(.*)$"]["GET"]=[&server](shared_ptr response, shared_ptr request) { checkpoint_handler(server, response, request); }; @@ -935,13 +992,13 @@ int initialize(int argc, char *argv[]) }; //TODO: add user name as parameter, all databases availiable - server.resource["^/%3[F|f]operation%3[D|d]show$"]["GET"]=[&server](shared_ptr response, shared_ptr request) + server.resource["^/%3[F|f]operation%3[D|d]show%26username%3[D|d](.*)%26password%3[D|d](.*)$"]["GET"]=[&server](shared_ptr response, shared_ptr request) { show_handler(server, response, request); }; //TODO: add user name as parameter, all databases availiable - server.resource["^/?operation=show$"]["GET"]=[&server](shared_ptr response, shared_ptr request) + server.resource["^/?operation=show&username=(.*)&password=(.*)$"]["GET"]=[&server](shared_ptr response, shared_ptr request) { show_handler(server, response, request); }; @@ -1254,60 +1311,55 @@ void build_thread(const shared_ptr& response, const shared username = UrlDecode(username); password = UrlDecode(password); - //check if the db_path is the path of system.nt - if(db_path == SYSTEM_PATH) - { - string error = "You has no rights to access system files"; - string resJson = CreateJson(205, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - return; - } - //check if database named [db_name] is already built - pthread_rwlock_rdlock(&already_build_map_lock); - if(already_build.find(db_name) != already_build.end()) - { - string error = "database already built."; - string resJson = CreateJson(201, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - - //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; - //return false; - pthread_rwlock_unlock(&already_build_map_lock); - return; - } - pthread_rwlock_unlock(&already_build_map_lock); - //check identity. pthread_rwlock_rdlock(&users_map_lock); std::map::iterator it = users.find(username); - if(it == users.end()) + if (it == users.end()) { string error = "username not find."; string resJson = CreateJson(903, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - - + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; //return false; pthread_rwlock_unlock(&users_map_lock); - return; + return; } - else if(it->second->getPassword() != password) + else if (it->second->getPassword() != password) { string error = "wrong password."; string resJson = CreateJson(902, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - - + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; //return false; pthread_rwlock_unlock(&users_map_lock); - return; + return; } pthread_rwlock_unlock(&users_map_lock); cout << "check identity successfully." << endl; + //check if the db_path is the path of system.nt + if(db_path == SYSTEM_PATH) + { + string error = "You have no rights to access system files"; + string resJson = CreateJson(205, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + return; + } + + //check if the db_name is system + if (db_name == "system") + { + string error = "Your db name to be built can not be system."; + string resJson = CreateJson(206, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + return; + } + if(db_name=="" || db_path=="") { string error = "Exactly 2 arguments required!"; @@ -1331,6 +1383,21 @@ void build_thread(const shared_ptr& response, const shared return; } + //check if database named [db_name] is already built + pthread_rwlock_rdlock(&already_build_map_lock); + if (already_build.find(db_name) != already_build.end()) + { + string error = "database already built."; + string resJson = CreateJson(201, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + //return false; + pthread_rwlock_unlock(&already_build_map_lock); + return; + } + pthread_rwlock_unlock(&already_build_map_lock); + //database += ".db"; string dataset = db_path; @@ -1366,7 +1433,6 @@ void build_thread(const shared_ptr& response, const shared delete current_database; current_database = NULL; - if(!flag) { string error = "Import RDF file to database failed."; @@ -1384,6 +1450,7 @@ void build_thread(const shared_ptr& response, const shared ofstream f; f.open("./"+ database +".db/success.txt"); f.close(); + //by default, one can query or load or unload the database that is built by itself, so add the database name to the privilege set of the user if(addPrivilege(username, "query", db_name) == 0 || addPrivilege(username, "load", db_name) == 0 || addPrivilege(username, "unload", db_name) == 0) { @@ -1397,16 +1464,18 @@ void build_thread(const shared_ptr& response, const shared return; } cout << "add query and load and unload privilege succeed after build." << endl; + + //add database information to system.db pthread_rwlock_wrlock(&already_build_map_lock); cout << "already_build_map_lock acquired." << endl; - //add database name to already_build set. - //already_build.insert(db_name); - pthread_rwlock_t temp_lock; - pthread_rwlock_init(&temp_lock, NULL); - already_build.insert(pair(db_name, temp_lock)); - pthread_rwlock_destroy(&temp_lock); + string time = Util::get_date_time(); + struct DBInfo *temp_db = new DBInfo(db_name, username, time); + already_build.insert(pair(db_name, temp_db)); pthread_rwlock_unlock(&already_build_map_lock); - + string update = "INSERT DATA {<" + db_name + "> \"already_built\"." + + "<" + db_name + "> <" + username + "> ." + "<" + db_name + "> \"" + time + "\".}"; + updateSys(update); + cout << "database add done." << endl; // string success = db_name + " " + db_path; string success = "Import RDF file to database done."; string resJson = CreateJson(0, success, 0); @@ -1437,9 +1506,71 @@ void load_thread(const shared_ptr& response, const shared_ username = UrlDecode(username); password = UrlDecode(password); + //check identity. + pthread_rwlock_rdlock(&users_map_lock); + std::map::iterator it = users.find(username); + if (it == users.end()) + { + string error = "username not find."; + string resJson = CreateJson(903, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + //return false; + pthread_rwlock_unlock(&users_map_lock); + return; + } + else if (it->second->getPassword() != password) + { + string error = "wrong password."; + string resJson = CreateJson(902, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + //return false; + pthread_rwlock_unlock(&users_map_lock); + return; + } + pthread_rwlock_unlock(&users_map_lock); + + cout << "check identity successfully." << endl; + + //check if the db_name is system + if (db_name == "system") + { + string error = "no load privilege, operation failed."; + string resJson = CreateJson(302, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + return; + } + + // string db_name = argv[1]; + if (db_name == "") + { + string error = "Exactly 1 argument is required!"; + string resJson = CreateJson(904, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + //*response << "HTTP/1.1 200 ok\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + return; + } + + string database = db_name; + if (database.length() > 3 && database.substr(database.length() - 3, 3) == ".db") + { + //cout << "Your db name to be built should not end with \".db\"." << endl; + string error = "Your db name to be built should not end with \".db\"."; + string resJson = CreateJson(202, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + return; + } + //check if database named [db_name] is already build. pthread_rwlock_rdlock(&already_build_map_lock); - std::map::iterator it_already_build = already_build.find(db_name); + std::map::iterator it_already_build = already_build.find(db_name); if(it_already_build== already_build.end()) { string error = "Database not built yet."; @@ -1469,35 +1600,6 @@ void load_thread(const shared_ptr& response, const shared_ return; } pthread_rwlock_unlock(&databases_map_lock); - //check identity. - pthread_rwlock_rdlock(&users_map_lock); - std::map::iterator it = users.find(username); - if(it == users.end()) - { - string error = "username not find."; - string resJson = CreateJson(903, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - - //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; - //return false; - pthread_rwlock_unlock(&users_map_lock); - return; - } - else if(it->second->getPassword() != password) - { - string error = "wrong password."; - string resJson = CreateJson(902, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - - - //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; - //return false; - pthread_rwlock_unlock(&users_map_lock); - return; - } - pthread_rwlock_unlock(&users_map_lock); - - cout << "check identity successfully." << endl; //check privilege if(checkPrivilege(username, "load", db_name) == 0) @@ -1513,30 +1615,6 @@ void load_thread(const shared_ptr& response, const shared_ } cout << "check privilege successfully." << endl; - // string db_name = argv[1]; - if(db_name=="") - { - string error = "Exactly 1 argument is required!"; - string resJson = CreateJson(904, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - - - //*response << "HTTP/1.1 200 ok\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; - return; - } - - string database = db_name; - if(database.length() > 3 && database.substr(database.length()-3, 3) == ".db") - { - //cout << "Your db name to be built should not end with \".db\"." << endl; - string error = "Your db name to be built should not end with \".db\"."; - string resJson = CreateJson(202, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - - //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; - return; - } - // if(pthread_rwlock_tryrdlock(&database_load_lock) != 0) // { // string error = "Unable to load due to loss of lock"; @@ -1565,7 +1643,7 @@ void load_thread(const shared_ptr& response, const shared_ // return; // } - if(pthread_rwlock_trywrlock(&(it_already_build->second)) != 0) + if(pthread_rwlock_trywrlock(&(it_already_build->second->db_lock)) != 0) { string error = "Unable to load due to loss of lock"; string resJson = CreateJson(303, error, 0); @@ -1579,7 +1657,7 @@ void load_thread(const shared_ptr& response, const shared_ bool flag = current_database->load(); //delete current_database; //current_database = NULL; - cout << "load done." << endl; + //cout << "load done." << endl; if (!flag) { string error = "Failed to load the database."; @@ -1610,7 +1688,7 @@ void load_thread(const shared_ptr& response, const shared_ //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << success.length() << "\r\n\r\n" << success; - pthread_rwlock_unlock(&(it_already_build->second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); } bool load_handler(const HttpServer& server, const shared_ptr& response, const shared_ptr& request) @@ -1664,6 +1742,15 @@ void unload_thread(const shared_ptr& response, const share cout << "check identity successfully." << endl; + //check if the db_name is system + if (db_name == "system") + { + string error = "no unload privilege, operation failed."; + string resJson = CreateJson(601, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + return; + } + //check privilege if(checkPrivilege(username, "unload", db_name) == 0) { @@ -1715,10 +1802,10 @@ void unload_thread(const shared_ptr& response, const share pthread_rwlock_unlock(&databases_map_lock); return; } - //delete current_database; - //current_database = NULL; - std::map::iterator it_already_build = already_build.find(db_name); - if(pthread_rwlock_trywrlock(&(it_already_build->second)) != 0) + pthread_rwlock_rdlock(&already_build_map_lock); + std::map::iterator it_already_build = already_build.find(db_name); + pthread_rwlock_unlock(&already_build_map_lock); + if(pthread_rwlock_trywrlock(&(it_already_build->second->db_lock)) != 0) { string error = "Unable to unload due to loss of lock"; string resJson = CreateJson(602, error, 0); @@ -1739,7 +1826,7 @@ void unload_thread(const shared_ptr& response, const share //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << success.length() << "\r\n\r\n" << success; // pthread_rwlock_unlock(&database_load_lock); - pthread_rwlock_unlock(&(it_already_build->second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); pthread_rwlock_unlock(&databases_map_lock); } @@ -1766,46 +1853,74 @@ void drop_thread(const shared_ptr& response, const shared_ //check identity. pthread_rwlock_rdlock(&users_map_lock); std::map::iterator it = users.find(username); - if(it == users.end()) + if (it == users.end()) { string error = "username not find."; string resJson = CreateJson(903, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; pthread_rwlock_unlock(&users_map_lock); - return; + return; } - else if(it->second->getPassword() != password) + else if (it->second->getPassword() != password) { string error = "wrong password."; string resJson = CreateJson(902, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; pthread_rwlock_unlock(&users_map_lock); - return; + return; } pthread_rwlock_unlock(&users_map_lock); cout << "check identity successfully." << endl; + //check if the db_name is system + if (db_name == "system") + { + string error = "no drop privilege, operation failed."; + string resJson = CreateJson(701, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + return; + } + + //check if database named [db_name] is already build. + pthread_rwlock_rdlock(&already_build_map_lock); + std::map::iterator it_already_build = already_build.find(db_name); + if(it_already_build== already_build.end()) + { + string error = "Database not built yet."; + string resJson = CreateJson(203, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + pthread_rwlock_unlock(&already_build_map_lock); + return; + } + pthread_rwlock_unlock(&already_build_map_lock); + //check privilege - //if(checkPrivilege(username, "drop", db_name) == 0) - //{ - // string error = "no drop privilege, operation failed."; - // *response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; - // return; - //} - //cout << "check privilege successfully." << endl; + string creator = it_already_build->second->getCreator(); + if (creator != username) + { + if (username != ROOT_USERNAME) + { + string error = "no drop privilege, operation failed."; + string resJson = CreateJson(701, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + return; + } + } + cout << "check privilege successfully." << endl; //if database named [db_name] is loaded, unload it firstly pthread_rwlock_wrlock(&databases_map_lock); std::map::iterator iter = databases.find(db_name); if(iter != databases.end()) { - std::map::iterator it_already_build = already_build.find(db_name); - if(pthread_rwlock_trywrlock(&(it_already_build->second)) != 0) + if(pthread_rwlock_trywrlock(&(it_already_build->second->db_lock)) != 0) { string error = "Unable to unload due to loss of lock"; string resJson = CreateJson(602, error, 0); @@ -1824,33 +1939,26 @@ void drop_thread(const shared_ptr& response, const shared_ *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << success.length() << "\r\n\r\n" << success; - pthread_rwlock_unlock(&(it_already_build->second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); } pthread_rwlock_unlock(&databases_map_lock); - //check if database named [db_name] is already build. - pthread_rwlock_rdlock(&already_build_map_lock); - std::map::iterator it_already_build = already_build.find(db_name); - if(it_already_build== already_build.end()) - { - string error = "Database not built yet."; - string resJson = CreateJson(203, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - - //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; - pthread_rwlock_unlock(&already_build_map_lock); - return; - } - //drop database named [db_name] - pthread_rwlock_destroy(&(it_already_build->second)); + pthread_rwlock_rdlock(&already_build_map_lock); + struct DBInfo *temp_db = it_already_build->second; + string time = temp_db->getTime(); + delete temp_db; + temp_db = NULL; already_build.erase(db_name); string success = "Database " + db_name + " dropped."; string resJson = CreateJson(0, success, 0); *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << success.length() << "\r\n\r\n" << success; pthread_rwlock_unlock(&already_build_map_lock); + + string update = "DELETE DATA {<" + db_name + "> \"already_built\"." + + "<" + db_name + "> <" + creator + "> ." + "<" + db_name + "> \"" + time + "\".}"; + updateSys(update); string cmd; if(r) cmd = "rm -r " + db_name + ".db"; @@ -1912,7 +2020,7 @@ void query_thread(string db_name, string format, string db_query, const shared_p pthread_rwlock_unlock(&databases_map_lock); pthread_rwlock_rdlock(&already_build_map_lock); - std::map::iterator it_already_build = already_build.find(db_name); + std::map::iterator it_already_build = already_build.find(db_name); pthread_rwlock_unlock(&already_build_map_lock); //if(pthread_rwlock_tryrdlock(&(it_already_build->second)) != 0) //{ @@ -1920,7 +2028,7 @@ void query_thread(string db_name, string format, string db_query, const shared_p // *response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; // return; //} - pthread_rwlock_rdlock(&(it_already_build->second)); + pthread_rwlock_rdlock(&(it_already_build->second->db_lock)); //TODO:MODIFY // if(pthread_rwlock_tryrdlock(&database_load_lock) != 0) @@ -1948,7 +2056,7 @@ void query_thread(string db_name, string format, string db_query, const shared_p //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; - pthread_rwlock_unlock(&(it_already_build->second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); return; } FILE* output = NULL; @@ -2061,7 +2169,7 @@ void query_thread(string db_name, string format, string db_query, const shared_p //*response << "\r\nContent-Type: text/plain"; //*response << "\r\nCache-Control: no-cache" << "\r\nPragma: no-cache" << "\r\nExpires: 0"; //*response << "\r\n\r\n" << "0+" << query_time_s<< '+' << rs.ansNum << '+' << filename << '+' << success; - pthread_rwlock_unlock(&(it_already_build->second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); //return true; return; /* @@ -2129,7 +2237,7 @@ void query_thread(string db_name, string format, string db_query, const shared_p // //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << ansNum_s.length()+filename.length()+3; //*response << "\r\n\r\n" << "2+" << rs.ansNum << '+' << filename; - pthread_rwlock_unlock(&(it_already_build->second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); return; //return true; } @@ -2155,7 +2263,7 @@ void query_thread(string db_name, string format, string db_query, const shared_p //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; - pthread_rwlock_unlock(&(it_already_build->second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); //return false; return; } @@ -2173,6 +2281,15 @@ bool query_handler0(const HttpServer& server, const shared_ptr::iterator it = users.find(username); - if(it == users.end()) + if (it == users.end()) { string error = "username not find."; string resJson = CreateJson(903, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - - + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; pthread_rwlock_unlock(&users_map_lock); return false; } - else if(it->second->getPassword() != password) + else if (it->second->getPassword() != password) { string error = "wrong password."; string resJson = CreateJson(902, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - - + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; pthread_rwlock_unlock(&users_map_lock); return false; @@ -2234,6 +2351,15 @@ bool query_handler1(const HttpServer& server, const shared_ptr& response, const shar string thread_id = Util::getThreadID(); string log_prefix = "thread " + thread_id + " -- "; cout<& response, const shar // } string db_name = request->path_match[1]; + string username = request->path_match[2]; + string password = request->path_match[3]; db_name = UrlDecode(db_name); + username = UrlDecode(username); + password = UrlDecode(password); + //check identity. + pthread_rwlock_rdlock(&users_map_lock); + std::map::iterator it = users.find(username); + if (it == users.end()) + { + string error = "username not find."; + string resJson = CreateJson(903, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + pthread_rwlock_unlock(&users_map_lock); + return; + } + else if (it->second->getPassword() != password) + { + string error = "wrong password."; + string resJson = CreateJson(902, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + pthread_rwlock_unlock(&users_map_lock); + return; + } + pthread_rwlock_unlock(&users_map_lock); + cout << "check identity successfully." << endl; + + //check if the db_name is system and if the username is root + if ((db_name == "system") && (username != ROOT_USERNAME)) + { + string error = "no monitor privilege, operation failed."; + string resJson = CreateJson(502, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + return; + } + + //check if database named [db_name] is already load pthread_rwlock_rdlock(&databases_map_lock); std::map::iterator iter = databases.find(db_name); if(iter == databases.end()) @@ -2356,12 +2524,14 @@ void monitor_thread(const shared_ptr& response, const shar Database * _database = iter->second; pthread_rwlock_unlock(&databases_map_lock); - + //show statistical information of database named db_name pthread_rwlock_rdlock(&already_build_map_lock); - std::map::iterator it_already_build = already_build.find(db_name); + std::map::iterator it_already_build = already_build.find(db_name); + string creator = it_already_build->second->getCreator(); + string time = it_already_build->second->getTime(); pthread_rwlock_unlock(&already_build_map_lock); - if(pthread_rwlock_tryrdlock(&(it_already_build->second)) != 0) + if(pthread_rwlock_tryrdlock(&(it_already_build->second->db_lock)) != 0) { string error = "Unable to monitor due to loss of lock"; string resJson = CreateJson(501, error, 0); @@ -2376,6 +2546,8 @@ void monitor_thread(const shared_ptr& response, const shar string success; string name = _database->getName(); success = success + "database: " + name + "\r\n"; + success = success + "creator: " + creator + "\r\n"; + success = success + "built_time: " + time + "\r\n"; TYPE_TRIPLE_NUM triple_num = _database->getTripleNum(); success = success + "triple num: " + Util::int2string(triple_num) + "\r\n"; TYPE_ENTITY_LITERAL_ID entity_num = _database->getEntityNum(); @@ -2398,7 +2570,7 @@ void monitor_thread(const shared_ptr& response, const shar *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << success.length() << "\r\n\r\n" << success; - pthread_rwlock_unlock(&(it_already_build->second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); } bool monitor_handler(const HttpServer& server, const shared_ptr& response, const shared_ptr& request) @@ -2770,9 +2942,46 @@ bool login_handler(const HttpServer& server, const shared_ptr& response, const shared_ptr& request) { + string thread_id = Util::getThreadID(); + string log_prefix = "thread " + thread_id + " -- "; + cout<path_match[1]; + string password = request->path_match[2]; + username = UrlDecode(username); + password = UrlDecode(password); + + //check identity. + if (username != ROOT_USERNAME) + { + string error = "You have no rights to stop the server."; + string resJson = CreateJson(702, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + cout << "Stop server failed." << endl; + return false; + } + pthread_rwlock_rdlock(&users_map_lock); + std::map::iterator it = users.find(ROOT_USERNAME); + if(it->second->getPassword() != password) + { + string error = "wrong password."; + string resJson = CreateJson(902, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + pthread_rwlock_unlock(&users_map_lock); + cout << "Stop server failed." << endl; + return false; + } + pthread_rwlock_unlock(&users_map_lock); + cout << "check identity successfully." << endl; + //string success = "Server stopped."; //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << success.length() << "\r\n\r\n" << success; - checkall_thread(response, request); + bool flag = checkall_thread(response, request); + if (flag == false) + { + cout << "Stop server failed." << endl; + return false; + } cout<<"Server stopped."<& response, const s // } string db_name = request->path_match[1]; + string username = request->path_match[2]; + string password = request->path_match[3]; db_name = UrlDecode(db_name); + username = UrlDecode(username); + password = UrlDecode(password); + //check identity. + pthread_rwlock_rdlock(&users_map_lock); + std::map::iterator it = users.find(username); + if (it == users.end()) + { + string error = "username not find."; + string resJson = CreateJson(903, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + pthread_rwlock_unlock(&users_map_lock); + return; + } + else if (it->second->getPassword() != password) + { + string error = "wrong password."; + string resJson = CreateJson(902, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + pthread_rwlock_unlock(&users_map_lock); + return; + } + pthread_rwlock_unlock(&users_map_lock); + cout << "check identity successfully." << endl; + + //check if the db_name is system and if the username is root + if ((db_name == "system") && (username != ROOT_USERNAME)) + { + string error = "no checkpoint privilege, operation failed."; + string resJson = CreateJson(703, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + return; + } + + //check if database named [db_name] is loaded. pthread_rwlock_rdlock(&databases_map_lock); std::map::iterator iter = databases.find(db_name); if(iter == databases.end()) @@ -2802,25 +3053,37 @@ void checkpoint_thread(const shared_ptr& response, const s string resJson = CreateJson(304, error, 0); *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; pthread_rwlock_unlock(&databases_map_lock); return; } Database *current_database = iter->second; - pthread_rwlock_unlock(&databases_map_lock); - + pthread_rwlock_unlock(&databases_map_lock); + + //check privilege pthread_rwlock_rdlock(&already_build_map_lock); - std::map::iterator it_already_build = already_build.find(db_name); - pthread_rwlock_unlock(&databases_map_lock); - - if(pthread_rwlock_trywrlock(&(it_already_build->second)) != 0) + std::map::iterator it_already_build = already_build.find(db_name); + string creator = it_already_build->second->getCreator(); + pthread_rwlock_unlock(&already_build_map_lock); + if(creator != username) { - string error = "Unable to monitor due to loss of lock"; - string resJson = CreateJson(501, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; - - + if (username != ROOT_USERNAME) + { + string error = "no checkpoint privilege, operation failed."; + string resJson = CreateJson(703, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + return; + } + } + cout << "check privilege successfully." << endl; + + if(pthread_rwlock_trywrlock(&(it_already_build->second->db_lock)) != 0) + { + string error = "Unable to checkpoint due to loss of lock"; + string resJson = CreateJson(704, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; return; } @@ -2830,7 +3093,7 @@ void checkpoint_thread(const shared_ptr& response, const s //http://www.fx114.net/qa-63-143449.aspx current_database->save(); //NOTICE: this info is in header - string success = "Database saveed successfully."; + string success = "Database saved successfully."; //header and content are split by an empty line string resJson = CreateJson(0, success, 0); *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; @@ -2838,7 +3101,7 @@ void checkpoint_thread(const shared_ptr& response, const s //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << success.length() << "\r\n\r\n" << success; - pthread_rwlock_unlock(&(it_already_build->second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); } //TODO+BETTER: server choose to save a database when system is not busy @@ -2850,7 +3113,7 @@ bool checkpoint_handler(const HttpServer& server, const shared_ptr& response, const shared_ptr& request) +bool checkall_thread(const shared_ptr& response, const shared_ptr& request) { string thread_id = Util::getThreadID(); string log_prefix = "thread " + thread_id + " -- "; @@ -2861,32 +3124,51 @@ void checkall_thread(const shared_ptr& response, const sha string success; for(iter=databases.begin(); iter != databases.end(); iter++) { - Database *current_database = iter->second; string database_name = iter->first; + if (database_name == "system") + continue; + Database *current_database = iter->second; pthread_rwlock_rdlock(&already_build_map_lock); - std::map::iterator it_already_build = already_build.find(database_name); + std::map::iterator it_already_build = already_build.find(database_name); pthread_rwlock_unlock(&already_build_map_lock); - if(pthread_rwlock_trywrlock(&(it_already_build->second)) != 0) + if (pthread_rwlock_trywrlock(&(it_already_build->second->db_lock)) != 0) { - string error = "Unable to monitor due to loss of lock"; - string resJson = CreateJson(501, error, 0); - *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + string error = "Unable to checkpoint due to loss of lock"; + string resJson = CreateJson(704, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; pthread_rwlock_unlock(&databases_map_lock); - return; + return false; } current_database->save(); + delete current_database; + current_database = NULL; cout<< "Database " << database_name << " saved successfully." <second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); } + system_database->save(); + delete system_database; + system_database = NULL; + cout << "Database system saved successfully." << endl; pthread_rwlock_unlock(&databases_map_lock); - return; + + pthread_rwlock_rdlock(&already_build_map_lock); + std::map::iterator it_already_build; + for (it_already_build = already_build.begin(); it_already_build != already_build.end(); it_already_build++) + { + struct DBInfo *temp_db = it_already_build->second; + delete temp_db; + temp_db = NULL; + } + pthread_rwlock_unlock(&already_build_map_lock); + + return true; } bool checkall_handler(const HttpServer& server, const shared_ptr& response, const shared_ptr& request) @@ -2902,18 +3184,57 @@ void show_thread(const shared_ptr& response, const shared_ string log_prefix = "thread " + thread_id + " -- "; cout<path_match[1]; + string password = request->path_match[2]; + username = UrlDecode(username); + password = UrlDecode(password); + + //check identity. + pthread_rwlock_rdlock(&users_map_lock); + std::map::iterator it = users.find(username); + if(it == users.end()) + { + string error = "username not find."; + string resJson = CreateJson(903, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + pthread_rwlock_unlock(&users_map_lock); + return; + } + else if(it->second->getPassword() != password) + { + string error = "wrong password."; + string resJson = CreateJson(902, error, 0); + *response << "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " << resJson.length() << "\r\n\r\n" << resJson; + + + //*response << "HTTP/1.1 200 OK\r\nContent-Length: " << error.length() << "\r\n\r\n" << error; + pthread_rwlock_unlock(&users_map_lock); + return; + } + pthread_rwlock_unlock(&users_map_lock); + cout << "check identity successfully." << endl; + pthread_rwlock_rdlock(&already_build_map_lock); - std::map::iterator it_already_build; + std::map::iterator it_already_build; string success; for(it_already_build=already_build.begin(); it_already_build != already_build.end(); it_already_build++) { string database_name = it_already_build->first; - success = success + database_name; + string creator = it_already_build->second->getCreator(); + string time = it_already_build->second->getTime(); + if((database_name == "system")&&(username != ROOT_USERNAME)) + continue; + success = success + "database: " + database_name + "\r\n"; + success = success + "creator: " + creator + "\r\n"; + success = success + "built_time: " + time + "\r\n"; pthread_rwlock_rdlock(&databases_map_lock); if(databases.find(database_name)== databases.end()) - success = success + " unloaded\r\n"; + success = success + "status: unloaded\r\n\r\n"; else - success = success + " loaded\r\n"; + success = success + "status: loaded\r\n\r\n"; pthread_rwlock_unlock(&databases_map_lock); } string resJson = CreateJson(0, "success", 1, success); @@ -3344,8 +3665,7 @@ std::string CreateJson(int StatusCode, string StatusMsg, bool body, string Respo } void DB2Map() -{ - +{ string sparql = "select ?x ?y where{?x ?y.}"; string strJson = querySys(sparql); //cout << "DDDDDDDDDDDDDDDB2Map: strJson : " << strJson << endl; @@ -3410,16 +3730,70 @@ void DB2Map() //i++; } //cout << "out of first ptree" << endl; + + //insert already_built database from system.db to already_build map + sparql = "select ?x where{?x \"already_built\".}"; + strJson = querySys(sparql); + stringstream ss1; + ss1 << strJson; + read_json(ss1, pt); + p1 = pt.get_child("results"); + p2 = p1.get_child("bindings"); + for(ptree::iterator it = p2.begin(); it != p2.end(); ++it) + { + pp = it->second; + pp1 = pp.get_child("x"); + string db_name = pp1.get("value"); + struct DBInfo *temp_db = new DBInfo(db_name); + + string sparql2 = "select ?x ?y where{<" + db_name + "> ?x ?y.}"; + string strJson2 = querySys(sparql2); + stringstream ss2; + ss2 << strJson2; + ptree pt2, p12, p22, binding, pp12, pp22; + read_json(ss2, pt2); + p12 = pt2.get_child("results"); + p22 = p12.get_child("bindings"); + for(ptree::iterator it2 = p22.begin(); it2 != p22.end(); ++it2) + { + binding = it2->second; + pp12 = binding.get_child("x"); + pp22 = binding.get_child("y"); + string type = pp12.get("value"); + string info = pp22.get("value"); + if (type == "built_by") + temp_db->setCreator(info); + else if (type == "built_time") + temp_db->setTime(info); + } + already_build.insert(pair(db_name, temp_db)); + } + + //add bulit_time of system.db to already_build map + sparql = "select ?x where{ ?x.}"; + strJson = querySys(sparql); + stringstream ss2; + ss2 << strJson; + read_json(ss2, pt); + p1 = pt.get_child("results"); + p2 = p1.get_child("bindings"); + for (ptree::iterator it = p2.begin(); it != p2.end(); ++it) + { + pp = it->second; + pp1 = pp.get_child("x"); + string built_time = pp1.get("value"); + already_build.find("system")->second->setTime(built_time); + } } string querySys(string sparql) { string db_name = "system"; pthread_rwlock_rdlock(&already_build_map_lock); - std::map::iterator it_already_build = already_build.find(db_name); + std::map::iterator it_already_build = already_build.find(db_name); pthread_rwlock_unlock(&already_build_map_lock); - pthread_rwlock_rdlock(&(it_already_build->second)); + pthread_rwlock_rdlock(&(it_already_build->second->db_lock)); ResultSet rs; FILE* output = NULL; @@ -3439,7 +3813,7 @@ string querySys(string sparql) cout << "search query returned successfully." << endl; string success = rs.to_JSON(); - pthread_rwlock_unlock(&(it_already_build->second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); return success; } else @@ -3453,7 +3827,7 @@ string querySys(string sparql) error_code = 403; } - pthread_rwlock_unlock(&(it_already_build->second)); + pthread_rwlock_unlock(&(it_already_build->second->db_lock)); return error; } diff --git a/Main/ginit.cpp b/Main/ginit.cpp index c243588..3a60988 100644 --- a/Main/ginit.cpp +++ b/Main/ginit.cpp @@ -1,3 +1,11 @@ +/*============================================================================= +# Filename: ginit.cpp +# Author: suxunbin +# Mail: suxunbin@pku.edu.cn +# Last Modified: 2018-10-17 14:59 +# Description: used to initialize the system.db +=============================================================================*/ + #include "../Util/Util.h" #include "../Database/Database.h" @@ -10,11 +18,13 @@ int main(int argc, char * argv[]) if(boost::filesystem::exists("system.db")) return 0; } + + //build system.db Util util; string _db_path = "system"; string _rdf = "data/system/system.nt"; - Database _db(_db_path); - bool flag = _db.build(_rdf); + Database* _db = new Database(_db_path); + bool flag = _db->build(_rdf); if (flag) { cout << "import RDF file to database done." << endl; @@ -22,11 +32,44 @@ int main(int argc, char * argv[]) f.open("./"+ _db_path +".db/success.txt"); f.close(); } - else + else //if fails, drop system.db and return { cout << "import RDF file to database failed." << endl; string cmd = "rm -r " + _db_path + ".db"; system(cmd.c_str()); + delete _db; + _db = NULL; + return 0; } + + //insert built_time of system.db + delete _db; + _db = new Database(_db_path); + _db->load(); + string time = Util::get_date_time(); + string sparql = "INSERT DATA { \"" + time + "\".}"; + ResultSet _rs; + FILE* ofp = stdout; + string msg; + int ret = _db->query(sparql, _rs, ofp); + if (ret <= -100) // select query + { + if (ret == -100) + msg = _rs.to_str(); + else //query error + msg = "query failed"; + } + else //update query + { + if (ret >= 0) + msg = "update num : " + Util::int2string(ret); + else //update error + msg = "update failed."; + if (ret != -100) + cout << msg << endl; + } + delete _db; + _db = NULL; + cout << "system.db is built successfully!" << endl; return 0; } diff --git a/Main/shutdown.cpp b/Main/shutdown.cpp index 5331589..773fd5f 100644 --- a/Main/shutdown.cpp +++ b/Main/shutdown.cpp @@ -1,8 +1,19 @@ +/*============================================================================= +# Filename: shutdown.cpp +# Author: suxunbin +# Mail: suxunbin@pku.edu.cn +# Last Modified: 2018-10-16 16:15 +# Description: used to stop the ghttp server +=============================================================================*/ + #include "../api/http/cpp/client.h" #include "../Util/Util.h" using namespace std; +#define ROOT_USERNAME "root" +#define ROOT_PASSWORD "123456" + bool isNum(char *str) { for(int i = 0; i < strlen(str); i++) @@ -49,6 +60,6 @@ int main(int argc, char *argv[]) CHttpClient hc; string res; int ret; - ret = hc.Get("http://127.0.0.1:"+port+"/?operation=stop", res); + ret = hc.Get("http://127.0.0.1:" + port + "/?operation=stop&username=" + ROOT_USERNAME + "&password=" + ROOT_PASSWORD, res); return 0; } diff --git a/data/system/system.nt b/data/system/system.nt index d71fc35..ecaaaef 100644 --- a/data/system/system.nt +++ b/data/system/system.nt @@ -1 +1,2 @@ "123456" . + . diff --git a/docs/USAGE.md b/docs/USAGE.md index 19cfa10..fdd14d7 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -127,10 +127,13 @@ cout << answer << std::endl; gc.unload("lubm", "root", "123456"); // show all databases already built and if they are loaded -gc.show(); +gc.show("root", "123456"); // show statistical information of a loaded database -gc.monitor("lubm"); +gc.monitor("lubm", "root", "123456"); + +// save updates of a loaded database +gc.checkpoint("lubm", "root", "123456"); //add a user(with username: Jack, password: 2) answer = gc.user("add_user", "root", "123456", "Jack", "2"); diff --git a/scripts/test.sh b/scripts/test.sh index d8dd494..0760c22 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -2,6 +2,10 @@ #set -v +#initialize system.db +"bin/ginit" "--make" + +#test db=("bbug" "lubm" "num" "small") op=("bin/gbuild" "bin/gquery" "bin/gadd" "bin/gsub") path="./data/" @@ -142,5 +146,4 @@ else echo "Test failed!" fi -"bin/ginit" "--make" From 606518d6d1b7ae6c0f1b197d01029fbb28df1233 Mon Sep 17 00:00:00 2001 From: suxunbin Date: Sun, 21 Oct 2018 13:22:45 +0800 Subject: [PATCH 2/3] update scripts/test.sh --- scripts/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test.sh b/scripts/test.sh index 185fcbe..57c7b7c 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -3,7 +3,7 @@ #set -v #initialize system.db -"bin/ginit" "--make" +"bin/ginit" "--make" >& /dev/null #test db=("bbug" "lubm" "num" "small") From 3a94df0e662ec280ce6b06512ca92317bcd96c68 Mon Sep 17 00:00:00 2001 From: suxunbin Date: Thu, 25 Oct 2018 21:27:40 +0800 Subject: [PATCH 3/3] Add update triples test --- data/update_test.nt | 1 + makefile | 20 +++-- scripts/update_test.cpp | 185 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 data/update_test.nt create mode 100644 scripts/update_test.cpp diff --git a/data/update_test.nt b/data/update_test.nt new file mode 100644 index 0000000..0a0799f --- /dev/null +++ b/data/update_test.nt @@ -0,0 +1 @@ + . diff --git a/makefile b/makefile index 469eeee..0835ca5 100644 --- a/makefile +++ b/makefile @@ -59,6 +59,8 @@ objdir = .objs/ exedir = bin/ +testdir = scripts/ + lib_antlr = lib/libantlr.a api_cpp = api/socket/cpp/lib/libgstoreconnector.a @@ -111,7 +113,7 @@ inc = -I./tools/libantlr3c-3.4/ -I./tools/libantlr3c-3.4/include #gtest -TARGET = $(exedir)gbuild $(exedir)gserver $(exedir)gserver_backup_scheduler $(exedir)gclient $(exedir)gquery $(exedir)gconsole $(api_java) $(exedir)gadd $(exedir)gsub $(exedir)ghttp $(exedir)gmonitor $(exedir)gshow $(exedir)shutdown $(exedir)ginit +TARGET = $(exedir)gbuild $(exedir)gserver $(exedir)gserver_backup_scheduler $(exedir)gclient $(exedir)gquery $(exedir)gconsole $(api_java) $(exedir)gadd $(exedir)gsub $(exedir)ghttp $(exedir)gmonitor $(exedir)gshow $(exedir)shutdown $(exedir)ginit $(testdir)update_test all: $(TARGET) bash scripts/test.sh @@ -158,22 +160,23 @@ $(exedir)gconsole: $(lib_antlr) $(objdir)gconsole.o $(objfile) $(api_cpp) $(exedir)ghttp: $(lib_antlr) $(objdir)ghttp.o ./Server/server_http.hpp ./Server/client_http.hpp $(objfile) $(CC) $(EXEFLAG) -o $(exedir)ghttp $(objdir)ghttp.o $(objfile) $(library) $(inc) -DUSE_BOOST_REGEX $(openmp) - +$(testdir)update_test: $(lib_antlr) $(objdir)update_test.o $(objfile) + $(CC) $(EXEFLAG) -o $(testdir)update_test $(objdir)update_test.o $(objfile) $(library) $(openmp) #executables end #objects in Main/ begin -$(objdir)ginit.o: Main/ginit.cpp $(lib_antlr) +$(objdir)ginit.o: Main/ginit.cpp Database/Database.h Util/Util.h $(lib_antlr) $(CC) $(CFLAGS) Main/ginit.cpp $(inc) -o $(objdir)ginit.o $(openmp) -$(objdir)shutdown.o: Main/shutdown.cpp $(lib_antlr) +$(objdir)shutdown.o: Main/shutdown.cpp Database/Database.h Util/Util.h $(lib_antlr) $(CC) $(CFLAGS) Main/shutdown.cpp $(inc) -o $(objdir)shutdown.o $(openmp) -$(objdir)gmonitor.o: Main/gmonitor.cpp $(lib_antlr) +$(objdir)gmonitor.o: Main/gmonitor.cpp Database/Database.h Util/Util.h $(lib_antlr) $(CC) $(CFLAGS) Main/gmonitor.cpp $(inc) -o $(objdir)gmonitor.o $(openmp) -$(objdir)gshow.o: Main/gshow.cpp $(lib_antlr) +$(objdir)gshow.o: Main/gshow.cpp Database/Database.h Util/Util.h $(lib_antlr) $(CC) $(CFLAGS) Main/gshow.cpp $(inc) -o $(objdir)gshow.o $(openmp) $(objdir)gbuild.o: Main/gbuild.cpp Database/Database.h Util/Util.h $(lib_antlr) @@ -200,6 +203,11 @@ $(objdir)ghttp.o: Main/ghttp.cpp Server/server_http.hpp Server/client_http.hpp D #objects in Main/ end +#objects in scripts/ begin +$(objdir)update_test.o: scripts/update_test.cpp Database/Database.h Util/Util.h $(lib_antlr) + $(CC) $(CFLAGS) scripts/update_test.cpp $(inc) -o $(objdir)update_test.o $(openmp) +#objects in scripts/ end + #objects in kvstore/ begin diff --git a/scripts/update_test.cpp b/scripts/update_test.cpp new file mode 100644 index 0000000..04d0d9e --- /dev/null +++ b/scripts/update_test.cpp @@ -0,0 +1,185 @@ +/*============================================================================= +# Filename: update_test.cpp +# Author: suxunbin +# Mail: suxunbin@pku.edu.cn +# Last Modified: 2018-10-25 21:25 +# Description: used to test the correctness of update triples +=============================================================================*/ + +#include "../Util/Util.h" +#include "../Database/Database.h" + +using namespace std; + +//triple information +class triple{ +public: + string subject; + string predicate; + string object; + + triple(int s, int p, int o){ + subject = ""; + predicate = ""; + object = ""; + } + triple(string s, string p, string o){ + subject = s; + predicate = p; + object = o; + } + inline bool operator<(const triple& t) const + { + if (this->subject < t.subject) + return true; + else if (this->subject > t.subject) + return false; + else + { + if (this->predicate < t.predicate) + return true; + else if (this->predicate > t.predicate) + return false; + else + { + if (this->object < t.object) + return true; + else + return false; + } + } + } + inline bool operator==(const triple& t) const + { + if (this->subject != t.subject) + return false; + else + { + if (this->predicate != t.predicate) + return false; + else + { + if (this->object != t.object) + return false; + else + return true; + } + } + } +}; + +std::set update_triples; +std::set db_triples; +Database* db; + +int main(int argc, char * argv[]) +{ + //build update_test.db + Util util; + string db_name = "update_test"; + string db_path = "data/update_test.nt"; + db = new Database(db_name); + bool flag = db->build(db_path); + if (flag) + { + cout << "update_test.db is built done." << endl; + ofstream f; + f.open("./" + db_name + ".db/success.txt"); + f.close(); + } + else //if fails, drop update_test.db and return + { + cout << "update_test.db is built failed." << endl; + string cmd = "rm -r " + db_name + ".db"; + system(cmd.c_str()); + delete db; + db = NULL; + return 0; + } + + //load update_test.db + delete db; + db = new Database(db_name); + db->load(); + + //update triples test + srand((unsigned)time(NULL)); + update_triples.clear(); + triple temp(0, 0, 0); + update_triples.insert(temp); + for (int i = 0; i < 100; i++) + { + int a = rand() % 5 + 1; + int b = rand() % 5 + 1; + for (int j = 0; j < a; j++) + { + int s = rand() % 10; + int p = rand() % 10; + int o = rand() % 10; + triple t(s, p, o); + update_triples.insert(t); + string query = "INSERT DATA{" + t.subject + " " + t.predicate + " " + t.object + ".}"; + ResultSet _rs; + FILE* ofp = stdout; + int ret = db->query(query, _rs, ofp); + } + for (int j = 0; j < b; j++) + { + int s = rand() % 10; + int p = rand() % 10; + int o = rand() % 10; + triple t(s, p, o); + std::set::iterator it = update_triples.find(t); + if (it != update_triples.end()) + update_triples.erase(it); + string query = "DELETE DATA{" + t.subject + " " + t.predicate + " " + t.object + ".}"; + ResultSet _rs; + FILE* ofp = stdout; + int ret = db->query(query, _rs, ofp); + } + db_triples.clear(); + string query = "select ?s ?p ?o where{?s ?p ?o.}"; + ResultSet _rs; + FILE* ofp = NULL; + int ret = db->query(query, _rs, ofp); + for (int i = 0; i < _rs.ansNum; i++) + { + string s = _rs.answer[i][0]; + string p = _rs.answer[i][1]; + string o = _rs.answer[i][2]; + triple t(s, p, o); + db_triples.insert(t); + } + if (update_triples.size() != db_triples.size()) + { + cout << "Update triples exist errors." << endl; + delete db; + db = NULL; + string cmd = "rm -r " + db_name + ".db"; + system(cmd.c_str()); + return 0; + } + std::set::iterator it1; + std::set::iterator it2; + for (it1 = update_triples.begin(), it2 = db_triples.begin(); it1 != update_triples.end(); it1++, it2++) + { + if (*it1 == *it2) + continue; + else + { + cout << "Update triples exist errors." << endl; + delete db; + db = NULL; + string cmd = "rm -r " + db_name + ".db"; + system(cmd.c_str()); + return 0; + } + } + } + delete db; + db = NULL; + string cmd = "rm -r " + db_name + ".db"; + system(cmd.c_str()); + cout << "Test passed!" << endl; + return 0; +} \ No newline at end of file