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

📄 mal_sabaoth.c

📁 一个内存数据库的源代码这是服务器端还有客户端
💻 C
字号:
#line 39 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/mal/mal_sabaoth.mx"#include "mal_config.h"#include "mal_sabaoth.h"#include <stdio.h> /* fseek, rewind */#include <unistd.h>	/* unlink and friends */#include <errno.h>#include <string.h> /* for getting error messages */#include <assert.h>/** the directory where the databases are (aka dbfarm) */str _sabaoth_internal_dbfarm = NULL;/** the database which is "active" */str _sabaoth_internal_dbname = NULL;static str getFarmPath(str *ret, size_t size, str extra) {	if (_sabaoth_internal_dbfarm == NULL)		throw(MAL, "sabaoth.assert", "Sabaoth was not initialised!");	if (extra == NULL) {		snprintf(*ret, size, "%s", _sabaoth_internal_dbfarm);	} else {		snprintf(*ret, size, "%s%c%s", _sabaoth_internal_dbfarm, DIR_SEP, extra);	}	return(MAL_SUCCEED);}static str getDBPath(str *ret, size_t size, str extra) {	if (_sabaoth_internal_dbfarm == NULL)		throw(MAL, "sabaoth.assert", "Sabaoth was not initialised!");	if (_sabaoth_internal_dbname == NULL)		throw(MAL, "sabaoth.assert", "Cannot use this function when no database is active");	if (extra == NULL) {		snprintf(*ret, size, "%s%c%s",				_sabaoth_internal_dbfarm,				DIR_SEP,				_sabaoth_internal_dbname);	} else {		snprintf(*ret, size, "%s%c%s%c%s",				_sabaoth_internal_dbfarm,				DIR_SEP,				_sabaoth_internal_dbname,				DIR_SEP,				extra);	}	return(MAL_SUCCEED);}#line 92 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/mal/mal_sabaoth.mx"/** * Initialises this Sabaoth instance to use the given dbfarm and dbname. * dbfarm may be NULL to indicate that there is no active database.  The * arguments are copied for internal use. */void SABAOTHinit(str dbfarm, str dbname) {	size_t len;	assert(dbfarm != NULL);	if (_sabaoth_internal_dbfarm != NULL)		free(_sabaoth_internal_dbfarm);	if (_sabaoth_internal_dbname != NULL)		free(_sabaoth_internal_dbname);	len = strlen(dbfarm) + 1;	_sabaoth_internal_dbfarm = malloc(sizeof(char) * (len));	memcpy(_sabaoth_internal_dbfarm, dbfarm, len);	/* remove trailing slashes */	while (len > 0 && _sabaoth_internal_dbfarm[len - 1] == '/') {		_sabaoth_internal_dbfarm[len - 1] = '\0';		len--;	}	if (dbname == NULL) {		_sabaoth_internal_dbname = NULL;	} else {		len = strlen(dbname) + 1;		_sabaoth_internal_dbname = malloc(sizeof(char) * (len));		memcpy(_sabaoth_internal_dbname, dbname, len);	}}#line 128 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/mal/mal_sabaoth.mx"#define SCENARIOFILE ".scen"/** * Writes the given language to the scenarios file.  If the file doesn't * exist, it is created.  Multiple invocations of this function for the * same language are ignored. */str SABAOTHmarchScenario(int *ret, str *lang) {	FILE *f;	str buf = alloca(sizeof(char) * 256);	/* should be enough for now */	int len;	str path = alloca(sizeof(char) * (PATHLENGTH + 1));	str tmp;	(void)ret;	rethrow("sabaoth.marchScenario", tmp,			getDBPath(&path, PATHLENGTH, SCENARIOFILE));	if ((f = fopen(path, "a+")) != NULL) {		if ((len = fread(buf, 1, 255, f)) > 0) {			str p;			buf[len] = '\0';			/* find newlines and evaluate string */			while ((p = strchr(buf, '\n')) != NULL) {				*p = '\0';				if (strcmp(buf, *lang) == 0) {					(void)fclose(f);					return(MAL_SUCCEED);				}				buf = p;			}		}		/* append to the file */		fprintf(f, "%s\n", *lang);		(void)fflush(f);		(void)fclose(f);		return(MAL_SUCCEED);	}	throw(IO, "sabaoth.marchScenario", "unable to open file %s", path);}#line 171 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/mal/mal_sabaoth.mx"/** * Removes the given language from the scenarios file.  If the scenarios * file is empty (before or) after removing the language, the file is * removed. */str SABAOTHretreatScenario(int *ret, str *lang) {	FILE *f;	str buf = alloca(sizeof(char) * 256);	/* should be enough for now */	int len;	str path = alloca(sizeof(char) * (PATHLENGTH + 1));	str tmp;	(void)ret;	rethrow("sabaoth.retreatScenario", tmp,			getDBPath(&path, PATHLENGTH, SCENARIOFILE));	if ((f = fopen(path, "a+")) != NULL) {		if ((len = fread(buf, 1, 255, f)) > 0) {			str p;			FILE *tmp = tmpfile();			int written = 0;			buf[len] = '\0';			/* find newlines and evaluate string */			while ((p = strchr(buf, '\n')) != NULL) {				*p = '\0';				if (strcmp(buf, *lang) != 0) {					fprintf(tmp, "%s\n", buf);					written = 1;				}				buf = p;			}			if (written != 0) {				buf = alloca(sizeof(char) * 256);				/* no idea how to "move" a file by it's fd (sounds				 * impossible anyway) and tmpnam is so much "DO NOT USE"				 * that I decided to just copy over the file again... */				rewind(f);				fflush(tmp);				rewind(tmp);				len = fread(buf, 1, 256, tmp);				fwrite(buf, 1, len, f);				fflush(f);				fclose(f);				fclose(tmp); /* this should remove it automagically */				return(MAL_SUCCEED);			} else {				(void)fclose(f);				unlink(path);				return(MAL_SUCCEED);			}		} else if (len == 0) {			(void)fclose(f);			unlink(path);			return(MAL_SUCCEED);		} else { /* some error */			str err = strerror(errno);			(void)fclose(f);			throw(IO, "sabaoth.retreatScenario",					"error while reading from file: %s", err);		}	}	throw(IO, "sabaoth.retreatScenario", "unable to open file %s", path);}#line 238 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/mal/mal_sabaoth.mx"#define CONNECTIONFILE ".conn"/** * Writes an URI to the connection file based on the given arguments. * If the file doesn't exist, it is created.  Multiple invocations of * this function for the same arguments are NOT ignored. */str SABAOTHmarchConnection(int *ret, str *host, int *port, bit *ssl) {	FILE *f;	str path = alloca(sizeof(char) * (PATHLENGTH + 1));	str tmp;	(void)ret;	rethrow("sabaoth.marchConnection", tmp,			getDBPath(&path, PATHLENGTH, CONNECTIONFILE));	if ((f = fopen(path, "a")) != NULL) {		/* append to the file */		fprintf(f, "mapi%s:monetdb://%s:%i/\n", *ssl ? "s" : "", *host, *port);		(void)fflush(f);		(void)fclose(f);		return(MAL_SUCCEED);	}	throw(IO, "sabaoth.marchConnection",			"unable to open file %s", path);}#line 266 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/mal/mal_sabaoth.mx"/** * Removes all known publications of available services.  The function * name is a nostalgic phrase from "Defender of the Crown" from the * Commodore Amiga age. */str SABAOTHwildRetreat(int *ret) {	str path = alloca(sizeof(char) * (PATHLENGTH + 1));	str tmp;	(void)ret;	rethrow("sabaoth.wildRetreat", tmp,			getDBPath(&path, PATHLENGTH, SCENARIOFILE));	unlink(path);	rethrow("sabaoth.wildRetreat", tmp,			getDBPath(&path, PATHLENGTH, CONNECTIONFILE));	unlink(path);	return(MAL_SUCCEED);}#line 289 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/mal/mal_sabaoth.mx"#define UPLOGFILE ".uplog"/** * Writes a start attempt to the sabaoth start/stop log.  Examination of * the log at a later stage might reveal crashes of the server. */str SABAOTHregisterStart(int *ret) {	/* The sabaoth uplog is in fact a simple two column table that	 * contains a start time and a stop time.  Start times are followed	 * by a tab character, while stop times are followed by a newline.	 * This allows to detect crashes, while sabaoth only appends to the	 * uplog.	 */	FILE *f;	str path = alloca(sizeof(char) * (PATHLENGTH + 1));	str tmp;	(void)ret;	rethrow("sabaoth.registerStart", tmp,			getDBPath(&path, PATHLENGTH, UPLOGFILE));	if ((f = fopen(path, "a")) != NULL) {		/* append to the file */		fprintf(f, SZFMT "\t", (size_t)time(NULL));		(void)fflush(f);		(void)fclose(f);		return(MAL_SUCCEED);	}	throw(IO, "sabaoth.registerStart", "unable to open file %s", path);}#line 322 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/mal/mal_sabaoth.mx"/** * Writes a start attempt to the sabaoth start/stop log.  Examination of * the log at a later stage might reveal crashes of the server. */str SABAOTHregisterStop(int *ret) {	/* The sabaoth uplog is in fact a simple two column table that	 * contains a start time and a stop time.  Start times are followed	 * by a tab character, while stop times are followed by a newline.	 * This allows to detect crashes, while sabaoth only appends to the	 * uplog.	 */	FILE *f;	str path = alloca(sizeof(char) * (PATHLENGTH + 1));	str tmp;	(void)ret;	rethrow("sabaoth.registerStop", tmp,			getDBPath(&path, PATHLENGTH, UPLOGFILE));	if ((f = fopen(path, "a")) != NULL) {		/* append to the file */		fprintf(f, SZFMT "\n", (size_t)time(NULL));		(void)fflush(f);		(void)fclose(f);		return(MAL_SUCCEED);	}	throw(IO, "sabaoth.registerStop", "unable to open file %s", path);}#line 380 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB5/src/mal/mal_sabaoth.mx"/** */str SABAOTHgetStatus(sabdb** ret, str dbname) {	DIR *d;	struct dirent *e;	str buf = alloca(sizeof(char) * (PATHLENGTH + 1));	str data = alloca(sizeof(char) * 8096);	str path = alloca(sizeof(char) * (PATHLENGTH + 1));	str p;	int len;	FILE *f;	int fd;	sabdb* sdb = *ret;	sdb = NULL;	buf[PATHLENGTH] = '\0';	/* scan the parent for directories */	rethrow("sabaoth.getStatus", p,			getFarmPath(&path, PATHLENGTH, NULL));	d = opendir(path);	while ((e = readdir(d)) != NULL) {		if (dbname != NULL && strcmp(e->d_name, dbname) != 0)			continue;		sdb = malloc(sizeof(sabdb));		/* store the database name */		sdb->dbname = strdup(e->d_name);		/* add scenarios that are supported */		sdb->scens = NULL;		snprintf(buf, PATHLENGTH, "%s/%s/%s", path, e->d_name, SCENARIOFILE);		if ((f = fopen(buf, "r")) != NULL) {			if ((len = fread(data, 1, 8095, f)) > 0) {				sablist* np = NULL;				buf[len] = '\0';				while ((p = strchr(buf, '\n')) != NULL) {					*p = '\0';					if (sdb->scens == NULL) {						sdb->scens = malloc(sizeof(sablist));						sdb->scens->val = strdup(buf);						sdb->scens->next = NULL;						np = sdb->scens;					} else {						np = np->next = malloc(sizeof(sablist));						np->val = strdup(buf);						np->next = NULL;					}					buf = p + 1;				}				/* trailing stuff without an ending newline, is simply				 * not valid in Sabaoth, so we don't care */			}			(void)fclose(f);		}		/* add how this server can be reached */		sdb->conns = NULL;		snprintf(buf, PATHLENGTH, "%s/%s/%s", path, e->d_name, CONNECTIONFILE);		if ((f = fopen(buf, "r")) != NULL) {			if ((len = fread(data, 1, 8095, f)) > 0) {				sablist* np = NULL;				buf[len] = '\0';				while ((p = strchr(buf, '\n')) != NULL) {					*p = '\0';					if (sdb->conns == NULL) {						sdb->conns = malloc(sizeof(sablist));						sdb->conns->val = strdup(buf);						sdb->conns->next = NULL;						np = sdb->conns;					} else {						np = np->next = malloc(sizeof(sablist));						np->val = strdup(buf);						np->next = NULL;					}					buf = p + 1;				}				/* trailing stuff without an ending newline, is simply				 * not valid in Sabaoth, so we don't care */			}			(void)fclose(f);		}		/* check the state of the server by looking at its gdk lock:		 * - if we can lock it, the server has crashed or isn't running		 * - if we can't open it because it's locked, the server is		 *   running		 * - to distinguish between a crash and proper shutdown, consult		 *   the uplog		 */		snprintf(buf, PATHLENGTH, "%s/%s/%s", path, e->d_name, ".gdk_lock");		fd = MT_lockf(buf, F_TLOCK, 4, 1);		if (fd == -2) {			/* Locking failed; this can be because the lockfile couldn't			 * be created.  Probably there is no Mserver running for			 * that case also.			 */			sdb->state = SABdbInactive;		} else if (fd == -1) {			/* lock denied, so Mserver is running */			sdb->state = SABdbRunning;		} else {			char *log = alloca(sizeof(char) * (PATHLENGTH + 1));			log[PATHLENGTH] = '\0';			/* locking succeed, check for a crash in the uplog */			close(fd);			snprintf(log, PATHLENGTH, "%s/%s/%s", path, e->d_name, UPLOGFILE);			if ((f = fopen(log, "r")) != NULL) {				(void)fseek(f, -1, SEEK_END);				if (fread(data, 1, 1, f) != 1) {					/* the log is corrupt/wrong, assume no crash */					sdb->state = SABdbInactive;				} else if (data[0] == '\n') {					sdb->state = SABdbInactive;				} else { /* should be \t */					sdb->state = SABdbCrashed;				}				(void)fclose(f);			} else {				/* no uplog file? assume no crash */				sdb->state = SABdbInactive;			}			fd = MT_lockf(buf, F_ULOCK, 4, 1);			if (fd >= 0)				close(fd);		}	}	(void) closedir(d);	return(MAL_SUCCEED);}

⌨️ 快捷键说明

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