⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdk_bat.mx

📁 这个是内存数据库中的一个管理工具
💻 MX
📖 第 1 页 / 共 5 页
字号:
		if (b->hseqbase == oid_nil || flag == FALSE) {			return b;		}	}	if (flag)		flag |= (1 | b->hkey);	if (b->hkey != flag)		b->batDirtydesc = TRUE;	BATmirror(b)->tkey = b->hkey = flag;	if (!flag)		BATmirror(b)->tdense = b->hdense = 0;	if (flag && parent && ALIGNsynced(b, BBP_cache(parent)))		BATkey(BBP_cache(parent), TRUE);	return b;}BAT *BATset(BAT *b, int flag){	BATcheck(b, "BATset");	if (b->htype == TYPE_void) {		if (b->hseqbase == oid_nil && flag == BOUND2BTRUE)			BATkey(BATmirror(b), flag);	} else if (b->ttype == TYPE_void) {		if (b->tseqbase == oid_nil && flag == BOUND2BTRUE)			BATkey(b, flag);	} else {		if (flag)			flag = TRUE;		if (b->batSet != flag)			b->batDirtydesc = TRUE;		b->batSet = flag;	}	return b;}BAT *BATseqbase(BAT *b, oid o){	BATcheck(b, "BATseqbase");	if (ATOMtype(b->htype) == TYPE_oid) {		BAT *m = BATmirror(b);		if (b->hseqbase != o) {			b->batDirtydesc = TRUE;			/* zap alignment if column is changed by new seqbase */			if (b->htype == TYPE_void)				b->halign = m->talign = 0;		}		m->tseqbase = b->hseqbase = o;		/* adapt keyness */		if (BAThvoid(b)) {			if (o == oid_nil) {				if (b->hkey)					m->tkey = b->hkey = FALSE;			} else {				if (!b->hkey) {					m->tkey = b->hkey = TRUE;					b->H->nokey[0] = b->H->nokey[1] = 0; 				}			}		}	}	return b;}@}@- BATs have a logical name that is independent of their location in the file system (this depends on batCacheid).The dimensions of the BAT can be given a separate name.It helps front-ends in identifying the column of interest.The new name should be recognizable as an identifier.Otherwise interaction through the front-ends becomescomplicated.@{@cintBATname(BAT *b, str nme){	BATcheck(b, "BATname");	return BBPrename(b->batCacheid, nme);}strBATrename(BAT *b, str nme){	int ret = BATname(b, nme);	if (ret == 1) {		GDKerror("BATrename: identifier expected: %s\n", nme);	} else if (ret == BBPRENAME_ALREADY) {		GDKerror("BATrename: name is in use: '%s'.\n", nme);	} else if (ret == BBPRENAME_ILLEGAL) {		GDKerror("BATrename: illegal temporary name: '%s'\n", nme);	} else if (ret == BBPRENAME_LONG) {		GDKerror("BATrename: name too long: '%s'\n", nme);	} else if (b == NULL) {		GDKerror("BATrename: BAT argument missing\n");	}	return BBPname(b->batCacheid);}BAT *BATroles(BAT *b, str hnme, str tnme){	BATcheck(b, "BATroles");	if (b->hident && !default_ident(b->hident))		GDKfree(b->hident);	if (hnme)		b->hident = GDKstrdup( hnme );	else		b->hident = BATstring_h;	if (b->tident && !default_ident(b->tident))		GDKfree(b->tident);	if (tnme)		b->tident = GDKstrdup( tnme );	else		b->tident = BATstring_t;	return b;}BAT *BATcol_name(BAT *b, str tnme){	BATcheck(b, "BATcol_name");	if (b->tident && !default_ident(b->tident))		GDKfree(b->tident);	if (tnme)		b->tident = GDKstrdup( tnme );	else		b->tident = BATstring_t;	return b;}@}@+ BAT permissions, persistency and memory mapped heapsThe way large heaps are memory mapped is dependent both on the BAT persistency status (persistent or not)as well as their update permissions (readonly,append-only,writable).Let us recall the two main memory mapped file modes used to store heaps:@multitable @columnfractions .12 .8@item STORE_MMAP @tab files must be readonly, because you never know the exact saved status.       HEAPsave consists of the rather efficient msync(X).@item STORE_PRIV @tab files modify pages in swap area, and can be writable.       HEAPsave actually does a full write(X), while the mapped file stays in X.priv@end multitableNotice that PRIV storage is only required for persistent BATs that are already committed on disk. The crash-consistent state of transient BATs is irrelevant as they disappearafter a crash. Even the crash-consistency of persistent BATs that did not make their firstcommit is not relevant as they also will disappear.Also, some heaps may be in use with STORE_MMAP even if they are appendable, as we suppose ourcode is bug-free and we know we won't modify the already committed parts of the mappedfile pages. For string-heaps append-bats may mmap the heap if doubles are not  being eliminatedanymore (i.e. when the contents of the builtin hash table at the start of the string heapare not crucial anymore).@{@c#define ATOMappendpriv(t,h) ((BATatoms[t].atomHeapCheck != HEAP_check || !HEAP_mmappable(h)) && \			     (ATOMstorage(t) != TYPE_str || GDK_ELIMDOUBLES(h)))@}@- BATmmapChanging the storage status of heaps in a BAT is done in @:BATmmap@. The new semantics is to do nothing: the new mapping only takes effect the next time the bat is loaded. Thus we cannot modify the hp->storage fields, but rather store the new modes in specialbatMap fields that are used when the BAT descriptor is saved.This makes the BATmmap safer \& simpler as it is nowincorporated in the normal bat loading and saving mechanism.It also makes the mmap faster as when through caching youare finished with the BAT before it is ever swapped to diskit will never have been written, whereas the old mmap obliged you to save a BAT directly.@{@cintBATmmap(BAT *b, int bns, int hhp, int thp ){	BATcheck(b, "BATmmap");	IODEBUG THRprintf(GDKout, "#BATmmap(%s,%d,%d,%d)\n", BATgetId(b), bns, hhp, thp );	/* Reverse back if required, as this determines which heap is saved in the 	 * "hheap" file and which in the "theap" file.	 */	if (b->batCacheid < 0) {		int swap = hhp;		hhp = thp;		thp = swap;		b = BATmirror(b);	}	b->batMapdirty = TRUE;	b->batMapbuns = bns;	b->batMaphheap = hhp;	b->batMaptheap = thp;	if (b->batBuns) b->batBuns->newstorage = bns;	if (b->hheap) b->hheap->newstorage = hhp;	if (b->theap) b->theap->newstorage = thp;	b->batDirtydesc = 1;	return 0;}@- BATmadvise@= madvise	if (@1 >= 0 && (@2) && (@2)->base && ((@2)->storage&STORE_MMAP) &&	    MT_madvise((@2)->base, (@2)->free, @1)) {		GDKsyserror("madvise on @2 @1 failed.\n");		return -1;	}@= pin	if ( (@2) && (@2)->base && ((@2)->storage&STORE_MMAP)) {		MT_mmap_@1((@2)->base, (@2)->maxsize);	}@cintBATmadvise(BAT *b, int bns, int hhp, int thp ){	BATcheck(b, "BATmadvise");	@:madvise(bns,b->batBuns)@	@:madvise(hhp,b->hheap)@	@:madvise(thp,b->theap)@	return 0;}intBATmmap_pin(BAT *b){	BATcheck(b, "BATmmap_pin");	@:pin(pin,b->batBuns)@	@:pin(pin,b->hheap)@	@:pin(pin,b->theap)@	return 0;}intBATmmap_unpin(BAT *b){	BATcheck(b, "BATmmap_unpin");	@:pin(unpin,b->batBuns)@	@:pin(unpin,b->hheap)@	@:pin(unpin,b->theap)@	return 0;}@}@- BATcheckmodesChecks legal heap modes. This is done at BATsave time on a temporary copy of the BAT descriptor(DESCsetmodes). It now is also used from TMcommit, as one of the criteria for whether a heapneeds priv storage is whether the BAT has been committed ever (see also dirty_bat() in gdk_bbp.mx).@{@cstatic intHEAPcheckmode(Heap *h, int persistent, int unloadable, int writeable){	/* user may have requested illegal or system-wise unwanted mmap modes. correct this */	if (h->size > 0 && h->storage == STORE_MMAP && persistent && writeable) {		/* in a commit, we are sometimes forced to start treating MMAP heaps as PRIV */		if (!unloadable)			h->storage = STORE_PRIV;		return 1;	}	return 0;}intBATcheckmodes(BAT *b, int persistent, int unloadable){	int dirty = 0;	BATcheck(b, "BATcheckmodes");	if (HEAPcheckmode(b->batBuns, persistent, unloadable, b->batRestricted == BAT_WRITE)) {		b->batMapbuns = STORE_PRIV;		dirty = b->batMapdirty = TRUE;	}	if (b->hheap && (HEAPcheckmode(b->hheap, persistent, unloadable, b->batRestricted == BAT_WRITE || (b->batRestricted == BAT_APPEND && ATOMappendpriv(b->htype, b->hheap))))) {		b->batMaphheap = STORE_PRIV;		dirty = TRUE;	}	if (b->theap && (HEAPcheckmode(b->theap, persistent, unloadable, b->batRestricted == BAT_WRITE || (b->batRestricted == BAT_APPEND && ATOMappendpriv(b->ttype, b->theap))))) {		b->batMaptheap = STORE_PRIV;		dirty = TRUE;	}	b->batMapdirty |= dirty;	b->batDirtydesc |= dirty;	return dirty;}@}@- Change the BAT access permissions (read, append, write)BATsetaccess() may seem simple, but this has become very tricky when memory-mapped files are involved. In case of bats which are still transient changes are simple(just the batRestricted field).@-In case of a change from writable->readonly (PRIV->MMAP), nothing needs to be done immediately.The mapped BAT is saved in the old mode (in X, not X.priv), and made un-modifiable.As there are no updates, we need not worry about saving either.@-A change from readonly->writable (MMAP->PRIV) is more traumatic. We must unload, and re-load immediately, before the BAT can become modifiable.@-This picture is complicated further by the new MMAP heaps for temporary BATs.While such BATs are non-persistent, it is legal to have them as MMAP, becausethey won't need to survive a system crash (ie global abort), so we don't careabout consistent files.@-Now, for such non-persistent MMAP bats we want to keep the change writable->readonly (i.e. MMAP->MMAP) efficient, that is a simple msync(X) should be sufficient (no writing to X.priv). To change a temporary writable MMAP heap into a readonly permanentMMAP heap, we must *modify* the filename.@-To summarize, there are three heap attributes of interest;@itemize @itemH =(priv,map) heap mode as registered in h->storage @itemM =(priv,map) heap mode as has been requested from the OS @itemF =(X,X.priv) h->filename @end itemizeWe show now all 4 legal heap states, and transitions between them:@multitable @columnfractions 0.25 0.25 0.25item tabwritable:                      tab initially created by:tab when made readonly:item (1)tab[ H=priv,M=priv,F=X.priv ] tabload a writable mmap bat  tabgoto (4) item (2)tab[ H=map, M=map, F=X.priv ] tabnew temporary heap bat    tabgoto (3)readonly:                                                when made writable:item (3) tab[ H=map, M=map, F=X]       tabload a readonly mmap bat  tabif (persistent) goto (1) else goto (2)@item (4) [ H=map, M=priv,F=X.priv ] tabn.a.                      tabgoto (1)@end multitableNow we see that for BBPsync (heap\_move) it is sufficient to check for the .privsuffix to determine the appropriate backup\_bat behavior (i.e. register a X .killfileanticipating the write(X) besides a X.priv).HEAPsave: we do not need to worry about saving readonly bats: as we save them in BATsetaccess anyway just before changing modes, we know that readonly heaps will never be dirty and as such never saved. HEAPsave on a writable BAT just needs to look at H (h->storage) to know what to do.@{@c/* transition heap from readonly to writable (or appendable) */static intHEAPsetpriv(Heap *hp, int committed, int *remap, int *reload){	str p;	assert(hp);	if (hp->base == NULL || hp->storage == STORE_MEM || hp->filename == NULL || !committed) {		return hp->storage;	}	/* STORE_PRIV would indicate an illegal heap state */	assert(hp->storage != STORE_PRIV);	p = strstr(hp->filename, ".priv");	if (p) { 		/* state(4), goto state (1) */		*remap = TRUE;		return hp->storage = STORE_PRIV;	}	*remap = TRUE;	/* state(3), goto state (1) */	*reload = TRUE;	return STORE_PRIV;}/* transition heap from writable (or appendable) to readonly */static intHEAPsetmmap(Heap *hp, int committed, int *remap){	assert(hp);	if (hp->base == NULL || hp->storage == STORE_MEM || hp->filename == NULL || !committed ) {		return hp->storage;	}	*remap = TRUE;	if (hp->storage == STORE_MMAP) {		/* state(2), goto state (3) */		long_str src, dst;		str p = strstr(hp->filename, ".priv");		int ret;		assert(p);	/* absence of .priv would indicate an illegal heap state */		GDKfilepath(src, BATDIR, hp->filename, NULL);		*p = 0;		/* cut off .priv */		GDKfilepath(dst, BATDIR, hp->filename, NULL);		/* rename X.priv->X is not crucial for this to work (X.priv is not in the way) */		ret = rename(src, dst);		IODEBUG THRprintf(GDKout, "#BATsetaccess(HEAPsetmmap) rename(%s,%s) = %d\n", src, dst, ret);	} else {		/* state(1), goto state (4) */		hp->storage = STORE_MMAP;	/* direct change! */	}	return STORE_MMAP;}@= heap_unshare	if (b->@1->copied) {		Heap hp;		memset(&hp, 0, sizeof(Heap));		if (HEAPcopy(&hp, b->@1) < 0) {			GDKerror("%s: remapped @1 of %s could not be copied.\n", fcn, BATgetId(b));			return -1;		}		HEAPfree(b->@1);		*(b->@1) = hp;		b->@1->copied = 0;	}@cstatic intbatunshare(BAT* b, str fcn) {	@:heap_unshare(batBuns)@	if (b->hheap) @:heap_unshare(hheap)@	if (b->theap) @:heap_unshare(theap)@	b->batLview = 0;	BBPunshare(b->batParentid);	return 0;}BAT *BATsetaccess(BAT *b, int mode){	BATcheck(b, "BATsetaccess");	if (VIEWparent(b) && mode != BAT_READ) {		if (VIEWreset(b) == NULL)			return NULL;	}	if (b->batRestricted != mode) {		int m1 = 0, bak1 = b->batBuns->storage;		int m2 = 0, bak2 = b->hheap ? b->hheap->storage : -1;		int m

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -