changeset 36:5bae5570fb2e audiodb-debian

Merge trunk changes -r44:51 onto audio-debian branch
author mas01cr
date Wed, 29 Aug 2007 16:12:46 +0000
parents e736c35de0f6
children 531c627e0810
files audioDB.cpp audioDB.h docs/TODO.txt
diffstat 3 files changed, 71 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/audioDB.cpp	Fri Aug 17 11:44:27 2007 +0000
+++ b/audioDB.cpp	Wed Aug 29 16:12:46 2007 +0000
@@ -97,9 +97,12 @@
 
 #define O2_DEBUG
 
-  void audioDB::error(const char* a, const char* b){
-    cerr << a << ":" << b << endl;
-    exit(1);
+void audioDB::error(const char* a, const char* b, const char *sysFunc) {
+  cerr << a << ": " << b << endl;
+  if (sysFunc) {
+    perror(sysFunc);
+  }
+  exit(1);
 }
 
 audioDB::audioDB(const unsigned argc, char* const argv[], adb__queryResult *adbQueryResult):
@@ -427,24 +430,64 @@
 
 */
 
+void audioDB::get_lock(int fd, bool exclusive) {
+  struct flock lock;
+  int status;
+  
+  lock.l_type = exclusive ? F_WRLCK : F_RDLCK;
+  lock.l_whence = SEEK_SET;
+  lock.l_start = 0;
+  lock.l_len = 0; /* "the whole file" */
+
+ retry:
+  do {
+    status = fcntl(fd, F_SETLKW, &lock);
+  } while (status != 0 && errno == EINTR);
+
+  if (status) {
+    if (errno == EAGAIN) {
+      sleep(1);
+      goto retry;
+    } else {
+      error("fcntl lock error", "", "fcntl");
+    }
+  }
+}
+
+void audioDB::release_lock(int fd) {
+  struct flock lock;
+  int status;
+
+  lock.l_type = F_UNLCK;
+  lock.l_whence = SEEK_SET;
+  lock.l_start = 0;
+  lock.l_len = 0;
+
+  status = fcntl(fd, F_SETLKW, &lock);
+
+  if (status)
+    error("fcntl unlock error", "", "fcntl");
+}
+
 void audioDB::create(const char* dbName){
-  if ((dbfid = open (dbName, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
-    error("Can't open database file", dbName);
+  if ((dbfid = open (dbName, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
+    error("Can't create database file", dbName, "open");
+  get_lock(dbfid, 1);
 
   // go to the location corresponding to the last byte
   if (lseek (dbfid, O2_DEFAULTDBSIZE - 1, SEEK_SET) == -1)
-    error("lseek error in db file");
+    error("lseek error in db file", "", "lseek");
 
   // write a dummy byte at the last location
   if (write (dbfid, "", 1) != 1)
-    error("write error");
+    error("write error", "", "write");
   
   // mmap the output file
   if(verbosity)
     cerr << "header size:" << O2_HEADERSIZE << endl;
   if ((db = (char*) mmap(0, O2_DEFAULTDBSIZE, PROT_READ | PROT_WRITE,
 			 MAP_SHARED, dbfid, 0)) == (caddr_t) -1)
-    error("mmap error for creating database");
+    error("mmap error for creating database", "", "mmap");
   
   dbH = new dbTableHeaderT();
   assert(dbH);
@@ -472,15 +515,16 @@
 // Precondition: database has already been created
 void audioDB::initTables(const char* dbName, bool forWrite, const char* inFile=0){
   if ((dbfid = open (dbName, forWrite ? O_RDWR : O_RDONLY)) < 0)
-    error("Can't open database file", dbName);
-  
+    error("Can't open database file", dbName, "open");
+  get_lock(dbfid, forWrite);
+
   // open the input file
   if (inFile && (infid = open (inFile, O_RDONLY)) < 0)
-    error("can't open input file for reading", inFile);
+    error("can't open input file for reading", inFile, "open");
 
   // find size of input file
   if (inFile && fstat (infid,&statbuf) < 0)
-    error("fstat error finding size of input");
+    error("fstat error finding size of input", "", "fstat");
   
   // Get the database header info
   dbH = new dbTableHeaderT();
@@ -515,12 +559,12 @@
   // mmap the input file 
   if (inFile && (indata = (char*)mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, infid, 0))
       == (caddr_t) -1)
-    error("mmap error for input");
+    error("mmap error for input", "", "mmap");
 
   // mmap the database file
   if ((db = (char*) mmap(0, O2_DEFAULTDBSIZE, PROT_READ | (forWrite ? PROT_WRITE : 0),
 			 MAP_SHARED, dbfid, 0)) == (caddr_t) -1)
-    error("mmap error for creating database");
+    error("mmap error for initting tables of database", "", "mmap");
 
   // Make some handy tables with correct types
   fileTable= (char*)(db+fileTableOffset);
@@ -666,7 +710,8 @@
 void audioDB::batchinsert(const char* dbName, const char* inFile){
 
   if ((dbfid = open (dbName, O_RDWR)) < 0)
-    error("Can't open database file", dbName);
+    error("Can't open database file", dbName, "open");
+  get_lock(dbfid, 1);
 
   if(!key)
     key=inFile;
@@ -721,16 +766,16 @@
 
     // open the input file
     if (thisFile && (infid = open (thisFile, O_RDONLY)) < 0)
-      error("can't open feature file for reading", thisFile);
+      error("can't open feature file for reading", thisFile, "open");
   
     // find size of input file
     if (thisFile && fstat (infid,&statbuf) < 0)
-      error("fstat error finding size of input");
+      error("fstat error finding size of input", "", "fstat");
 
     // mmap the database file
     if ((db = (char*) mmap(0, O2_DEFAULTDBSIZE, PROT_READ | PROT_WRITE,
 			   MAP_SHARED, dbfid, 0)) == (caddr_t) -1)
-      error("mmap error for creating database");
+      error("mmap error for batchinsert into database", "", "mmap");
     
     // Make some handy tables with correct types
     fileTable= (char*)(db+fileTableOffset);
@@ -758,7 +803,7 @@
     // mmap the input file 
     if (thisFile && (indata = (char*)mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, infid, 0))
 	== (caddr_t) -1)
-      error("mmap error for input");
+      error("mmap error for input", "", "mmap");
   
   
     // Linear scan of filenames check for pre-existing feature
@@ -833,7 +878,7 @@
   // mmap the database file
   if ((db = (char*) mmap(0, O2_DEFAULTDBSIZE, PROT_READ | PROT_WRITE,
 			 MAP_SHARED, dbfid, 0)) == (caddr_t) -1)
-    error("mmap error for creating database");
+    error("mmap error for creating database", "", "mmap");
   
   if(verbosity)
     cerr << COM_BATCHINSERT << " " << dbName << " " << totalVectors << " vectors " 
--- a/audioDB.h	Fri Aug 17 11:44:27 2007 +0000
+++ b/audioDB.h	Wed Aug 29 16:12:46 2007 +0000
@@ -215,7 +215,7 @@
   struct timeval tv2;
     
   // private methods
-  void error(const char* a, const char* b = "");
+  void error(const char* a, const char* b = "", const char *sysFunc = 0);
   void pointQuery(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult=0);
   void trackPointQuery(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult=0);
   void trackSequenceQueryNN(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult=0);
@@ -233,6 +233,8 @@
   audioDB(const unsigned argc, char* const argv[], adb__queryResult *adbQueryResult=0);
   ~audioDB();
   int processArgs(const unsigned argc, char* const argv[]);
+  void get_lock(int fd, bool exclusive);
+  void release_lock(int fd);
   void create(const char* dbName);
   void drop();
   void insert(const char* dbName, const char* inFile);
--- a/docs/TODO.txt	Fri Aug 17 11:44:27 2007 +0000
+++ b/docs/TODO.txt	Wed Aug 29 16:12:46 2007 +0000
@@ -8,6 +8,9 @@
 o test suite
 o SOAP to serialize queryFile and keyList
 o SOAP to serialize files on insert / batch insert ?
+:-) DONE don't overwrite existing files on db create
+:-) DONE implement fcntl()-based locking.
+o test locking discipline (particularly over NFS between heterogenous clients)
 
 M. Casey 13/08/07