コード例 #1
0
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();
}
コード例 #2
0
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();
}
コード例 #3
0
ファイル: launcher.cpp プロジェクト: nomit007/f4
/**
 * 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;
}
コード例 #4
0
ファイル: properties.c プロジェクト: sekcheong/monetdb
/**
 * 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);
}
コード例 #5
0
ファイル: discoveryrunner.c プロジェクト: jaiminpan/Monetdb
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);
}
コード例 #6
0
ファイル: merovingian.c プロジェクト: jaiminpan/Monetdb
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);
}
コード例 #7
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;
}
コード例 #8
0
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;
}