creaImageIOTimestampDatabaseHandler.cpp

Go to the documentation of this file.
00001 #include <creaImageIOTimestampDatabaseHandler.h>
00002 #include <creaImageIOSystem.h>
00003 
00004 #include "CppSQLite3.h"
00005 
00006 #include <sys/stat.h>
00007 
00008 #include <deque>
00009 
00010 #include <boost/filesystem.hpp>
00011 #include <boost/algorithm/string/replace.hpp>
00012 
00013 namespace creaImageIO
00014 {
00015         using namespace tree;
00016   //=============================================================
00017   TimestampDatabaseHandler::TimestampDatabaseHandler(const std::string& filename)
00018     : mFileName(filename)
00019   {
00020     mDB = new CppSQLite3DB;
00021     GimmickMessage(1,"SQLite version : "
00022                    <<std::string(mDB->SQLiteVersion())<< std::endl);
00023   }
00024   //=============================================================
00025 
00026   //=============================================================
00027   TimestampDatabaseHandler::~TimestampDatabaseHandler()
00028   {
00029     delete mDB;
00030   }
00031   //=============================================================
00032   //=====================================================================
00033   bool TimestampDatabaseHandler::Open()
00034   {
00035     return DBOpen();
00036   }
00037 
00038   //=====================================================================
00039   bool TimestampDatabaseHandler::Create()
00040   {
00041     return DBCreate();
00042   }
00043   //=====================================================================
00044 
00045 
00046   //=====================================================================
00047   bool TimestampDatabaseHandler::Close()
00048   {
00049     return true;
00050   }
00051   //=====================================================================
00052 
00053 
00054   //=====================================================================
00055   bool TimestampDatabaseHandler::Destroy()
00056   {
00057     return false;
00058   }
00059 
00060 
00061 
00062 
00063 
00064 
00065   //=====================================================================
00066   // SQLite DB specific methods
00067   //=====================================================================
00068   //=====================================================================
00069 #define QUERYTIMESTAMPDB(QUER,RES)                                              \
00070     try                                                                 \
00071       {                                                                 \
00072         GimmickMessage(2,"SQL query: '"<<QUER<<"'"<<std::endl);         \
00073         RES = mDB->execQuery(QUER.c_str());                             \
00074       }                                                                 \
00075     catch (CppSQLite3Exception& e)                                      \
00076       {                                                                 \
00077         GimmickError("SQLite query '"<<QUER<<"' : "                     \
00078                      << e.errorCode() << ":"                            \
00079                      << e.errorMessage() );                             \
00080       }                                                                 \
00081   //=====================================================================
00082 #define UPDATETIMESTAMPDB(UP)                                                   \
00083   try                                                                   \
00084     {                                                                   \
00085       GimmickMessage(2,"SQL update: '"<<UP<<"'"<<std::endl);            \
00086       mDB->execDML(UP.c_str());                                         \
00087     }                                                                   \
00088   catch (CppSQLite3Exception& e)                                        \
00089     {                                                                   \
00090       GimmickError("SQLite update '"<<UP<<"' Error : "                  \
00091                    << e.errorCode() << ":"                              \
00092                    << e.errorMessage() );                               \
00093     }                                                                   
00094   //=====================================================================
00095 
00096 
00097    //=====================================================================
00098   bool TimestampDatabaseHandler::DBOpen()
00099   {
00100     GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
00101                    <<"' ... "<<std::endl);
00102     // OPENING FILE
00103     if (!boost::filesystem::exists(GetFileName())) 
00104       {
00105         return false;
00106       }
00107 
00108     try
00109       {
00110         mDB->open(GetFileName().c_str());
00111       }
00112     catch (CppSQLite3Exception& e)
00113       {
00114         GimmickError("Opening '"<<GetFileName()<<"' : "
00115                      << e.errorCode() << ":" 
00116                      << e.errorMessage());
00117         return false;
00118       }
00119 
00120     GimmickDebugMessage(1,"Opening SQLite database '"<<GetFileName()
00121                    <<"' ... OK"<<std::endl);
00122     return true;
00123   }
00124   //=====================================================================
00125 
00126   //=====================================================================
00127   bool TimestampDatabaseHandler::DBCreate()
00128   {
00129     GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
00130                    <<"' ... "<<std::endl);
00131 
00132     if (boost::filesystem::exists(GetFileName())) 
00133       {
00134         GimmickError(GetFileName()<<"' : "
00135                      << "file already exists");
00136         return false;
00137       }
00138     
00139     // OPENING
00140     try
00141       {
00142         mDB->open(GetFileName().c_str());
00143       }
00144     catch (CppSQLite3Exception& e)
00145       {
00146         GimmickError(e.errorCode() << ":" 
00147                      << e.errorMessage() <<std::endl);
00148         return false;
00149       }
00150     
00151      
00152     // CREATING TABLES
00153     
00154     std::string command;
00155   
00156     
00157             command = "CREATE TABLE ";
00158             command += "FILES";
00159             command += "\n(\nID INTEGER PRIMARY KEY";
00160                 command += ",\nPARENT_ID int not null"; 
00161             command += ",\nPATH text";
00162                 command += ",\nLastModified datetext";
00163                 command += ",\nLastRead datetext";
00164                 command += ",\nTopLevelNodeId text";
00165                 command += ",\nReferencedDB text";
00166                 command += ",\nconstraint FK_PARENT foreign key (PARENT_ID) references ";
00167                 command += "FILES";
00168                 command += "(ID) on delete restrict on update restrict";
00169               
00170             command += "\n)";
00171             UPDATETIMESTAMPDB(command);
00172             
00173     return true;
00174   }
00175 
00176 
00177 
00178   //=====================================================================
00179   void TimestampDatabaseHandler::CleanPath(std::string& str) const
00180   {
00181          size_t pos;
00182          do
00183      {
00184          pos = str.find('\\');
00185          if ((int)pos!=-1)  
00186                  {
00187                          str.replace(pos, 1, "/");
00188                  }
00189      }
00190      while ((int)pos!=-1);
00191   }
00192   //=====================================================================
00193 
00194   bool TimestampDatabaseHandler::AddDirectory(const std::string& parent,
00195                                                                                    const std::string& path, 
00196                                                                                    const time_t lastModif, 
00197                                                                                    const time_t lastRead,
00198                                                                                    const std::string& refdb)
00199   {
00200          bool valid=false;
00201          std::string par=parent.c_str();
00202          std::string pat=path.c_str();
00203          CleanPath(par);
00204          CleanPath(pat);
00205 
00206          std::string pathId=IsIndexed(pat,refdb);
00207          //Case: It is a root parent
00208          if(parent.compare("")==0)
00209          {
00210                  if(pathId.compare("")==0)
00211                  {
00212                         AddFile(pat,lastModif,lastRead,refdb);
00213                         valid=true;
00214                  }
00215                  else
00216                  {
00217                          valid=CheckTimestamp(pathId, lastModif, refdb);
00218                  }
00219          }
00220          else 
00221          {
00222                  std::string parentId=IsIndexed(par,refdb);
00223                  //Case: Parent is not in database
00224                  if(parentId.compare("")==0)
00225                 {
00226                         AddFile(par,lastModif,lastRead,refdb);
00227                         parentId=IsIndexed(par,refdb);
00228                 }
00229 
00230                 //Case path is not in database
00231                 if(pathId.compare("")==0)
00232                 {
00233                     AddFile(parentId,pat,lastModif,lastRead,refdb);
00234                         valid=true;
00235                 }
00236                 //Parent and path are in the database
00237                 else
00238                 {
00239                         SetAttribute("PARENT_ID",parentId,"ID", pathId);
00240                         valid=CheckTimestamp(pathId, lastModif, refdb);
00241                 }
00242          }
00243          return valid;
00244         
00245   }
00246 
00247   //=====================================================================
00248 
00249   void TimestampDatabaseHandler::AddFile(const std::string& path, const time_t lastModif, const time_t lastRead,  const std::string& refdb)
00250   {
00251         std::stringstream out;
00252         out<<"INSERT INTO FILES (PARENT_ID,PATH,LastModified,LastRead,ReferencedDB) VALUES(0,'"<<path<<"',";
00253         out<<lastModif<<","<<lastRead<<",'"<<refdb<<"');";
00254     UPDATETIMESTAMPDB(out.str());
00255         
00256   }
00257 
00258    //=====================================================================
00259 
00260   void TimestampDatabaseHandler::AddFile(const std::string& parentId, 
00261                                                                                  const std::string& path, 
00262                                                                                  const time_t lastModif, 
00263                                                                                  const time_t lastRead,  
00264                                                                                  const std::string& refdb)
00265   {
00266         std::stringstream out;
00267         out<<"INSERT INTO FILES (PARENT_ID,PATH,LastModified,LastRead,ReferencedDB) VALUES("<<parentId<<",'"<<path<<"',";
00268         out<<lastModif<<","<<lastRead<<",'"<<refdb<<"');";
00269     UPDATETIMESTAMPDB(out.str());
00270   }
00271 
00272   //=====================================================================
00273   std::string TimestampDatabaseHandler::IsIndexed(const std::string& path, const std::string& refdb)
00274   {
00275         std::string pat=path.c_str();
00276         CleanPath(pat);
00277         std::stringstream out;
00278         std::stringstream result;
00279         out<<"SELECT ID FROM FILES WHERE PATH='"<<pat<<"' AND REFERENCEDDB='"<<refdb<<"';";
00280                 
00281         CppSQLite3Query q;
00282         QUERYTIMESTAMPDB(out.str(),q);
00283         
00284         
00285         while (!q.eof())
00286           {
00287             for (int fld = 0; fld < q.numFields(); fld++)
00288               {
00289                           result<<q.getStringField(fld);
00290               }
00291             q.nextRow();
00292           }
00293 
00294           return result.str();
00295   }
00296 
00297   //=====================================================================
00298   void TimestampDatabaseHandler::SetAttribute(const std::string& attName, 
00299                                                                                         const std::string& attValue,
00300                                                                                         const std::string& searchParam,
00301                                                                                         const std::string& searchValue)
00302   {
00303         std::string av=attValue.c_str();
00304         std::string sv=searchValue.c_str();
00305         CleanPath(av);
00306         CleanPath(sv);
00307 
00308         std::string sql = "UPDATE FILES SET ";
00309     sql += attName;
00310     sql += " = '";
00311     sql += av;
00312     sql += "' WHERE ";
00313         sql += searchParam;
00314         sql += " = '";
00315     sql += sv;
00316         sql += "'";
00317     UPDATETIMESTAMPDB(sql);
00318   }
00319  
00320   //=====================================================================
00321   void TimestampDatabaseHandler::RemoveNode(const std::string& searchAtt, const tree::Node* node, const std::string& refdb)
00322   {
00323           int n=node->GetNumberOfChildren();
00324           if(n>0)
00325           {
00326                   std::vector<tree::Node*> children=node->GetChildrenList();
00327                   std::vector<tree::Node*>::iterator it;
00328                   for(it=children.begin();it!=children.end();++it)
00329                   {
00330                           RemoveNode(searchAtt,(*it),refdb);
00331                   }
00332           }
00333           else if(node->GetLevel()==3)
00334           {
00335                   RemoveFile(searchAtt,node->GetAttribute("FullFileName"),refdb);
00336           }
00337           else
00338           {
00339                   DBRemove("TopLevelNodeId",node->GetAttribute("ID"),refdb);
00340           }
00341 
00342 
00343   }
00344   //=====================================================================
00345   void TimestampDatabaseHandler::RemoveFile(const std::string& searchAtt, const std::string& searchVal, const std::string& refdb )
00346   {
00347           
00348           std::stringstream result;
00349           std::string sel="SELECT PARENT_ID FROM FILES WHERE "+searchAtt+"='"+searchVal+"' AND REFERENCEDDB='"+refdb+"';";
00350                 
00351           CppSQLite3Query q;
00352           QUERYTIMESTAMPDB(sel,q);
00353         
00354           while (!q.eof())
00355           {
00356             for (int fld = 0; fld < q.numFields(); fld++)
00357               {
00358                           result<<q.getStringField(fld);
00359               }
00360             q.nextRow();
00361           }
00362           DBRemove(searchAtt,searchVal,refdb);
00363           
00364                   int nChildren=0;
00365                   sel="SELECT ID FROM FILES WHERE PARENT_ID='"+result.str()+"'";
00366                   CppSQLite3Query q2;
00367                   QUERYTIMESTAMPDB(sel,q2);
00368                   while (!q2.eof())
00369                         {
00370                                 nChildren++;
00371                                 q2.nextRow();
00372                         }
00373                         if(nChildren<1)
00374                         {
00375                                 if(!result.str().compare("0"))
00376                                 {
00377                                 RemoveFile("ID",result.str(),refdb);
00378                                 }
00379                                 else
00380                                 {
00381                                 DBRemove("ID",result.str(),refdb);
00382                                 }
00383                         }
00384   }
00385 
00386   //=====================================================================
00387   void TimestampDatabaseHandler::DBRemove(const std::string& searchAtt, const std::string& searchVal, const std::string& refdb)
00388   {
00389        
00390     std::string query = "DELETE FROM FILES WHERE "+searchAtt+"='"+ searchVal + "' AND REFERENCEDDB='"+refdb+"';";
00391     UPDATETIMESTAMPDB(query);
00392   }
00393 
00394    //=====================================================================
00395   bool TimestampDatabaseHandler::CheckTimestamp(const std::string pathId, const time_t lastModif, const std::string& refdb)
00396   {
00397         std::string sel="SELECT LastModified FROM FILES WHERE ID='"+pathId+"' AND REFERENCEDDB='"+refdb+"';";
00398         CppSQLite3Query q;
00399         QUERYTIMESTAMPDB(sel,q);
00400         double timestamp;
00401         
00402         while (!q.eof())
00403           {
00404             for (int fld = 0; fld < q.numFields(); fld++)
00405               {
00406                           timestamp=q.getFloatField(fld);
00407               }
00408             q.nextRow();
00409           }
00410 
00411           
00412           std::stringstream lm;
00413           lm<<lastModif;
00414           double modif=atof((lm.str()).c_str());
00415           if(timestamp<modif)
00416           {
00417                   SetAttribute("LastModified",lm.str(),"ID",pathId);
00418                   return true;
00419           }
00420           return false;  
00421   }
00422 
00423   //=====================================================================
00424   void TimestampDatabaseHandler::RemoveEntries(const std::string i_table, 
00425                 const std::string i_attribute, 
00426                 const std::string i_operand, 
00427                 const std::string i_val)
00428     {
00429         std::stringstream query;
00430                 query<<"DELETE  FROM "<<i_table<<" WHERE "<<i_attribute<<" "<<i_operand<<" '"<<i_val<<"'";
00431         UPDATETIMESTAMPDB(query.str());
00432         }
00433 
00434 }// namespace creaImageIO
00435