Changeset: 7216677df467 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=7216677df467 Modified Files: gdk/gdk_bbp.c gdk/gdk_heap.c Branch: Jul2015 Log Message:
Fix problems when (sub)committing bats that were formerly memory mapped. Create a persistent bat, fill it so that it becomes memory mapped, then commit it. Then clear the bat forcibly (BATclear with force=TRUE) and fill it with some new values. Commit that. The final step is restart the server and look at the bat. It now contains old data. The problem was with the second commit that didn't deal properly with the .new file that was created during the first commit which was then found by the restarting server and interpreted as the current content where in fact it was stale content. diffs (118 lines): diff --git a/gdk/gdk_bbp.c b/gdk/gdk_bbp.c --- a/gdk/gdk_bbp.c +++ b/gdk/gdk_bbp.c @@ -3355,8 +3355,8 @@ BBPprepare(bit subcommit) } static gdk_return -do_backup(const char *srcdir, const char *nme, const char *extbase, - Heap *h, int tp, int dirty, bit subcommit) +do_backup(const char *srcdir, const char *nme, const char *ext, + Heap *h, int dirty, bit subcommit) { gdk_return ret = GDK_SUCCEED; @@ -3364,10 +3364,11 @@ do_backup(const char *srcdir, const char * protection); however, if we're backing up for subcommit * and a backup already exists in the main backup directory * (see GDKupgradevarheap), move the file */ - if (subcommit && file_exists(h->farmid, BAKDIR, nme, extbase)) { - if (file_move(h->farmid, BAKDIR, SUBDIR, nme, extbase) != GDK_SUCCEED) + if (subcommit && file_exists(h->farmid, BAKDIR, nme, ext)) { + if (file_move(h->farmid, BAKDIR, SUBDIR, nme, ext) != GDK_SUCCEED) return GDK_FAIL; - } else if (h->storage != STORE_MMAP) { + } + if (h->storage != STORE_MMAP) { /* STORE_PRIV saves into X.new files. Two cases could * happen. The first is when a valid X.new exists * because of an access change or a previous @@ -3377,23 +3378,34 @@ do_backup(const char *srcdir, const char * X.new files (after a crash). To protect against * these we write X.new.kill files in the backup * directory (see heap_move). */ - char ext[16]; + char extnew[16]; gdk_return mvret = GDK_SUCCEED; - if (h->filename && h->newstorage == STORE_PRIV) - snprintf(ext, sizeof(ext), "%s.new", extbase); - else - snprintf(ext, sizeof(ext), "%s", extbase); - if (tp && dirty && !file_exists(h->farmid, BAKDIR, nme, ext)) { - /* file will be saved (is dirty), move the old - * image into backup */ - mvret = heap_move(h, srcdir, subcommit ? SUBDIR : BAKDIR, nme, ext); - } else if (subcommit && tp && - (dirty || file_exists(h->farmid, BAKDIR, nme, ext))) { - /* file is clean. move the backup into the - * subcommit dir (commit should eliminate - * backup) */ - mvret = file_move(h->farmid, BAKDIR, SUBDIR, nme, ext); + snprintf(extnew, sizeof(extnew), "%s.new", ext); + if (dirty && + !file_exists(h->farmid, BAKDIR, nme, extnew) && + !file_exists(h->farmid, BAKDIR, nme, ext)) { + /* if the heap is dirty and there is no heap + * file (with or without .new extension) in + * the BAKDIR, move the heap (preferably with + * .new extension) to the correct backup + * directory */ + if (file_exists(h->farmid, srcdir, nme, extnew)) + mvret = heap_move(h, srcdir, + subcommit ? SUBDIR : BAKDIR, + nme, extnew); + else + mvret = heap_move(h, srcdir, + subcommit ? SUBDIR : BAKDIR, + nme, ext); + } else if (subcommit) { + /* if subcommit, wqe may need to move an + * already made backup from BAKDIR to + * SUBSIR */ + if (file_exists(h->farmid, BAKDIR, nme, extnew)) + mvret = file_move(h->farmid, BAKDIR, SUBDIR, nme, extnew); + else if (file_exists(h->farmid, BAKDIR, nme, ext)) + mvret = file_move(h->farmid, BAKDIR, SUBDIR, nme, ext); } /* there is a situation where the move may fail, * namely if this heap was not supposed to be existing @@ -3440,20 +3452,20 @@ BBPbackup(BAT *b, bit subcommit) nme[sizeof(nme) - 1] = 0; srcdir[s - srcdir] = 0; - if (do_backup(srcdir, nme, "head", &b->H->heap, b->htype, + if (b->htype != TYPE_void && + do_backup(srcdir, nme, "head", &b->H->heap, b->batDirty || b->H->heap.dirty, subcommit) != GDK_SUCCEED) goto fail; - if (do_backup(srcdir, nme, "tail", &b->T->heap, b->ttype, + if (b->ttype != TYPE_void && + do_backup(srcdir, nme, "tail", &b->T->heap, b->batDirty || b->T->heap.dirty, subcommit) != GDK_SUCCEED) goto fail; if (b->H->vheap && do_backup(srcdir, nme, "hheap", b->H->vheap, - b->htype && b->hvarsized, b->batDirty || b->H->vheap->dirty, subcommit) != GDK_SUCCEED) goto fail; if (b->T->vheap && do_backup(srcdir, nme, "theap", b->T->vheap, - b->ttype && b->tvarsized, b->batDirty || b->T->vheap->dirty, subcommit) != GDK_SUCCEED) goto fail; GDKfree(srcdir); diff --git a/gdk/gdk_heap.c b/gdk/gdk_heap.c --- a/gdk/gdk_heap.c +++ b/gdk/gdk_heap.c @@ -583,6 +583,10 @@ HEAPfree(Heap *h, int remove) if (path && unlink(path) < 0 && errno != ENOENT) perror(path); GDKfree(path); + path = GDKfilepath(h->farmid, BATDIR, h->filename, "new"); + if (path && unlink(path) < 0 && errno != ENOENT) + perror(path); + GDKfree(path); } GDKfree(h->filename); h->filename = NULL; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list