#ifndef __JDB_JDB__ #define __JDB_JDB__ #include #include #include #include #include #include #include #include #include #include "dbclient/KM3NeTDBClient.h" #include "JSystem/JStat.hh" #include "JLang/JManip.hh" #include "JSon/JSon.hh" #include "JDB/JDBReader.hh" /** * \author mdejong */ namespace JDATABASE {} namespace JPP { using namespace JDATABASE; } namespace JDATABASE { using KM3NeT::DB::DBException; using KM3NeT::DB::Server; using KM3NeT::DB::Client; using KM3NeT::DB::ResultSet; using KM3NeT::DB::Selector; using JLANG::JDatabaseException; using JSON::json; /** * Wrapper class for server name. * * By reading the name of the server, this class will automatically set the server in class JDB. */ struct JServer : public std::string { /** * Default constructor. */ JServer() {} /** * Constructor. * * \param server server name */ JServer(const char* server) : std::string(server) {} }; /** * Named list of available database servers. */ static std::vector< std::pair > LIST_OF_SERVERS = { { "Default", Server::Default }, { "Test", Server::Test }, { "Lyon", Server::Lyon }, { "Lyon2", Server::Lyon2 }, { "Napoli", Server::Napoli } }; /** * Get server by name. * * \param server server name * \return server */ inline const Server& getServer(const std::string& server) { for (const auto& element : LIST_OF_SERVERS) { if (element.first == server) { return element.second; } } THROW(JDatabaseException, "Invalid server name " << server); } /** * Get list of names of available database servers. * * \return server names */ inline std::vector getServernames() { std::vector buffer; const char* const server = getenv("DATABASE_SERVER"); if (server != NULL) { buffer.push_back(server); } for (const auto& element : LIST_OF_SERVERS) { if (std::find(buffer.begin(), buffer.end(), element.first) == buffer.end()) { buffer.push_back(element.first); } } return buffer; } /** * Get default server. * * The default server is defined by: * -# named server from environment variable DATABASE_SERVER; else * -# first server in LIST_OF_SERVERS if not empty; else * -# default server Server::Default; * * \return server */ inline const Server& getServer() { const char* const server = getenv("DATABASE_SERVER"); if (server != NULL) return getServer(server); else if (!LIST_OF_SERVERS.empty()) return LIST_OF_SERVERS[0].second; else return Server::Default; } /** * Get private cookie. * * \return cookie */ inline const char* getPrivateCookie() { const char* home = getenv("HOME"); return MAKE_CSTRING((home != NULL ? home : ".") << "/" << ".km3netdb_cookie"); } /** * Get public cookie. * * \return cookie */ inline const char* getPublicCookie() { return getenv("DBCOOKIE"); } /** * Cookie prefix. */ static const char PREFIX_COOKIE = '_'; /** * This string is prepended to every parameter in the database output for the corresponding process. */ static const std::string PREFIX_DATAFILTER = "DAQ_triggerParameters"; static const std::string PREFIX_ADF = "DAQ_ADF"; /** * Auxiliary class for connection to data base. */ class JDB : public std::shared_ptr { private: /** * Get server. * * \return server */ static inline Server& get_server() { static Server server = JDATABASE::getServer(); return server; } public: /** * Get server. * * \return server */ static inline const Server& getServer() { return get_server(); } /** * Set server. * * \param server server */ static inline void setServer(const Server& server) { get_server() = server; } /** * Get connection to database. * * \return database connection */ static JDB& get() { static JDB db; return db; } /** * Reset connection to database. */ static void reset() { JDB& db = JDB::get(); if (db.get() != NULL) { db->Close(); static_cast&>(db).reset(); } } /** * Reset connection to database. * * \param usr user name * \param pwd pass word */ static void reset(const std::string& usr, const std::string& pwd) { static_cast&>(JDB::get()) = Client::Create(getServer(), usr.c_str(), pwd.c_str()); } /** * Reset connection to database. * * \param cookie persistent cookie */ static void reset(const std::string& cookie) { using namespace std; using namespace JPP; string buffer = cookie; if (getFileStatus(cookie.c_str())) { ifstream in(cookie.c_str()); getline(in, buffer); in.close(); } const string::size_type pos = buffer.find(PREFIX_COOKIE); if (pos != string::npos) { buffer.erase(0, pos); } static_cast&>(JDB::get()) = Client::Create(getServer(), buffer.c_str()); } /** * Reset connection to database. * * An attempt to make a connection to the database is made in the following order, * using: * -# user name and password, if neither empty; * -# given cookie, if not empty; * -# private cookie file (created with JCookie.sh); * -# public cookie (defined by environment variable DBCOOKIE); * * \param usr user name * \param pwd password * \param cookie persistent cookie */ static void reset(const std::string& usr, const std::string& pwd, const std::string& cookie) { using namespace std; using namespace JPP; if (usr != "" && pwd != "") JDB::reset(usr, pwd); else if (cookie != "") JDB::reset(cookie); else if (getFileStatus(getPrivateCookie())) JDB::reset(getPrivateCookie()); else if (getPublicCookie() != NULL) JDB::reset(getPublicCookie()); else THROW(JDatabaseException, "Missing user name / password or cookie file."); } private: /** * Default constructor. */ JDB() {} JDB(const JDB&); JDB& operator=(const JDB&); }; /** * Read server name from input stream. * * This operation will accordingly set the database server, if possible. * * \param in input stream * \param server server * \return input stream */ inline std::istream& operator>>(std::istream& in, JServer& server) { if (in >> static_cast(server)) { JDB::setServer(getServer(server)); } return in; } /** * Get table name. * * \return table name */ template inline const char* getTable() { return JTable_t::getName(); } /** * Get column name. * * \param data_member data member * \return column name */ template inline const char* getColumn(JType_t JTable_t::*data_member) { JTable_t* pc = NULL; TClass* rc = dynamic_cast(TDictionary::GetDictionary(typeid(JTable_t))); if (rc != NULL) { for( std::unique_ptr i(rc->GetListOfDataMembers()->MakeIterator()); const TDataMember* p = (const TDataMember*) i->Next(); ) { if (p->GetOffset() == (char*) &(pc->*data_member) - (char*) pc) { return p->GetName(); } } } return NULL; } /** * Get column names. * * \return column names */ template inline std::vector getColumns() { using namespace JPP; std::vector buffer; TClass* rc = dynamic_cast(TDictionary::GetDictionary(typeid(JTable_t))); if (rc != NULL) { for (std::unique_ptr i(rc->GetListOfDataMembers()->MakeIterator()); const TDataMember* p = (const TDataMember*) i->Next(); ) { if (JRootClass::is_class(*p)) { buffer.push_back(p->GetName()); } } } return buffer; } /** * Get result set. * * \param query query / table name * \return result set */ inline ResultSet& getResultSet(const std::string& query) { return JDB::get()->StreamDS(query.c_str(), std::vector()); } /** * Get result set. * * \param query query / table name * \param selection selection * \return result set */ inline ResultSet& getResultSet(const std::string& query, const std::vector& selection) { return JDB::get()->StreamDS(query.c_str(), selection); } /** * Get result set. * * \param js json * \param query query / table name */ inline void to_json(json& js, const std::string& query) { *(JDB::get()->APIv2Select(query.c_str(), std::vector())) >> js; } /** * Get result set. * * \param js json * \param query query / table name * \param selection selection */ inline void to_json(json& js, const std::string& query, const std::vector& selection) { *(JDB::get()->APIv2Select(query.c_str(), selection)) >> js; } } #endif