📄 mal_sabaoth.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 + -