Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

DatabaseManager.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   SpikeStream Application                                               *
00003  *   Copyright (C) 2007 by David Gamez                                     *
00004  *   david@davidgamez.eu                                                   *
00005  *   Version 0.1                                                           *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 
00023 //SpikeStream includes
00024 #include "DatabaseManager.h"
00025 #include "SpikeStreamMainWindow.h"
00026 #include "Debug.h"
00027 
00028 //Qt includes
00029 #include <qlayout.h>
00030 #include <qpushbutton.h>
00031 #include <qaccel.h>
00032 #include <qmessagebox.h>
00033 
00034 
00035 /*! Constructor. */
00036 DatabaseManager::DatabaseManager(QWidget * parent, QString flNme, bool saveDB, DBInterface* netDBInter, DBInterface* archDBInter, DBInterface* pattDBInter, DBInterface* devDBInter) : QDialog(parent){
00037         //Store references to databases and file name
00038         netDBInterface = netDBInter;
00039         archDBInterface = archDBInter;
00040         pattDBInterface = pattDBInter;
00041         devDBInterface = devDBInter;
00042         fileName = flNme;
00043         saveMode= saveDB;
00044 
00045         //Set caption
00046         if(saveMode)
00047                 this->setCaption("Save Databases");
00048         else
00049                 this->setCaption("Load Databases");
00050 
00051         //Get rid of extension from filename
00052         fileNameNoExtension = fileName.section('.', 0, 0);
00053 
00054         //Set up QProcess for running the script
00055         process = new QProcess(this);
00056 
00057         //Connect process to slots
00058         connect( process, SIGNAL(readyReadStdout()), this, SLOT(readFromStdout()) );
00059         connect( process, SIGNAL(readyReadStderr()), this, SLOT(readFromStderr()) );
00060         connect( process, SIGNAL(processExited()), this, SLOT(processExited()) );
00061 
00062         //Create vertical layout to organise widget
00063         QVBoxLayout *verticalBox = new QVBoxLayout(this, 10, 10);
00064 
00065         //Add table to enable the databases to be saved or loaded to be selected
00066         dbTable = new QTable(0, 3, this);
00067         dbTable->setShowGrid(false);
00068         dbTable->setSorting(false);
00069         dbTable->setSelectionMode(QTable::NoSelection);
00070         dbTable->verticalHeader()->hide();
00071         dbTable->setLeftMargin(0);
00072         QHeader * dbTableHeader = dbTable->horizontalHeader();
00073         nameCol = 0;
00074         dbTableHeader->setLabel(nameCol, "Database");
00075         dbTable->setColumnWidth(nameCol, 200);
00076         hostCol = 1;
00077         dbTableHeader->setLabel(hostCol, "Host");
00078         dbTable->setColumnWidth(hostCol, 150);
00079         selectionCol = 2;
00080         dbTableHeader->setLabel(selectionCol, "");
00081         dbTable->setColumnWidth(selectionCol, 50);
00082 
00083         verticalBox->addWidget(dbTable);
00084 
00085         //In save mode fill table with information about the databases to save
00086         if(saveMode){
00087                 netDBRow = addDatabaseToTable(netDBInterface);
00088                 archDBRow = addDatabaseToTable(archDBInterface);
00089                 pattDBRow = addDatabaseToTable(pattDBInterface);
00090                 devDBRow = addDatabaseToTable(devDBInterface);
00091         }
00092         //In load mode need to get list of saved databases and add them to the table
00093         else{
00094                 //Set row numbers of databases to -1
00095                 netDBRow = -1;
00096                 archDBRow = -1;
00097                 pattDBRow = -1;
00098                 devDBRow = -1;
00099                 getAvailableDatabases();
00100         }
00101 
00102         //Set up ok and cancel buttons
00103         QHBoxLayout *buttonBox = new QHBoxLayout();
00104         QPushButton *okPushButton = new QPushButton("Ok", this);
00105         QPushButton *cancelPushButton = new QPushButton("Cancel", this);        
00106         buttonBox->addWidget(okPushButton);
00107         buttonBox->addWidget(cancelPushButton);
00108 
00109         verticalBox->addLayout(buttonBox);
00110         
00111         connect (okPushButton, SIGNAL(clicked()), this, SLOT(okButtonPressed()));
00112         connect (cancelPushButton, SIGNAL(clicked()), this, SLOT(cancelButtonPressed()));
00113         
00114         //Set up accelerator for return button
00115         QAccel *returnAccel = new QAccel( this );
00116     returnAccel->connectItem( returnAccel->insertItem( Key_Enter ), this, SLOT(okButtonPressed()));
00117 
00118         //Create busy dialog
00119         busyDialog = new BusyDialog(this, "Database Manager");
00120         busyDialog->setModal(true);
00121 
00122         //Set appropriate size
00123         this->resize(500, 300);
00124 }
00125 
00126 
00127 /*! Destructor. */
00128 DatabaseManager::~DatabaseManager(){
00129         #ifdef MEMORY_DEBUG
00130                 cout<<"DESTROYING DATABASE MANAGER"<<endl;
00131         #endif//MEMORY_DEBUG
00132 }
00133 
00134 
00135 //---------------------------------------------------------------------------
00136 //-------------------------------- SLOTS ------------------------------------
00137 //---------------------------------------------------------------------------
00138 
00139 /*! Hides dialog when cancel button is pressed. */
00140 void DatabaseManager::cancelButtonPressed(){
00141         this->hide();
00142 }
00143 
00144 
00145 /*! Checks to see which databases are to be saved or loaded and carries out the 
00146         appropriate actions. */
00147 void DatabaseManager::okButtonPressed(){
00148         //Work through the table and fill stack with selected databases
00149         if(netDBRow != -1){
00150                 if(((QCheckTableItem*)dbTable->item(netDBRow, selectionCol))->isChecked()){
00151                         dbStack.push(netDBInterface);
00152                 }
00153         }
00154         if(archDBRow != -1){
00155                 if(((QCheckTableItem*)dbTable->item(archDBRow, selectionCol))->isChecked()){
00156                         dbStack.push(archDBInterface);
00157                 }
00158         }
00159         if(pattDBRow != -1){
00160                 if(((QCheckTableItem*)dbTable->item(pattDBRow, selectionCol))->isChecked()){
00161                         dbStack.push(pattDBInterface);
00162                 }
00163         }
00164         if(devDBRow != -1){
00165                 if(((QCheckTableItem*)dbTable->item(devDBRow, selectionCol))->isChecked()){
00166                         dbStack.push(devDBInterface);
00167                 }
00168         }
00169 
00170         //Check to see that at least one database is going to be saved
00171         if(dbStack.empty()){
00172                 if(saveMode)
00173                         QMessageBox::information(this, "Saving Databases", "No databases selected for saving.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
00174                 else
00175                         QMessageBox::information(this, "Loading Databases", "No databases selected for loading.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
00176                 return;
00177         }
00178 
00179         //Save selected databases
00180         if(saveMode){
00181                 //Show busy dialog
00182                 busyDialog->showDialog("Saving databases, please wait...");
00183 
00184                 if(dbStack.size() == 1){
00185                         saveDatabase(dbStack.top(), true);
00186                 }
00187                 else{
00188                         saveDatabase(dbStack.top(), false);
00189                 }
00190         }
00191         //Load selected databases from the file
00192         else{
00193                 //Show busy dialog
00194                 busyDialog->showDialog("Loading databases, please wait...");
00195 
00196                 //Load the database at the top of the stack
00197                 loadDatabase(dbStack.top());
00198         }
00199 }
00200 
00201 
00202 /*! Slot called when QProcess exits. */
00203 void DatabaseManager::processExited(){
00204         if(savingDatabase){//Script saving database should have finished
00205                 #ifdef SAVE_DATABASES_DEBUG
00206                         cout<<"DatabaseManager: Saving database script exited"<<endl;
00207                 #endif//SAVE_DATABASES_DEBUG
00208                 savingDatabase = false;
00209 
00210                 //No more databases left to save
00211                 if(dbStack.empty()){
00212                         //Hide busy dialog
00213                         busyDialog->hide();
00214         
00215                         //Check file is there
00216                         if(!QFile::exists(fileName)){
00217                                 QMessageBox::critical (this, "Save Error", "Cannot find new file: " + fileName, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
00218                         }
00219 
00220                         //Hide dialog
00221                         this->hide();   
00222                 }
00223 
00224                 //One more database left to save, so apply compression
00225                 else if(dbStack.size() == 1){
00226                         saveDatabase(dbStack.top(), true);
00227                 }
00228 
00229                 //Several databases still to save, so just add to tar archive without compression
00230                 else{
00231                         saveDatabase(dbStack.top(), false);
00232                 }
00233         }
00234         else if(loadingDatabase){
00235                 #ifdef LOAD_DATABASES_DEBUG
00236                         cout<<"LoadSpikeStreamDatabase script exited"<<endl;
00237                 #endif//LOAD_DATABASES_DEBUG
00238                 loadingDatabase = false;
00239 
00240                 //No more databases left to save
00241                 if(dbStack.empty()){
00242                         //Hide busy dialog
00243                         busyDialog->hide();
00244 
00245                         //Hide dialog
00246                         this->hide();   
00247                 }
00248                 //Load next database on stack
00249                 else{
00250                         loadDatabase(dbStack.top());
00251                 }
00252         }
00253         else if(listingDatabases){
00254                 listingDatabases = false;
00255                 fillLoadTable();
00256         }
00257         else
00258                 cerr<<"DatabaseManager: UNKNOWN PROCESS HAS FINISHED"<<endl;
00259 }
00260 
00261 
00262 /*! Reads output from stderr generated by process.
00263         Tries to terminate process. */
00264 void DatabaseManager::readFromStderr(){
00265         busyDialog->hide();
00266 
00267         //Display error
00268         QMessageBox::critical (this, "Process Error", "Process has output an error.\nSee command line for more details.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
00269 
00270         //Print out current process arguments
00271         cerr<<"DatabaseManager: PROCESS ERROR: ";
00272         QStringList processArgs = process->arguments();
00273         for(unsigned int i=0; i<processArgs.size(); ++i)
00274                 cerr<<processArgs[i]<<" ";
00275         cerr<<endl;
00276 
00277         //Print out error from process
00278         cerr<<"------------------- Start error message ----------------------"<<endl;
00279         while(process->canReadLineStderr()){
00280                 QString processString = process->readLineStderr();
00281                 cerr<<processString<<endl;
00282         }
00283         cerr<<"-------------------  End error message ----------------------"<<endl;
00284 
00285         //Clean up
00286         process->tryTerminate();//Politely ask process to quit
00287         busyDialog->hide();
00288 }
00289 
00290 
00291 /*! Prints stdout.
00292         When listing databases this is used to get the list of databases
00293         available in a file. */
00294 void DatabaseManager::readFromStdout(){
00295         #ifdef LOAD_DATABASES_DEBUG
00296                 cout<<"DatabaseManager: Normal process output: "<<endl;
00297         #endif//LOAD_DATABASES_DEBUG
00298         #ifdef SAVE_DATABASES_DEBUG
00299                 cout<<"DatabaseManager: Normal process output: "<<endl;
00300         #endif//SAVE_DATABASES_DEBUG
00301         while(process->canReadLineStdout()){
00302                 QString processString = process->readLineStdout();
00303                 #ifdef LOAD_DATABASES_DEBUG
00304                         cout<<processString<<endl;
00305                 #endif//LOAD_DATABASES_DEBUG
00306                 #ifdef SAVE_DATABASES_DEBUG
00307                         cout<<processString<<endl;
00308                 #endif//SAVE_DATABASES_DEBUG
00309 
00310                 if(listingDatabases){
00311                         if(processString == "Start files"){
00312                                 storeList = true;
00313                         }
00314                         else if(processString == "End files"){
00315                                 storeList = false;
00316                         }
00317                         else if(storeList){
00318                                 loadDBList += processString;
00319                         }
00320                 }
00321         }
00322 }
00323 
00324 
00325 //----------------------------------------------------------------------------
00326 //-------------------------- PRIVATE METHODS ---------------------------------
00327 //----------------------------------------------------------------------------
00328 
00329 /*! Adds the information in the database to the table. */
00330 int DatabaseManager::addDatabaseToTable(DBInterface* dbInter){
00331         //Add new row to the table
00332         unsigned int currentRowNumber = dbTable->numRows();
00333         dbTable->insertRows(currentRowNumber, 1);
00334 
00335         //Add database name
00336         DBParameters dbParam = dbInter->getDBParameters();
00337         dbTable->setItem(currentRowNumber, nameCol, new QTableItem(dbTable, QTableItem::Never, dbParam.database));
00338 
00339         //Add host name
00340         dbTable->setItem(currentRowNumber, hostCol, new QTableItem(dbTable, QTableItem::Never, dbParam.host));
00341 
00342         //Add check box to select table
00343         QCheckTableItem *tempCheckTableItem = new QCheckTableItem(dbTable, QString(""));
00344         tempCheckTableItem->setChecked(false);
00345         dbTable->setItem(currentRowNumber, selectionCol, tempCheckTableItem);
00346 
00347         //Return row number
00348         return currentRowNumber;
00349 }
00350 
00351 
00352 /*! Looks at list of databases stored in the file and adds them to the table. */
00353 void DatabaseManager::fillLoadTable(){
00354         //Get parameters from the databases
00355         DBParameters netDBParam = netDBInterface->getDBParameters();
00356         DBParameters archDBParam = archDBInterface->getDBParameters();
00357         DBParameters pattDBParam = pattDBInterface->getDBParameters();
00358         DBParameters devDBParam = devDBInterface->getDBParameters();
00359 
00360         //Add name to table if it matches the name of one of the existing databases
00361         for(unsigned int i=0; i<loadDBList.size(); ++i){
00362                 if(loadDBList[i].section('.', 0, 0) == netDBParam.database)
00363                         netDBRow = addDatabaseToTable(netDBInterface);
00364                 else if(loadDBList[i].section('.', 0, 0) == archDBParam.database)
00365                         archDBRow = addDatabaseToTable(archDBInterface);
00366                 else if(loadDBList[i].section('.', 0, 0) == pattDBParam.database)
00367                         pattDBRow = addDatabaseToTable(pattDBInterface);
00368                 else if (loadDBList[i].section('.', 0, 0) == devDBParam.database)
00369                         devDBRow = addDatabaseToTable(devDBInterface);
00370         }
00371 }
00372 
00373 
00374 /*! Uses the DBFileInspector script to list all of the databases in the file. */
00375 void DatabaseManager::getAvailableDatabases(){
00376         //Add arguments to qprocess
00377         process->clearArguments();      
00378         process->addArgument(SpikeStreamMainWindow::workingDirectory + "/scripts/DBFileInspector");
00379 
00380         //File
00381         process->addArgument(fileName);
00382 
00383         //Start the process
00384         if ( process->start() ) {
00385                 savingDatabase = false;
00386                 loadingDatabase = false;
00387                 listingDatabases = true;
00388         }
00389         else{
00390                 //Error handling
00391                 QString msgString("DBFileInspector failed to start when listing contents of ");
00392                 msgString += fileName;
00393                 QMessageBox::critical (this, "List Error", msgString, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
00394         }
00395 }
00396 
00397 
00398 /*! Loads a database from the file using LoadSpikeStreamDatabase script. */
00399 void DatabaseManager::loadDatabase(DBInterface* dbInter){
00400         //Get information about database
00401         DBParameters dbParam = dbInter->getDBParameters();
00402 
00403         //Add arguments to qprocess
00404         process->clearArguments();      
00405         process->addArgument(SpikeStreamMainWindow::workingDirectory + "/scripts/LoadSpikeStreamDatabase");
00406 
00407         //User argument
00408         QString userArg("-u");
00409         userArg += dbParam.user;
00410         process->addArgument(userArg);
00411 
00412         //Password argument
00413         QString passwordArg("-p");
00414         passwordArg += dbParam.password;
00415         process->addArgument(passwordArg);
00416 
00417         //Host argument
00418         QString hostArg("-h");
00419         hostArg += dbParam.host;
00420         process->addArgument(hostArg);
00421 
00422         //Database
00423         process->addArgument(dbParam.database);
00424 
00425         //File
00426         process->addArgument(fileName);
00427 
00428         //Pop the reference to the database off the stack
00429         dbStack.pop();
00430         
00431         //Start the process
00432         if ( process->start() ) {
00433                 savingDatabase = false;
00434                 loadingDatabase = true;
00435                 listingDatabases = false;
00436         }
00437         else{
00438                 //Error handling
00439                 QString msgString("LoadSpikeStreamDatabase script failed to start with database: ");
00440                 msgString += dbParam.database;
00441                 QMessageBox::critical (this, "Load Error", msgString, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
00442         }
00443 }
00444 
00445 
00446 /*! Saves a database into the file using SaveSpikeStreamDatabase script.
00447         If it is the last database to be saved, compress should be set to true
00448         so that the file is compressed. */
00449 void DatabaseManager::saveDatabase(DBInterface* dbInter, bool compress){
00450 
00451         //Get information about database
00452         DBParameters dbParam = dbInter->getDBParameters();
00453 
00454         //Add arguments to qprocess
00455         process->clearArguments();      
00456         process->addArgument(SpikeStreamMainWindow::workingDirectory + "/scripts/SaveSpikeStreamDatabase");
00457 
00458         //User argument
00459         QString userArg("-u");
00460         userArg += dbParam.user;
00461         process->addArgument(userArg);
00462 
00463         //Password argument
00464         QString passwordArg("-p");
00465         passwordArg += dbParam.password;
00466         process->addArgument(passwordArg);
00467 
00468         //Host argument
00469         QString hostArg("-h");
00470         hostArg += dbParam.host;
00471         process->addArgument(hostArg);
00472 
00473         //Database
00474         process->addArgument(dbParam.database);
00475 
00476         //File
00477         process->addArgument(fileNameNoExtension);
00478 
00479         //Compress or not
00480         if(compress)
00481                 process->addArgument("--compress");
00482 
00483         //Pop the reference to the database off the stack
00484         dbStack.pop();
00485         
00486         //Start the process
00487         if ( process->start() ) {
00488                 savingDatabase = true;
00489                 loadingDatabase = false;
00490                 listingDatabases = false;
00491         }
00492         else{
00493                 //Error handling
00494                 QString msgString("mysqldump failed to start when saving database ");
00495                 msgString += dbParam.database;
00496                 QMessageBox::critical (this, "Save Error", msgString, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
00497         }
00498 }
00499 
00500 

Generated on Mon Sep 3 22:29:04 2007 for SpikeStream Application by  doxygen 1.4.4