#ifndef __JRUNCONTROLTOOLKIT__ #define __JRUNCONTROLTOOLKIT__ #include #include #include #include #include #include "JLang/JException.hh" #include "JLang/JLangToolkit.hh" #include "JSystem/JNetwork.hh" #include "JNet/JHostname.hh" #include "JNet/JPrefix.hh" #include "JDAQ/JDAQTags.hh" /** * \author mdejong */ namespace KM3NETDAQ { using JLANG::JIOException; using JNET::JTag; using JNET::JHostname; /** * Get the wild card. * * \return wild card */ inline char getWildCard() { return WILD_CARD; } /** * Get the event name delimeter. * * \return event name delimeter */ inline char getEventnameDelimeter() { return EVENTNAME_DELIMETER; } /** * Get the token delimeter for command messages. * * \return token delimeter */ inline char getTokenDelimeter() { return TOKEN_DELIMETER[0]; } /** * Auxiliary class for handling event name and optional number. */ struct JEvent_t { /** * Default constructor. */ JEvent_t() : event_name ("?"), event_number(0) {} /** * Constructor. * * \param name event name * \param number event number */ JEvent_t(const std::string& name, const int number) : event_name (name), event_number(number) {} /** * Get event name. * * \return event name */ const std::string& getName() const { return event_name; } /** * Get event number. * * \return event number */ int getNumber() const { return event_number; } /** * Convert string to event. * * \param buffer buffer * \return event */ static JEvent_t toValue(const std::string& buffer) { using namespace std; using namespace JPP; JEvent_t object; const string::size_type sep = buffer.find(EVENTNAME_DELIMETER); if (sep != string::npos) { istringstream(buffer.substr(sep + 1)) >> object.event_number; object.event_name = trim(buffer.substr(0, sep)); } else { object.event_name = trim(buffer); object.event_number = -1; } return object; } /** * Read event name and optional number from input stream. * * \param in input stream * \param object event * \return input stream */ friend inline std::istream& operator>>(std::istream& in, JEvent_t& object) { std::string buffer; in >> buffer; object = JEvent_t::toValue(buffer); return in; } /** * Write event to output stream. * * \param out output stream * \param object event * \return output stream */ friend inline std::ostream& operator<<(std::ostream& out, const JEvent_t& object) { out << object.event_name; if (object.event_number != -1) { out << getEventnameDelimeter() << object.event_number; } return out; } protected: std::string event_name; int event_number; }; /** * Get process name of run control client. * The process name corresponds to the name of the executable file. * A wild card in the client name is replaced by the process name. * * \param name name of client * \param process name of process * \return process name */ inline std::string getProcessName(const std::string& name, const std::string& process) { using namespace std; string buffer(name); size_t j = buffer.find_first_of(getWildCard()); if (j != string::npos) { buffer.replace(j, 1, process); } return buffer; } /** * Get full name of run control client. * The full name is the unique identifier of each run control client. * * \param hostname name of host * \param name name of client * \return full name */ inline std::string getFullName(const std::string& hostname, const std::string& name) { using namespace JSYSTEM; return (RUN_CONTROL_CLIENT + getTokenDelimeter() + getIPaddress(getIPnumber(hostname)) + getTokenDelimeter() + name); } /** * Get full name of run control client. * * \param buffer full name (possibly followed by more text) * \return full name */ inline std::string getFullName(const std::string& buffer) { using namespace std; size_t j = 0; j = buffer.find_first_of(getTokenDelimeter(), (j != string::npos ? j : 0)); j = buffer.find_first_of(getTokenDelimeter(), (j != string::npos ? ++j : 0)); j = buffer.find_first_of(getTokenDelimeter(), (j != string::npos ? ++j : 0)); return buffer.substr(0, j); } /** * Simple data structure for DAQ run. */ struct JDAQRun { /** * Default constructor . */ JDAQRun() : unique_id(-1), run (-1) {} /** * Constructor . * * \param path directory path * \param run run number * \param extension file name extension */ JDAQRun(const std::string& path, const int run, const std::string& extension = "root") { this->path = path; this->unique_id = -1; this->run = run; this->extension = extension; } /** * Constructor . * * \param path directory path * \param unique_id unique identifier * \param run run number * \param extension file name extension */ JDAQRun(const std::string& path, const int unique_id, const int run, const std::string& extension = "root") { this->path = path; this->unique_id = unique_id; this->run = run; this->extension = extension; } /** * Constructor. * * \param file_name file name */ JDAQRun(const char* file_name) { *this = valueOf(file_name); } /** * Get file name prefix. * * \return prefix */ static const char* getPrefix() { return "KM3NeT"; } /** * Extract DAQ run parameters. * * \param file_name file name * \return DAQ run parameters */ static JDAQRun valueOf(const std::string& file_name) { JDAQRun result; using namespace std; string buffer(file_name); for (string::iterator i = buffer.begin(); i != buffer.end(); ++i) { if (*i == '_') { *i = ' '; } } istringstream is(buffer); if (is >> result.path >> result.unique_id) { size_t pos = result.path.find(getPrefix()); // standard %KM3NeT file name? if (pos == string::npos) { pos = result.path.rfind("/"); // standard directory path } if (pos != string::npos) { result.path.erase(pos); } if (!(is >> result.run)) { result.run = result.unique_id; // no unique identifier result.unique_id = -1; is.clear(); } is >> result.extension; if (!result.extension.empty() && result.extension[0] == '.') { result.extension.erase(0, 1); } return result; } throw JIOException("JDAQRun::valueOf() error parsing " + buffer); } /** * Convert DAQ run to string. * * \return string */ std::string toString() const { using namespace std; ostringstream os; if (!path.empty()) { os << path; if (*path.rbegin() != '/') { os << '/'; } } os << getPrefix() << "_" << setw(8) << setfill('0') << unique_id << "_" << setw(8) << setfill('0') << run << '.' << extension; return os.str(); } /** * Get file name of run. * * \param path directory path * \param unique_id unique identifier * \param run run number * \return file name */ static inline std::string getFilename(const std::string& path, const int unique_id, const int run) { return JDAQRun(path, unique_id, run).toString(); } std::string path; //!< directory path int unique_id; //!< unique identifier int run; //!< run number std::string extension; //!< file name extension }; /** * Get unique tag of run control client. * The unique tag is used to communicate with a single client. * * The unique tag consists of a sequence of 8 characters, where * character 1-4 correspond the hexadecimal coded subaddress of the IP number of the host and * character 5-8 to the short name of the client (i.e.\ part following the client name delimeter). * * \param hostname host name * \param name client name * \return tag */ inline JTag getUniqueTag(const std::string& hostname, const std::string& name) { using namespace std; using namespace JSYSTEM; ostringstream os; os << hex << getSubaddress(getIPnumber(hostname)); string::size_type pos = name.find_first_of(CLIENTNAME_DELIMETER); if (pos != string::npos) { os << name.substr(pos + 1, 4); } return JTag(os.str()); } /** * Auxiliary class for itemization of process list. */ class JDAQProcess : public JHostname { public: /** * Default constructor. */ JDAQProcess() : JHostname(), index () {} /** * Constructor. * * \param hostname host name * \param key index */ JDAQProcess(const JHostname& hostname, const std::string& key = "") : JHostname(), index (key) {} /** * Get unique tag. * * \return tag */ JTag getUniqueTag() const { using namespace std; using namespace JSYSTEM; ostringstream os; os << hex << getSubaddress(getIPnumber(this->hostname)) << this->index; return JTag(os.str()); } /** * Test whether given tag equals. * The comparison is based on the unique tag. * * \param tag tag * \return true if match; else false */ bool equals(const JTag& tag) const { return this->getUniqueTag() == tag; } /** * Test whether given port equals. * The comparison is based on the IP number and port number. * * \param port port * \return true if match; else false */ bool equals(int port) const { return (JSYSTEM::getIPnumber() == JSYSTEM::getIPnumber(this->hostname) && port == this->port); } /** * Test whether given host name equals. * The comparison is based on the IP number and port number. * * \param hostname host name * \return true if match; else false */ bool equals(const JHostname& hostname) const { return (JSYSTEM::getIPnumber(hostname.hostname) == JSYSTEM::getIPnumber(this->hostname) && hostname.port == this->port); } /** * Read process from input stream. * * \param in input stream * \param object process * \return input stream */ friend inline std::istream& operator>>(std::istream& in, JDAQProcess& object) { in >> object.index; in >> static_cast(object); return in; } /** * Write process to output stream. * * \param out output stream * \param object process * \return output stream */ friend inline std::ostream& operator<<(std::ostream& out, const JDAQProcess& object) { out << object.index; out << ' '; out << static_cast(object); return out; } std::string index; //!< index in process list }; /** * Get name of state. * Note that this method is used for backward compatibility. * * \param name name of state * \return name of state */ inline std::string getStateName(const std::string& name) { using namespace std; static const string target = "Operational."; string buffer = name; const string::size_type pos = buffer.find(target); if (pos != string::npos) return buffer.erase(pos, target.size()); else return buffer; } } #endif