int main(int argc, char **argv) { const int maxThreads = omp_get_max_threads(); if (argc < 4) { fprintf(stderr, "Usage: bench <csv file> <input size> <num threads> [<num threads> ...]\n"); return -1; } FILE *const csvFile = csv_open(argv[1]); if (csvFile == NULL) { return -1; } const int len = safe_strtol(argv[2]); if (len < 1) { fprintf(stderr, "Input size must be positive\n"); return -1; } TYPE *nrs = random_array(len, time(NULL)); if (nrs == NULL) { return -1; } for (int i = 3; i < argc; i++) { int threads = safe_strtol(argv[i]); if (threads < 1) { threads = maxThreads; } omp_set_num_threads(threads); printf("%s. omp_get_max_threads() == %d\n", algorithm_name, threads); /* Bench the parallel implementation. */ double start = omp_get_wtime(); if (prefix_sums(nrs, len, NULL) != 0) { return -1; } double par_time = omp_get_wtime() - start; printf("elements: %d; par time: %f\n\n", len, par_time); fprintf(csvFile, "%s,%d,%d,%f\n", algorithm_name, threads, len, par_time); } free(nrs); csv_close(csvFile); return 0; }
static enum test_return test_safe_strtol(void) { int32_t val; assert(safe_strtol("123", &val)); assert(val == 123); assert(safe_strtol("+123", &val)); assert(val == 123); assert(safe_strtol("-123", &val)); assert(val == -123); assert(!safe_strtol("", &val)); /* empty */ assert(!safe_strtol("123BOGUS", &val)); /* non-numeric */ assert(!safe_strtol("92837498237498237498029383", &val)); /* out of range */ /* extremes: */ /* This actually works on 64-bit ubuntu assert(!safe_strtol("2147483648", &val)); // (expt 2.0 31.0) */ assert(safe_strtol("2147483647", &val)); /* (- (expt 2.0 31) 1) */ assert(val == 2147483647L); /* This actually works on 64-bit ubuntu assert(!safe_strtol("-2147483649", &val)); // (- (expt -2.0 31) 1) */ /* We'll allow space to terminate the string. And leading space. */ assert(safe_strtol(" 123 foo", &val)); assert(val == 123); return TEST_PASS; }
END_TEST START_TEST (test_safe_strtol) { int32_t val; fail_unless(safe_strtol("123", &val), "Failed parsing 123"); fail_unless(val == 123, "123 != 123"); fail_unless(safe_strtol("+123", &val), "Failed parsing +123"); fail_unless(val == 123, "+123 != 123"); fail_unless(safe_strtol("-123", &val), "Failed parsing -123"); fail_unless(val == -123, "-123 != -123"); fail_if(safe_strtol("", &val), "Parsing empty string"); fail_if(safe_strtol("123BOGUS", &val), "Parsed 123BOGUS"); fail_if(safe_strtol("92837498237498237498029383", &val), "Parsed out of range value."); /* extremes: */ /* This actually works on 64-bit ubuntu assert(!safe_strtol("2147483648", &val)); /* (expt 2.0 31.0) */ */ fail_unless(safe_strtol("2147483647", &val), "Failed parsing upper limit."); /* (- (expt 2.0 31) 1) */ fail_unless(val == 2147483647L, "2147483647 != 2147483647L"); /* This actually works on 64-bit ubuntu assert(!safe_strtol("-2147483649", &val)); /* (- (expt -2.0 31) 1) */ */ /* We'll allow space to terminate the string. And leading space. */ fail_unless(safe_strtol(" 123 foo", &val), "Failed parsing \" 123 foo\""); fail_unless(val == 123, "\" 123 foo\" != 123"); }
static int snd_func_iops(snd_config_t **dst, snd_config_t *root, snd_config_t *src, snd_config_t *private_data, int op) { snd_config_t *n; snd_config_iterator_t i, next; const char *id; char *res = NULL; long result = 0, val; int idx = 0, err, hit; err = snd_config_search(src, "integers", &n); if (err < 0) { SNDERR("field integers not found"); goto __error; } err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating integers"); goto __error; } do { hit = 0; snd_config_for_each(i, next, n) { snd_config_t *n = snd_config_iterator_entry(i); const char *id; long i; if (snd_config_get_id(n, &id) < 0) continue; err = safe_strtol(id, &i); if (err < 0) { SNDERR("id of field %s is not an integer", id); err = -EINVAL; goto __error; } if (i == idx) { idx++; err = snd_config_get_integer(n, &val); if (err < 0) { SNDERR("invalid integer for id %s", id); err = -EINVAL; goto __error; } switch (op) { case 0: result += val; break; case 1: result *= val; break; } hit = 1; } } } while (hit); err = snd_config_get_id(src, &id); if (err >= 0) err = snd_config_imake_integer(dst, id, result); free(res); __error: return err; }
/** * \brief Returns an integer environment value. * \param dst The function puts the handle to the result configuration node * (with type integer) at the address specified by \p dst. * \param root Handle to the root source node. * \param src Handle to the source node, with definitions for \c vars and * \c default. * \param private_data Handle to the \c private_data node. * \return Zero if successful, otherwise a negative error code. * * Example: \code { @func igetenv vars [ MY_DEVICE DEVICE D ] default 0 } \endcode */ int snd_func_igetenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src, snd_config_t *private_data) { snd_config_t *d; const char *str, *id; int err; long v; err = snd_func_getenv(&d, root, src, private_data); if (err < 0) return err; err = snd_config_get_string(d, &str); if (err < 0) { snd_config_delete(d); return err; } err = safe_strtol(str, &v); if (err < 0) { snd_config_delete(d); return err; } snd_config_delete(d); err = snd_config_get_id(src, &id); if (err < 0) return err; err = snd_config_imake_integer(dst, id, v); if (err < 0) return err; return 0; }
static void load_ping_recipe(char **params, struct ping_test_recipe *out) { assert(params); assert(out); for (int i = 0; params[i]; i++) { int value = 0; char *p = NULL; p = strchr(params[i], '='); assert(p); if (!safe_strtol(p+1, &value)) { moxi_log_write("Failed to parse ``%s'' as number\n", p+1); assert(false); } if (starts_with("ksize=", params[i])) { out->keysize = value; } else if (starts_with("vsize=", params[i])) { out->valsize = value; } else if (starts_with("iterations=", params[i])) { out->iterations = value; } else { if (settings.verbose > 1) { moxi_log_write("Unknown recipe property: %s\n", params[i]); } } } }
int safe_strtoi(char *arg, int* value) { int error; long lvalue = *value; error = safe_strtol(arg, &lvalue); *value = (int) lvalue; return error; }
/** * \brief Gets the control interface index from the given ASCII string. * \param ascii The string to be parsed. * \return The control interface index if successful, otherwise a negative error code. */ int snd_config_get_ctl_iface_ascii(const char *ascii) { long v; snd_ctl_elem_iface_t idx; if (isdigit(ascii[0])) { if (safe_strtol(ascii, &v) >= 0) { if (v < 0 || v > SND_CTL_ELEM_IFACE_LAST) return -EINVAL; return v; } } for (idx = 0; idx <= SND_CTL_ELEM_IFACE_LAST; idx++) { if (strcasecmp(snd_ctl_elem_iface_name(idx), ascii) == 0) return idx; } return -EINVAL; }
// process a memcached set command. void process_update_command(conn *c, token_t *tokens, const size_t ntokens, int comm, bool handle_cas) { int vlen; assert(c != NULL); if (tokens[KEY_TOKEN].length > KEY_MAX_LENGTH || !safe_strtol(tokens[4].value, (int32_t *)&vlen)) { error_response(c, "CLIENT_ERROR bad command line format"); return; } if (vlen < 0) { error_response(c, "CLIENT_ERROR bad command line format"); return; } // setup value to be read c->sbytes = vlen + 2; // for \r\n consumption. conn_set_state(c, conn_read_value); }
/** * Function to start the server and let it listen on a random port * * @param port_out where to store the TCP port number the server is * listening on * @param is_daemon set to true if you want to run the memcached server * as a daemon process * @return the pid of the memcached server */ static pid_t start_server(in_port_t *port_out, bool is_daemon) { pid_t pid; FILE *fp; char buffer[80]; char environment[80]; char pid_file[80]; char *filename; snprintf(environment, sizeof(environment), "MEMCACHED_PORT_FILENAME=/tmp/ports.%lu", (long)getpid()); filename = environment + strlen("MEMCACHED_PORT_FILENAME="); snprintf(pid_file, sizeof(pid_file), "/tmp/pid.%lu", (long)getpid()); remove(filename); remove(pid_file); pid = fork(); assert(pid != -1); if (pid == 0) { /* Child */ char *argv[20]; int arg = 0; putenv(environment); #ifdef __sun putenv("LD_PRELOAD=watchmalloc.so.1"); putenv("MALLOC_DEBUG=WATCH"); #endif if (!is_daemon) { argv[arg++] = "./timedrun"; argv[arg++] = "15"; } argv[arg++] = "./memcached-debug"; argv[arg++] = "-p"; argv[arg++] = "-1"; argv[arg++] = "-U"; argv[arg++] = "0"; /* Handle rpmbuild and the like doing this as root */ if (getuid() == 0) { argv[arg++] = "-u"; argv[arg++] = "root"; } if (is_daemon) { argv[arg++] = "-d"; argv[arg++] = "-P"; argv[arg++] = pid_file; } argv[arg++] = NULL; assert(execv(argv[0], argv) != -1); } /* Yeah just let us "busy-wait" for the file to be created ;-) */ while (access(filename, F_OK) == -1) { usleep(10); } fp = fopen(filename, "r"); if (fp == NULL) { fprintf(stderr, "Failed to open the file containing port numbers: %s\n", strerror(errno)); assert(false); } *port_out = (in_port_t)-1; while ((fgets(buffer, sizeof(buffer), fp)) != NULL) { if (strncmp(buffer, "TCP INET: ", 10) == 0) { int32_t val; assert(safe_strtol(buffer + 10, &val)); *port_out = (in_port_t)val; } } fclose(fp); assert(remove(filename) == 0); if (is_daemon) { int32_t val; /* loop and wait for the pid file.. There is a potential race * condition that the server just created the file but isn't * finished writing the content, but I'll take the chance.... */ while (access(pid_file, F_OK) == -1) { usleep(10); } fp = fopen(pid_file, "r"); if (fp == NULL) { fprintf(stderr, "Failed to open pid file: %s\n", strerror(errno)); assert(false); } assert(fgets(buffer, sizeof(buffer), fp) != NULL); fclose(fp); assert(safe_strtol(buffer, &val)); pid = (pid_t)val; } return pid; }
int main(int argc, char **argv) { int ret = 0; MPI_Init(&argc, &argv); if (argc < 4) { fprintf(stderr, "Usage: bench <csv file> <input size> <input upper bound>\n"); ret = -1; goto out; } const int size = safe_strtol(argv[2]); if (size < 1) { fprintf(stderr, "Input size must be greater than 0\n"); ret = -1; goto out; } const int upper_bound = safe_strtol(argv[3]); if (size < 1) { fprintf(stderr, "Input upper bound must be greater than 0\n"); ret = -1; goto out; } int processes; MPI_Comm_size(MPI_COMM_WORLD, &processes); int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); /* We need to generate the same array in each process. The master process * determines a seed and broadcasts it to all others. */ int seed = time(NULL); MPI_Bcast(&seed, 1, MPI_INT, MASTER, MPI_COMM_WORLD); TYPE *a = random_array(size, upper_bound, seed); DEBUG("%s. MPI_Comm_size %d, MPI_Comm_rank %d, seed %d\n", algorithm_name, processes, rank, seed); /* Everything is set up, start sorting and time how long it takes. */ MPI_Barrier(MPI_COMM_WORLD); double start = MPI_Wtime(); TYPE *c = bucket_sort(a, size, upper_bound); double end = MPI_Wtime(); double localElapsed = end - start; double totalElapsed; MPI_Reduce(&localElapsed, &totalElapsed, 1, MPI_DOUBLE, MPI_MAX, MASTER, MPI_COMM_WORLD); free(a); free(c); /* Only the master process (rank 0) outputs information. */ if (rank == MASTER) { printf("processes: %d, elements: %d; upper bound: %d; time: %f\n", processes, size, upper_bound, totalElapsed); /* Persist this run in our csv file. */ FILE *const csvFile = csv_open(argv[1]); if (csvFile == NULL) { return -1; } fprintf(csvFile, "%s,%d,%d,%f\n", algorithm_name, processes, size, totalElapsed); csv_close(csvFile); } out: MPI_Finalize(); return ret; }
/** Note: the key and val param buffers are modified. */ void cproxy_parse_behavior_key_val(char *key, char *val, proxy_behavior *behavior) { uint32_t ms = 0; uint32_t x = 0; bool ok = false; assert(behavior != NULL); if (key != NULL && val != NULL) { key = trimstr(key); val = trimstr(val); if (wordeq(key, "cycle")) { ok = safe_strtoul(val, &behavior->cycle); } else if (wordeq(key, "downstream_max") || wordeq(key, "concurrency")) { ok = safe_strtoul(val, &behavior->downstream_max); } else if (wordeq(key, "downstream_conn_max")) { ok = safe_strtoul(val, &behavior->downstream_conn_max); } else if (wordeq(key, "weight") || wordeq(key, "downstream_weight")) { ok = safe_strtoul(val, &behavior->downstream_weight); } else if (wordeq(key, "retry") || wordeq(key, "downstream_retry")) { ok = safe_strtoul(val, &behavior->downstream_retry); } else if (wordeq(key, "protocol") || wordeq(key, "downstream_protocol")) { if (wordeq(val, "ascii") || wordeq(val, "memcached-ascii") || wordeq(val, "membase-ascii")) { behavior->downstream_protocol = proxy_downstream_ascii_prot; ok = true; } else if (wordeq(val, "binary") || wordeq(val, "memcached-binary") || wordeq(val, "membase-binary")) { behavior->downstream_protocol = proxy_downstream_binary_prot; ok = true; } else { if (settings.verbose > 1) { moxi_log_write("unknown behavior prot: %s\n", val); } } } else if (wordeq(key, "timeout") || wordeq(key, "downstream_timeout") || wordeq(key, "downstream_conn_timeout")) { ok = safe_strtoul(val, &ms); behavior->downstream_timeout.tv_sec = floor(ms / 1000.0); behavior->downstream_timeout.tv_usec = (ms % 1000) * 1000; } else if (wordeq(key, "downstream_conn_queue_timeout")) { ok = safe_strtoul(val, &ms); behavior->downstream_conn_queue_timeout.tv_sec = floor(ms / 1000.0); behavior->downstream_conn_queue_timeout.tv_usec = (ms % 1000) * 1000; } else if (wordeq(key, "wait_queue_timeout")) { ok = safe_strtoul(val, &ms); behavior->wait_queue_timeout.tv_sec = floor(ms / 1000.0); behavior->wait_queue_timeout.tv_usec = (ms % 1000) * 1000; } else if (wordeq(key, "connect_timeout")) { ok = safe_strtoul(val, &ms); behavior->connect_timeout.tv_sec = floor(ms / 1000.0); behavior->connect_timeout.tv_usec = (ms % 1000) * 1000; } else if (wordeq(key, "auth_timeout")) { ok = safe_strtoul(val, &ms); behavior->auth_timeout.tv_sec = floor(ms / 1000.0); behavior->auth_timeout.tv_usec = (ms % 1000) * 1000; } else if (wordeq(key, "time_stats")) { ok = safe_strtoul(val, &x); behavior->time_stats = x; } else if (wordeq(key, "mcs_opts")) { if (strlen(val) < sizeof(behavior->mcs_opts)) { strcpy(behavior->mcs_opts, val); ok = true; } } else if (wordeq(key, "connect_max_errors")) { ok = safe_strtoul(val, &behavior->connect_max_errors); } else if (wordeq(key, "connect_retry_interval")) { ok = safe_strtoul(val, &behavior->connect_retry_interval); } else if (wordeq(key, "front_cache_max")) { ok = safe_strtoul(val, &behavior->front_cache_max); } else if (wordeq(key, "front_cache_lifespan")) { ok = safe_strtoul(val, &behavior->front_cache_lifespan); } else if (wordeq(key, "front_cache_spec")) { if (strlen(val) < sizeof(behavior->front_cache_spec)) { strcpy(behavior->front_cache_spec, val); ok = true; } } else if (wordeq(key, "front_cache_unspec")) { if (strlen(val) < sizeof(behavior->front_cache_unspec)) { strcpy(behavior->front_cache_unspec, val); ok = true; } } else if (wordeq(key, "key_stats_max")) { ok = safe_strtoul(val, &behavior->key_stats_max); } else if (wordeq(key, "key_stats_lifespan")) { ok = safe_strtoul(val, &behavior->key_stats_lifespan); } else if (wordeq(key, "key_stats_spec")) { if (strlen(val) < sizeof(behavior->key_stats_spec)) { strcpy(behavior->key_stats_spec, val); ok = true; } } else if (wordeq(key, "key_stats_unspec")) { if (strlen(val) < sizeof(behavior->key_stats_unspec)) { strcpy(behavior->key_stats_unspec, val); ok = true; } } else if (wordeq(key, "optimize_set")) { if (strlen(val) < sizeof(behavior->optimize_set)) { strcpy(behavior->optimize_set, val); ok = true; } } else if (wordeq(key, "usr")) { if (strlen(val) < sizeof(behavior->usr)) { strcpy(behavior->usr, val); ok = true; } } else if (wordeq(key, "pwd")) { if (strlen(val) < sizeof(behavior->pwd)) { strcpy(behavior->pwd, val); ok = true; } } else if (wordeq(key, "host")) { if (strlen(val) < sizeof(behavior->host)) { strcpy(behavior->host, val); ok = true; } } else if (wordeq(key, "port")) { ok = safe_strtol(val, &behavior->port); } else if (wordeq(key, "bucket")) { if (strlen(val) < sizeof(behavior->bucket)) { strcpy(behavior->bucket, val); ok = true; } } else if (wordeq(key, "port_listen")) { ok = safe_strtol(val, &behavior->port_listen); } else if (wordeq(key, "default_bucket_name")) { if (strlen(val) < sizeof(behavior->default_bucket_name)) { strcpy(behavior->default_bucket_name, val); ok = true; } } else if (key[0] == '#') { // Comment. ok = true; } else { if (settings.verbose > 1) { moxi_log_write("ERROR: unknown behavior key: %s\n", key); } } } if (ok == false) { moxi_log_write("ERROR: config error in key: %s value: %s\n", key, val); } }
/** * \brief Merges the given strings. * \param dst The function puts the handle to the result configuration node * (with type string) at the address specified by \p dst. * \param root Handle to the root source node. * \param src Handle to the source node, with a definition for \c strings. * \param private_data Handle to the \c private_data node. * \return A non-negative value if successful, otherwise a negative error code. * * Example (result is "a1b2c3"): \code { @func concat strings [ "a1" "b2" "c3" ] } \endcode */ int snd_func_concat(snd_config_t **dst, snd_config_t *root, snd_config_t *src, snd_config_t *private_data) { snd_config_t *n; snd_config_iterator_t i, next; const char *id; char *res = NULL, *tmp; int idx = 0, len = 0, len1, err, hit; err = snd_config_search(src, "strings", &n); if (err < 0) { SNDERR("field strings not found"); goto __error; } err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating strings"); goto __error; } do { hit = 0; snd_config_for_each(i, next, n) { snd_config_t *n = snd_config_iterator_entry(i); char *ptr; const char *id; long i; if (snd_config_get_id(n, &id) < 0) continue; err = safe_strtol(id, &i); if (err < 0) { SNDERR("id of field %s is not an integer", id); err = -EINVAL; goto __error; } if (i == idx) { idx++; err = snd_config_get_ascii(n, &ptr); if (err < 0) { SNDERR("invalid ascii string for id %s", id); err = -EINVAL; goto __error; } len1 = strlen(ptr); tmp = realloc(res, len + len1 + 1); if (tmp == NULL) { free(ptr); free(res); err = -ENOMEM; goto __error; } memcpy(tmp + len, ptr, len1); free(ptr); len += len1; tmp[len] = '\0'; res = tmp; hit = 1; } } } while (hit); if (res == NULL) { SNDERR("empty string is not accepted"); err = -EINVAL; goto __error; } err = snd_config_get_id(src, &id); if (err >= 0) err = snd_config_imake_string(dst, id, res); free(res); __error: return err; }
/** * \brief Returns an environment value. * \param dst The function puts the handle to the result configuration node * (with type string) at the address specified by \p dst. * \param root Handle to the root source node. * \param src Handle to the source node, with definitions for \c vars and * \c default. * \param private_data Handle to the \c private_data node. * \return Zero if successful, otherwise a negative error code. * * Example: \code { @func getenv vars [ MY_CARD CARD C ] default 0 } \endcode */ int snd_func_getenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src, snd_config_t *private_data) { snd_config_t *n, *d; snd_config_iterator_t i, next; const char *res, *id; char *def = NULL; int idx = 0, err, hit; err = snd_config_search(src, "vars", &n); if (err < 0) { SNDERR("field vars not found"); goto __error; } err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating vars"); goto __error; } err = snd_config_search(src, "default", &d); if (err < 0) { SNDERR("field default not found"); goto __error; } err = snd_config_evaluate(d, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating default"); goto __error; } err = snd_config_get_ascii(d, &def); if (err < 0) { SNDERR("error getting field default"); goto __error; } do { hit = 0; snd_config_for_each(i, next, n) { snd_config_t *n = snd_config_iterator_entry(i); const char *ptr; long i; if (snd_config_get_id(n, &id) < 0) continue; if (snd_config_get_type(n) != SND_CONFIG_TYPE_STRING) { SNDERR("field %s is not a string", id); err = -EINVAL; goto __error; } err = safe_strtol(id, &i); if (err < 0) { SNDERR("id of field %s is not an integer", id); err = -EINVAL; goto __error; } if (i == idx) { idx++; err = snd_config_get_string(n, &ptr); if (err < 0) { SNDERR("invalid string for id %s", id); err = -EINVAL; goto __error; } res = getenv(ptr); if (res != NULL && *res != '\0') goto __ok; hit = 1; } } } while (hit); res = def; __ok: err = snd_config_get_id(src, &id); if (err >= 0) err = snd_config_imake_string(dst, id, res); __error: free(def); return err; }