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

📄 gdk_bbp.mx

📁 这个是内存数据库中的一个管理工具
💻 MX
📖 第 1 页 / 共 5 页
字号:
                        /* BBPtrim was unloading this bat that just now lost its last refcnt. */                        incref(i, logical, FALSE); /* cannot destroy it now; back off */                        swap_unloading = TRUE;                 } else {		        BBP_status_on(i, BBPUNLOADING, "BBPdecref");		        swap = TRUE;                }	}	/* unlock before re-locking in unload; as saving a dirty persistent bat may take a long time */	if (lock)		gdk_unset_lock(GDKswapLock[i & BBPLOCKMASK], "BBPdecref");        if (swap_unloading) {		BBPspin(i, "BBPdecref", BBPUNLOADING);  /* wait for unload to complete */		decref(i, logical, lock);  /* and just try again */	} else if (swap) {		int destroy = BBP_lrefs(i) == 0 && (BBP_status(i) & BBPDELETED) == 0;		b = BBPquickdesc(i, TRUE);		if (destroy) {			BBPdestroy(b);	/* free memory (if loaded) and delete from disk (if transient but saved) */		} else if (b) {			BBP_unload_inc(i, "BBPdecref");			BBPfree(b, "BBPdecref" );	/* free memory of transient */		}	}	return refs;}intBBPdecref(bat i, int logical){	int lock = locked_by ? BBP_getpid() != locked_by : 1;	if (BBPcheck(i, "BBPdecref") == 0) {		return -1;	}	if (i < 0)		i = -i;	if (lock)		gdk_set_lock(GDKswapLock[i & BBPLOCKMASK], "BBPdecref");	return decref(i, logical, lock);}@-M5 often changes the physical ref into a logical reference.This state change consist of the sequence BBPincref(b,TRUE);BBPunfix(b).A faster solution is given below, because it does not triggerthe BBP management actions, such as garbage collecting the bats.[first step, initiate code change]@cvoidBBPkeepref(bat i){	int lock = locked_by ? BBP_getpid() != locked_by : 1;	if (i == bat_nil) 		return ;	if (i < 0)		i = -i;	if (BBPcheck(i, "BBPkeepref")) {		if (lock)			gdk_set_lock(GDKswapLock[i & BBPLOCKMASK], "BBPkeepref");		while (BBP_status(i) & BBPUNLOADING) {			if (lock)				gdk_unset_lock(GDKswapLock[i & BBPLOCKMASK], "BBPincref spin wait");			MT_sleep_ms(1);			if (lock)				gdk_set_lock(GDKswapLock[i & BBPLOCKMASK], "BBPincref spin wait");		}		/* got the lock */		++BBP_lrefs(i);		--BBP_refs(i);		if (lock)			gdk_unset_lock(GDKswapLock[i & BBPLOCKMASK], "BBPfix"); 		/* decref(i, FALSE, lock);*/	}}voidBBPreleaselref(bat i){	int lock = locked_by ? BBP_getpid() != locked_by : 1;	if (i == bat_nil || BBP_lrefs(i)<= 0) 		return ;	if (i < 0)		i = -i;	if (BBPcheck(i, "BBPreleaselref")) {		if (lock)			gdk_set_lock(GDKswapLock[i & BBPLOCKMASK], "BBPreleaselref");		while (BBP_status(i) & BBPUNLOADING) {			if (lock)				gdk_unset_lock(GDKswapLock[i & BBPLOCKMASK], "BBPincref spin wait");			MT_sleep_ms(1);			if (lock)				gdk_set_lock(GDKswapLock[i & BBPLOCKMASK], "BBPincref spin wait");		}		/* got the lock */		--BBP_lrefs(i);		if (lock)			gdk_unset_lock(GDKswapLock[i & BBPLOCKMASK], "BBPfix"); 	}}voidBBPreleaseref(bat i){	int lock = locked_by ? BBP_getpid() != locked_by : 1;	if (i == bat_nil || BBP_refs(i)<=0)		return ;	if (i < 0)		i = -i;	if (BBPcheck(i, "BBPreleaseref")) {		if (lock)			gdk_set_lock(GDKswapLock[i & BBPLOCKMASK], "BBPreleaseref");		while (BBP_status(i) & BBPUNLOADING) {			if (lock)				gdk_unset_lock(GDKswapLock[i & BBPLOCKMASK], "BBPincref spin wait");			MT_sleep_ms(1);			if (lock)				gdk_set_lock(GDKswapLock[i & BBPLOCKMASK], "BBPincref spin wait");		}		/* got the lock */		--BBP_refs(i);		if (lock)			gdk_unset_lock(GDKswapLock[i & BBPLOCKMASK], "BBPfix"); 	}}static INLINE voidunshare(bat parent){	int lock = locked_by ? BBP_getpid() != locked_by : 1;	if (parent < 0)		parent = -parent;	if (lock)		gdk_set_lock(GDKswapLock[parent & BBPLOCKMASK], "BBPunshare");	if (--BBP_cache(parent)->batSharecnt == 0) { 		(void) decref(parent, FALSE, lock);	} else if (lock) {		gdk_unset_lock(GDKswapLock[parent & BBPLOCKMASK], "BBPunshare");	}}voidBBPunshare(bat parent) {	unshare(parent);}@- BBPreclaim is a user-exported function; the common way to destroy a BAT the hard way. Return values:-1 = bat cannot be unloaded (it has more than your own memory fix) 0 = unloaded successfully 1 = unload failed (due to write-to-disk failure)@cintBBPreclaim(BAT *b){	int lock = locked_by ? BBP_getpid() != locked_by : 1;	bat i = ABS(b->batCacheid);	int reclaim_while_unloading = 0;	int ret = 0;	if (lock)		gdk_set_lock(GDKswapLock[i & BBPLOCKMASK], "BBPreclaim");	BATDEBUG THRprintf(GDKout, "#BBPreclaim: bat(%d) view=%d lrefs=%d ref=%d stat=%d\n", (int) b->batCacheid, b->batSharecnt, BBP_lrefs(b->batCacheid), BBP_refs(b->batCacheid), BBP_status(b->batCacheid));	if (BBP_refs(b->batCacheid) > 1) {		GDKerror("BBPreclaim: %d refs > 1 (%d)\n", i, BBP_refs(i));		ret = -1;	} else if (BBP_status(i) & BBPUNLOADING) {                /* BBPtrim was unloading this bat that just now is getting killed. */                reclaim_while_unloading = TRUE;         } else {		/* unload whatever the LRU in the BBP */		BBP_refs(b->batCacheid) = 0;		BBP_status_on(i, BBPUNLOADING, "BBPreclaim");	}	if (lock)		gdk_unset_lock(GDKswapLock[i & BBPLOCKMASK], "BBPreclaim");        if (reclaim_while_unloading) {		BBPspin(i, "BBPreclaim", BBPUNLOADING);  /* wait for unload to complete */		return BBPreclaim(b);	}	/* BBPfree potentially saves the BAT. Do this after releasing the short-term lock */	if (ret == 0) {		int destroy = BBP_lrefs(i) == 0 && (BBP_status(i) & BBPDELETED) == 0;		if (destroy) {			ret = BBPdestroy(BBP_cache(i));		} else {			BBP_unload_inc(i, "BBPreclaim");			ret = BBPfree(b, "BBPreclaim" );		}	}	return ret;}@-BBPdescriptor checks whether BAT needs loading and does so if necessary. You musthave at least one fix on the BAT before calling this.@cBAT *BBPdescriptor(bat i){	int lock = locked_by ? BBP_getpid() != locked_by : 1;	int load = FALSE;	bat j = ABS(i);	BAT *b = NULL;	if (!BBPcheck(i, "BBPdescriptor")) {		return NULL;	}	assert(BBP_refs(i));	if ((b = BBP_cache(i)) == NULL) {		if (lock)			gdk_set_lock(GDKswapLock[j & BBPLOCKMASK], "BBPdescriptor");		while (BBP_status(j) & BBPWAITING) {	/* wait for bat to be loaded by other thread */			if (lock)				gdk_unset_lock(GDKswapLock[j & BBPLOCKMASK], "BBPdescriptor");			MT_sleep_ms(1);			if (lock)				gdk_set_lock(GDKswapLock[j & BBPLOCKMASK], "BBPdescriptor");		}		if (BBPvalid(j)) {			b = BBP_cache(i);			if (b == NULL) {				load = TRUE;				BBP_status_on(j, BBPLOADING, "BBPdescriptor");			}		}		if (lock)			gdk_unset_lock(GDKswapLock[j & BBPLOCKMASK], "BBPdescriptor");	}	if (load) {		IODEBUG THRprintf(GDKout, "#load %s\n", BBPname(i));		b = BATload_intern(i);		BBPin++;		/* clearing bits can be done without the lock */		BBP_status_off(j, BBPLOADING, "BBPdescriptor");	}	return b;}@-In BBPsave executes unlocked; it just marks the BBP_status of the BAT to BBPsaving, so othersthat want to save or unload this BAT must spin lock on the BBP_status field.@cintBBPsave(BAT *b){	int lock = locked_by ? BBP_getpid() != locked_by : 1;	bat bid = ABS(b->batCacheid);	int ret = 0;	if (BBP_lrefs(bid) == 0 || !BATdirty(b)) 		/* do nothing */		return 0;	if (lock)		gdk_set_lock(GDKswapLock[bid & BBPLOCKMASK], "BBPsave");	if (BBP_status(bid) & BBPSAVING) {		/* wait until save in other thread completes */		BBPspin(bid, "BBPsave", BBPSAVING);		if (lock)			gdk_unset_lock(GDKswapLock[bid & BBPLOCKMASK], "BBPsave");	} else {		/* save it */		int flags = BBPSAVING;		if (DELTAdirty(b)) {			flags |= BBPSWAPPED;			BBPdirty(1);		}		if (b->batPersistence != PERSISTENT) {			flags |= BBPTMP;		}		BBP_status_on(bid, flags, "BBPsave");		if (lock)			gdk_unset_lock(GDKswapLock[bid & BBPLOCKMASK], "BBPsave");		IODEBUG THRprintf(GDKout, "#save %s\n", BATgetId(b));		/* do the time-consuming work unlocked */         	if (BBP_status(bid) & BBPEXISTING) 			ret = BBPbackup(b, FALSE);		if (ret == 0) {			BBPout++;			ret = (BATsave(b) == NULL);		}		/* clearing bits can be done without the lock */		BBP_status_off(bid, BBPSAVING, "BBPsave");	}	return ret;}@-TODO merge BBPfree with BATfree? Its function is to prepare a BAT for beingunloaded (or even destroyed, if the BAT is not persistent).@cstatic int BBPaddtobin(BAT *b);static intBBPdestroy(BAT *b) {	int clear = 1;	bat parent = b->batParentid; 	if (VIEWparent(b)) { /* a physical view */		VIEWdestroy(b);	} else {		/* bats that get destroyed must unfix their atoms */		int (*hunfix) (ptr) = BATatoms[b->htype].atomUnfix;		int (*tunfix) (ptr) = BATatoms[b->ttype].atomUnfix;		BUN p, q;		int xx;		assert(b->batSharecnt == 0);		if (hunfix) {			DELloop(b, p, q, xx) {				(*hunfix) (BUNhead(b, p));			}			BATloopFast(b, p, q, xx) {				(*hunfix) (BUNhead(b, p));			}		}		if (tunfix) {			DELloop(b, p, q, xx) {				(*tunfix) (BUNtail(b, p));			}			BATloopFast(b, p, q, xx) {				(*tunfix) (BUNtail(b, p));			}		}		clear = BBPaddtobin(b);	/* plan for re-use */	}	if (clear)		BBPclear(b->batCacheid);	/* if destroyed; de-register from BBP */	/* parent released when completely done with child */	if (parent) unshare(parent);	return 0;}static intBBPfree(BAT *b, str calledFrom ){	bat bid = ABS(b->batCacheid), parent = b->batParentid;	int ret;	assert(BBPswappable(b));	/* write dirty BATs before being unloaded */	ret = BBPsave(b);        if (ret == 0) {                if (VIEWparent(b)) { /* physical view */		        VIEWdestroy(b);	        } else {	   	        assert(b->batSharecnt == 0); 		        if (BBP_cache(bid)) BATfree(b);	/* free memory */	        }	        BBPuncacheit_(bid, FALSE);	        if (b->batMapdirty) {		        DESCsetmodes(b, b);		        b->batMapdirty = 0;	        }	}	/* clearing bits can be done without the lock */	BBP_status_off(bid, BBPUNLOADING, calledFrom);	BBP_unload_dec(bid, calledFrom);		/* parent released when completely done with child */	if (ret == 0 && parent) unshare(parent);	return ret;}@}@- Storage trimmingBBPtrim unloads the least recently used BATs to free memory resources.It gets passed targets in bytes of physical memory and logicalvirtual memory resources to free. Overhead costs are reduced bymaking just one scan, analyzing the first BBPMAXTRIM batsand keeping the result in a list for later use (the oldest bat now is going to be the oldest bat in the future as well).This list is sorted on last-used timestamp. BBPtrim keeps unloadingBATs till the targets are met or there are no more BATs to unload.In determining whether a BAT will be unloaded, first it hasto be BBPswappable, and second its resources occupied mustbe of the requested type. The algorithm actually makes two passes,in the first only clean bats are unloaded (in order of their stamp).In order to keep this under control with multiple threads allrunning out of memory at the same time, we make sure that @itemize@item just one thread does a BBPtrim at a time (by having a BBPtrimLock set).@itemwhile decisions are made as to which bats to unload (1) the BBP isscanned, and (2) unload decisions are made. Due to these properties,the search\&decide phase of BBPtrim acquires both GDKcacheLock (due to (1))iand all GDKswapLocks (due to (2)). They must be released during the actual unloading.  (as otherwise deadlock occurs => unloading a bat may e.g. kill an accelerator that is a BAT, which in turn requires BBP lock acquisition).@itemto avoid further deadlock, the update functions in BBP that hold either GDKcacheLock or a GDKswapLock may never cause a BBPtrim (notice that BBPtrim could theoretically be set off just by allocating a little piece of memory, e.g. GDKstrdup()). If these routines must alloc memory, they must set the BBP\_notrim variable, acquiring the addition GDKtrimLock, in order to prevent such deadlock.@itemthe BBPtrim is atomic; only releases its locks when all BAT unload work is done. This ensures that if all memory requests that triggeredBBPtrim could possible be satisfied by unloading BATs, this will succeed.@end itemizeThe scan phase was optimized further in order to stop early whenit is a priori known that the targets are met (which is the case if theBBPtrim is not due to memory shortage but due to the ndesc quota).Note that scans may always stop before BBPsize as the BBPMAXTRIM is a fixednumber which may be smaller. As such, a mechanism was added to resumea broken off scan at the point where scanning was broken off rather thanalways starting at BBP[1] (this does more justice to the lower numbered bats and will more quickly find fresh unload candidates).We also refined the swap criterion. If the BBPtrim was initiated due to:- too much descriptors: small bats are unloaded first (from LRU cold to hot)  

⌨️ 快捷键说明

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