📄 gdk_bbp.c
字号:
}/* return and revive a cached bat from the cache */static INLINE bat batcache_get(int bin) { batcache_int i = batcache_batbin[bin]; if (i >= 0) { /* manage fifo-list */ int bid = batcache[i].bid; batcache_int j = batcache[i].fifo_prev; batcache_int k = batcache[i].fifo_next; if (j < 0) { assert(batcache_first == i); batcache_first = k; } else { batcache[j].fifo_next = k; } if (k < 0) { assert(batcache_last == i); batcache_last = j; } else { batcache[k].fifo_prev = j; } batcache[i].fifo_next = batcache_free; batcache_free = i; /* manage bin-list */ batcache_batbin[bin] = j = batcache[i].bin_next; if (j >= 0) batcache[j].bin_prev = -1; /* revive the bat */ *BBP_logical(bid) = 't'; BBP_refs(bid)++; /* clearing bits can be done without the lock */ BBP_status_off(bid, BBPUNLOADING, "BBPrecycle"); return bid; } return 0;}extern char* BATstring_h;extern char* BATstring_t;static intBBPaddtobin(BAT *b){ int bin = BATCACHE_BIN(b->htype, b->ttype); bat bid = b->batCacheid, parent = VIEWparent(b); char *s = BBP_logical(bid); BAT *m = BBP_cache(-bid); /* only cache simple non-saved non-renamed transient bats */ if (m == NULL || batcache_minsize == 0 || b->batCopiedtodisk || b->batLview || BBPtmpcheck(s) == 0 || b->htype > TYPE_str || b->ttype > TYPE_str) { BATdelete(b); /* handles persistent case also (file deletes) */ return 1; } if ((parent == 0) && (b->htype | b->ttype)) { /* additional restrictions do not hold for views and void,void bats */ int bunwidth = batcache_widthbin[bin]; size_t minsize = bunwidth * batcache_minsize; size_t maxsize = minsize+minsize; /* bat should be of the right size, types and BUN layoutt */ if (b->batBuns->size < minsize || b->batBuns->size >= maxsize || BUNsize(b) != bunwidth || BATCACHE_NOTYPE(b->htype) || BATCACHE_NOTYPE(b->ttype)) { BATdelete(b); /* handles persistent case also (file deletes) */ return 1; } } assert(BBP_refs(bid) == 0); assert(BBP_lrefs(bid) == 0); assert(b->batCacheid > 0); /* change views into void,void bats */ if (parent) { BATstore *bs = (BATstore*) b; /* cut view loose from parent */ VIEWunlink(b); unshare(parent); b->batParentid = 0; /* take care of mirror views */ b->H = m->T = &bs->H; b->T = m->H = &bs->T; /* make it a void,void bat */ b->dims = m->dims = batcache_dims; b->batBuns->base = NULL; /* was shared with parent! */ b->hheap = b->theap = NULL; } /* free non-reusable stuff that has to be freed anyway */ if (b->hident != BATstring_h) { if (b->hident) GDKfree(b->hident); b->hident = BATstring_h; } if (b->tident != BATstring_t) { if (b->tident) GDKfree(b->tident); b->tident = BATstring_t; } if (b->hhash) HASHremove(b); if (b->thash) HASHremove(BBPcache(-bid)); if (b->H->props) { PROPdestroy(b->H->props); b->H->props = NULL; } if (b->T->props) { PROPdestroy(b->T->props); b->T->props = NULL; } gdk_set_lock(GDKcacheLock, "BBPaddtobin"); batcache_put(bin, b->batCacheid); gdk_unset_lock(GDKcacheLock, "BBPaddtobin"); return 0;}BAT *BBPrecycle(int ht, int tt, ssize_t cap){ int bin = BATCACHE_BIN(ht,tt); bat bid = 0; BAT *b; if (cap > batcache_minsize || BATCACHE_NOTYPE(ht) || BATCACHE_NOTYPE(tt)) return NULL; gdk_set_lock(GDKcacheLock, "BBPrecycle"); bid = batcache_get(bin); gdk_unset_lock(GDKcacheLock, "BBPrecycle"); b = BBP_cache(bid); if (b) { /* make the bat empty; do this extra work only if the bat is reused (not in BBPaddtobin) */ BAT *m = BBP_cache(-bid); b->htype = m->ttype = ht; b->hsorted = ATOMlinear(ht)?GDK_SORTED:0; b->dims.headloc = m->dims.tailloc = 0; b->halign = 0; b->hkey = m->tkey = FALSE; b->hdense = 0; b->hseqbase = m->tseqbase = (ht == TYPE_void) ? oid_nil : 0; b->ttype = m->htype = tt; b->tsorted = ATOMlinear(tt)?GDK_SORTED:0; b->dims.tailloc = m->dims.headloc = batcache_locbin[bin]; b->talign = 0; b->tkey = m->hkey = FALSE; b->tdense = 0; b->tseqbase = m->hseqbase = (tt == TYPE_void) ? oid_nil : 0; b->batSet = FALSE; b->batFirst = b->batInserted = b->batDeleted = b->batBuns->base; b->batRestricted = 0; b->batBuns->free = 0; b->batDirty = TRUE; BATsetcount(b,0); if (b->hheap) memset(b->hheap->base, 0, b->hheap->free = GDK_STRHASHTABLE*sizeof(var_t)); if (b->theap) memset(b->theap->base, 0, b->theap->free = GDK_STRHASHTABLE*sizeof(var_t)); return b; } return NULL;}/* query and change the minimum bat size to cache */wrdBBPrecycle_minsize(wrd val){ gdk_set_lock(GDKcacheLock, "BBPrecycle_minsize"); if (val != wrd_nil) { /* flush the cache */ while(batcache_first >= 0) { batcache_int i = batcache_del(); batcache[i].fifo_next = batcache_free; batcache_free = i; } batcache_minsize = val; } val = (wrd) batcache_minsize; gdk_unset_lock(GDKcacheLock, "BBPrecycle_minsize"); return val;}#line 2482 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx"#line 2522 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx"static BAT *dirty_bat(bat i, int subcommit, int *unload){ if (BBPvalid(i)) { int unloadable = (BBP_refs(i) == 0); /* are no other threads currently executing on this image?? */ int newbat = (BBP_status(i) & BBPNEW); BAT *b; BBPspin(i, "dirty_bat", BBPSAVING); b = BBP_cache(i); if (b != NULL) { if (BBP_status(i) & BBPPERSISTENT) { if (unload) *unload = BATcheckmodes(b, newbat, unloadable) && unloadable; if (subcommit || BATdirty(b)) return b; /* the bat is loaded, persistent and dirty */ } } else if (BBP_status(i) & BBPSWAPPED) { b = (BAT *) BBPquickdesc(i, TRUE); if (b) { if (unload) (void) BATcheckmodes(b, newbat, 0); if (subcommit || b->batDirtydesc) return b; /* only the desc is loaded & dirty */ } } } return NULL;}#line 2552 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx"#line 2559 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx"static intfile_move(str srcdir, str dstdir, str name, str e){ long_str ext; int ret = 0; strcpy(ext, e); ret = GDKmove(srcdir, name, ext, dstdir, name, ext); if (ret == 0) { return 0; } if (ret == 0) { return 0; } else { long_str path; struct stat st; GDKfilepath(path, srcdir, name, ext); if (stat(path, &st)) { /* source file does not exist; the best recovery is to give an error but continue * by considering the BAT as not saved; making sure that this time it does get saved. */ return 2; /* indicate something fishy, but not fatal */ } } return 1;}/* returns 1 if the file exists */static intfile_exists(str dir, str name, str ext){ long_str path; struct stat st; GDKfilepath(path, dir, name, ext); return (stat(path, &st) == 0);}static intheap_move(Heap *hp, str srcdir, str dstdir, str nme, str ext){ /* see doc at BATsetaccess()/gdk_bat.mx for an expose on .priv heap modes */ if (file_exists(dstdir, nme, ext)) { return 0; /* dont overwrite heap with the committed state already in dstdir */ } else if (hp->filename && hp->storage == STORE_PRIV) { long_str path; struct stat st; GDKfilepath(path, srcdir, nme, ext); if (stat(path, &st)) { /* in order to prevent half-saved X files surviving a recover * we create a dummy file in the BACKUP(dstdir) whose precense * will trigger BBPrecover to remove them. Thus, X.priv will * prevail where it otherwise wouldn't have. */ FILE *fp; long_str kill_ext; strcpy(kill_ext, ext); strcat(kill_ext, ".kill"); GDKfilepath(path, dstdir, nme, kill_ext); fp = fopen(path, "w"); IODEBUG THRprintf(GDKout, "#open %s = %d\n", path, fp?0:-1); if (fp != NULL) { fclose(fp); return 0; } else { return 1; } } /* if X.priv already has a saved X, that one is backed up as normal.. */ } return file_move(srcdir, dstdir, nme, ext);}#line 2635 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx"#line 2649 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx"static int backup_files = 0, backup_dir = 0, backup_subdir = 0;static intBBPprepare(bit subcommit){ int start_subcommit, ret = 0, set = 1 + subcommit; /* tmLock is only used here, helds usually very shortly just to protect the file counters */ gdk_unset_lock(GDKtmLock, "BBPprepare"); start_subcommit = (subcommit && backup_subdir == 0); if (start_subcommit) { /* starting a subcommit. Make sure SUBDIR and DELDIR are clean */ ret = (BBPrecover_subdir() < 0) ; } if (backup_files == 0) { struct stat st; backup_dir = 0; ret = (stat(BAKDIR, &st) == 0 && BBPrecover()); if (ret == 0) { /* make a new BAKDIR */ ret = mkdir(BAKDIR, 0755); IODEBUG THRprintf(GDKout, "#mkdir %s = %d\n", BAKDIR, ret); } } if (ret == 0 && start_subcommit) { /* make a new SUBDIR (subdir of BAKDIR) */ ret = mkdir(SUBDIR, 0755); IODEBUG THRprintf(GDKout, "#mkdir %s = %d\n", SUBDIR, ret); } if (ret == 0 && backup_dir != set) { /* a valid backup dir *must* at least contain BBP.dir */ if (GDKmove(backup_dir?BAKDIR:BATDIR, "BBP", "dir", subcommit?SUBDIR:BAKDIR, "BBP", "dir")) { ret = 1; } else { backup_dir = set; } } /* increase counters */ if (ret == 0) { backup_subdir += subcommit; backup_files++; } gdk_unset_lock(GDKtmLock, "BBPprepare"); return ret?-1:0;}intBBPbackup(BAT *b, bit subcommit){ long_str srcdir, nme; str s = BBP_physical(b->batCacheid); int ret = 0; if (BBPprepare(subcommit)) { return -1; } if (b->batCopiedtodisk == 0 || nme == NULL || b->batPersistence != PERSISTENT) { return 0; } /* determine location dir and physical suffix */ GDKfilepath(srcdir, BATDIR, s, NULL); s = strrchr(srcdir, DIR_SEP); strcpy(nme, ++s); srcdir[s - srcdir] = 0; if ((b->batDirty || b->batDirtydesc) && !file_exists(BAKDIR, nme, "desc")) { /* file will be saved (is dirty), move the old image into backup */ ret |= file_move(srcdir, subcommit?SUBDIR:BAKDIR, nme, "desc"); } else if (subcommit && (b->batDirty || b->batDirtydesc || file_exists(BAKDIR, nme, "desc"))) { /* file is clean. move the backup into the subcommit dir (commit should eliminate backup) */ ret |= file_move(BAKDIR, SUBDIR, nme, "desc"); } if (ret & 1) return -1;#line 2739 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx" #line 2727 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx" if (b->batBuns && b->batBuns->storage != STORE_MMAP) { /* direct mmap is unprotected (readonly usage, or has WAL protection) */ str ext = (b->batBuns->filename && b->batBuns->storage == STORE_PRIV)?"buns.kill":"buns"; if (( b->batDirty || b->batDirtybuns) && !file_exists(BAKDIR, nme, ext)) { /* file will be saved (is dirty), move the old image into backup */ ret |= heap_move(b->batBuns, srcdir, subcommit?SUBDIR:BAKDIR, nme, "buns"); } else if (subcommit && (( b->batDirty || b->batDirtybuns) || file_exists(BAKDIR, nme, ext))) { /* file is clean. move the backup into the subcommit dir (commit should eliminate backup) */ ret |= file_move(BAKDIR, SUBDIR, nme, ext); } if (ret & 1) return -1; }#line 2739 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx" #line 2727 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx" if (b->hheap && b->hheap->storage != STORE_MMAP) { /* direct mmap is unprotected (readonly usage, or has WAL protection) */ str ext = (b->hheap->filename && b->hheap->storage == STORE_PRIV)?"hheap.kill":"hheap"; if (( (b->batDirty || b->hheapdirty) && b->htype && b->hvarsized) && !file_exists(BAKDIR, nme, ext)) { /* file will be saved (is dirty), move the old image into backup */ ret |= heap_move(b->hheap, srcdir, subcommit?SUBDIR:BAKDIR, nme, "hheap"); } else if (subcommit && (( (b->batDirty || b->hheapdirty) && b->htype && b->hvarsized) || file_exists(BAKDIR, nme, ext))) { /* file is clean. move the backup into the subcommit dir (commit should eliminate backup) */ ret |= file_move(BAKDIR, SUBDIR, nme, ext); } if (ret & 1) return -1; }#line 2740 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx" #line 2727 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx" if (b->theap && b->theap->storage != STORE_MMAP) { /* direct mmap is unprotected (readonly usage, or has WAL protection) */ str ext = (b->theap->filename && b->theap->storage == STORE_PRIV)?"theap.kill":"theap"; if (( (b->batDirty || b->theapdirty) && b->ttype && b->tvarsized) && !file_exists(BAKDIR, nme, ext)) { /* file will be saved (is dirty), move the old image into backup */ ret |= heap_move(b->theap, srcdir, subcommit?SUBDIR:BAKDIR, nme, "theap"); } else if (subcommit && (( (b->batDirty || b->theapdirty) && b->ttype && b->tvarsized) || file_exists(BAKDIR, nme, ext))) { /* file is clean. move the backup into the subcommit dir (commit should eliminate backup) */ ret |= file_move(BAKDIR, SUBDIR, nme, ext); } if (ret & 1) return -1; }#line 2741 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx" return 0;}#line 2745 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx"#line 2758 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_bbp.mx"intBBPsync(int cnt, bat* subcommit){ int ret = 0, bbpdirty = 0; int t0 = 0, t1 = 0; PERFDEBUG t0 = t1 = GDKms(); ret = BBPprepare(subcommit != NULL); /* PHASE 1: safeguard everything in a backup-dir */ bbpdirty = BBP_dirty; if (OIDdirty()) { bbpdirty = BBP_dirty = 1; } if (ret == 0) { int idx = 0; while(++idx < cnt) { bat i = subcommit?subcommit[idx]:idx; if (BBP_status(i) & BBPEXISTING) { BAT *b = dirty_bat(i, subcommit != NULL, NULL); if (b != NULL && BBPbackup(b, subcommit != NULL)) break; } } ret = (idx < cnt); } PERFDEBUG THRprintf(GDKout, "#BBPsync (move time %d) %d files\n", (t1 = GDKms()) - t0, backup_files); /* PHASE 2: save the repository */ if (ret == 0) { int idx = 0; while(++idx < cnt) { bat i = subcommit?subcommit[idx]:idx; if (BBP_status(i) & BBPPERSISTENT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -