/* * 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. */ void * GDKmallocmax(size_t size, size_t *maxsize, int emergency) { ssize_t *s = NULL; if (size == 0) { #ifdef GDK_MEM_NULLALLOWED return NULL; #else GDKfatal("GDKmallocmax: called with size " SZFMT "", size); #endif } size = (size + 7) & ~7; /* round up to a multiple of eight */ GDKmalloc_prefixsize(s, size); if (s == NULL) { GDKmemfail("GDKmalloc", size); GDKmalloc_prefixsize(s, size); if (s == NULL) { if (emergency == 0) { GDKerror("GDKmallocmax: failed for " SZFMT " bytes", size); return NULL; } GDKfatal("GDKmallocmax: failed for " SZFMT " bytes", size); } else { THRprintf(GDKstdout, "#GDKmallocmax: recovery ok. Continuing..\n"); } } *maxsize = size; heapinc(size + MALLOC_EXTRA_SPACE); return (void *) s; }
ptr GDKreallocmax(void *blk, size_t size, size_t *maxsize, int emergency) { void *oldblk = blk; ssize_t oldsize = 0; size_t newsize; if (blk == NULL) { return GDKmallocmax(size, maxsize, emergency); } if (size == 0) { #ifdef GDK_MEM_NULLALLOWED GDKfree_(blk); *maxsize = 0; return NULL; #else GDKfatal("GDKreallocmax: called with size 0"); #endif } size = (size + 7) & ~7; /* round up to a multiple of eight */ oldsize = GDK_MEM_BLKSIZE(blk); /* check against duplicate free */ assert((oldsize & 2) == 0); newsize = size + MALLOC_EXTRA_SPACE; blk = realloc(((char *) blk) - MALLOC_EXTRA_SPACE, newsize + GLIBC_BUG); if (blk == NULL) { GDKmemfail("GDKrealloc", newsize); blk = realloc(((char *) oldblk) - MALLOC_EXTRA_SPACE, newsize); if (blk == NULL) { if (emergency == 0) { GDKerror("GDKreallocmax: failed for " SZFMT " bytes", newsize); return NULL; } GDKfatal("GDKreallocmax: failed for " SZFMT " bytes", newsize); } else { THRprintf(GDKstdout, "#GDKremallocmax: " "recovery ok. Continuing..\n"); } } /* place MALLOC_EXTRA_SPACE bytes before it */ assert((((size_t) blk) & 4) == 0); blk = ((char *) blk) + MALLOC_EXTRA_SPACE; ((ssize_t *) blk)[-1] = (ssize_t) newsize; /* adapt statistics */ heapinc(newsize); heapdec(oldsize); *maxsize = size; return blk; }
/* * @+ Concurrency control * Concurrency control requires actions at several levels of the * system. First, it should be ensured that each database is * controlled by a single server 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 directory for improved speed. * * Before the locks and threads are initiated, we cannot use the * normal routines yet. So we have a local fatal here instead of * GDKfatal. */ static void GDKlockHome(void) { char *p = 0, buf[1024], host[PATHLENGTH]; /* * Go there and obtain the global database lock. */ if (chdir(GDKdbpathStr) < 0) { char GDKdirStr[PATHLENGTH]; /* The DIR_SEP at the end of the path is needed for a * successful call to GDKcreatedir */ snprintf(GDKdirStr, PATHLENGTH, "%s%c", GDKdbpathStr, DIR_SEP); if (!GDKcreatedir(GDKdirStr)) GDKfatal("GDKlockHome: could not create %s\n", GDKdbpathStr); if (chdir(GDKdbpathStr) < 0) GDKfatal("GDKlockHome: could not move to %s\n", GDKdbpathStr); IODEBUG THRprintf(GDKstdout, "#GDKlockHome: created directory %s\n", GDKdbpathStr); } 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 { IODEBUG THRprintf(GDKstdout, "#GDKlockHome: ignoring empty or invalid %s.\n", GDKLOCK); host[0] = 0; } /* * We have the lock, are the only process currently allowed in * this section. */ MT_init(); OIDinit(); /* * Print the new process list in the global lock file. */ fseek(GDKlockFile, 0, SEEK_SET); if (ftruncate(fileno(GDKlockFile), 0) < 0) GDKfatal("GDKlockHome: Could not truncate %s\n", GDKLOCK); fflush(GDKlockFile); GDKlog(GDKLOGON); /* * In shared mode, we allow more parties to join. Release the lock. * No need yet to use GDKstoppedLock: there are no other threads. */ ATOMIC_SET_int(GDKstopped, 0, GDKstoppedLock, ""); }
static void tstAligned(void) { #ifdef STRUCT_ALIGNED int allAligned=0; ValRecord v; ptr val, base; base = (ptr) & v.val.ival; val= (ptr) & v.val.bval; if(val != base){ allAligned = -1; } val= (ptr) & v.val.btval; if(val != base){ allAligned = -1; } val= (ptr) & v.val.shval; if(val != base){ allAligned = -1; } val= (ptr) & v.val.bval; if(val != base){ allAligned = -1; } val= (ptr) & v.val.ival; if(val != base){ allAligned = -1; } val= (ptr) & v.val.oval; if(val != base){ allAligned = -1; } val= (ptr) & v.val.pval; if(val != base){ allAligned = -1; } val= (ptr) & v.val.fval; if(val != base){ allAligned = -1; } val= (ptr) & v.val.dval; if(val != base){ allAligned = -1; } val= (ptr) & v.val.lval; if(val != base){ allAligned = -1; } #ifdef HAVE_HGE val= (ptr) & v.val.hval; if(val != base){ allAligned = -1; } #endif val= (ptr) & v.val.sval; if(val != base){ allAligned = -1; } if(allAligned<0) GDKfatal("Recompile with STRUCT_ALIGNED flag disabled\n"); #endif }
MalStkPtr newGlobalStack(int size) { MalStkPtr s; s = (MalStkPtr) GDKzalloc(stackSize(size) + offsetof(MalStack, stk)); if (s == NULL) GDKfatal("newGlobalStack:can not obtain memory\n"); s->stksize = size; return s; }
void THRdel(Thread t) { if (t < GDKthreads || t > GDKthreads + THREADS) { GDKfatal("THRdel: illegal call\n"); } MT_lock_set(&GDKthreadLock, "THRdel"); /* The stream may haven been closed (e.g. in freeClient) causing an abort PARDEBUG THRprintf(GDKstdout, "#pid = " SZFMT ", disconnected, %d left\n", (size_t) t->pid, GDKnrofthreads); */ t->pid = 0; GDKnrofthreads--; MT_lock_unset(&GDKthreadLock, "THRdel"); }
/* release all savepoints up including the given named savepoint * but keep the current changes. * */ int mvc_release(mvc *m, const char *name) { int ok = SQL_OK; int res = Q_TRANS; sql_trans *tr = m->session->tr; assert(tr); assert(m->session->active); /* only release active transactions */ if (mvc_debug) fprintf(stderr, "#mvc_release %s\n", (name) ? name : ""); if (!name) mvc_rollback(m, 0, name); while (tr && (!tr->name || strcmp(tr->name, name) != 0)) tr = tr->parent; if (!tr || !tr->name || strcmp(tr->name, name) != 0) { (void)sql_error(m, 010, "release savepoint %s doesn't exists", name); m->session->status = -1; return -1; } tr = m->session->tr; store_lock(); while (ok == SQL_OK && (!tr->name || strcmp(tr->name, name) != 0)) { /* commit all intermediate savepoints */ if (sql_trans_commit(tr) != SQL_OK) GDKfatal("release savepoints should not fail"); tr = sql_trans_destroy(tr); } tr->name = NULL; store_unlock(); m->session->tr = tr; m->session->schema = find_sql_schema(m->session->tr, m->session->schema_name); m->type = res; return res; }
int GDKinit(opt *set, int setlen) { char *dbpath = mo_find_option(set, setlen, "gdk_dbpath"); char *p; opt *n; int i, j, nlen = 0; char buf[16]; /* some sanity checks (should also find if symbols are not defined) */ assert(sizeof(char) == SIZEOF_CHAR); assert(sizeof(short) == SIZEOF_SHORT); assert(sizeof(int) == SIZEOF_INT); assert(sizeof(long) == SIZEOF_LONG); assert(sizeof(lng) == SIZEOF_LNG); assert(sizeof(oid) == SIZEOF_OID); assert(sizeof(void *) == SIZEOF_VOID_P); assert(sizeof(wrd) == SIZEOF_WRD); assert(sizeof(size_t) == SIZEOF_SIZE_T); assert(sizeof(ptrdiff_t) == SIZEOF_PTRDIFF_T); assert(SIZEOF_OID == SIZEOF_INT || SIZEOF_OID == SIZEOF_LNG); #ifdef NEED_MT_LOCK_INIT MT_lock_init(&MT_system_lock,"MT_system_lock"); ATOMIC_INIT(GDKstoppedLock, "GDKstoppedLock"); ATOMIC_INIT(mbyteslock, "mbyteslock"); MT_lock_init(&GDKnameLock, "GDKnameLock"); MT_lock_init(&GDKthreadLock, "GDKthreadLock"); MT_lock_init(&GDKtmLock, "GDKtmLock"); #endif for (i = 0; i <= BBP_BATMASK; i++) { MT_lock_init(&GDKbatLock[i].swap, "GDKswapLock"); MT_lock_init(&GDKbatLock[i].hash, "GDKhashLock"); MT_lock_init(&GDKbatLock[i].imprints, "GDKimprintsLock"); } for (i = 0; i <= BBP_THREADMASK; i++) { MT_lock_init(&GDKbbpLock[i].alloc, "GDKcacheLock"); MT_lock_init(&GDKbbpLock[i].trim, "GDKtrimLock"); GDKbbpLock[i].free = 0; } errno = 0; if (!GDKenvironment(dbpath)) return 0; if ((p = mo_find_option(set, setlen, "gdk_debug"))) GDKdebug = strtol(p, NULL, 10); if ((p = mo_find_option(set, setlen, "gdk_mem_pagebits"))) GDK_mem_pagebits = (int) strtol(p, NULL, 10); mnstr_init(); MT_init_posix(); THRinit(); #ifndef NATIVE_WIN32 BATSIGinit(); #endif #ifdef WIN32 (void) signal(SIGABRT, BATSIGabort); _set_abort_behavior(0, _CALL_REPORTFAULT | _WRITE_ABORT_MSG); _set_error_mode(_OUT_TO_STDERR); #endif GDKlockHome(); /* Mserver by default takes 80% of all memory as a default */ GDK_mem_maxsize = GDK_mem_maxsize_max = (size_t) ((double) MT_npages() * (double) MT_pagesize() * 0.815); #ifdef NATIVE_WIN32 GDK_mmap_minsize = GDK_mem_maxsize_max; #else GDK_mmap_minsize = MIN( 1<<30 , GDK_mem_maxsize_max/6 ); /* per op: 2 args + 1 res, each with head & tail => (2+1)*2 = 6 ^ */ #endif GDK_mem_bigsize = 1024*1024; GDKremovedir(DELDIR); BBPinit(); HEAPcacheInit(); GDKkey = BATnew(TYPE_void, TYPE_str, 100); GDKval = BATnew(TYPE_void, TYPE_str, 100); if (GDKkey == NULL) GDKfatal("GDKinit: Could not create environment BAT"); if (GDKval == NULL) GDKfatal("GDKinit: Could not create environment BAT"); BATseqbase(GDKkey,0); BATkey(GDKkey, BOUND2BTRUE); BATrename(GDKkey, "environment_key"); BATmode(GDKkey, TRANSIENT); BATseqbase(GDKval,0); BATkey(GDKval, BOUND2BTRUE); BATrename(GDKval, "environment_val"); BATmode(GDKval, TRANSIENT); n = (opt *) malloc(setlen * sizeof(opt)); for (i = 0; i < setlen; i++) { int done = 0; for (j = 0; j < nlen; j++) { if (strcmp(n[j].name, set[i].name) == 0) { if (n[j].kind < set[i].kind) { n[j] = set[i]; } done = 1; break; } } if (!done) { n[nlen] = set[i]; nlen++; } } for (i = 0; i < nlen; i++) GDKsetenv(n[i].name, n[i].value); free(n); if ((p = GDKgetenv("gdk_dbpath")) != NULL && (p = strrchr(p, DIR_SEP)) != NULL) { GDKsetenv("gdk_dbname", p + 1); #if DIR_SEP != '/' /* on Windows look for different separator */ } else if ((p = GDKgetenv("gdk_dbpath")) != NULL && (p = strrchr(p, '/')) != NULL) { GDKsetenv("gdk_dbname", p + 1); #endif } if ((p = GDKgetenv("gdk_mem_maxsize"))) { GDK_mem_maxsize = MAX(1 << 26, (size_t) strtoll(p, NULL, 10)); } if ((p = GDKgetenv("gdk_vm_maxsize"))) { GDK_vm_maxsize = MAX(1 << 30, (size_t) strtoll(p, NULL, 10)); } if ((p = GDKgetenv("gdk_mem_bigsize"))) { /* when allocating >6% of all RAM; do so using * vmalloc() iso malloc() */ lng max_mem_bigsize = GDK_mem_maxsize_max / 16; /* sanity check to avoid memory fragmentation */ GDK_mem_bigsize = (size_t) MIN(max_mem_bigsize, strtoll(p, NULL, 10)); } if ((p = GDKgetenv("gdk_mmap_minsize"))) { GDK_mmap_minsize = MAX(REMAP_PAGE_MAXSIZE, (size_t) strtoll(p, NULL, 10)); } if (GDKgetenv("gdk_mem_pagebits") == NULL) { snprintf(buf, sizeof(buf), "%d", GDK_mem_pagebits); GDKsetenv("gdk_mem_pagebits", buf); } if (GDKgetenv("gdk_mem_bigsize") == NULL) { snprintf(buf, sizeof(buf), SZFMT, GDK_mem_bigsize); GDKsetenv("gdk_mem_bigsize", buf); } if (GDKgetenv("monet_pid") == NULL) { snprintf(buf, sizeof(buf), "%d", (int) getpid()); GDKsetenv("monet_pid", buf); } GDKnr_threads = GDKgetenv_int("gdk_nr_threads", 0); if (GDKnr_threads == 0) GDKnr_threads = MT_check_nr_cores(); #ifdef NATIVE_WIN32 GDK_mmap_minsize /= (GDKnr_threads ? GDKnr_threads : 1); #else /* WARNING: This unconditionally overwrites above settings, */ /* incl. setting via MonetDB env. var. "gdk_mmap_minsize" ! */ GDK_mmap_minsize = MIN( 1<<30 , (GDK_mem_maxsize_max/6) / (GDKnr_threads ? GDKnr_threads : 1) ); /* per op: 2 args + 1 res, each with head & tail => (2+1)*2 = 6 ^ */ #endif if ((p = mo_find_option(set, setlen, "gdk_vmtrim")) == NULL || strcasecmp(p, "yes") == 0) MT_create_thread(&GDKvmtrim_id, GDKvmtrim, &GDK_mem_maxsize, MT_THR_JOINABLE); return 1; }
int main(int argc, char **av) { char *prog = *av; opt *set = NULL; int idx = 0, grpdebug = 0, debug = 0, setlen = 0, listing = 0, i = 0; str dbinit = NULL; str err = MAL_SUCCEED; char prmodpath[1024]; char *modpath = NULL; char *binpath = NULL; str *monet_script; static struct option long_options[] = { { "config", 1, 0, 'c' }, { "dbpath", 1, 0, 0 }, { "dbinit", 1, 0, 0 }, { "debug", 2, 0, 'd' }, { "help", 0, 0, '?' }, { "version", 0, 0, 0 }, { "readonly", 0, 0, 'r' }, { "set", 1, 0, 's' }, { "threads", 0, 0, 0 }, { "memory", 0, 0, 0 }, { "properties", 0, 0, 0 }, { "io", 0, 0, 0 }, { "transactions", 0, 0, 0 }, { "trace", 2, 0, 't' }, { "modules", 0, 0, 0 }, { "algorithms", 0, 0, 0 }, { "optimizers", 0, 0, 0 }, { "performance", 0, 0, 0 }, #if 0 { "xproperties", 0, 0, 0 }, #endif { "forcemito", 0, 0, 0 }, { "heaps", 0, 0, 0 }, { 0, 0, 0, 0 } }; #if defined(_MSC_VER) && defined(__cplusplus) set_terminate(mserver_abort); #endif if (setlocale(LC_CTYPE, "") == NULL) { GDKfatal("cannot set locale\n"); } #ifdef HAVE_MALLOPT if (malloc_init) { /* for (Red Hat) Linux (6.2) unused and ignored at least as of glibc-2.1.3-15 */ /* for (Red Hat) Linux (8) used at least as of glibc-2.2.93-5 */ if (mallopt(M_MXFAST, 192)) { fprintf(stderr, "!monet: mallopt(M_MXFAST,192) fails.\n"); } #ifdef M_BLKSZ if (mallopt(M_BLKSZ, 8 * 1024)) { fprintf(stderr, "!monet: mallopt(M_BLKSZ,8*1024) fails.\n"); } #endif } malloc_init = 0; #else (void) malloc_init; /* still unused */ #endif if (getcwd(monet_cwd, PATHLENGTH - 1) == NULL) { perror("pwd"); GDKfatal("monet_init: could not determine current directory\n"); } /* retrieve binpath early (before monet_init) because some * implementations require the working directory when the binary was * called */ binpath = get_bin_path(); if (!(setlen = mo_builtin_settings(&set))) usage(prog, -1); setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_single_user", "yes"); for (;;) { int option_index = 0; int c = getopt_long(argc, av, "c:d::rs:t::?", long_options, &option_index); if (c == -1) break; switch (c) { case 0: if (strcmp(long_options[option_index].name, "dbpath") == 0) { size_t optarglen = strlen(optarg); /* remove trailing directory separator */ while (optarglen > 0 && (optarg[optarglen - 1] == '/' || optarg[optarglen - 1] == '\\')) optarg[--optarglen] = '\0'; setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_dbpath", optarg); break; } if (strcmp(long_options[option_index].name, "dbinit") == 0) { if (dbinit) fprintf(stderr, "#warning: ignoring multiple --dbinit argument\n"); else dbinit = optarg; break; } if (strcmp(long_options[option_index].name, "version") == 0) { monet_version(); exit(0); } /* debugging options */ if (strcmp(long_options[option_index].name, "properties") == 0) { grpdebug |= GRPproperties; break; } if (strcmp(long_options[option_index].name, "algorithms") == 0) { grpdebug |= GRPalgorithms; break; } if (strcmp(long_options[option_index].name, "optimizers") == 0) { grpdebug |= GRPoptimizers; break; } #if 0 if (strcmp(long_options[option_index].name, "xproperties") == 0) { grpdebug |= GRPxproperties; break; } #endif if (strcmp(long_options[option_index].name, "forcemito") == 0) { grpdebug |= GRPforcemito; break; } if (strcmp(long_options[option_index].name, "performance") == 0) { grpdebug |= GRPperformance; break; } if (strcmp(long_options[option_index].name, "io") == 0) { grpdebug |= GRPio; break; } if (strcmp(long_options[option_index].name, "memory") == 0) { grpdebug |= GRPmemory; break; } if (strcmp(long_options[option_index].name, "modules") == 0) { grpdebug |= GRPmodules; break; } if (strcmp(long_options[option_index].name, "transactions") == 0) { grpdebug |= GRPtransactions; break; } if (strcmp(long_options[option_index].name, "threads") == 0) { grpdebug |= GRPthreads; break; } if (strcmp(long_options[option_index].name, "trace") == 0) { mal_trace = optarg? optarg:"ISTest"; break; } if (strcmp(long_options[option_index].name, "heaps") == 0) { grpdebug |= GRPheaps; break; } usage(prog, -1); /* not reached */ case 'c': setlen = mo_add_option(&set, setlen, opt_cmdline, "config", optarg); break; case 'd': if (optarg) { debug |= strtol(optarg, NULL, 10); } else { debug |= 1; } break; case 'r': setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_readonly", "yes"); break; case 's': { /* should add option to a list */ char *tmp = strchr(optarg, '='); if (tmp) { *tmp = '\0'; setlen = mo_add_option(&set, setlen, opt_cmdline, optarg, tmp + 1); } else fprintf(stderr, "ERROR: wrong format %s\n", optarg); } break; case 't': mal_trace = optarg? optarg:"ISTest"; break; case '?': /* a bit of a hack: look at the option that the current `c' is based on and see if we recognize it: if -? or --help, exit with 0, else with -1 */ usage(prog, strcmp(av[optind - 1], "-?") == 0 || strcmp(av[optind - 1], "--help") == 0 ? 0 : -1); default: fprintf(stderr, "ERROR: getopt returned character " "code '%c' 0%o\n", c, c); usage(prog, -1); } } if (!(setlen = mo_system_config(&set, setlen))) usage(prog, -1); if (debug || grpdebug) { long_str buf; if (debug) mo_print_options(set, setlen); debug |= grpdebug; /* add the algorithm tracers */ snprintf(buf, sizeof(long_str) - 1, "%d", debug); setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_debug", buf); } #ifdef RDEBUG printf("parameter ok\n"); #endif monet_script = (str *) malloc(sizeof(str) * (argc + 1)); if (monet_script) { monet_script[idx] = NULL; while (optind < argc) { monet_script[idx] = absolute_path(av[optind]); monet_script[idx + 1] = NULL; optind++; idx++; } } if (monet_init(set, setlen) == 0) { mo_free_options(set, setlen); return 0; } mo_free_options(set, setlen); #ifdef RDEBUG printf("monet_init ok\n"); #endif GDKsetenv("monet_version", VERSION); GDKsetenv("monet_release", MONETDB_RELEASE); if ((modpath = GDKgetenv("monet_mod_path")) == NULL) { /* start probing based on some heuristics given the binary * location: * bin/mserver5 -> ../ * libX/monetdb5/lib/ * probe libX = lib, lib32, lib64, lib/64 */ char *libdirs[] = { "lib", "lib64", "lib/64", "lib32", NULL }; size_t i; struct stat sb; if (binpath != NULL) { char *p = strrchr(binpath, DIR_SEP); if (p != NULL) *p = '\0'; p = strrchr(binpath, DIR_SEP); if (p != NULL) { *p = '\0'; for (i = 0; libdirs[i] != NULL; i++) { snprintf(prmodpath, sizeof(prmodpath), "%s%c%s%cmonetdb5", binpath, DIR_SEP, libdirs[i], DIR_SEP); if (stat(prmodpath, &sb) == 0) { modpath = prmodpath; break; } } } else { printf("#warning: unusable binary location, " "please use --set monet_mod_path=/path/to/... to " "allow finding modules\n"); fflush(NULL); } } else { printf("#warning: unable to determine binary location, " "please use --set monet_mod_path=/path/to/... to " "allow finding modules\n"); fflush(NULL); } if (modpath != NULL) GDKsetenv("monet_mod_path", modpath); } #ifdef RDEBUG printf("modpath ok\n"); #endif /* configure sabaoth to use the right dbpath and active database */ msab_dbpathinit(GDKgetenv("gdk_dbpath")); /* wipe out all cruft, if left over */ if ((err = msab_wildRetreat()) != NULL) { /* just swallow the error */ free(err); } /* From this point, the server should exit cleanly. Discussion: * even earlier? Sabaoth here registers the server is starting up. */ if ((err = msab_registerStarting()) != NULL) { /* throw the error at the user, but don't die */ fprintf(stderr, "!%s\n", err); free(err); } #ifdef RDEBUG printf("some stuff\n"); #endif #ifdef HAVE_SIGACTION { struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = handler; if ( sigaction(SIGINT, &sa, NULL) == -1 || sigaction(SIGQUIT, &sa, NULL) == -1 || sigaction(SIGTERM, &sa, NULL) == -1) { fprintf(stderr, "!unable to create signal handlers\n"); } } #else signal(SIGINT, handler); #ifdef SIGQUIT signal(SIGQUIT, handler); #endif signal(SIGTERM, handler); #endif { str lang = "mal"; /* we inited mal before, so publish its existence */ if ((err = msab_marchScenario(lang)) != NULL) { /* throw the error at the user, but don't die */ fprintf(stderr, "!%s\n", err); free(err); } } #ifdef RDEBUG printf("scenario ok\n"); #endif { /* unlock the vault, first see if we can find the file which * holds the secret */ char secret[1024]; char *secretp = secret; FILE *secretf; size_t len; if (GDKgetenv("monet_vault_key") == NULL) { /* use a default (hard coded, non safe) key */ snprintf(secret, sizeof(secret), "%s", "Xas632jsi2whjds8"); } else { if ((secretf = fopen(GDKgetenv("monet_vault_key"), "r")) == NULL) { snprintf(secret, sizeof(secret), "unable to open vault_key_file %s: %s", GDKgetenv("monet_vault_key"), strerror(errno)); /* don't show this as a crash */ msab_registerStop(); GDKfatal("%s", secret); } len = fread(secret, 1, sizeof(secret), secretf); secret[len] = '\0'; len = strlen(secret); /* secret can contain null-bytes */ if (len == 0) { snprintf(secret, sizeof(secret), "vault key has zero-length!"); /* don't show this as a crash */ msab_registerStop(); GDKfatal("%s", secret); } else if (len < 5) { fprintf(stderr, "#warning: your vault key is too short " "(" SZFMT "), enlarge your vault key!\n", len); } fclose(secretf); } if ((err = AUTHunlockVault(&secretp)) != MAL_SUCCEED) { /* don't show this as a crash */ msab_registerStop(); GDKfatal("%s", err); } } /* make sure the authorisation BATs are loaded */ if ((err = AUTHinitTables()) != MAL_SUCCEED) { /* don't show this as a crash */ msab_registerStop(); GDKfatal("%s", err); } #ifdef RDEBUG printf("vaultkey ok\n"); #endif if (mal_init()) { /* don't show this as a crash */ msab_registerStop(); return 0; } #ifdef RDEBUG printf("mal_init ok\n"); #endif #if (0) if (!loadLibrary("lib_leaker", TRUE)) return 42; #endif #ifdef RDEBUG printf("lib_leaker ok\n"); #endif if (GDKgetenv("mal_listing")) sscanf(GDKgetenv("mal_listing"), "%d", &listing); MSinitClientPrg(mal_clients, "user", "main"); if (dbinit == NULL) dbinit = GDKgetenv("dbinit"); if (dbinit) callString(mal_clients, dbinit, listing); #ifdef RDEBUG printf("MSinitClientPrg ok\n"); #endif emergencyBreakpoint(); if ((err = compileOptimizer(mal_clients, "leaker_pipe")) != MAL_SUCCEED) mnstr_printf(mal_clients->fdout, "OPT_COMPILE: %s\n", err); //callString(mal_clients, "sql.start();\n", 0); if (monet_script) for (i = 0; monet_script[i]; i++) { str msg = evalFile(mal_clients, monet_script[i], listing); /* check for internal exception message to terminate */ if (msg) { if (strcmp(msg, "MALException:client.quit:Server stopped.") == 0) mal_exit(); fprintf(stderr, "#%s: %s\n", monet_script[i], msg); GDKfree(msg); } GDKfree(monet_script[i]); monet_script[i] = 0; } if ((err = msab_registerStarted()) != NULL) { /* throw the error at the user, but don't die */ fprintf(stderr, "!%s\n", err); free(err); } if (monet_script) free(monet_script); MSserveClient(mal_clients); /* mal_exit calls MT_global_exit, so statements after this call will * never get reached */ mal_exit(); return 0; }
int mvc_commit(mvc *m, int chain, const char *name) { sql_trans *cur, *tr = m->session->tr; int ok = SQL_OK;//, wait = 0; assert(tr); assert(m->session->active); /* only commit an active transaction */ if (mvc_debug) fprintf(stderr, "#mvc_commit %s\n", (name) ? name : ""); if (m->session->status < 0) { (void)sql_error(m, 010, "40000!COMMIT: transaction is aborted, will ROLLBACK instead"); mvc_rollback(m, chain, name); return -1; } /* savepoint then simply make a copy of the current transaction */ if (name && name[0] != '\0') { sql_trans *tr = m->session->tr; if (mvc_debug) fprintf(stderr, "#mvc_savepoint\n"); store_lock(); m->session->tr = sql_trans_create(m->session->stk, tr, name); store_unlock(); m->type = Q_TRANS; if (m->qc) /* clean query cache, protect against concurrent access on the hash tables (when functions already exists, concurrent mal will build up the hash (not copied in the trans dup)) */ qc_clean(m->qc); m->session->schema = find_sql_schema(m->session->tr, m->session->schema_name); if (mvc_debug) fprintf(stderr, "#mvc_commit %s done\n", name); return 0; } /* first release all intermediate savepoints */ cur = tr; tr = tr->parent; if (tr->parent) { store_lock(); while (tr->parent != NULL && ok == SQL_OK) { tr = sql_trans_destroy(tr); } store_unlock(); } cur -> parent = tr; tr = cur; store_lock(); /* if there is nothing to commit reuse the current transaction */ if (tr->wtime == 0) { if (!chain) sql_trans_end(m->session); m->type = Q_TRANS; if (mvc_debug) fprintf(stderr, "#mvc_commit %s done\n", (name) ? name : ""); store_unlock(); return 0; } /* while (tr->schema_updates && store_nr_active > 1) { store_unlock(); MT_sleep_ms(100); wait += 100; if (wait > 1000) { (void)sql_error(m, 010, "40000!COMMIT: transaction is aborted because of DDL concurrency conflicts, will ROLLBACK instead"); mvc_rollback(m, chain, name); return -1; } store_lock(); } * */ /* validation phase */ if (sql_trans_validate(tr)) { if ((ok = sql_trans_commit(tr)) != SQL_OK) { char *msg = sql_message("40000!COMMIT: transaction commit failed (perhaps your disk is full?) exiting (kernel error: %s)", GDKerrbuf); GDKfatal("%s", msg); _DELETE(msg); } } else { store_unlock(); (void)sql_error(m, 010, "40000!COMMIT: transaction is aborted because of concurrency conflicts, will ROLLBACK instead"); mvc_rollback(m, chain, name); return -1; } sql_trans_end(m->session); if (chain) sql_trans_begin(m->session); store_unlock(); m->type = Q_TRANS; if (mvc_debug) fprintf(stderr, "#mvc_commit %s done\n", (name) ? name : ""); return ok; }
str instruction2str(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int flg) { int i, tab = 4; str base, s, t; size_t len= (mb->stop < 1000? 1000: mb->stop) * 128 /* max realistic line length estimate */; str arg; base = s = GDKmalloc(len); if ( s == NULL) return s; if (flg) { s[0] = 0; t = s; } else { s[0] = '#'; if (p->typechk == TYPE_UNKNOWN) { s[1] = '!'; /* error */ s[2] = 0; t = s + 2; } else { s[1] = 0; t = s + 1; } } advance(t,base,len); if (p->token == REMsymbol) { /* do nothing */ } else if (p->barrier) { if (p->barrier == LEAVEsymbol || p->barrier == REDOsymbol || p->barrier == RETURNsymbol || p->barrier == YIELDsymbol || p->barrier == RAISEsymbol) { for(;tab>0;tab--) *t++= ' '; *t= 0; advance(t,base,len); } snprintf(t,(len-(t-base)), "%s ", operatorName(p->barrier)); advance(t,base,len); } else if( functionStart(p) && flg != LIST_MAL_CALL ){ return fcnDefinition(mb, p, s, flg, base, len); } else if (!functionExit(p) && flg!=LIST_MAL_CALL) { // beautify with tabs for(;tab>0;tab--) *t++= ' '; *t= 0; advance(t,base,len); } switch (p->token<0?-p->token:p->token) { case FCNcall: case FACcall: case PATcall: case CMDcall: case ASSIGNsymbol : // is any variable explicit or used for (i = 0; i < p->retc; i++) if (!getVarTmp(mb, getArg(p, i)) || isVarUsed(mb, getArg(p, i)) || isVarUDFtype(mb,getArg(p,i))) break; if (i == p->retc) break; /* display multi-assignment list */ if (p->retc > 1) *t++ = '('; for (i = 0; i < p->retc; i++) { arg= renderTerm(mb, stk, p, i, flg); snprintf(t,(len-(t-base)), "%s", arg); GDKfree(arg); advance(t,base,len); if (i < p->retc - 1) *t++ = ','; } if (p->retc > 1) *t++ = ')'; if (p->argc > p->retc || getFunctionId(p)) { sprintf(t, " := "); t += 4; } *t = 0; break; case ENDsymbol: snprintf(t,(len-(t-base)), "end %s.%s", getModuleId(getInstrPtr(mb,0)), getFunctionId(getInstrPtr(mb, 0))); advance(t,base,len); break; case COMMANDsymbol: case FUNCTIONsymbol: case FACTORYsymbol: case PATTERNsymbol: if (flg & LIST_MAL_VALUE) { snprintf(t,(len-(t-base)), "%s ", operatorName(p->token)); advance(t,base,len); break; } return fcnDefinition(mb, p, s, flg, base, len); case REMsymbol: case NOOPsymbol: if(getVar(mb, getArg(p, 0))->value.val.sval) snprintf(t,(len-(t-base)), "#%s ", getVar(mb, getArg(p, 0))->value.val.sval); else snprintf(t, (len-(t-base)), "# "); break; default: snprintf(t, (len-(t-base))," unknown symbol ?%d? ", p->token); } advance(t,base,len); if (getModuleId(p)) snprintf(t, (len-(t-base)),"%s.", getModuleId(p)); advance(t,base,len); if (getFunctionId(p)) { snprintf(t, (len-(t-base)), "%s(", getFunctionId(p)); } else if (p->argc > p->retc + 1) snprintf(t, (len-(t-base)), "("); advance(t,base,len); for (i = p->retc; i < p->argc; i++) { arg= renderTerm(mb, stk, p, i, flg); snprintf(t,(len-(t-base)), "%s", arg); GDKfree(arg); advance(t,base,len); if (i < p->argc -1){ snprintf(t, (len-(t-base)), ","); advance(t,base,len); } } if (getFunctionId(p) || p->argc > p->retc + 1) snprintf(t,(len-(t-base)), ")"); advance(t,base,len); if (p->token != REMsymbol){ snprintf(t,(len-(t-base)), ";"); advance(t,base,len); } /* we may accidentally overwrite */ if (t > s + len) GDKfatal("instruction2str:"); return base; }