#12 fixed race condition in TCFDB on linux
authoradam <adamansky@gmail.com>
Mon, 22 Apr 2013 10:27:58 +0000 (17:27 +0700)
committeradam <adamansky@gmail.com>
Mon, 22 Apr 2013 10:27:58 +0000 (17:27 +0700)
tcejdb/tcfdb.c
tcejdb/tcfdb.h
tcejdb/tcfmttest.c

index f2fe9ee..525aaa7 100644 (file)
@@ -119,7 +119,7 @@ static bool tcfdbvanishimpl(TCFDB *fdb);
 static bool tcfdbcopyimpl(TCFDB *fdb, const char *path);
 static bool tcfdbiterjumpimpl(TCFDB *fdb, int64_t id);
 static bool tcfdbforeachimpl(TCFDB *fdb, TCITER iter, void *op);
-static bool tcfdbftruncate(TCFDB *fdb, off_t length) __attribute__ ((unused));
+static bool tcfdbftruncate(TCFDB *fdb, off_t length) __attribute__((unused));
 static bool tcfdbftruncate2(TCFDB *fdb, off_t length, int opts);
 
 EJDB_INLINE bool tcfdblockmethod(TCFDB *fdb, bool wr);
@@ -2147,6 +2147,7 @@ static bool tcfdbputimpl(TCFDB *fdb, int64_t id, const void *vbuf, int vsiz, int
     if (vsiz > (int64_t) fdb->width) vsiz = fdb->width;
     TCDODEBUG(fdb->cnt_readrec++);
     uint64_t nsiz = FDBHEADSIZ + id * fdb->rsiz;
+
     if (nsiz > fdb->fsiz) {
         if (nsiz > fdb->limsiz) {
             tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);
@@ -2203,10 +2204,12 @@ static bool tcfdbputimpl(TCFDB *fdb, int64_t id, const void *vbuf, int vsiz, int
                     fdb->max = id;
                 }
             }
+            FDBUNLOCKATTR(fdb);
+            FDBUNLOCKSMEM(fdb);
+            return !err;
         }
         FDBUNLOCKATTR(fdb);
         FDBUNLOCKSMEM(fdb);
-        return !err;
     }
 
     //Take a read lock on shared mem because
@@ -2982,10 +2985,14 @@ static bool tcfdbftruncate(TCFDB *fdb, off_t length) {
 
 static bool tcfdbftruncate2(TCFDB *fdb, off_t length, int opts) {
 #ifndef _WIN32
+    bool err = false;
     length = length ? tcpagealign(length) : 0;
     if (!(fdb->omode & FDBOWRITER) || (length <= fdb->fsiz && !(opts & FDBTRALLOWSHRINK))) {
         return true;
     }
+    if (!(opts & FDBWRITENOLOCK) && !FDBLOCKSMEM2(fdb, true)) {
+        return false;
+    }
     if (length > fdb->fsiz && !(opts & FDBTRALLOWSHRINK)) {
         off_t o1 = tcpagealign((_maxof(off_t) - length < FDBXFSIZINC) ? length : length + FDBXFSIZINC);
         off_t o2 = tcpagealign((((uint64_t) length) * 3) >> 1);
@@ -2996,10 +3003,11 @@ static bool tcfdbftruncate2(TCFDB *fdb, off_t length, int opts) {
     }
     if (ftruncate(fdb->fd, length) == 0) {
         fdb->fsiz = length;
-        return true;
     } else {
-        return false;
+        err = true;
     }
+    if (!(opts & FDBWRITENOLOCK)) FDBUNLOCKSMEM(fdb);
+    return !err;
 #else
     bool err = false;
     LARGE_INTEGER size;
index 8e6d878..0496bb0 100644 (file)
@@ -66,7 +66,7 @@ typedef struct { /* type of structure for a fixed-length database */
     time_t mtime; /* modification time */
     uint64_t limsiz; /* limit size of the file */
     uint64_t rnum; /* number of the records */
-    uint64_t fsiz; /* size of the database file */
+    volatile uint64_t fsiz; /* size of the database file */
     uint64_t min; /* minimum ID number */
     uint64_t max; /* maximum ID number */
     uint64_t iter; /* ID number of the iterator */
index af28c55..b96e450 100644 (file)
@@ -807,12 +807,15 @@ static void *threadwrite(void *targ) {
     int base = id * rnum;
     for (int i = 1; i <= rnum; i++) {
         char buf[RECBUFSIZ];
+
+        
         int len = sprintf(buf, "%08d", base + (rnd ? myrand(i) + 1 : i));
         if (!tcfdbput2(fdb, buf, len, buf, len)) {
             eprint(fdb, __LINE__, "tcfdbput2");
             err = true;
             break;
         }
+
         if (id == 0 && rnum > 250 && i % (rnum / 250) == 0) {
             iputchar('.');
             if (i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);