Foam::InjectionModel<CloudType>::InjectionModel ( const dictionary& dict, CloudType& owner, const word& type ) : dict_(dict), owner_(owner), coeffDict_(dict.subDict(type + "Coeffs")), SOI_(readScalar(coeffDict_.lookup("SOI"))), volumeTotal_(0.0), massTotal_(dimensionedScalar(coeffDict_.lookup("massTotal")).value()), massInjected_(0.0), nInjections_(0), parcelsAddedTotal_(0), parcelBasis_(pbNumber), time0_(owner.db().time().value()), timeStep0_(0.0) { // Provide some info // - also serves to initialise mesh dimensions - needed for parallel runs // due to lazy evaluation of valid mesh dimensions Info<< " Constructing " << owner.mesh().nGeometricD() << "-D injection" << endl; word parcelBasisType = coeffDict_.lookup("parcelBasisType"); if (parcelBasisType == "mass") { parcelBasis_ = pbMass; } else if (parcelBasisType == "number") { parcelBasis_ = pbNumber; } else { FatalErrorIn ( "Foam::InjectionModel<CloudType>::InjectionModel" "(" "const dictionary&, " "CloudType&, " "const word&" ")" )<< "parcelBasisType must be either 'number' or 'mass'" << nl << exit(FatalError); } readProps(); }
Foam::InjectionModel<CloudType>::InjectionModel(CloudType& owner) : dict_(dictionary::null), owner_(owner), coeffDict_(dictionary::null), SOI_(0.0), volumeTotal_(0.0), massTotal_(0.0), massInjected_(0.0), nInjections_(0), parcelsAddedTotal_(0), parcelBasis_(pbNumber), time0_(0.0), timeStep0_(0.0) { readProps(); }
/** * Initialize the global variables for this process's environment. */ int init(int argc, char** argv) { // debug controlled by environment variable or --v argument debug = getenv("fan_launcher_debug") != NULL; for (int i=1; i<argc; ++i) if (strcmp(argv[i], "--v") == 0) debug = true; if (debug) { printf("-- launcher version %s\n", LAUNCHER_VERSION); for (int i=0; i<argc; ++i) printf("-- args[%d] = \"%s\"\n", i, argv[i]); printf("-- init\n"); } // get my module char p[MAX_PATH]; if (!GetModuleFileName(NULL, p, MAX_PATH)) return err("GetModuleFileName"); // walk up two levels of the path to get fan home: // {fanHome}\bin\me.exe int len = strlen(p); for (; len > 0; len--) if (p[len] == '\\') { p[len] = '\0'; break; } for (; len > 0; len--) if (p[len] == '\\') { p[len] = '\0'; break; } strcpy(fanHome, p); if (debug) printf("-- fanHome = %s\n", fanHome); // parse etc/sys/config.props sprintf(p, "%s\\etc\\sys\\config.props", fanHome); sysProps = readProps(p); if (sysProps == NULL) printf("WARN: Cannot read config.props: \"%s\"", p); // debug props if (debug) { printf("-- config.props:\n"); for (Prop* p = sysProps; p != NULL; p = p->next) printf("-- %s=%s\n", p->name, p->val); } return 0; }
/** * Sets a single property, performing all necessary checks to validate * the key and associated value. */ char * setProp(char *path, char *key, char *val) { char *err; char buf[8096]; confkeyval *props = getDefaultProps(); confkeyval *kv; readProps(props, path); kv = findConfKey(props, key); if (kv == NULL) { snprintf(buf, sizeof(buf), "no such property: %s", key); freeConfFile(props); free(props); return(strdup(buf)); } /* first just attempt to set the value (type-check) in memory */ if ((err = setConfVal(kv, val)) != NULL) { freeConfFile(props); free(props); return(err); } if (val != NULL) { /* handle the semantially enriched types */ if (strcmp(key, "forward") == 0) { if (strcmp(val, "proxy") != 0 && strcmp(val, "redirect") != 0) { snprintf(buf, sizeof(buf), "expected 'proxy' or 'redirect' " "for property 'forward', got: %s", val); freeConfFile(props); free(props); return(strdup(buf)); } } else if (strcmp(key, "shared") == 0) { char *value = val; /* check if tag matches [A-Za-z0-9./]+ */ if (*value == '\0') { freeConfFile(props); free(props); return(strdup("tag to share cannot be empty")); } while (*value != '\0') { if (!( (*value >= 'A' && *value <= 'Z') || (*value >= 'a' && *value <= 'z') || (*value >= '0' && *value <= '9') || (*value == '.' || *value == '/') )) { snprintf(buf, sizeof(buf), "invalid character '%c' at %d " "in tag name '%s'\n", *value, (int)(value - val), val); freeConfFile(props); free(props); return(strdup(buf)); } value++; } } } /* ok, if we've reached this point we can write this stuff out! */ writeProps(props, path); freeConfFile(props); free(props); return(NULL); }
void discoveryRunner(void *d) { int sock = *(int *)d; int s = -1; struct sockaddr_storage peer_addr; socklen_t peer_addr_len; fd_set fds; struct timeval tv; int c; /* avoid first announce, the HELO will cause an announce when it's * received by ourself */ time_t deadline = 1; time_t now = 0; int forceannc = 0; sabdb *orig; sabdb *stats; confkeyval *ckv; confkeyval *kv; confkeyval *discttl; err e; remotedb rdb; remotedb prv; char *val; ssize_t nread; char buf[512]; /* our packages should be pretty small */ char host[128]; char service[8]; /* start shouting around that we're here ;) request others to tell * what databases they have */ snprintf(buf, 512, "HELO %s", _mero_hostname); broadcast(buf); ckv = getDefaultProps(); discttl = findConfKey(_mero_props, "discoveryttl"); /* main loop */ while (_mero_keep_listening == 1) { now = time(NULL); /* do a round of announcements, we're ahead of the ttl because * when we announce, we add 60 seconds to avoid a "gap" */ if (forceannc == 1 || deadline <= now) { forceannc = 0; /* set new deadline */ deadline = now + discttl->ival; /* list all known databases */ if ((e = msab_getStatus(&stats, NULL)) != NULL) { Mfprintf(_mero_discerr, "msab_getStatus error: %s, " "discovery services disabled\n", e); free(e); return; } for (orig = stats; stats != NULL; stats = stats->next) { readProps(ckv, stats->path); kv = findConfKey(ckv, "shared"); val = kv->val == NULL ? "" : kv->val; /* skip databases under maintenance */ if (strcmp(val, "no") != 0 && stats->locked != 1) { /* craft ANNC message for this db */ if (strcmp(val, "yes") == 0) val = ""; snprintf(buf, 512, "ANNC %s%s%s mapi:monetdb://%s:%u/ %d", stats->dbname, val[0] == '\0' ? "" : "/", val, _mero_hostname, (unsigned int)getConfNum(_mero_props, "port"), discttl->ival + 60); broadcast(buf); } freeConfFile(ckv); } if (orig != NULL) msab_freeStatus(&orig); if (getConfNum(_mero_props, "control") != 0) { /* announce control port */ snprintf(buf, 512, "ANNC * %s:%u %d", _mero_hostname, (unsigned int)getConfNum(_mero_props, "port"), discttl->ival + 60); /* coverity[string_null] */ broadcast(buf); } } /* do a round to see if we have to cleanup anything (expired * ttl) */ pthread_mutex_lock(&_mero_remotedb_lock); prv = NULL; rdb = _mero_remotedbs; while (rdb != NULL) { if (rdb->ttl > 0 && rdb->ttl <= now) { /* expired, let's remove */ if (prv == NULL) { _mero_remotedbs = rdb->next; } else { prv->next = rdb->next; } Mfprintf(_mero_discout, "neighbour database %s%s " "has expired\n", rdb->conn, rdb->fullname); free(rdb->dbname); free(rdb->conn); free(rdb->fullname); free(rdb); break; } prv = rdb; rdb = rdb->next; } pthread_mutex_unlock(&_mero_remotedb_lock); peer_addr_len = sizeof(struct sockaddr_storage); FD_ZERO(&fds); FD_SET(sock, &fds); /* Wait up to 5 seconds. */ tv.tv_sec = 5; tv.tv_usec = 0; nread = select(sock + 1, &fds, NULL, NULL, &tv); if (nread <= 0) { /* assume only failure is EINTR */ /* nothing interesting has happened */ buf[0] = '\0'; continue; } nread = recvfrom(sock, buf, 512, 0, (struct sockaddr *)&peer_addr, &peer_addr_len); if (nread == -1) { buf[0] = '\0'; continue; /* ignore failed request */ } s = getnameinfo((struct sockaddr *)&peer_addr, peer_addr_len, host, 128, service, 8, NI_NUMERICSERV); if (s != 0) { Mfprintf(_mero_discerr, "cannot retrieve name info: %s\n", gai_strerror(s)); continue; /* skip this message */ } /* ignore messages from broadcast interface */ if (strcmp(host, "0.0.0.0") == 0) continue; /* forward messages not coming from ourself to all routes that * are active */ if (strcmp(host, _mero_hostname) != 0) { disc_message_tap h = _mero_disc_msg_taps; for (; h != NULL; h = h->next) { if (write(h->fd, buf, nread) == -1) { /* really nothing to be done here, since this is * best effort stuff, keep the condition to keep * fortification warnings off */ } } } if (strncmp(buf, "HELO ", 5) == 0) { /* HELLO message, respond with current databases */ Mfprintf(_mero_discout, "new neighbour %s (%s)\n", buf + 5, host); /* sleep a random amount of time to avoid an avalanche of * ANNC messages flooding the network */ /* coverity[dont_call] */ c = 1 + (int)(2500.0 * (rand() / (RAND_MAX + 1.0))); sleep_ms(c); /* force an announcement round by dropping the deadline */ forceannc = 1; continue; } else if (strncmp(buf, "LEAV ", 5) == 0) { /* LEAVE message, unregister database */ char *sp = NULL; char *dbname; char *conn; strtok_r(buf, " ", &sp); /* discard the msg type */ dbname = strtok_r(NULL, " ", &sp); conn = strtok_r(NULL, " ", &sp); if (dbname == NULL || conn == NULL) continue; if (removeRemoteDB(dbname, conn) == 0) Mfprintf(_mero_discout, "received leave request for unknown database " "%s%s from %s\n", conn, dbname, host); } else if (strncmp(buf, "ANNC ", 5) == 0) { /* ANNOUNCE message, register database */ char *sp = NULL; char *dbname; char *conn; char *ttl; strtok_r(buf, " ", &sp); /* discard the msg type */ dbname = strtok_r(NULL, " ", &sp); conn = strtok_r(NULL, " ", &sp); ttl = strtok_r(NULL, " ", &sp); if (dbname == NULL || conn == NULL || ttl == NULL) continue; if (addRemoteDB(dbname, conn, atoi(ttl)) == 1) { if (strcmp(dbname, "*") == 0) { Mfprintf(_mero_discout, "registered neighbour %s\n", conn); } else { Mfprintf(_mero_discout, "new database " "%s%s (ttl=%ss)\n", conn, dbname, ttl); } } } else { Mfprintf(_mero_discout, "ignoring unknown message from " "%s:%s: '%s'\n", host, service, buf); } } /* now notify of our soon to be absence ;) */ /* list all known databases */ if ((e = msab_getStatus(&stats, NULL)) != NULL) { Mfprintf(_mero_discerr, "msab_getStatus error: %s, " "discovery services disabled\n", e); free(e); free(ckv); return; } /* craft LEAV messages for each db */ c = 0; orig = stats; while (stats != NULL) { readProps(ckv, stats->path); kv = findConfKey(ckv, "shared"); if (kv->val != NULL && strcmp(kv->val, "no") != 0) { snprintf(buf, 512, "LEAV %s mapi:monetdb://%s:%u/", stats->dbname, _mero_hostname, (unsigned int)getConfNum(_mero_props, "port")); broadcast(buf); c = 1; } freeConfFile(ckv); stats = stats->next; } if (orig != NULL) msab_freeStatus(&orig); /* deregister this merovingian, so it doesn't remain a stale entry */ if (getConfNum(_mero_props, "control") != 0) { snprintf(buf, 512, "LEAV * %s:%u", _mero_hostname, (unsigned int)getConfNum(_mero_props, "port")); broadcast(buf); } free(ckv); }
int main(int argc, char *argv[]) { err e; int argp; char dbfarm[1024]; char *pidfilename = NULL; char *p; FILE *pidfile = NULL; char control_usock[1024]; char mapi_usock[1024]; dpair d = NULL; struct _dpair dpcons; struct _dpair dpmero; struct _dpair dpdisc; struct _dpair dpcont; int pfd[2]; pthread_t tid = 0; struct sigaction sa; int ret; int lockfd = -1; int sock = -1; int usock = -1; int unsock = -1; int socku = -1; unsigned short port = 0; char discovery = 0; struct stat sb; FILE *oerr = NULL; pthread_mutexattr_t mta; int thret; char merodontfork = 0; confkeyval ckv[] = { {"logfile", strdup("merovingian.log"), 0, STR}, {"pidfile", strdup("merovingian.pid"), 0, STR}, {"sockdir", strdup("/tmp"), 0, STR}, {"port", strdup(MERO_PORT), atoi(MERO_PORT), INT}, {"exittimeout", strdup("60"), 60, INT}, {"forward", strdup("proxy"), 0, OTHER}, {"discovery", strdup("true"), 1, BOOLEAN}, {"discoveryttl", strdup("600"), 600, INT}, {"control", strdup("false"), 0, BOOLEAN}, {"passphrase", NULL, 0, STR}, { NULL, NULL, 0, INVALID} }; confkeyval *kv; int retfd = -1; /* seed the randomiser for when we create a database, send responses * to HELO, etc */ srand(time(NULL)); /* figure out our hostname */ gethostname(_mero_hostname, 128); /* where is the mserver5 binary we fork on demand? * first try to locate it based on our binary location, fall-back to * hardcoded bin-dir */ _mero_mserver = get_bin_path(); if (_mero_mserver != NULL) { /* replace the trailing monetdbd by mserver5, fits nicely since * they happen to be of same length */ char *s = strrchr(_mero_mserver, '/'); if (s != NULL && strcmp(s + 1, "monetdbd") == 0) { s++; *s++ = 'm'; *s++ = 's'; *s++ = 'e'; *s++ = 'r'; *s++ = 'v'; *s++ = 'e'; *s++ = 'r'; *s++ = '5'; if (stat(_mero_mserver, &sb) == -1) _mero_mserver = NULL; } } /* setup default database properties, constants: unlike historical * versions, we do not want changing defaults any more */ _mero_db_props = getDefaultProps(); kv = findConfKey(_mero_db_props, "shared"); kv->val = strdup("yes"); kv = findConfKey(_mero_db_props, "readonly"); kv->val = strdup("no"); kv = findConfKey(_mero_db_props, "nclients"); kv->val = strdup("64"); kv = findConfKey(_mero_db_props, "type"); kv->val = strdup("database"); kv = findConfKey(_mero_db_props, "optpipe"); kv->val = strdup("default_pipe"); { /* nrthreads */ int ncpus = -1; char cnt[8]; #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) /* this works on Linux, Solaris and AIX */ ncpus = sysconf(_SC_NPROCESSORS_ONLN); #elif defined(HAVE_SYS_SYSCTL_H) && defined(HW_NCPU) /* BSD */ size_t len = sizeof(int); int mib[3]; /* Everyone should have permission to make this call, * if we get a failure something is really wrong. */ mib[0] = CTL_HW; mib[1] = HW_NCPU; mib[2] = -1; sysctl(mib, 3, &ncpus, &len, NULL, 0); #elif defined(WIN32) SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); ncpus = sysinfo.dwNumberOfProcessors; #endif if (ncpus > 0) { snprintf(cnt, sizeof(cnt), "%d", ncpus); kv = findConfKey(_mero_db_props, "nthreads"); kv->val = strdup(cnt); } } *dbfarm = '\0'; if (argc > 1) { if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "help") == 0) { exit(command_help(argc - 1, &argv[1])); } else if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "version") == 0) { exit(command_version()); } else if (strcmp(argv[1], "create") == 0) { exit(command_create(argc - 1, &argv[1])); } else if (strcmp(argv[1], "get") == 0) { exit(command_get(ckv, argc - 1, &argv[1])); } else if (strcmp(argv[1], "set") == 0) { exit(command_set(ckv, argc - 1, &argv[1])); } else if (strcmp(argv[1], "start") == 0) { if (argc > 3 && strcmp(argv[2], "-n") == 0) merodontfork = 1; if (argc == 3 + merodontfork) { int len; len = snprintf(dbfarm, sizeof(dbfarm), "%s", argv[2 + merodontfork]); if (len > 0 && (size_t)len >= sizeof(dbfarm)) { Mfprintf(stderr, "fatal: dbfarm exceeds allocated " \ "path length, please file a bug at " \ "http://bugs.monetdb.org/\n"); exit(1); } } else { command_help(argc, argv); exit(1); } } else if (strcmp(argv[1], "stop") == 0) { exit(command_stop(ckv, argc - 1, &argv[1])); } else { fprintf(stderr, "monetdbd: unknown command: %s\n", argv[1]); command_help(0, NULL); exit(1); } } else { command_help(0, NULL); exit(1); } assert(*dbfarm != '\0'); /* fork into background before doing anything more */ if (!merodontfork) { char buf[4]; /* Fork into the background immediately. By doing this our child * can simply do everything it needs to do itself. Via a pipe it * will tell us if it is happy or not. */ if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); return(1); } switch (fork()) { case -1: /* oops, forking went wrong! */ Mfprintf(stderr, "unable to fork into background: %s\n", strerror(errno)); return(1); case 0: /* detach client from controlling tty, we only write to the * pipe to daddy */ if (setsid() < 0) Mfprintf(stderr, "hmmm, can't detach from controlling tty, " "continuing anyway\n"); retfd = open("/dev/null", O_RDONLY); dup2(retfd, 0); close(retfd); close(pfd[0]); /* close unused read end */ retfd = pfd[1]; /* store the write end */ break; default: /* the parent, we want it to die, after we know the child * has a good time */ close(pfd[1]); /* close unused write end */ if (read(pfd[0], &buf, 1) != 1) { Mfprintf(stderr, "unable to retrieve startup status\n"); return(1); } close(pfd[0]); return(buf[0]); /* whatever the child returned, we return */ } } /* use after the logger thread has started */ #define MERO_EXIT(status) if (!merodontfork) { \ char s = status; \ if (write(retfd, &s, 1) != 1 || close(retfd) != 0) { \ Mfprintf(stderr, "could not write to parent\n"); \ } \ if (status != 0) { \ Mfprintf(stderr, "fatal startup condition encountered, " \ "aborting startup\n"); \ goto shutdown; \ } \ } else { \ if (status != 0) { \ Mfprintf(stderr, "fatal startup condition encountered, " \ "aborting startup\n"); \ goto shutdown; \ } \ } /* use before logger thread has started */ #define MERO_EXIT_CLEAN(status) if (!merodontfork) { \ char s = status; \ if (write(retfd, &s, 1) != 1 || close(retfd) != 0) { \ Mfprintf(stderr, "could not write to parent\n"); \ } \ exit(s); \ } else { \ exit(status); \ } /* check if dbfarm actually exists */ if (stat(dbfarm, &sb) == -1) { Mfprintf(stderr, "dbfarm directory '%s' does not exist, " "use monetdbd create first\n", dbfarm); MERO_EXIT_CLEAN(1); } /* chdir to dbfarm so we are at least in a known to exist location */ if (chdir(dbfarm) < 0) { Mfprintf(stderr, "could not move to dbfarm '%s': %s\n", dbfarm, strerror(errno)); MERO_EXIT_CLEAN(1); } /* absolutise dbfarm if it isn't yet (we're in it now) */ if (dbfarm[0] != '/') { if (getcwd(dbfarm, sizeof(dbfarm)) == NULL) { if (errno == ERANGE) { Mfprintf(stderr, "current path exceeds allocated path length" \ "please file a bug at http://bugs.monetdb.org\n"); } else { Mfprintf(stderr, "could not get dbfarm working directory: %s\n", strerror(errno)); } MERO_EXIT_CLEAN(1); } } if (_mero_mserver == NULL) { _mero_mserver = BINDIR "/mserver5"; if (stat(_mero_mserver, &sb) == -1) { /* exit early if this is not going to work well */ Mfprintf(stderr, "cannot stat %s executable: %s\n", _mero_mserver, strerror(errno)); MERO_EXIT_CLEAN(1); } } /* read the merovingian properties from the dbfarm */ if (readProps(ckv, ".") != 0) { Mfprintf(stderr, "cannot find or read properties file, was " "this dbfarm created by `monetdbd create`?\n"); MERO_EXIT_CLEAN(1); } _mero_props = ckv; pidfilename = getConfVal(_mero_props, "pidfile"); p = getConfVal(_mero_props, "forward"); if (strcmp(p, "redirect") != 0 && strcmp(p, "proxy") != 0) { Mfprintf(stderr, "invalid forwarding mode: %s, defaulting to proxy\n", p); kv = findConfKey(_mero_props, "forward"); setConfVal(kv, "proxy"); writeProps(_mero_props, "."); } kv = findConfKey(_mero_props, "port"); if (kv->ival <= 0 || kv->ival > 65535) { Mfprintf(stderr, "invalid port number: %s, defaulting to %s\n", kv->val, MERO_PORT); setConfVal(kv, MERO_PORT); writeProps(_mero_props, "."); } port = (unsigned short)kv->ival; discovery = getConfNum(_mero_props, "discovery"); /* check and trim the hash-algo from the passphrase for easy use * lateron */ kv = findConfKey(_mero_props, "passphrase"); if (kv->val != NULL) { char *h = kv->val + 1; if ((p = strchr(h, '}')) == NULL) { Mfprintf(stderr, "warning: incompatible passphrase (not hashed as " MONETDB5_PASSWDHASH "), disabling passphrase\n"); } else { *p = '\0'; if (strcmp(h, MONETDB5_PASSWDHASH) != 0) { Mfprintf(stderr, "warning: passphrase hash '%s' incompatible, " "expected '%s', disabling passphrase\n", h, MONETDB5_PASSWDHASH); } else { setConfVal(kv, p + 1); } } } /* set up UNIX socket paths for control and mapi */ p = getConfVal(_mero_props, "sockdir"); snprintf(control_usock, sizeof(control_usock), "%s/" CONTROL_SOCK "%d", p, port); snprintf(mapi_usock, sizeof(control_usock), "%s/" MERO_SOCK "%d", p, port); /* lock such that we are alone on this world */ if ((lockfd = MT_lockf(".merovingian_lock", F_TLOCK, 4, 1)) == -1) { /* locking failed */ Mfprintf(stderr, "another monetdbd is already running\n"); MERO_EXIT_CLEAN(1); } else if (lockfd == -2) { /* directory or something doesn't exist */ Mfprintf(stderr, "unable to create %s/.merovingian_lock file: %s\n", dbfarm, strerror(errno)); MERO_EXIT_CLEAN(1); } _mero_topdp = &dpcons; _mero_topdp->pid = 0; _mero_topdp->type = MERO; _mero_topdp->dbname = NULL; /* where should our msg output go to? */ p = getConfVal(_mero_props, "logfile"); /* write to the given file */ _mero_topdp->out = open(p, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); if (_mero_topdp->out == -1) { Mfprintf(stderr, "unable to open '%s': %s\n", p, strerror(errno)); MT_lockf(".merovingian_lock", F_ULOCK, 4, 1); close(lockfd); MERO_EXIT_CLEAN(1); } _mero_topdp->err = _mero_topdp->out; _mero_logfile = fdopen(_mero_topdp->out, "a"); d = _mero_topdp->next = &dpmero; /* redirect stdout */ if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } d->out = pfd[0]; dup2(pfd[1], 1); close(pfd[1]); /* redirect stderr */ if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } /* before it is too late, save original stderr */ oerr = fdopen(dup(2), "w"); d->err = pfd[0]; dup2(pfd[1], 2); close(pfd[1]); d->pid = getpid(); d->type = MERO; d->dbname = "merovingian"; /* separate entry for the neighbour discovery service */ d = d->next = &dpdisc; if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } d->out = pfd[0]; _mero_discout = fdopen(pfd[1], "a"); if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } d->err = pfd[0]; _mero_discerr = fdopen(pfd[1], "a"); d->pid = getpid(); d->type = MERO; d->dbname = "discovery"; d->next = NULL; /* separate entry for the control runner */ d = d->next = &dpcont; if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } d->out = pfd[0]; _mero_ctlout = fdopen(pfd[1], "a"); if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } d->err = pfd[0]; _mero_ctlerr = fdopen(pfd[1], "a"); d->pid = getpid(); d->type = MERO; d->dbname = "control"; d->next = NULL; /* allow a thread to relock this mutex */ pthread_mutexattr_init(&mta); pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&_mero_topdp_lock, &mta); if ((thret = pthread_create(&tid, NULL, (void *(*)(void *))logListener, (void *)NULL)) != 0) { Mfprintf(oerr, "%s: FATAL: unable to create logthread: %s\n", argv[0], strerror(thret)); MERO_EXIT(1); } 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) { Mfprintf(oerr, "%s: FATAL: unable to create signal handlers: %s\n", argv[0], strerror(errno)); MERO_EXIT(1); } sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = huphandler; if (sigaction(SIGHUP, &sa, NULL) == -1) { Mfprintf(oerr, "%s: FATAL: unable to create signal handlers: %s\n", argv[0], strerror(errno)); MERO_EXIT(1); } sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = segvhandler; if (sigaction(SIGSEGV, &sa, NULL) == -1) { Mfprintf(oerr, "%s: FATAL: unable to create signal handlers: %s\n", argv[0], strerror(errno)); MERO_EXIT(1); } sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &sa, NULL) == -1) { Mfprintf(oerr, "%s: FATAL: unable to create signal handlers: %s\n", argv[0], strerror(errno)); MERO_EXIT(1); } sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = childhandler; if (sigaction(SIGCHLD, &sa, NULL) == -1) { Mfprintf(oerr, "%s: FATAL: unable to create signal handlers: %s\n", argv[0], strerror(errno)); MERO_EXIT(1); } /* make sure we will be able to write our pid */ if ((pidfile = fopen(pidfilename, "w")) == NULL) { Mfprintf(stderr, "unable to open '%s%s%s' for writing: %s\n", pidfilename[0] != '/' ? dbfarm : "", pidfilename[0] != '/' ? "/" : "", pidfilename, strerror(errno)); MERO_EXIT(1); } msab_dbfarminit(dbfarm); /* write out the pid */ Mfprintf(pidfile, "%d\n", (int)d->pid); fclose(pidfile); Mfprintf(stdout, "Merovingian %s (%s) starting\n", MERO_VERSION, MONETDB_RELEASE); Mfprintf(stdout, "monitoring dbfarm %s\n", dbfarm); /* open up connections */ if ( (e = openConnectionTCP(&sock, port, stdout)) == NO_ERR && /* coverity[operator_confusion] */ (unlink(control_usock) | unlink(mapi_usock) | 1) && (e = openConnectionUNIX(&socku, mapi_usock, 0, stdout)) == NO_ERR && (discovery == 0 || (e = openConnectionUDP(&usock, port)) == NO_ERR) && (e = openConnectionUNIX(&unsock, control_usock, S_IRWXO, _mero_ctlout)) == NO_ERR ) { pthread_t ctid = 0; pthread_t dtid = 0; if (discovery == 1) { _mero_broadcastsock = socket(AF_INET, SOCK_DGRAM, 0); ret = 1; if ((setsockopt(_mero_broadcastsock, SOL_SOCKET, SO_BROADCAST, &ret, sizeof(ret))) == -1) { Mfprintf(stderr, "cannot create broadcast package, " "discovery services disabled\n"); close(usock); usock = -1; } _mero_broadcastaddr.sin_family = AF_INET; _mero_broadcastaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); /* the target port is our configured port, not elegant, but how * else can we do it? can't broadcast to all ports or something */ _mero_broadcastaddr.sin_port = htons(port); } /* From this point merovingian considers itself to be in position to * start running, so flag the parent we will have fun. */ MERO_EXIT(0); /* Paranoia umask, but good, because why would people have to sniff * our private parts? */ umask(S_IRWXG | S_IRWXO); /* handle control commands */ if ((thret = pthread_create(&ctid, NULL, (void *(*)(void *))controlRunner, (void *)&unsock)) != 0) { Mfprintf(stderr, "unable to create control command thread: %s\n", strerror(thret)); ctid = 0; } /* start neighbour discovery and notification thread */ if (usock >= 0 && (thret = pthread_create(&dtid, NULL, (void *(*)(void *))discoveryRunner, (void *)&usock)) != 0) { Mfprintf(stderr, "unable to start neighbour discovery thread: %s\n", strerror(thret)); dtid = 0; } /* handle external connections main loop */ e = acceptConnections(sock, socku); /* wait for the control runner and discovery thread to have * finished announcing they're going down */ close(unsock); if (ctid != 0) pthread_join(ctid, NULL); if (usock >= 0) { close(usock); if (dtid != 0) pthread_join(dtid, NULL); } } /* control channel is already closed at this point */ if (unsock != -1 && unlink(control_usock) == -1) Mfprintf(stderr, "unable to unlink control socket '%s': %s\n", control_usock, strerror(errno)); if (socku != -1 && unlink(mapi_usock) == -1) Mfprintf(stderr, "unable to unlink mapi socket '%s': %s\n", mapi_usock, strerror(errno)); if (e != NO_ERR) { /* console */ Mfprintf(oerr, "%s: %s\n", argv[0], e); /* logfile */ Mfprintf(stderr, "%s\n", e); MERO_EXIT(1); } shutdown: /* stop started mservers */ kv = findConfKey(ckv, "exittimeout"); if (d->next != NULL && atoi(kv->val) > 0) { dpair t; threadlist tl = NULL, tlw = tl; pthread_mutex_lock(&_mero_topdp_lock); t = d->next; while (t != NULL) { if (tl == NULL) { tl = tlw = malloc(sizeof(struct _threadlist)); } else { tlw = tlw->next = malloc(sizeof(struct _threadlist)); } tlw->next = NULL; if ((thret = pthread_create(&(tlw->tid), NULL, (void *(*)(void *))terminateProcess, (void *)t)) != 0) { Mfprintf(stderr, "%s: unable to create thread to terminate " "database '%s': %s\n", argv[0], t->dbname, strerror(thret)); tlw->tid = 0; } t = t->next; } pthread_mutex_unlock(&_mero_topdp_lock); /* wait for all processes to be terminated */ tlw = tl; while (tlw != NULL) { if (tlw->tid != 0 && (argp = pthread_join(tlw->tid, NULL)) != 0) { Mfprintf(stderr, "failed to wait for termination thread: " "%s\n", strerror(argp)); } tl = tlw->next; free(tlw); tlw = tl; } } /* need to do this here, since the logging thread is shut down as * next thing */ Mfprintf(stdout, "Merovingian %s stopped\n", MERO_VERSION); _mero_keep_logging = 0; if (tid != 0 && (argp = pthread_join(tid, NULL)) != 0) { Mfprintf(oerr, "failed to wait for logging thread: %s\n", strerror(argp)); } if (_mero_topdp != NULL) { close(_mero_topdp->out); if (_mero_topdp->out != _mero_topdp->err) close(_mero_topdp->err); } /* remove files that suggest our existence */ unlink(".merovingian_lock"); if (pidfilename != NULL) { unlink(pidfilename); free(pidfilename); } /* mostly for valgrind... */ freeConfFile(ckv); if (_mero_db_props != NULL) { freeConfFile(_mero_db_props); free(_mero_db_props); } if (lockfd >= 0) { MT_lockf(".merovingian_lock", F_ULOCK, 4, 1); close(lockfd); } /* the child's return code at this point doesn't matter, as noone * will see it */ return(0); }
MStatus AlembicCurvesDeformNode::deform(MDataBlock &dataBlock, MItGeometry &iter, const MMatrix &localToWorld, unsigned int geomIndex) { // get the envelope data float env = dataBlock.inputValue(envelope).asFloat(); if (env == 0.0f) { // deformer turned off return MStatus::kSuccess; } // update the frame number to be imported double inputTime = dataBlock.inputValue(mTimeAttr).asTime().as(MTime::kSeconds); MString &fileName = dataBlock.inputValue(mFileNameAttr).asString(); MString &identifier = dataBlock.inputValue(mIdentifierAttr).asString(); // check if we have the file if (fileName != mFileName || identifier != mIdentifier) { mSchema.reset(); if (fileName != mFileName) { delRefArchive(mFileName); mFileName = fileName; addRefArchive(mFileName); } mIdentifier = identifier; // get the object from the archive Abc::IObject iObj = getObjectFromArchive(mFileName, identifier); if (!iObj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' not found in archive '" + mFileName + "'."); return MStatus::kFailure; } AbcG::ICurves obj(iObj, Abc::kWrapExisting); if (!obj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' in archive '" + mFileName + "' is not a Curves."); return MStatus::kFailure; } mSchema = obj.getSchema(); } if (!mSchema.valid()) { return MStatus::kFailure; } { ESS_PROFILE_SCOPE("AlembicCurvesDeformNode::deform readProps"); Alembic::Abc::ICompoundProperty arbProp = mSchema.getArbGeomParams(); Alembic::Abc::ICompoundProperty userProp = mSchema.getUserProperties(); readProps(inputTime, arbProp, dataBlock, thisMObject()); readProps(inputTime, userProp, dataBlock, thisMObject()); // Set all plugs as clean // Even if one of them failed to get set, // trying again in this frame isn't going to help for (unsigned int i = 0; i < mGeomParamPlugs.length(); i++) { dataBlock.outputValue(mGeomParamPlugs[i]).setClean(); } for (unsigned int i = 0; i < mUserAttrPlugs.length(); i++) { dataBlock.outputValue(mUserAttrPlugs[i]).setClean(); } } // get the sample SampleInfo sampleInfo = getSampleInfo(inputTime, mSchema.getTimeSampling(), mSchema.getNumSamples()); // check if we have to do this at all if (mLastSampleInfo.floorIndex == sampleInfo.floorIndex && mLastSampleInfo.ceilIndex == sampleInfo.ceilIndex) { return MStatus::kSuccess; } mLastSampleInfo = sampleInfo; // access the camera values AbcG::ICurvesSchema::Sample sample; AbcG::ICurvesSchema::Sample sample2; mSchema.get(sample, sampleInfo.floorIndex); if (sampleInfo.alpha != 0.0) { mSchema.get(sample2, sampleInfo.ceilIndex); } Abc::P3fArraySamplePtr samplePos = sample.getPositions(); Abc::P3fArraySamplePtr samplePos2; if (sampleInfo.alpha != 0.0) { samplePos2 = sample2.getPositions(); } // iteration should not be necessary. the iteration is only // required if the same mesh is attached to the same deformer // several times float blend = (float)sampleInfo.alpha; float iblend = 1.0f - blend; unsigned int index = 0; for (iter.reset(); !iter.isDone(); iter.next()) { index = iter.index(); // MFloatPoint pt = iter.position(); MPoint pt = iter.position(); MPoint abcPos = pt; float weight = weightValue(dataBlock, geomIndex, index) * env; if (weight == 0.0f) { continue; } float iweight = 1.0f - weight; if (index >= samplePos->size()) { continue; } bool done = false; if (sampleInfo.alpha != 0.0) { if (samplePos2->size() == samplePos->size()) { abcPos.x = iweight * pt.x + weight * (samplePos->get()[index].x * iblend + samplePos2->get()[index].x * blend); abcPos.y = iweight * pt.y + weight * (samplePos->get()[index].y * iblend + samplePos2->get()[index].y * blend); abcPos.z = iweight * pt.z + weight * (samplePos->get()[index].z * iblend + samplePos2->get()[index].z * blend); done = true; } } if (!done) { abcPos.x = iweight * pt.x + weight * samplePos->get()[index].x; abcPos.y = iweight * pt.y + weight * samplePos->get()[index].y; abcPos.z = iweight * pt.z + weight * samplePos->get()[index].z; } iter.setPosition(abcPos); } return MStatus::kSuccess; }
MStatus AlembicCurvesNode::compute(const MPlug &plug, MDataBlock &dataBlock) { ESS_PROFILE_SCOPE("AlembicCurvesNode::compute"); MStatus status; // update the frame number to be imported const double inputTime = dataBlock.inputValue(mTimeAttr).asTime().as(MTime::kSeconds); MString &fileName = dataBlock.inputValue(mFileNameAttr).asString(); MString &identifier = dataBlock.inputValue(mIdentifierAttr).asString(); // check if we have the file if (fileName != mFileName || identifier != mIdentifier) { mSchema.reset(); if (fileName != mFileName) { delRefArchive(mFileName); mFileName = fileName; addRefArchive(mFileName); } mIdentifier = identifier; // get the object from the archive Abc::IObject iObj = getObjectFromArchive(mFileName, identifier); if (!iObj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' not found in archive '" + mFileName + "'."); return MStatus::kFailure; } AbcG::ICurves obj(iObj, Abc::kWrapExisting); if (!obj.valid()) { MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier + "' in archive '" + mFileName + "' is not a Curves."); return MStatus::kFailure; } mObj = obj; mSchema = obj.getSchema(); mCurvesData = MObject::kNullObj; } if (!mSchema.valid()) { return MStatus::kFailure; } { ESS_PROFILE_SCOPE("AlembicCurvesNode::compute readProps"); Alembic::Abc::ICompoundProperty arbProp = mSchema.getArbGeomParams(); Alembic::Abc::ICompoundProperty userProp = mSchema.getUserProperties(); readProps(inputTime, arbProp, dataBlock, thisMObject()); readProps(inputTime, userProp, dataBlock, thisMObject()); // Set all plugs as clean // Even if one of them failed to get set, // trying again in this frame isn't going to help for (unsigned int i = 0; i < mGeomParamPlugs.length(); i++) { dataBlock.outputValue(mGeomParamPlugs[i]).setClean(); } for (unsigned int i = 0; i < mUserAttrPlugs.length(); i++) { dataBlock.outputValue(mUserAttrPlugs[i]).setClean(); } } // get the sample SampleInfo sampleInfo = getSampleInfo(inputTime, mSchema.getTimeSampling(), mSchema.getNumSamples()); // check if we have to do this at all if (!mCurvesData.isNull() && mLastSampleInfo.floorIndex == sampleInfo.floorIndex && mLastSampleInfo.ceilIndex == sampleInfo.ceilIndex) { return MStatus::kSuccess; } mLastSampleInfo = sampleInfo; const float blend = (float)sampleInfo.alpha; // access the camera values AbcG::ICurvesSchema::Sample sample; AbcG::ICurvesSchema::Sample sample2; mSchema.get(sample, sampleInfo.floorIndex); if (blend != 0.0f) { mSchema.get(sample2, sampleInfo.ceilIndex); } Abc::P3fArraySamplePtr samplePos = sample.getPositions(); Abc::P3fArraySamplePtr samplePos2 = sample2.getPositions(); Abc::Int32ArraySamplePtr nbVertices = sample.getCurvesNumVertices(); const bool applyBlending = (blend == 0.0f) ? false : (samplePos->size() == samplePos2->size()); Abc::FloatArraySamplePtr pKnotVec = getKnotVector(mObj); Abc::UInt16ArraySamplePtr pOrders = getCurveOrders(mObj); MArrayDataHandle arrh = dataBlock.outputArrayValue(mOutGeometryAttr); MArrayDataBuilder builder = arrh.builder(); // reference: // http://download.autodesk.com/us/maya/2010help/API/multi_curve_node_8cpp-example.html const int degree = (sample.getType() == AbcG::kCubic) ? 3 : 1; const bool closed = (sample.getWrap() == AbcG::kPeriodic); unsigned int pointOffset = 0; unsigned int knotOffset = 0; for (int ii = 0; ii < nbVertices->size(); ++ii) { const unsigned int nbCVs = (unsigned int)nbVertices->get()[ii]; const int ldegree = (pOrders) ? pOrders->get()[ii] : degree; const int nbSpans = (int)nbCVs - ldegree; MDoubleArray knots; if (pKnotVec) { const unsigned int nb_knot = nbCVs + ldegree - 1; for (unsigned int i = 0; i < nb_knot; ++i) { knots.append(pKnotVec->get()[knotOffset + i]); } knotOffset += nb_knot; } else { for (int span = 0; span <= nbSpans; ++span) { knots.append(double(span)); if (span == 0 || span == nbSpans) { for (int m = 1; m < degree; ++m) { knots.append(double(span)); } } } } MPointArray points; if (samplePos->size() > 0) { points.setLength((unsigned int)nbCVs); if (applyBlending) { for (unsigned int i = 0; i < nbCVs; ++i) { const Abc::P3fArraySample::value_type &vals1 = samplePos->get()[pointOffset + i]; const Abc::P3fArraySample::value_type &vals2 = samplePos2->get()[pointOffset + i]; MPoint &pt = points[i]; pt.x = vals1.x + (vals2.x - vals1.x) * blend; pt.y = vals1.y + (vals2.y - vals1.y) * blend; pt.z = vals1.z + (vals2.z - vals1.z) * blend; } } else { for (unsigned int i = 0; i < nbCVs; ++i) { const Abc::P3fArraySample::value_type &vals = samplePos->get()[pointOffset + i]; MPoint &pt = points[i]; pt.x = vals.x; pt.y = vals.y; pt.z = vals.z; } } pointOffset += nbCVs; } // create a subd either with or without uvs MObject mmCurvesData = MFnNurbsCurveData().create(); if (ldegree == 1 || ldegree == 3) mCurves.create(points, knots, ldegree, closed ? MFnNurbsCurve::kClosed : MFnNurbsCurve::kOpen, false, false, mmCurvesData); builder.addElement(ii).set(mmCurvesData); } arrh.set(builder); arrh.setAllClean(); return MStatus::kSuccess; }