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
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
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
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
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
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
00224 if(parentId.compare("")==0)
00225 {
00226 AddFile(par,lastModif,lastRead,refdb);
00227 parentId=IsIndexed(par,refdb);
00228 }
00229
00230
00231 if(pathId.compare("")==0)
00232 {
00233 AddFile(parentId,pat,lastModif,lastRead,refdb);
00234 valid=true;
00235 }
00236
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 }
00435