# HG changeset patch # User mas01cr # Date 1188403966 0 # Node ID 5bae5570fb2ea1cf2de4f1db903065028ae862d9 # Parent e736c35de0f6a452e14e7ca1f9a48a14d6aa293d Merge trunk changes -r44:51 onto audio-debian branch diff -r e736c35de0f6 -r 5bae5570fb2e audioDB.cpp --- 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 " diff -r e736c35de0f6 -r 5bae5570fb2e audioDB.h --- 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); diff -r e736c35de0f6 -r 5bae5570fb2e docs/TODO.txt --- 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