static void GDKvmtrim(void *limit) { int highload = 0; ssize_t prevmem = 0, prevrss = 0; (void) limit; do { int t; size_t rss; ssize_t rssdiff, memdiff; size_t cursize; /* sleep using catnaps so we can exit in a timely fashion */ for (t = highload ? 500 : 5000; t > 0; t -= CATNAP) { MT_sleep_ms(CATNAP); if (GDKexiting()) return; } rss = MT_getrss(); rssdiff = (ssize_t) rss - (ssize_t) prevrss; cursize = GDKvm_cursize(); memdiff = (ssize_t) cursize - (ssize_t) prevmem; MEMDEBUG THRprintf(GDKstdout, "alloc = " SZFMT " %+zd rss = " SZFMT " %+zd\n", cursize, memdiff, rss, rssdiff); prevmem = cursize; prevrss = rss; if (memdiff >= 0 && rssdiff < -32 * (ssize_t) MT_pagesize()) { BBPtrim(rss); highload = 1; } else { highload = 0; } } while (!GDKexiting()); }
void mal_exit(void){ str err; /* * Before continuing we should make sure that all clients * (except the console) have left the scene. */ MCstopClients(0); #if 0 { int reruns=0, go_on; do{ if ( (go_on = MCactiveClients()) ) MT_sleep_ms(1000); mnstr_printf(mal_clients->fdout,"#MALexit: %d clients still active\n", go_on); } while (++reruns < SERVERSHUTDOWNDELAY && go_on > 1); } #endif stopHeartbeat(); #ifdef HAVE_JSONSTORE stopHttpdaemon(); #endif stopMALdataflow(); stopProfiling(); RECYCLEdrop(mal_clients); /* remove any left over intermediates */ unloadLibraries(); #if 0 /* skip this to solve random crashes, needs work */ freeModuleList(mal_clients->nspace); finishNamespace(); if( mal_clients->prompt) GDKfree(mal_clients->prompt); if( mal_clients->errbuf) GDKfree(mal_clients->errbuf); if( mal_clients->bak) GDKfree(mal_clients->bak); if( mal_clients->fdin){ /* missing protection against closing stdin stream */ (void) mnstr_close(mal_clients->fdin->s); (void) bstream_destroy(mal_clients->fdin); } if( mal_clients->fdout && mal_clients->fdout != GDKstdout) { (void) mnstr_close(mal_clients->fdout); (void) mnstr_destroy(mal_clients->fdout); } #endif /* deregister everything that was registered, ignore errors */ if ((err = msab_wildRetreat()) != NULL) { fprintf(stderr, "!%s", err); free(err); } /* the server will now be shut down */ if ((err = msab_registerStop()) != NULL) { fprintf(stderr, "!%s", err); free(err); } GDKexit(0); /* properly end GDK */ }
str ALARMsleep(void *res, int *secs) { (void) res; /* fool compilers */ if (*secs < 0) throw(MAL, "alarm.sleep", "negative delay"); MT_sleep_ms(*secs * 1000); return MAL_SUCCEED; }
/* * Really really get the lock. Now!! */ static int GDKgetHome(void) { if (MT_pagesize() == 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) { IODEBUG THRprintf(GDKstdout, "#GDKgetHome: blocking on lock '%s'.\n", GDKLOCK); MT_lockf(GDKLOCK, F_LOCK, 4, 1); } return 1; }
str ALARMsleep(int *res, int *secs) { (void) res; /* fool compilers */ if (*secs < 0) throw(MAL, "alarm.sleep", "negative delay"); #ifdef __CYGWIN__ /* CYGWIN cannot handle SIGALRM with sleep */ { lng t = GDKusec() + (*secs)*1000000; while (GDKusec() < t) ; } #else MT_sleep_ms(*secs * 1000); #endif return MAL_SUCCEED; }
str SQLsession(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { str msg = MAL_SUCCEED; str logmsg; int cnt=0; (void) mb; (void) stk; (void) pci; if (SQLinitialized == 0 && (msg = SQLprelude(NULL)) != MAL_SUCCEED) return msg; msg = setScenario(cntxt, "sql"); // Wait for any recovery process to be finished do { MT_sleep_ms(1000); logmsg = GDKgetenv("recovery"); if( logmsg== NULL && ++cnt == 5) throw(SQL,"SQLinit","#WARNING server not ready, recovery in progress\n"); }while (logmsg == NULL); return msg; }
/* coverity[+kill] */ void GDKexit(int status) { if (ATOMIC_CAS_int(GDKstopped, 0, 1, GDKstoppedLock, "GDKexit") == 0) { MT_lock_set(&GDKthreadLock, "GDKexit"); GDKnrofthreads = 0; MT_lock_unset(&GDKthreadLock, "GDKexit"); if (GDKvmtrim_id) MT_join_thread(GDKvmtrim_id); MT_sleep_ms(CATNAP); /* 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(); #if 0 /* we can't clean up after killing threads */ BBPexit(); #endif GDKlog(GDKLOGOFF); GDKunlockHome(); #if !defined(ATOMIC_LOCK) && !defined(NDEBUG) TEMDEBUG GDKlockstatistics(1); #endif MT_global_exit(status); } }
int main(int argc, char **av) { char *prog = *av; opt *set = NULL; int i, grpdebug = 0, debug = 0, setlen = 0, listing = 0; str err = MAL_SUCCEED; char prmodpath[FILENAME_MAX]; const char *modpath = NULL; char *binpath = NULL; str *monet_script; char *dbpath = NULL; char *dbextra = NULL; int verbosity = 0; static struct option long_options[] = { { "config", required_argument, NULL, 'c' }, { "dbpath", required_argument, NULL, 0 }, { "dbextra", required_argument, NULL, 0 }, { "daemon", required_argument, NULL, 0 }, { "debug", optional_argument, NULL, 'd' }, { "help", no_argument, NULL, '?' }, { "version", no_argument, NULL, 0 }, { "verbose", optional_argument, NULL, 'v' }, { "readonly", no_argument, NULL, 'r' }, { "single-user", no_argument, NULL, 0 }, { "set", required_argument, NULL, 's' }, { "threads", no_argument, NULL, 0 }, { "memory", no_argument, NULL, 0 }, { "properties", no_argument, NULL, 0 }, { "io", no_argument, NULL, 0 }, { "transactions", no_argument, NULL, 0 }, { "trace", optional_argument, NULL, 't' }, { "modules", no_argument, NULL, 0 }, { "algorithms", no_argument, NULL, 0 }, { "optimizers", no_argument, NULL, 0 }, { "performance", no_argument, NULL, 0 }, { "forcemito", no_argument, NULL, 0 }, { "heaps", no_argument, NULL, 0 }, { NULL, 0, NULL, 0 } }; #if defined(_MSC_VER) && defined(__cplusplus) set_terminate(mserver_abort); #endif #ifdef _MSC_VER _CrtSetReportMode(_CRT_ERROR, 0); _CrtSetReportMode(_CRT_ASSERT, 0); _set_invalid_parameter_handler(mserver_invalid_parameter_handler); #ifdef _TWO_DIGIT_EXPONENT _set_output_format(_TWO_DIGIT_EXPONENT); #endif #endif if (setlocale(LC_CTYPE, "") == NULL) { fprintf(stderr, "cannot set locale\n"); exit(1); } if (getcwd(monet_cwd, FILENAME_MAX - 1) == NULL) { perror("pwd"); fprintf(stderr,"monet_init: could not determine current directory\n"); exit(-1); } /* 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); for (;;) { int option_index = 0; int c = getopt_long(argc, av, "c:d::rs:t::v::?", 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'; dbpath = absolute_path(optarg); if( dbpath == NULL) fprintf(stderr, "#error: can not allocate memory for dbpath\n"); else setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_dbpath", dbpath); break; } if (strcmp(long_options[option_index].name, "dbextra") == 0) { if (dbextra) fprintf(stderr, "#warning: ignoring multiple --dbextra arguments\n"); else dbextra = optarg; break; } #ifdef HAVE_CONSOLE if (strcmp(long_options[option_index].name, "daemon") == 0) { setlen = mo_add_option(&set, setlen, opt_cmdline, "monet_daemon", optarg); break; } #endif if (strcmp(long_options[option_index].name, "single-user") == 0) { setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_single_user", "yes"); 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 (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 = 1; break; } if (strcmp(long_options[option_index].name, "heaps") == 0) { grpdebug |= GRPheaps; break; } usage(prog, -1); /* not reached */ case 'c': /* coverity[var_deref_model] */ setlen = mo_add_option(&set, setlen, opt_cmdline, "config", optarg); break; case 'd': if (optarg) { char *endarg; debug |= strtol(optarg, &endarg, 10); if (*endarg != '\0') { fprintf(stderr, "ERROR: wrong format for --debug=%s\n", optarg); usage(prog, -1); } } 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 */ /* coverity[var_deref_model] */ 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 = 1; break; case 'v': if (optarg) { char *endarg; verbosity = (int) strtol(optarg, &endarg, 10); if (*endarg != '\0') { fprintf(stderr, "ERROR: wrong format for --verbose=%s\n", optarg); usage(prog, -1); } } else { verbosity++; } 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, (uint8_t) c); usage(prog, -1); } } if (!(setlen = mo_system_config(&set, setlen))) usage(prog, -1); GDKsetdebug(debug | grpdebug); /* add the algorithm tracers */ if (debug) mo_print_options(set, setlen); GDKsetverbose(verbosity); monet_script = (str *) malloc(sizeof(str) * (argc + 1)); if (monet_script == NULL) { fprintf(stderr, "!ERROR: cannot allocate memory for script \n"); exit(1); } i = 0; while (optind < argc) { monet_script[i] = absolute_path(av[optind]); if (monet_script[i] == NULL) { fprintf(stderr, "!ERROR: cannot allocate memory for script \n"); exit(1); } i++; optind++; } monet_script[i] = NULL; if (!dbpath) { dbpath = absolute_path(mo_find_option(set, setlen, "gdk_dbpath")); if (!dbpath) { fprintf(stderr, "!ERROR: cannot allocate memory for database directory \n"); exit(1); } } if (BBPaddfarm(dbpath, 1 << PERSISTENT) != GDK_SUCCEED || BBPaddfarm(dbextra ? dbextra : dbpath, 1 << TRANSIENT) != GDK_SUCCEED) { fprintf(stderr, "!ERROR: cannot add farm\n"); exit(1); } if (GDKcreatedir(dbpath) != GDK_SUCCEED) { fprintf(stderr, "!ERROR: cannot create directory for %s\n", dbpath); exit(1); } GDKfree(dbpath); if (monet_init(set, setlen) == 0) { mo_free_options(set, setlen); if (GDKerrbuf && *GDKerrbuf) fprintf(stderr, "%s\n", GDKerrbuf); exit(1); } mo_free_options(set, setlen); if (GDKsetenv("monet_version", GDKversion()) != GDK_SUCCEED || GDKsetenv("monet_release", #ifdef MONETDB_RELEASE MONETDB_RELEASE #else "unreleased" #endif ) != GDK_SUCCEED) { fprintf(stderr, "!ERROR: GDKsetenv failed\n"); exit(1); } 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 */ size_t pref; /* "remove" common prefix of configured BIN and LIB * directories from LIBDIR */ for (pref = 0; LIBDIR[pref] != 0 && BINDIR[pref] == LIBDIR[pref]; pref++) ; const char *libdirs[] = { &LIBDIR[pref], "lib", "lib64", "lib/64", "lib32", NULL, }; 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++) { int len = snprintf(prmodpath, sizeof(prmodpath), "%s%c%s%cmonetdb5", binpath, DIR_SEP, libdirs[i], DIR_SEP); if (len == -1 || len >= FILENAME_MAX) continue; 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) != GDK_SUCCEED) { fprintf(stderr, "!ERROR: GDKsetenv failed\n"); exit(1); } } /* 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 HAVE_SIGACTION { struct sigaction sa; (void) 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 #ifdef _MSC_VER if (!SetConsoleCtrlHandler(winhandler, TRUE)) fprintf(stderr, "!unable to create console control handler\n"); #else if(signal(SIGINT, handler) == SIG_ERR) fprintf(stderr, "!unable to create signal handlers\n"); #ifdef SIGQUIT if(signal(SIGQUIT, handler) == SIG_ERR) fprintf(stderr, "!unable to create signal handlers\n"); #endif if(signal(SIGTERM, handler) == SIG_ERR) fprintf(stderr, "!unable to create signal handlers\n"); #endif #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); } } { /* 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) { fprintf(stderr, "unable to open vault_key_file %s: %s\n", GDKgetenv("monet_vault_key"), strerror(errno)); /* don't show this as a crash */ msab_registerStop(); exit(1); } len = fread(secret, 1, sizeof(secret), secretf); secret[len] = '\0'; len = strlen(secret); /* secret can contain null-bytes */ if (len == 0) { fprintf(stderr, "vault key has zero-length!\n"); /* don't show this as a crash */ msab_registerStop(); exit(1); } else if (len < 5) { fprintf(stderr, "#warning: your vault key is too short " "(%zu), enlarge your vault key!\n", len); } fclose(secretf); } if ((err = AUTHunlockVault(secretp)) != MAL_SUCCEED) { /* don't show this as a crash */ msab_registerStop(); fprintf(stderr, "%s\n", err); freeException(err); exit(1); } } /* make sure the authorisation BATs are loaded */ if ((err = AUTHinitTables(NULL)) != MAL_SUCCEED) { /* don't show this as a crash */ msab_registerStop(); fprintf(stderr, "%s\n", err); freeException(err); exit(1); } if (mal_init()) { /* don't show this as a crash */ msab_registerStop(); return 0; } if((err = MSinitClientPrg(mal_clients, "user", "main")) != MAL_SUCCEED) { msab_registerStop(); fprintf(stderr, "%s\n", err); freeException(err); exit(1); } emergencyBreakpoint(); for (i = 0; monet_script[i]; i++) { str msg = evalFile(monet_script[i], listing); /* check for internal exception message to terminate */ if (msg) { if (strcmp(msg, "MALException:client.quit:Server stopped.") == 0) mal_exit(0); fprintf(stderr, "#%s: %s\n", monet_script[i], msg); freeException(msg); } GDKfree(monet_script[i]); monet_script[i] = 0; } free(monet_script); if ((err = msab_registerStarted()) != NULL) { /* throw the error at the user, but don't die */ fprintf(stderr, "!%s\n", err); free(err); } #ifdef HAVE_CONSOLE if (!monet_daemon) { MSserveClient(mal_clients); } else #endif while (!interrupted && !GDKexiting()) { MT_sleep_ms(100); } /* mal_exit calls exit, so statements after this call will * never get reached */ mal_exit(0); return 0; }
int main(int argc, char **argv) { int i; char *err = NULL; /*char name[MYBUFSIZ + 1];*/ char hostname[1024]; static SOCKET sockfd; Actuator ac = NULL; int option_index = 0; static struct option long_options[13] = { { "port", 1, 0, 'p' }, { "actuator", 1, 0, 'a' }, { "active", 0, 0, 'a' }, { "passive", 0, 0, 'p' }, { "statistics", 0, 0, 's' }, { "protocol", 1, 0, 'p' }, { "events", 1, 0, 'e' }, { "host", 1, 0, 'h' }, { "help", 1, 0, '?' }, { "timestamp", 0, 0, 't' }, { "trace", 0, 0, 't' }, { 0, 0, 0, 0 } }; THRdata[0] = (void *) file_wastream(stdout, "stdout"); THRdata[1] = (void *) file_rastream(stdin, "stdin"); for (i = 0; i < THREADS; i++) { GDKthreads[i].tid = i + 1; } for (;;) { /* int option_index=0;*/ int c = getopt_long(argc, argv, "p:a:a:p:s:p:e:h:?:t:t:0", long_options, &option_index); if (c == -1) break; switch (c) { case 't': if (strcmp(long_options[option_index].name, "trace") == 0) { trace = optarg ? atol(optarg) : 1; } else if (strcmp(long_options[option_index].name, "timestamp") == 0) { timestamp = optarg ? atol(optarg) : 1; } else { usage(); exit(0); } break; case 'e': if (strcmp(long_options[option_index].name, "events") == 0) { events = optarg ? atol(optarg) : 1; } else { usage(); exit(0); } break; case 'a': if (strcmp(long_options[option_index].name, "active") == 0) { mode = ACTIVE; break; } else actuator = optarg ? optarg : "dummy"; break; case 'p': if (strcmp(long_options[option_index].name, "port") == 0) { port = optarg ? atol(optarg) : -1; break; } else if (strcmp(long_options[option_index].name, "passive") == 0) { mode = PASSIVE; break; } else if (strcmp(long_options[option_index].name, "protocol") == 0) { if (strcmp(optarg, "TCP") == 0 || strcmp(optarg, "tcp") == 0) { protocol = TCP; break; } if (strcmp(optarg, "UDP") == 0 || strcmp(optarg, "udp") == 0) { protocol = UDP; break; } } break; case 's': if (strcmp(long_options[option_index].name, "statistics") == 0) { statistics = optarg ? atol(optarg) : 100; break; } else { usage(); exit(0); } break; case 'h': host = optarg; break; case '?': default: usage(); exit(0); } } signal(SIGABRT, stopListening); #ifdef SIGPIPE signal(SIGPIPE, stopListening); #endif #ifdef SIGHUP signal(SIGHUP, stopListening); #endif signal(SIGTERM, stopListening); signal(SIGINT, stopListening); /* display properties */ if (trace) { mnstr_printf(ACout, "--host=%s\n", host); mnstr_printf(ACout, "--port=%d\n", port); mnstr_printf(ACout, "--actuator=%s\n", actuator); mnstr_printf(ACout, "--events=%d\n", events); mnstr_printf(ACout, "--timestamp=%d\n", timestamp); mnstr_printf(ACout, "--statistics=%d\n", statistics); mnstr_printf(ACout, "--%s\n", mode == ACTIVE ? "active" : "passive"); } strncpy(hostname, host, 1024); if (strcmp(host, "localhost") == 0) gethostname(hostname, 1024); host = hostname; ac = ACnew(actuator); /*name[0] = 0;*/ err = NULL; if (mode == PASSIVE) { ac->fromServer = udp_rastream(host, port, actuator); if (ac->fromServer == 0) { mnstr_printf(ACout, "Failed to access stream %s:%d\n", host, port); return 0; } consumeStream(ac); #ifdef _DEBUG_ACTUATOR_ mnstr_printf(ACout, "stream consumed\n"); #endif } if (mode == ACTIVE) do { err = socket_client_connect(&sockfd, host, port); if (err) { mnstr_printf(ACout, "actuator connect fails: %s\n", err); MT_sleep_ms(1000); } } while (err); if (mode == PASSIVE) { err = socket_server_listen(sockfd, &(ac->newsockfd)); if (err) { mnstr_printf(ACout, "ACTUATOR:server listen fails:%s\n", err); return 0; } } do { if (mode == PASSIVE) { #ifdef _DEBUG_ACTUATOR_ mnstr_printf(ACout, "Actuator listens\n"); #endif if (protocol == UDP) ac->fromServer = udp_rastream(host, port, actuator); else ac->fromServer = socket_rastream(ac->newsockfd, actuator); if (ac->fromServer == NULL) { perror("Actuator: Could not open stream"); mnstr_printf(ACout, "stream %s.%d.%s\n", host, port, actuator); return 0; } consumeStream(ac); } else if (mode == ACTIVE) { #ifdef _DEBUG_ACTUATOR_ mnstr_printf(ACout, "Actuator connects\n"); #endif err = socket_client_connect(&(ac->newsockfd), host, port); if (err) { mnstr_printf(ACout, "ACTUATOR:start client:%s\n", err); continue; } #ifdef _DEBUG_ACTUATOR_ mnstr_printf(ACout, "Initialize stream\n"); #endif if (protocol == UDP) ac->fromServer = udp_rastream(host, port, actuator); else ac->fromServer = socket_rastream(ac->newsockfd, actuator); if (ac->fromServer == NULL) { perror("Actuator: Could not open stream"); mnstr_printf(ACout, "stream %s.%d.%s\n", host, port, actuator); continue; } } consumeStream(ac); } while (mode == PASSIVE && (events == -1 || tuples < events)); socket_close(sockfd); terminate(ac); return 0; }
static void produceDataStream(Sensor se) { char buf[MYBUFSIZ + 1], *tuple, *c, *d; FILE *fd; int i, snr; int multiply=1000, usec = 0; time_t lasttime = 0, tm = 0; struct tm stm; /* read a events of messages from a file or standard input. It is processed multiple times. The header is the delay imposed */ snr = 0; do { if ( datafile == 0){ fd = stdin; } else { fd = fopen(datafile, "r"); if (fd == NULL) { mnstr_printf(SEout, "Could not open file '%s'\n", datafile); close_stream(se->toServer); se->toServer = NULL; return; } } /* read the event requests and sent when the becomes */ while (fgets(buf, MYBUFSIZ, fd) != 0) { int newdelay = delay; tuple = buf; if ( timecolumn >= 0 ) { /* calculate the difference with previous event */ /* use a simplistic csv file format */ c= buf; for ( i = timecolumn; i> 0; i--){ if ( (d=strchr(c,(int)','))){ c= d+1; } } /* convert time to epoch in seconds*/ memset(&stm, 0, sizeof(struct tm)); if ( c ){ c = strptime(c,"%Y-%m-%d %H:%M:%S", &stm); tm = mktime(&stm); if ( *c == '.') { /* microseconds */ usec = atoi(c+1); if ( usec) multiply = 1; } } /* calculate time differential in seconds */ if ( lasttime ) newdelay = (int) difftime(tm,lasttime) * multiply + usec; lasttime = tm; if (trace && newdelay) mnstr_printf(SEout, "delayed %d\n", newdelay); MT_sleep_ms(newdelay); } else if (delay > 0) { /* wait */ MT_sleep_ms(delay); } if (delay < 0) { mnstr_printf(SEout, "%s", tuple); mnstr_printf(SEout, "send it?"); getchar(); } if (trace) mnstr_printf(SEout, "%s", tuple); if ((mnstr_write(se->toServer, tuple, 1, strlen(tuple))) == -1 && (errno == EPIPE)) { mnstr_printf(SEout, "errno:%s\n", strerror(errno)); return; } } fclose(fd); snr++; } while (snr != events); }
static void produceStream(Sensor se) { int b; int slen; char buf[MYBUFSIZ + 1]; /* compose an event message locally first */ char tuple[MYBUFSIZ + 1]; /* scratch area for a single tuple element */ int tlen, maxtuple = MYBUFSIZ; int buflen; int numberOFtuples = 0; #ifdef SENSOR_DEBUG mnstr_printf(SEout, "#Start producing the stream\n"); mnstr_printf(SEout, "#%d events, batchsize is %d, columns are %d\n", events, batchsize, columns); #endif /* create scratch space for a single tuple, this should be enough for integer fields */ buflen = 0; while (numberOFtuples < (events * batchsize) || events == -1) { int i; lng currenttsmp = 0; if (delay > 0) { /* wait */ MT_sleep_ms(delay); } if (delay < 0) { mnstr_printf(SEout, "#send next?"); getchar(); } buf[0] = 0; slen = 0; tlen = 0; if (batchsize > 1) { snprintf(tuple, maxtuple, "#%d\n", batchsize); tlen += (int) strlen(tuple + tlen); strncpy(buf, tuple, tlen); slen += tlen; } /* construct a single event record batch */ for (b = batchsize; b > 0; b--) { /* the first column is used for event identifier tagging */ tlen = 0; if (autoincrement) { snprintf(tuple + tlen, maxtuple - tlen, "%d", autoincrement); tlen += (int) strlen(tuple + tlen); autoincrement++; } /* if timestamp is set then the next colum will contain the wall-clock microstamp. This reduces the number of additional columns to be produced by 1 */ if (timestamp) { currenttsmp = GDKusec(); snprintf(tuple + tlen, maxtuple - tlen, "%s" LLFMT "", (autoincrement ? separator[protocol] : ""), currenttsmp); tlen += (int) strlen(tuple + tlen); if (tlen >= maxtuple) { mnstr_printf(SEout, "Buffer not large enough to handle request.\n"); mnstr_printf(SEout, "recompile with larger constant \n"); return; } } /* we only generate integer based events for now */ for (i = (timestamp ? 1 : 0) + (autoincrement ? 1 : 0); i < columns; i++) { if (i) snprintf(tuple + tlen, maxtuple - tlen, "%s%d", separator[protocol], rand()); else snprintf(tuple + tlen, maxtuple - tlen, "%d", rand()); tlen += (int) strlen(tuple + tlen); } snprintf(tuple + tlen, maxtuple - tlen, "\n"); tlen += (int) strlen(tuple + tlen); /* now add the tuple to the buffer if there is room left*/ if (MYBUFSIZ - buflen <= tlen) { mnstr_printf(SEout, "Buffer not large enough to handle request.\n"); mnstr_printf(SEout, "recompile with larger constant \n"); return; } strncpy(buf + slen, tuple, tlen); slen += tlen; numberOFtuples++; } /* the batch has now been created, it should be shipped */ /* watch out, the buffer is not NULL terminated */ if (mnstr_write(se->toServer, buf, 1, slen) == -1 && ((errno == EPIPE) || (errno == ECONNRESET))) { mnstr_printf(SEout, "errno:%s %d\n", strerror(errno), errno); close_stream(se->toServer); se->toServer = NULL; return; } if (trace) { buf[slen] = 0; mnstr_printf(SEout, "%s", buf); /*mnstr_flush(SEout);*/ } } /* you should not close the stream to quickly because then you may loose part of the input */ if (protocol != DEB) { mnstr_printf(SEout, "Columns: %d\n", columns); mnstr_printf(SEout, "Batch size: %d\n", batchsize); mnstr_printf(SEout, "total Number of batches: %d\n", events); mnstr_printf(SEout, "Delay: %d\n", delay); } mnstr_printf(SEout, "ready to close connection?"); (void) getchar(); close_stream(se->toServer); se->toServer = NULL; }
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 }, { "daemon", 1, 0, 0 }, { "debug", 2, 0, 'd' }, { "help", 0, 0, '?' }, { "version", 0, 0, 0 }, { "readonly", 0, 0, 'r' }, { "single-user", 0, 0, 0 }, { "set", 1, 0, 's' }, { "threads", 0, 0, 0 }, { "memory", 0, 0, 0 }, { "properties", 0, 0, 0 }, { "io", 0, 0, 0 }, { "transactions", 0, 0, 0 }, { "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); for (;;) { int option_index = 0; int c = getopt_long(argc, av, "c:d::rs:?", 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; } #ifdef HAVE_CONSOLE if (strcmp(long_options[option_index].name, "daemon") == 0) { setlen = mo_add_option(&set, setlen, opt_cmdline, "monet_daemon", optarg); break; } #endif if (strcmp(long_options[option_index].name, "single-user") == 0) { setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_single_user", "yes"); 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, "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 '?': /* 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); } 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); 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); } /* 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 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); } } { /* 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); } if (mal_init()) { /* don't show this as a crash */ msab_registerStop(); return 0; } 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); emergencyBreakpoint(); 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); #ifdef HAVE_CONSOLE if (!monet_daemon) { MSserveClient(mal_clients); } else #endif while (1) MT_sleep_ms(5000); /* mal_exit calls MT_global_exit, so statements after this call will * never get reached */ mal_exit(); return 0; }
static void DFLOWworker(void *T) { struct worker *t = (struct worker *) T; DataFlow flow; FlowEvent fe = 0, fnxt = 0; int id = (int) (t - workers); Thread thr; str error = 0; int i,last; Client cntxt; InstrPtr p; thr = THRnew("DFLOWworker"); GDKsetbuf(GDKmalloc(GDKMAXERRLEN)); /* where to leave errors */ GDKerrbuf[0] = 0; MT_lock_set(&dataflowLock, "DFLOWworker"); cntxt = t->cntxt; MT_lock_unset(&dataflowLock, "DFLOWworker"); if (cntxt) { /* wait until we are allowed to start working */ MT_sema_down(&t->s, "DFLOWworker"); } while (1) { if (fnxt == 0) { MT_lock_set(&dataflowLock, "DFLOWworker"); cntxt = t->cntxt; MT_lock_unset(&dataflowLock, "DFLOWworker"); fe = q_dequeue(todo, cntxt); if (fe == NULL) { if (cntxt) { /* we're not done yet with work for the current * client (as far as we know), so give up the CPU * and let the scheduler enter some more work, but * first compensate for the down we did in * dequeue */ MT_sema_up(&todo->s, "DFLOWworker"); MT_sleep_ms(1); continue; } /* no more work to be done: exit */ break; } } else fe = fnxt; if (ATOMIC_GET(exiting, exitingLock, "DFLOWworker")) { break; } fnxt = 0; assert(fe); flow = fe->flow; assert(flow); /* whenever we have a (concurrent) error, skip it */ if (flow->error) { q_enqueue(flow->done, fe); continue; } /* skip all instructions when we have encontered an error */ if (flow->error == 0) { #ifdef USE_MAL_ADMISSION if (MALadmission(fe->argclaim, fe->hotclaim)) { fe->hotclaim = 0; /* don't assume priority anymore */ if (todo->last == 0) MT_sleep_ms(DELAYUNIT); q_requeue(todo, fe); continue; } #endif error = runMALsequence(flow->cntxt, flow->mb, fe->pc, fe->pc + 1, flow->stk, 0, 0); PARDEBUG fprintf(stderr, "#executed pc= %d wrk= %d claim= " LLFMT "," LLFMT " %s\n", fe->pc, id, fe->argclaim, fe->hotclaim, error ? error : ""); #ifdef USE_MAL_ADMISSION /* release the memory claim */ MALadmission(-fe->argclaim, -fe->hotclaim); #endif /* update the numa information. keep the thread-id producing the value */ p= getInstrPtr(flow->mb,fe->pc); for( i = 0; i < p->argc; i++) flow->mb->var[getArg(p,i)]->worker = thr->tid; MT_lock_set(&flow->flowlock, "DFLOWworker"); fe->state = DFLOWwrapup; MT_lock_unset(&flow->flowlock, "DFLOWworker"); if (error) { MT_lock_set(&flow->flowlock, "DFLOWworker"); /* only collect one error (from one thread, needed for stable testing) */ if (!flow->error) flow->error = error; MT_lock_unset(&flow->flowlock, "DFLOWworker"); /* after an error we skip the rest of the block */ q_enqueue(flow->done, fe); continue; } } /* see if you can find an eligible instruction that uses the * result just produced. Then we can continue with it right away. * We are just looking forward for the last block, which means we * are safe from concurrent actions. No other thread can steal it, * because we hold the logical lock. * All eligible instructions are queued */ #ifdef USE_MAL_ADMISSION { InstrPtr p = getInstrPtr(flow->mb, fe->pc); assert(p); fe->hotclaim = 0; for (i = 0; i < p->retc; i++) fe->hotclaim += getMemoryClaim(flow->mb, flow->stk, p, i, FALSE); } #endif MT_lock_set(&flow->flowlock, "DFLOWworker"); for (last = fe->pc - flow->start; last >= 0 && (i = flow->nodes[last]) > 0; last = flow->edges[last]) if (flow->status[i].state == DFLOWpending && flow->status[i].blocks == 1) { flow->status[i].state = DFLOWrunning; flow->status[i].blocks = 0; flow->status[i].hotclaim = fe->hotclaim; flow->status[i].argclaim += fe->hotclaim; fnxt = flow->status + i; break; } MT_lock_unset(&flow->flowlock, "DFLOWworker"); q_enqueue(flow->done, fe); if ( fnxt == 0) { int last; MT_lock_set(&todo->l, "DFLOWworker"); last = todo->last; MT_lock_unset(&todo->l, "DFLOWworker"); if (last == 0) profilerHeartbeatEvent("wait", 0); } } GDKfree(GDKerrbuf); GDKsetbuf(0); THRdel(thr); MT_lock_set(&dataflowLock, "DFLOWworker"); t->flag = EXITED; MT_lock_unset(&dataflowLock, "DFLOWworker"); }