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

📄 gdk_utils.mx

📁 这个是内存数据库中的一个管理工具
💻 MX
📖 第 1 页 / 共 4 页
字号:
	s[-1] |= 2;	if (size < 0) {		size_t maxsize = (size_t) s[-2];		size = -size;		MT_alloc_register((char *) (s - 2), maxsize, 's');		GDKvmfree((char *) (s - 2), (size_t) size, maxsize);	} else {#ifndef NDEBUG		/* The check above detects obvious duplicate free's,		 * but fails in case the "check-bit" is cleared between		 * two free's (e.g., as the respective memory has been 		 * re-allocated and initialized.		 * To simplify detection & debugging of duplicate free's,		 * we now overwrite the to be freed memory, which will		 * (1) trigger a segfault in case the memory had already		 * been freed and/or trigger some error in case the memory		 * is accessed after is has been freed.		 * To avoid performance penalty in the "production version",		 * we only do this in debugging/development mode (i.e.,		 * when configured with --enable-assert).		 * Disable at runtime via `Mserver --debug=33554432` or		 * `debugmask(or(debugmask(),33554432));` in MIL.		 */		DEADBEEFCHK memset(s,0xDB,size - (8 + (size & 1))); /* 0xDeadBeef */#endif#ifdef GDK_MEM_MISALIGN		if (size & 1)			free(((char *) s) - 4);		else#endif			free(((char *) s) - 8);		@:heapdec(size,s)@	}}ptrGDKreallocmax(void *blk, size_t size, size_t * maxsize, int emergency){	ssize_t oldsize = 0, *s = (ssize_t *) blk;	if (s == NULL) {		return GDKmallocmax(size, maxsize, emergency);	}#ifdef GDK_MEM_NULLALLOWED	if (size == 0) {		GDKfree(blk);		*maxsize = 0;		return NULL;	}#endif	if (size <= 0) {		GDKfatal("GDKreallocmax: called with size %u", size);	}	/* round up to a multiple of four */	size = (size + 3) & ~3;	oldsize = GDK_MEM_BLKSIZE(s);	/* check against duplicate free */	assert((oldsize & 2) == 0);	if (oldsize < 0) {		size_t newsize = size + sizeof(size_t) + sizeof(size_t);		size_t oldmax = (size_t) s[-2];		size_t newmax = MAX(*maxsize, newsize);		s = (ssize_t *) GDKvmrealloc((ptr) (s - 2), (size_t) - oldsize, newsize, oldmax, &newmax, emergency);		if (s == NULL && !emergency)			return NULL;		s[0] = newmax;		s[1] = -((ssize_t) newsize);		*maxsize = newmax - (sizeof(size_t) + sizeof(size_t));		return (ptr) (s + 2);	}#ifndef GDK_MEM_MISALIGN	if (size <= GDK_mem_bigsize) {		size_t newsize = size + 8;		blk = realloc(((char *) blk) - 8, newsize);		if (blk != NULL) {			/* place 8 bytes before it */			assert((((size_t) blk) & 4) == 0);			blk = ((char *) blk) + 8;			((ssize_t *) blk)[-1] = (ssize_t) newsize;			/* adapt statistics */			@:heapinc(newsize,blk)@			@:heapdec(oldsize,s)@			*maxsize = size;			return blk;		}	}	/* alloc&copy due too failed realloc (may be very big heap that needs vm) */#else	/* alloc&copy because we cannot trust realloc due to misalignment */	if (oldsize & 1)		oldsize = MIN(size, (size_t) oldsize - 5);	else#endif		oldsize = MIN(size, (size_t) (oldsize - 8));	blk = (void *) GDKmallocmax(size, maxsize, emergency);	if (blk) {		memcpy(blk, s, oldsize);		GDKfree(s);	}	return (void *) blk;}ptrGDKrealloc(void *blk, size_t size){	return GDKreallocmax(blk, size, &size, 1);}char *GDKstrdup(const char *s){	int l = strLen(s);	char *n = (char *) GDKmalloc(l);	memcpy(n, s, l);	return n;}@- virtual memoryallocations affect only the logical VM resources.@cvoidGDKvminc(size_t len){	@:meminc(0,len,"GDKvminc")@	CHKMEM(0, len);}void *GDKmmap(char *path, int mode, off_t off, size_t len){	void *ret = MT_mmap(path, mode, off, len);	if (ret == (void *) -1L) {		GDKmemfail("GDKmmap", len, 0, BBPTRIM_ALL);		ret = MT_mmap(path, mode, off, len);		if (ret != (void *) -1L) {			THRprintf(GDKout, "#GDKmmap: recovery ok. Continuing..\n");		}	}	if (ret != (void *) -1L) {		MT_alloc_register(ret, len, 'M');		GDKvminc(len);	}	return (void *) ret;}intGDKmunmap(void *addr, size_t size){	int ret;	MT_alloc_register(addr, size, 'm');	ret = MT_munmap(addr, size);	if (ret == 0) {		@:memdec(0,size,"GDKunmap")@	}	return ret;}@- VM allocthis affects both physical and logical memory resources.The emergency flag can be set to force a fatal error if needed.Otherwise, the caller is able to deal with the lack of memory.@cvoid *GDKvmalloc(size_t size, size_t * maxsize, int emergency){	void *ret = MT_vmalloc(size, maxsize);	if (ret == NULL) {		GDKmemfail("GDKvmalloc", size, BBPTRIM_ALL, BBPTRIM_ALL);		ret = MT_vmalloc(size, maxsize);		if (ret == NULL) {			if (emergency == 0)				return NULL;			MT_alloc_print();			GDKfatal("GDKvmalloc: failed for %u bytes", size);		} else {			THRprintf(GDKout, "#GDKvmalloc(" SZFMT "): recovery ok. Continuing..\n", size);		}	}	if (ret != NULL) {		@:meminc(size,*maxsize,"GDKvmalloc")@		CHKMEM(size, *maxsize);	}	return ret;}void *GDKvmrealloc(void *pold, size_t oldsize, size_t newsize, size_t oldmax, size_t * newmax, int emergency){	void *ret = MT_vmrealloc(pold, oldsize, newsize, oldmax, newmax);	if (ret == NULL) {		GDKmemfail("GDKvrealloc", newsize, BBPTRIM_ALL, BBPTRIM_ALL);		ret = MT_vmrealloc(pold, oldsize, newsize, oldmax, newmax);		if (ret == NULL) {			if (emergency == 0)				return NULL;			MT_alloc_print();			GDKfatal("GDKvrealloc: failed for %u bytes (from %u)", newsize, oldsize);		} else {			THRprintf(GDKout, "#GDKvmrealloc(" SZFMT "): recovery ok. Continuing..\n", newsize);		}	}	if (ret != NULL) {		@:memdec(oldsize,oldmax,"GDKvmrealloc")@		@:meminc(newsize,*newmax,"GDKvmrealloc")@		CHKMEM(newsize, *newmax);	}	return ret;}voidGDKvmfree(void *blk, size_t size, size_t maxsize){	MT_vmfree(blk, maxsize);	@:memdec(size,maxsize,"GDKvmfree")@}@}@+ Session InitializationThe parameter @emph{db} is followed by the database name relative tothe environment variable dbfarm.The parameter @emph{monetrc} tells that the system variables settingshould be overruled by the specification given in the file argument.This format is only necessary to temporarily experiment with variable settings,without disturbing a system/site default setting.The interface code to the operating system is highly dependent onthe processing environment. It can be filtered away with compile-time flags.Suicide is necessary due to some system implementation errors.The kernel requires file descriptors for I/O with the user.They are thread specific and should be obtained by a function.The arguments relevant for the kernel are extracted from the list.Their value is turned into a blanc space.@{@hgdk_export int GDKrecovery;@cint GDKtime_startsec, GDKrecovery = 0;@hgdk_export int GDKinit(char *dbname, char *dbfarm, int alloc_map);@cvoidGDKprotect(void){	int i;	if (GDKprotected == 0) {		TMDEBUG printf("# GDKlocks created\n");		MT_init_lock(GDKthreadLock);		for (i = 0; i <= BBPLOCKMASK; i++) {			MT_init_lock(GDKswapLock[i]);			MT_init_lock(GDKhashLock[i]);		}		MT_init_lock(GDKcacheLock);		MT_init_lock(GDKunloadLock);		MT_init_cond(GDKunloadCond);		MT_init_lock(GDKtrimLock);		MT_init_lock(GDKtmLock);		GDKprotected = 1;	}}#ifndef WIN32static voidGDKvmtrim(void *limit){	int wt = 1;	do {		stream *fp = NULL;		MT_sleep_ms(wt ? 5000 : 500);		MEMDEBUG {			fp = GDKout;			THRprintf(fp, "#GDKvmtrim(" LLFMT ")\n", (long long) *(size_t *) limit);		}		wt = !MT_mmap_trim(*(size_t *) limit, fp);	} while (!GDKstopped);}#endifintGDKinit(char *dbname, char *dbfarm, int alloc_map){	gdk_alloc_map = alloc_map;	errno = 0;	if (!GDKenvironment(dbname, dbfarm))		return 0;	stream_init();	MT_init_posix(alloc_map);	THRinit();#ifndef NATIVE_WIN32	BATSIGinit();#endif	GDKlockHome();	/* init time */#ifdef HAVE_GETTIMEOFDAY	{		struct timeval tp;		gettimeofday(&tp, NULL);		GDKtime_startsec = tp.tv_sec;	}#else#ifdef HAVE_FTIME	{		struct timeb tb;		ftime(&tb);		GDKtime_startsec = (int) tb.time;	}#endif#endif	if (GDKembedded)		GDKprotected = 0;	/* Mserver intends to rob 95% of all memory as a default */	GDK_vm_minsize = GDK_mem_maxsize = (size_t) ((double) MT_npages() * (double) MT_pagesize() * 0.815);	GDKmemchk(TRUE, TRUE);	GDKremovedir(DELDIR);	BBPinit();	GDKenv = BATnew(TYPE_str, TYPE_str, 100);	if (GDKenv == NULL)		GDKfatal("GDKinit: Could not create environment BAT");	BATrename(GDKenv, "monet_environment");	BATmode(GDKenv, TRANSIENT);#ifndef WIN32	if (!GDKembedded) {		MT_Id t;		MT_create_thread(&t, GDKvmtrim, &GDK_mem_maxsize);	}#endif	return 1;}@-Upon closing the session, all persistent BATs should be saved andthe transient BATs should be removed.The buffer pool manager takes care of this.@hgdk_export int GDKstopped;@cint GDKstopped = 1;@hgdk_export void GDKexit(int status);@cvoidGDKexit(int status){	gdk_set_lock(GDKthreadLock, "GDKexit");	if (GDKstopped == 0) {		GDKstopped++;	/* shouldn't there be a lock here? */		GDKnrofthreads = 0;		gdk_unset_lock(GDKthreadLock, "GDKexit");		/* Kill all threads except myself */		if (status == 0) {			MT_Id pid = MT_getpid();			Thread t, s;			for (t = GDKthreads, s = t + THREADS; t < s; t++) {				if (t->pid) {					MT_Id victim = t->pid;					if (t->pid != pid)						MT_kill_thread(victim);				}			}		}		(void) GDKgetHome();		BBPexit();		GDKlog(GDKLOGOFF);		GDKunlockHome();		MT_global_exit(status);	}	gdk_unset_lock(GDKthreadLock, "GDKexit");}@All semaphores used by the application should be mentioned here.They are initialized during system initialization.@cint GDKdebug = 0;int GDKembedded = 0;int GDKprotected = 0;MT_Lock GDKthreadLock;MT_Lock GDKswapLock[BBPLOCKMASK + 1];MT_Lock GDKhashLock[BBPLOCKMASK + 1];MT_Lock GDKcacheLock, GDKtrimLock;MT_Lock GDKunloadLock;MT_Lock GDKtmLock;MT_Cond GDKunloadCond;@}@+ Concurrency controlConcurrency control requires actions at several levels of the system.First, it should be ensured that each database  is controlled by a singleserver process (group). Subsequent attempts should be stopped.This is regulated through file locking against ".gdk_lock".Furthermore, the server process is moved to the database directoryfor improved speed.@-Before the locks and threads are initiated, we cannot use thenormal routines yet. So we have a local fatal here instead of GDKfatal.@{@cvoidGDKlockHome(void){	char *p = 0, buf[1024], host[PATHLENGTH];	char GDKdirStr[PATHLENGTH];@-Go there and obtain the global database lock.@c	/* The DIR_SEP at the end of the path is needed for a succesfull	   call to GDKcreatedir */	snprintf(GDKdirStr, PATHLENGTH, "%s%c%s%c", GDKdbfarmStr, DIR_SEP, GDKdbnameStr, DIR_SEP);	if (chdir(GDKdirStr) < 0) {		if (!GDKcreatedir(GDKdirStr) || chdir(GDKdirStr) < 0)			GDKfatal("GDKlockHome: could not move to %s\n", GDKdirStr);		GDKwarning("GDKlockHome: created directory %s\n", GDKdirStr);	}	if (GDKrecovery && unlink(GDKLOCK) < 0) {		GDKfatal("GDKlockHome: unlock DB failed\n");	}	umask(0000);	if (MT_lockf(GDKLOCK, F_TLOCK, 4, 1) < 0) {		GDKlockFile = 0;		GDKfatal("GDKlockHome: Database lock '%s' denied\n", GDKLOCK);	}	if ((GDKlockFile = fopen(GDKLOCK, "rb+")) == NULL) {		GDKfatal("GDKlockHome: Could not open %s\n", GDKLOCK);	}	if (fgets(buf, 1024, GDKlockFile) && (p = strchr(buf, ':')))		*p = 0;	if (p) {		sprintf(host, " from '%s'", buf);	} else {		GDKwarning("GDKlockHome: ignoring empty or invalid %s.\n", GDKLOCK);		host[0] = 0;	}@-We have the lock, are the only process currently allowed in this section.@c	MT_init();	OIDinit();@-Print the new process list in the global lock file.@c	fseek(GDKlockFile, 0, SEEK_SET);	ftruncate(fileno(GDKlockFile), 0);	fflush(GDKlockFile);	GDKlog(GDKLOGON);@-In shared mode, we allow more parties to join. Release the lock.@c	GDKstopped = 0;}voidGDKunlockHome(void){	if (GDKlockFile) {		MT_lockf(GDKLOCK, F_ULOCK, 4, 1);		fclose(GDKlockFile);		GDKlockFile = 0;	}}@-Really really get the lock. Now!!@cintGDKgetHome(void){	if (MT_initialized() == 0 || GDKlockFile)		return 0;	while ((GDKlockFile = fopen(GDKLOCK, "r+")) == NULL) {		GDKerror("GDKgetHome: PANIC on open %s. sleep(1)\n", GDKLOCK);		MT_sleep_ms(1000);	}	if (MT_lockf(GDKLOCK, F_TLOCK, 4, 1) < 0) {		GDKwarning("GDKgetHome: blocking on lock '%s'.\n", GDKLOCK);		MT_lockf(GDKLOCK, F_LOCK, 4, 1);	}	return 1;}@}@+ Error handlingErrors come in three flavors: warnings, non-fatal and fatal errors.A fatal error leaves a core dump behind after trying tosafe the content of the relation.A non-fatal error returns a message to the userand aborts the current transaction.Fatal errors are also recorded on the system log for post-mortemanalysis.In non-silent mode the errors are immediately sent to output,which makes it hard for upper layers to detect if an errorwas produced in the process. To facilitate such testing,a global error count is maintained on a thread basis,which can be read out by the function GDKerrorCount();@{@cint GDKsilent = 0;static int THRerrorcount[THREADDATA];/* do the real work for GDKaddbuf below. */static void

⌨️ 快捷键说明

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