/* * dbSubsystem.cc * * Created on: July 23, 2014 * Author: Hovanes Egiyan */ #include "dbSubsystem.hh" using namespace std; // SQL String to find the columns for a subsystem with a known unique id QString dbSubsystem::sqlFindSubsysColumns = "SELECT " " Detector_Hierarchy.id as id, Detector_Hierarchy.parent_id as parent_id, " " Detector_Hierarchy.name as name, Detector_Hierarchy.type as type, " " Detector_Hierarchy.chanid as chanid, Detector_Hierarchy.mtime as mtime " " FROM detector_hierarchy WHERE id='%1'" ; // SQL String to find the children of the current subsystem QString dbSubsystem::sqlFindChildren = "SELECT " " Detector_Hierarchy.id as id, Detector_Hierarchy.parent_id as parent_id, " " Detector_Hierarchy.name as name, Detector_Hierarchy.type as type, " " Detector_Hierarchy.chanid as chanid, Detector_Hierarchy.mtime as mtime " " FROM detector_hierarchy WHERE parent_id='%1'" ; // SQL String to find the crate for a channel QString dbSubsystem::sqlFindCrates = "SELECT " " Crate.crateid as crid, Crate.name as crname, " " Crate.Function as crFunction, Crate.host as crhost, " " Module.slot as mslot, Module.type as mtype, " " Channel.channel as chnum, Channel.col_name as chtype, " " Channel.enable as enable " " FROM Channel JOIN " " Module ON Channel.moduleid = Module.moduleid, " " Crate ON Module.crateid = Crate.crateid " " WHERE Channel.chanid='%1' "; // SQL string to find some useful parameters for the channel QString dbSubsystem::sqlFindChannels = dbSubsystem::sqlFindCrates; // Constructor dbSubsystem::dbSubsystem( string uri, int subsystemID, dbSubsystem* parent ) : dbObject( uri ), id( subsystemID ), parent_id(0), name(""), type(""), chanid(0), mtime(""), children(), parentSys(parent) { // Constructor for the class. Creates the object, then to create objects for the children. // That function will call the constructor for children, so the process will go recursively. checkDB(); QSqlQuery query(db); // Find the fields for this detector element to assign the data members QString sqlString = sqlFindSubsysColumns.arg(subsystemID); qWarning() << sqlString << endl; query.prepare(sqlString); query.exec(); qDebug() << "The query has been executed, result size is " << dbObject::sqlSize(query) ; 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 detectors with id " << subsystemID << " , to be exact there are " << dbObject::sqlSize(query); qWarning() << errMsg.str().c_str() << endl; throw StringException(errMsg.str()); } query.next(); qDebug() << "Creating a subsytem object with " << dbObject::sqlSize(query) << " elements and id " << subsystemID ; // this->id = query.value(0).toInt(); this->parent_id = query.value(1).toInt(); this->name = query.value(2).toString().toStdString(); this->type = query.value(3).toString().toStdString(); this->chanid = query.value(4).toInt(); this->mtime = query.value(5).toDateTime().toString().toStdString(); cout << this->parent_id << this->name << endl; query.finish(); // After creating the object find the children of this subsystem children = this->findChildren(); return; } // Destructor dbSubsystem::~dbSubsystem() { // if( db.isOpen() ) db.close(); // Loop over all children and destroy them for (unsigned iChild = 0; iChild < children.size(); iChild++) { cout << "Deleting child at " << children[iChild] << endl; delete children[iChild]; } } // Finds children of this subsystem. Note that this function will create other // objects of this class which will in turn call this function. The recursive process // continues until we reach an object with no children found and the functions start returning vector dbSubsystem::findChildren() { checkDB(); QSqlQuery query(db); // Search for all the raws in the detector_hierarchy with the parent_id column matching // the self.parent_id of this object QString sqlString = sqlFindChildren.arg(this->id); qWarning() << sqlString << endl; query.prepare(sqlString); query.exec(); qDebug() << "The query has been executed" << endl; vector childList; if ( dbObject::sqlSize(query) < 1 ) { cout << "The size is " << dbObject::sqlSize(query) << ", Defining parameters for " << this->id << endl; defineChannelParameters(); } else { cout << "Looking for children for " << this->id << endl; while ( query.next() ) { int childID = query.value( 0 ).toInt(); dbSubsystem* newSubSystem = new dbSubsystem( dbURI, childID, this ); childList.push_back( newSubSystem ); } } query.finish(); return childList; } // Return the full path with a specified separator string dbSubsystem::getFullPath( string separator ) { if( parentSys == 0 ) return this->name; else return this->parentSys->getFullPath( separator ) + separator + this->name ; } // Return the name of the top (parentless) subsystem that this element belongs to. string dbSubsystem::getRootName() { if( parentSys == 0 ) { cout << "Returning root name " << name << endl; return this->name; } else { cout << "Will try to find root name of parent of " << name << endl; return this->parentSys->getRootName() ; } } // Return a vector with all channels that belong to this detector vector dbSubsystem::getChannelVector() { // qDebug() << "Making the vector with all channels for subsystem " << getFullPath().c_str() << endl; checkDB(); vector channelVector; if (children.size() > 0) { // Combine the crate maps from all children if not at the bottom of the branch for (unsigned iChild = 0; iChild < children.size(); iChild++) { dbSubsystem* child = children[iChild]; vector childChannelVec = child->getChannelVector(); channelVector.insert( channelVector.end(), childChannelVec.begin(), childChannelVec.end() ); } } else { channelVector.push_back( this ); } return channelVector; } vector dbSubsystem::getCrateVector() { // qDebug() << "Making the vector with all crates for subsystem " << getFullPath().c_str() << endl; vector crateVec; if (children.size() > 0) { // Combined the crate maps from all children if not at the bottom of the branch for (unsigned iChild = 0; iChild < children.size(); iChild++) { dbSubsystem* child = children[iChild]; try { vector childCrateVec = child->getCrateVector(); crateVec.insert( crateVec.end(), childCrateVec.begin(), childCrateVec.end() ); } catch ( NoCrateException& e ) { cout << "Caught exception: " << e.what() << endl; continue; } } } else { checkDB(); QSqlQuery query(db); // Search for the crate in the DB for this particular channel QString sqlString = sqlFindCrates.arg(chanid); // qWarning() << sqlString << endl; query.prepare(sqlString); query.exec(); // qDebug() << "The query has been executed" << endl; // cout << " The query size is " << query.size() << " affected rows is " << query.numRowsAffected() << endl; // cout << " The feature support is " << db.driver()->hasFeature(QSqlDriver::QuerySize) << 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 channel " << getFullPath() << " , to be exact there are " << dbObject::sqlSize(query); qWarning() << errMsg.str().c_str() << endl; throw StringException(errMsg.str()); } if( query.next() ) { int crateID = query.value(0).toInt(); // cout << "Crate ID is " << crateID << endl; dbCrate* newCrate = new dbCrate(dbURI, crateID); // cout << "Adding " << hex << showbase << newCrate // << "to the crate vector" << endl; crateVec.push_back(newCrate); query.finish(); } else { // Raise an exception if there are no raws for this channel stringstream errMsg; errMsg << "Error: No crates found for the subsystem id " << id << endl; qWarning() << errMsg.str().c_str() << endl; throw NoCrateException(errMsg.str()); } } return crateVec; } // Method to print into an ostream string dbSubsystem::printToStream( ostream& stream ) { stringstream prtStream; prtStream << endl << "Subsystem with id " << id << ", parent " << parent_id << ", name " << name << ", type " << type << ", chanid " << chanid ; if( children.size() > 0 ) { prtStream << endl << "Children are "; } for( unsigned iChild = 0; iChild < children.size(); iChild++ ) { printToStream( prtStream ); } prtStream << endl << "Full path is " + this->getFullPath("->"); string prtString = prtStream.str(); stream << prtString; return prtString; } void dbSubsystem::defineChannelParameters() { } map > dbSubsystem::findChannels() { checkDB(); map > channelMap; unsigned long iChannel = 0; if (children.size() > 0) { // Combined the crate maps from all children if not at the bottom of the branch for (unsigned iChild = 0; iChild < children.size(); iChild++) { dbSubsystem* child = children[iChild]; map > childChannelMap = child->findChannels(); channelMap.insert(childChannelMap.begin(), childChannelMap.end()); } } else { QSqlQuery query(db); // Search for the crate in the DB for this particular channel QString sqlString = sqlFindChannels.arg(chanid); 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 channels for detector component " << getFullPath() << " , to be exact there are " << dbObject::sqlSize(query); qWarning() << errMsg.str().c_str() << endl; throw StringException(errMsg.str()); } query.next(); string crateName = query.value(1).toString().toStdString(); string crateType = query.value(2).toString().toStdString(); string crateHost = query.value(3).toString().toStdString(); string slotNumber = query.value(4).toString().toStdString(); string boardType = query.value(5).toString().toStdString(); string chanNum = query.value(6).toString().toStdString(); string chanType = query.value(7).toString().toStdString(); string chanEnable = query.value(8).toString().toStdString(); map tmpMap; tmpMap["DETch"] = getFullPath(":"); tmpMap["PSNAME"] = crateName; tmpMap["SLOT"] = slotNumber; tmpMap["CHANNUM"] = chanNum; tmpMap["BOARD"] = boardType; tmpMap["TYPE"] = chanType; tmpMap["ENABLE"] = chanEnable; channelMap[iChannel] = tmpMap; iChannel++; query.finish(); } return channelMap; } // Operator for printing using output stream ostream& operator<< ( ostream& stream, dbSubsystem& subsystem ) { subsystem.printToStream( stream ); return stream; }