/* * dbCrate.cc * * Created on: July 26, 2014 * Author: Hovanes Egiyan */ #include "dbCrate.hh" map dbCrate::crateMap; // SQL String to find the crate for a given id QString dbCrate::sqlFindCrates = "SELECT " " Crate.crateid as crid, Crate.name as crname, " " Crate.Function as crFunction, Crate.host as crhost " " FROM Crate WHERE Crate.crateid='%1' "; dbCrate::dbCrate( string uri, int dbID ) : dbObject( uri ), id( dbID), name(""), host(""), ipAddress(""), type("") { checkDB(); QSqlQuery query(db); // Search for the crate in the DB for this particular channel using unique ID QString sqlString = sqlFindCrates.arg(dbID); // qWarning() << sqlString << endl; query.prepare(sqlString); query.exec(); // qDebug() << "The query has been executed" << endl; if (dbObject::sqlSize(query) > 1) { // Raise an exception if there are too many rows from the previous SQL // There has to be only one entry in the table for each unique id stringstream errMsg; errMsg << "Error: Too many crates for the id " << dbID << " , to be exact there are " << dbObject::sqlSize(query); qWarning() << errMsg.str().c_str() << endl; throw StringException(errMsg.str()); } query.next(); name = query.value(1).toString().toStdString(); type = query.value(2).toString().toStdString(); host = query.value(3).toString().toStdString(); hostName2address(); // cout << "Adding the crate with hostname " << host << " to the map" << endl; // Add to the list of all crates if it is not there yet. // Only one crate with a given hostname will be registered in the map of crates // since the hostname is how we will identify the crates on the network. if( crateMap.count( host ) > 0 ) { // cout << "Crate with hostname " << host << " already exist in the map " << crateMap[host]->name << " of type " << crateMap[host]->type << endl; if( this->type != crateMap[host]->type || this->name != crateMap[host]->name ) { cout << "Name mismatch" << endl; // Raise an exception if there is a chassis with this hostname but // different type or different name stringstream errMsg; errMsg << "Error: Cannot instantiate crate with host name " << host << " type " << type << " and name " << name << "." << endl; errMsg << "\tThere is already a chassis with host name " << host << " but type " << crateMap[host]->type << " and name " << crateMap[name]->name ; qWarning() << errMsg.str().c_str() << endl; cerr << errMsg.str() << endl; throw StringException(errMsg.str()); } } else { crateMap[host] = this; } return; } dbCrate::~dbCrate() { // TODO Auto-generated destructor stub } // Static method to load EPICS DB for all registered crates. void dbCrate::loadRecords( string prefix, string crateName, int slot ) { // Call dbLoadRecords for each type of drivers. // Each drivers keeps track of all chassis and will // load the records for all the chassis registered at this point. { // CAEN SY1527 driver loads the chassis EPICS records CAENx527DbLoadRecords( prefix.c_str(), crateName.c_str(), slot ); cout << "CAENx527DbLoadRecords() was called with prefix <" << prefix << "> " "and crate name <" << crateName << "> and slot number " << slot << endl; } { // MPOD driver load the MPD chassis records dbLoadRecordsMPOD( prefix.c_str() , crateName.c_str(), slot ); cout << "dbLoadRecordsMPOD() was called with prefix " << prefix << "> " "and crate name <" << crateName << "> and slot number " << slot << endl; } { // Driver for IU bases loads the records for bases and power chassis int anagateSlot = 4; if ( 0 <= slot || slot <= 4 ) { anagateSlot = slot; } string busName = BaseIUDevice::DeviceID::Int2String( anagateSlot ); BaseIURecordMaker::LoadRecords( prefix.c_str(), crateName, busName ); // dbLoadRecordsIU(prefix.c_str(), crateName, busName); cout << "dbLoadRecordsIU has been called with prefix <" << prefix << "> " "and crate name <" << crateName << "> and bus name <" << busName << ">" << endl; } return; } // Configure this crate by calling corresponding configure function // of the appropriate driver chosen based on the "type" of the chassis. void dbCrate::configureCrate(int slot) { if (type == "IU_HV") { if (slot == -1) { // try to configure all busses on the anagate module for IU PMT base HV control cout << "dbCrate::configureCrate : Will configure all buses on crate " << name << endl; drvBaseIUConfigAnagate(host.c_str(), name.c_str(), "base", -1); } else { if (0 <= slot || slot <= 3) { // Configure a single anagate bus after converting the number into a string string busName = BaseIUDevice::DeviceID::Int2String(slot); BaseIUVirtBusID busID(host, "", name, "base"); busID = busID + busName; cout << "dbCrate::configureCrate : Will configure individual bus " << busID.GetBusStr() << " on crate " << name << " called port " << busID.GetPort() << endl; drvBaseIUConfigBus(host.c_str(), busName.c_str(), busID.GetPort().c_str(), "base"); } } return; } if (type == "BIAS/LV") { if (slot == -1) { // Try to configure the MPOD crate // We use IP address here so that each SNMP record does not query the SNS server on every processing drvMPODConfig(ipAddress.c_str(), name.c_str(), 10); } return; } if (type == "HV") { if (slot == -1) { // try to configure CAEN SY1527 crate CAENx527ConfigureCrate(const_cast(name.c_str()), const_cast(host.c_str()), NULL, NULL); } return; } } // Get ip from domain name string dbCrate::hostName2address() { struct addrinfo hints, *servinfo, *p; struct sockaddr_in *h; int rv; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6 hints.ai_socktype = SOCK_STREAM; if ( (rv = getaddrinfo(host.c_str(), "http", &hints, &servinfo)) != 0 ) { stringstream errMsg; errMsg << "Error converting hostname to IP address for hostname " << host << " - getaddrinfo: " << gai_strerror(rv) ; qWarning() << errMsg.str().c_str() << endl; cerr << errMsg.str() << endl; throw StringException(errMsg.str()); } // loop through all the results and return the last one we find for (p = servinfo; p != NULL; p = p->ai_next) { h = (struct sockaddr_in *) p->ai_addr; ipAddress = inet_ntoa(h->sin_addr); } freeaddrinfo(servinfo); // all done with this structure return ipAddress; }