Bladeren bron

Put cache in independent database because of issue #204

Now there will be a ctkDICOMTagCache.txt in the same
directory with the ctkDICOMDatabase.sql that stores
the cached tags.
Steve Pieper 13 jaren geleden
bovenliggende
commit
261841d091
2 gewijzigde bestanden met toevoegingen van 69 en 24 verwijderingen
  1. 15 9
      Libs/DICOM/Core/Testing/Cpp/ctkDICOMDatabaseTest2.cpp
  2. 54 15
      Libs/DICOM/Core/ctkDICOMDatabase.cpp

+ 15 - 9
Libs/DICOM/Core/Testing/Cpp/ctkDICOMDatabaseTest2.cpp

@@ -46,6 +46,9 @@ int ctkDICOMDatabaseTest2( int argc, char * argv [] )
 
   ctkDICOMDatabase database;
   QDir databaseDirectory = QDir::temp();
+  databaseDirectory.remove("ctkDICOMDatabase.sql");
+  databaseDirectory.remove("ctkDICOMTagCache.sql");
+
   QFileInfo databaseFile(databaseDirectory, QString("database.test"));
   database.openDatabase(databaseFile.absoluteFilePath());
 
@@ -129,15 +132,6 @@ int ctkDICOMDatabaseTest2( int argc, char * argv [] )
     }
 
 
-  QString knownSeriesDescription("3D Cor T1 FAST IR-prepped GRE");
-
-  QString foundSeriesDescription = database.instanceValue(instanceUID, tag);
-
-  if (foundSeriesDescription != knownSeriesDescription)
-    {
-    std::cerr << "ctkDICOMDatabase: invalid element value returned" << std::endl;
-    return EXIT_FAILURE;
-    }
 
   //
   // Test the tag cache
@@ -161,12 +155,15 @@ int ctkDICOMDatabaseTest2( int argc, char * argv [] )
     return EXIT_FAILURE;
     }
 
+
   if (database.cachedTag(instanceUID, tag) != QString(""))
     {
     std::cerr << "ctkDICOMDatabase: tag cache should return empty string for unknown instance tag" << std::endl;
     return EXIT_FAILURE;
     }
 
+  QString knownSeriesDescription("3D Cor T1 FAST IR-prepped GRE");
+
   if (!database.cacheTag(instanceUID, tag, knownSeriesDescription))
     {
     std::cerr << "ctkDICOMDatabase: could not insert instance tag" << std::endl;
@@ -179,6 +176,15 @@ int ctkDICOMDatabaseTest2( int argc, char * argv [] )
     return EXIT_FAILURE;
     }
 
+
+  QString foundSeriesDescription = database.instanceValue(instanceUID, tag);
+
+  if (foundSeriesDescription != knownSeriesDescription)
+    {
+    std::cerr << "ctkDICOMDatabase: invalid element value returned" << std::endl;
+    return EXIT_FAILURE;
+    }
+
   database.closeDatabase();
   database.initializeDatabase();
 

+ 54 - 15
Libs/DICOM/Core/ctkDICOMDatabase.cpp

@@ -21,19 +21,19 @@
 #include <stdexcept>
 
 // Qt includes
-#include <QSqlQuery>
-#include <QSqlRecord>
-#include <QSqlError>
-#include <QVariant>
 #include <QDate>
-#include <QStringList>
-#include <QSet>
-#include <QFile>
+#include <QDebug>
 #include <QDirIterator>
+#include <QFile>
 #include <QFileInfo>
-#include <QDebug>
 #include <QFileSystemWatcher>
 #include <QMutexLocker>
+#include <QSet>
+#include <QSqlError>
+#include <QSqlQuery>
+#include <QSqlRecord>
+#include <QStringList>
+#include <QVariant>
 
 // ctkDICOM includes
 #include "ctkDICOMDatabase.h"
@@ -109,6 +109,11 @@ public:
 
   /// tagCache table has been checked to exist
   bool TagCacheVerified;
+  /// tag cache has independent database to avoid locking issue
+  /// with other access to the database which need to be
+  /// reading while the tag cache is writing
+  QSqlDatabase TagCacheDatabase;
+  QString TagCacheDatabaseFilename;
 
   int insertPatient(const ctkDICOMDataset& ctkDataset);
   void insertStudy(const ctkDICOMDataset& ctkDataset, int dbPatientID);
@@ -133,6 +138,7 @@ void ctkDICOMDatabasePrivate::init(QString databaseFilename)
   Q_Q(ctkDICOMDatabase);
 
   q->openDatabase(databaseFilename);
+
 }
 
 //------------------------------------------------------------------------------
@@ -214,6 +220,11 @@ void ctkDICOMDatabase::openDatabase(const QString databaseFile, const QString& c
       QFileSystemWatcher* watcher = new QFileSystemWatcher(QStringList(databaseFile),this);
       connect(watcher, SIGNAL(fileChanged(QString)),this, SIGNAL (databaseChanged()) );
     }
+
+  // set up the tag cache for use later
+  QFileInfo fileInfo(d->DatabaseFileName);
+  d->TagCacheDatabaseFilename = QString( fileInfo.dir().path() + "/ctkDICOMTagCache.sql" );
+  d->TagCacheVerified = false;
 }
 
 
@@ -333,6 +344,7 @@ void ctkDICOMDatabase::closeDatabase()
 {
   Q_D(ctkDICOMDatabase);
   d->Database.close();
+  d->TagCacheDatabase.close();
 }
 
 //
@@ -1196,13 +1208,32 @@ bool ctkDICOMDatabase::tagCacheExists()
     {
     return true;
     }
-  QSqlQuery cacheExists( d->Database );
+
+  // try to open the database if it's not already open
+  if ( !(d->TagCacheDatabase.isOpen()) )
+    {
+    qDebug() << "TagCacheDatabase not open\n";
+    d->TagCacheDatabase = QSqlDatabase::addDatabase("QSQLITE", "TagCache");
+    d->TagCacheDatabase.setDatabaseName(d->TagCacheDatabaseFilename);
+    if ( !(d->TagCacheDatabase.open()) )
+      {
+      qDebug() << "TagCacheDatabase would not open!\n";
+      qDebug() << "TagCacheDatabaseFilename is: " << d->TagCacheDatabaseFilename << "\n";
+      return false;
+      }
+    }
+
+  // check that the table exists
+  QSqlQuery cacheExists( d->TagCacheDatabase );
   cacheExists.prepare("SELECT * FROM TagCache LIMIT 1");
   bool success = d->loggedExec(cacheExists);
   if (success)
     {
+    qDebug() << "TagCacheDatabase verified!\n";
     d->TagCacheVerified = true;
+    return true;
     }
+  qDebug() << "TagCacheDatabase NOT verified based on table check!\n";
   return false;
 }
 
@@ -1214,13 +1245,15 @@ bool ctkDICOMDatabase::initializeTagCache()
   // First, drop any existing table
   if ( this->tagCacheExists() )
     {
-    QSqlQuery dropCacheTable( d->Database );
+    qDebug() << "TagCacheDatabase drop existing table\n";
+    QSqlQuery dropCacheTable( d->TagCacheDatabase );
     dropCacheTable.prepare( "DROP TABLE TagCache" );
     d->loggedExec(dropCacheTable);
     }
 
   // now create a table
-  QSqlQuery createCacheTable( d->Database );
+  qDebug() << "TagCacheDatabase adding table\n";
+  QSqlQuery createCacheTable( d->TagCacheDatabase );
   createCacheTable.prepare(
     "CREATE TABLE TagCache (SOPInstanceUID, Tag, Value, PRIMARY KEY (SOPInstanceUID, Tag))" );
   bool success = d->loggedExec(createCacheTable);
@@ -1238,9 +1271,12 @@ QString ctkDICOMDatabase::cachedTag(const QString sopInstanceUID, const QString
   Q_D(ctkDICOMDatabase);
   if ( !this->tagCacheExists() )
     {
-    this->initializeTagCache();
+    if ( !this->initializeTagCache() )
+      {
+      return( "" );
+      }
     }
-  QSqlQuery selectValue( d->Database );
+  QSqlQuery selectValue( d->TagCacheDatabase );
   selectValue.prepare( "SELECT Value FROM TagCache WHERE SOPInstanceUID = :sopInstanceUID AND Tag = :tag" );
   selectValue.bindValue(":sopInstanceUID",sopInstanceUID);
   selectValue.bindValue(":tag",tag);
@@ -1259,9 +1295,12 @@ bool ctkDICOMDatabase::cacheTag(const QString sopInstanceUID, const QString tag,
   Q_D(ctkDICOMDatabase);
   if ( !this->tagCacheExists() )
     {
-    this->initializeTagCache();
+    if ( !this->initializeTagCache() )
+      {
+      return false;
+      }
     }
-  QSqlQuery insertTag( d->Database );
+  QSqlQuery insertTag( d->TagCacheDatabase );
   insertTag.prepare( "INSERT OR REPLACE INTO TagCache VALUES(:sopInstanceUID, :tag, :value)" );
   insertTag.bindValue(":sopInstanceUID",sopInstanceUID);
   insertTag.bindValue(":tag",tag);