Beispiel #1
0
static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */
    udb_query_t *q, udb_query_preparation_area_t *prep_area)
{
  const char *statement;
  dbi_result res;
  size_t column_num;
  char **column_names;
  char **column_values;
  int status;
  size_t i;

  /* Macro that cleans up dynamically allocated memory and returns the
   * specified status. */
#define BAIL_OUT(status) \
  if (column_names != NULL) { sfree (column_names[0]); sfree (column_names); } \
  if (column_values != NULL) { sfree (column_values[0]); sfree (column_values); } \
  if (res != NULL) { dbi_result_free (res); res = NULL; } \
  return (status)

  column_names = NULL;
  column_values = NULL;

  statement = udb_query_get_statement (q);
  assert (statement != NULL);

  res = dbi_conn_query (db->connection, statement);
  if (res == NULL)
  {
    char errbuf[1024];
    ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
        "dbi_conn_query failed: %s",
        db->name, udb_query_get_name (q),
        cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
    BAIL_OUT (-1);
  }
  else /* Get the number of columns */
  {
    unsigned int db_status;

    db_status = dbi_result_get_numfields (res);
    if (db_status == DBI_FIELD_ERROR)
    {
      char errbuf[1024];
      ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
          "dbi_result_get_numfields failed: %s",
          db->name, udb_query_get_name (q),
          cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
      BAIL_OUT (-1);
    }

    column_num = (size_t) db_status;
    DEBUG ("cdbi_read_database_query (%s, %s): There are %zu columns.",
        db->name, udb_query_get_name (q), column_num);
  }

  /* Allocate `column_names' and `column_values'. {{{ */
  column_names = calloc (column_num, sizeof (*column_names));
  if (column_names == NULL)
  {
    ERROR ("dbi plugin: calloc failed.");
    BAIL_OUT (-1);
  }

  column_names[0] = calloc (column_num, DATA_MAX_NAME_LEN);
  if (column_names[0] == NULL)
  {
    ERROR ("dbi plugin: calloc failed.");
    BAIL_OUT (-1);
  }
  for (i = 1; i < column_num; i++)
    column_names[i] = column_names[i - 1] + DATA_MAX_NAME_LEN;

  column_values = calloc (column_num, sizeof (*column_values));
  if (column_values == NULL)
  {
    ERROR ("dbi plugin: calloc failed.");
    BAIL_OUT (-1);
  }

  column_values[0] = calloc (column_num, DATA_MAX_NAME_LEN);
  if (column_values[0] == NULL)
  {
    ERROR ("dbi plugin: calloc failed.");
    BAIL_OUT (-1);
  }
  for (i = 1; i < column_num; i++)
    column_values[i] = column_values[i - 1] + DATA_MAX_NAME_LEN;
  /* }}} */

  /* Copy the field names to `column_names' */
  for (i = 0; i < column_num; i++) /* {{{ */
  {
    const char *column_name;

    column_name = dbi_result_get_field_name (res, (unsigned int) (i + 1));
    if (column_name == NULL)
    {
      ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
          "Cannot retrieve name of field %zu.",
          db->name, udb_query_get_name (q), i + 1);
      BAIL_OUT (-1);
    }

    sstrncpy (column_names[i], column_name, DATA_MAX_NAME_LEN);
  } /* }}} for (i = 0; i < column_num; i++) */

  udb_query_prepare_result (q, prep_area, (db->host ? db->host : hostname_g),
      /* plugin = */ "dbi", db->name,
      column_names, column_num, /* interval = */ (db->interval > 0) ? db->interval : 0);

  /* 0 = error; 1 = success; */
  status = dbi_result_first_row (res); /* {{{ */
  if (status != 1)
  {
    char errbuf[1024];
    ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
        "dbi_result_first_row failed: %s. Maybe the statement didn't "
        "return any rows?",
        db->name, udb_query_get_name (q),
        cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
    udb_query_finish_result (q, prep_area);
    BAIL_OUT (-1);
  } /* }}} */

  /* Iterate over all rows and call `udb_query_handle_result' with each list of
   * values. */
  while (42) /* {{{ */
  {
    status = 0;
    /* Copy the value of the columns to `column_values' */
    for (i = 0; i < column_num; i++) /* {{{ */
    {
      status = cdbi_result_get_field (res, (unsigned int) (i + 1),
          column_values[i], DATA_MAX_NAME_LEN);

      if (status != 0)
      {
        ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
            "cdbi_result_get_field (%zu) failed.",
            db->name, udb_query_get_name (q), i + 1);
        status = -1;
        break;
      }
    } /* }}} for (i = 0; i < column_num; i++) */

    /* If all values were copied successfully, call `udb_query_handle_result'
     * to dispatch the row to the daemon. */
    if (status == 0) /* {{{ */
    {
      status = udb_query_handle_result (q, prep_area, column_values);
      if (status != 0)
      {
        ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
            "udb_query_handle_result failed.",
            db->name, udb_query_get_name (q));
      }
    } /* }}} */

    /* Get the next row from the database. */
    status = dbi_result_next_row (res); /* {{{ */
    if (status != 1)
    {
      if (dbi_conn_error (db->connection, NULL) != 0)
      {
        char errbuf[1024];
        WARNING ("dbi plugin: cdbi_read_database_query (%s, %s): "
            "dbi_result_next_row failed: %s.",
            db->name, udb_query_get_name (q),
            cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
      }
      break;
    } /* }}} */
  } /* }}} while (42) */

  /* Tell the db query interface that we're done with this query. */
  udb_query_finish_result (q, prep_area);

  /* Clean up and return `status = 0' (success) */
  BAIL_OUT (0);
#undef BAIL_OUT
} /* }}} int cdbi_read_database_query */
Beispiel #2
0
int lcc_getval (lcc_connection_t *c, lcc_identifier_t *ident, /* {{{ */
    size_t *ret_values_num, gauge_t **ret_values, char ***ret_values_names)
{
  char ident_str[6 * LCC_NAME_LEN];
  char ident_esc[12 * LCC_NAME_LEN];
  char command[14 * LCC_NAME_LEN];

  lcc_response_t res;
  size_t   values_num;
  gauge_t *values = NULL;
  char   **values_names = NULL;

  size_t i;
  int status;

  if (c == NULL)
    return (-1);

  if (ident == NULL)
  {
    lcc_set_errno (c, EINVAL);
    return (-1);
  }

  /* Build a commend with an escaped version of the identifier string. */
  status = lcc_identifier_to_string (c, ident_str, sizeof (ident_str), ident);
  if (status != 0)
    return (status);

  snprintf (command, sizeof (command), "GETVAL %s",
      lcc_strescape (ident_esc, ident_str, sizeof (ident_esc)));
  command[sizeof (command) - 1] = 0;

  /* Send talk to the daemon.. */
  status = lcc_sendreceive (c, command, &res);
  if (status != 0)
    return (status);

  if (res.status != 0)
  {
    LCC_SET_ERRSTR (c, "Server error: %s", res.message);
    lcc_response_free (&res);
    return (-1);
  }

  values_num = res.lines_num;

#define BAIL_OUT(e) do { \
  lcc_set_errno (c, (e)); \
  free (values); \
  if (values_names != NULL) { \
    for (i = 0; i < values_num; i++) { \
      free (values_names[i]); \
    } \
  } \
  free (values_names); \
  lcc_response_free (&res); \
  return (-1); \
} while (0)

  /* If neither the values nor the names are requested, return here.. */
  if ((ret_values == NULL) && (ret_values_names == NULL))
  {
    if (ret_values_num != NULL)
      *ret_values_num = values_num;
    lcc_response_free (&res);
    return (0);
  }

  /* Allocate space for the values */
  if (ret_values != NULL)
  {
    values = (gauge_t *) malloc (values_num * sizeof (*values));
    if (values == NULL)
      BAIL_OUT (ENOMEM);
  }

  if (ret_values_names != NULL)
  {
    values_names = (char **) calloc (values_num, sizeof (*values_names));
    if (values_names == NULL)
      BAIL_OUT (ENOMEM);
  }

  for (i = 0; i < res.lines_num; i++)
  {
    char *key;
    char *value;
    char *endptr;

    key = res.lines[i];
    value = strchr (key, '=');
    if (value == NULL)
      BAIL_OUT (EILSEQ);

    *value = 0;
    value++;

    if (values != NULL)
    {
      endptr = NULL;
      errno = 0;
      values[i] = strtod (value, &endptr);

      if ((endptr == value) || (errno != 0))
        BAIL_OUT (errno);
    }

    if (values_names != NULL)
    {
      values_names[i] = strdup (key);
      if (values_names[i] == NULL)
        BAIL_OUT (ENOMEM);
    }
  } /* for (i = 0; i < res.lines_num; i++) */

  if (ret_values_num != NULL)
    *ret_values_num = values_num;
  if (ret_values != NULL)
    *ret_values = values;
  if (ret_values_names != NULL)
    *ret_values_names = values_names;

  lcc_response_free (&res);

  return (0);
} /* }}} int lcc_getval */
Beispiel #3
0
void test_timed (flux_t *h)
{
    flux_reduce_t *r;
    int i, errors;
    double timeout;

    clear_counts ();

    ok ((r = flux_reduce_create (h, reduce_ops, 0.1, NULL,
                                 FLUX_REDUCE_TIMEDFLUSH)) != NULL,
        "timed: flux_reduce_create works");
    if (!r)
        BAIL_OUT();
    ok (flux_reduce_opt_get (r, FLUX_REDUCE_OPT_TIMEOUT, &timeout,
                             sizeof (timeout)) == 0 && timeout == 0.1,
        "timed: flux_reduce_opt_get TIMEOUT returned timeout");

    /* Append 100 items in batch 0 before starting reactor.
     * Reduction occurs at each append.
     * Nothing should be sinked.
     */
    errors = 0;
    for (i = 0; i < 100; i++) {
        if (flux_reduce_append (r, xstrdup ("hi"), 0) < 0)
            errors++;
    }
    ok (errors == 0,
        "timed.0: flux_reduce_append added 100 items");
    cmp_ok (reduce_calls, "==", 99,
        "timed.0: op.reduce called 99 times");
    cmp_ok (sink_calls, "==", 0,
        "timed.0: op.sink called 0 times");

    /* Start reactor so timeout handler can run.
     * It should fire once and sink all items in one sink call.
     */
    ok (flux_reactor_run (flux_get_reactor (h), 0) == 0,
        "timed.0: reactor completed normally");
    cmp_ok (sink_calls, "==", 1,
        "timed.0: op.sink called 1 time");
    cmp_ok (sink_items, "==", 100,
        "timed.0: op.sink processed 100 items");

    clear_counts ();

    /* Now append one more item to batch 0.
     * It should be immediately flushed.
     */
    ok (flux_reduce_append (r, xstrdup ("hi"), 0) == 0,
        "timed.0: flux_reduce_append added 1 more item");
    cmp_ok (reduce_calls, "==", 0,
        "timed.0: op.reduce not called");
    cmp_ok (sink_calls, "==", 1,
        "timed.0: op.sink called 1 time");
    cmp_ok (sink_items, "==", 1,
        "timed.0: op.sink processed 1 items");

    clear_counts ();

    /* Append 100 items to batch 1.
     * It should behave like the first batch.
     */
    errors = 0;
    for (i = 0; i < 100; i++) {
        if (flux_reduce_append (r, xstrdup ("hi"), 1) < 0)
            errors++;
    }
    ok (errors == 0,
        "timed.1: flux_reduce_append added 100 items");
    cmp_ok (reduce_calls, "==", 99,
        "timed.1: op.reduce called 99 times");
    cmp_ok (sink_calls, "==", 0,
        "timed.1: op.sink called 0 times");

    /* Start reactor so timeout handler can run.
     * It should fire once and sink all items in one sink call.
     */
    ok (flux_reactor_run (flux_get_reactor (h), 0) == 0,
        "timed.1: reactor completed normally");
    cmp_ok (sink_calls, "==", 1,
        "timed.1: op.sink called 1 time");
    cmp_ok (sink_items, "==", 100,
        "timed.1: op.sink processed 100 items");

    flux_reduce_destroy (r);
}
static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
    udb_result_preparation_area_t *prep_area,
    char **column_names, size_t column_num)
{
  size_t i;

  if ((r == NULL) || (prep_area == NULL))
    return (-EINVAL);

#define BAIL_OUT(status) \
  prep_area->ds = NULL; \
  sfree (prep_area->instances_pos); \
  sfree (prep_area->values_pos); \
  sfree (prep_area->metadata_pos); \
  sfree (prep_area->instances_buffer); \
  sfree (prep_area->values_buffer); \
  sfree (prep_area->metadata_buffer); \
  return (status)

  /* Make sure previous preparations are cleaned up. */
  udb_result_finish_result (r, prep_area);
  prep_area->instances_pos = NULL;
  prep_area->values_pos = NULL;
  prep_area->metadata_pos = NULL;

  /* Read `ds' and check number of values {{{ */
  prep_area->ds = plugin_get_ds (r->type);
  if (prep_area->ds == NULL)
  {
    ERROR ("db query utils: udb_result_prepare_result: Type `%s' is not "
        "known by the daemon. See types.db(5) for details.",
        r->type);
    BAIL_OUT (-1);
  }

  if (prep_area->ds->ds_num != r->values_num)
  {
    ERROR ("db query utils: udb_result_prepare_result: The type `%s' "
        "requires exactly %zu value%s, but the configuration specifies %zu.",
        r->type,
        prep_area->ds->ds_num, (prep_area->ds->ds_num == 1) ? "" : "s",
        r->values_num);
    BAIL_OUT (-1);
  }
  /* }}} */

  /* Allocate r->instances_pos, r->values_pos, r->metadata_post,
   * r->instances_buffer, r->values_buffer, and r->metadata_buffer {{{ */
  if (r->instances_num > 0)
  {
    prep_area->instances_pos
      = (size_t *) calloc (r->instances_num, sizeof (size_t));
    if (prep_area->instances_pos == NULL)
    {
      ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
      BAIL_OUT (-ENOMEM);
    }

    prep_area->instances_buffer
      = (char **) calloc (r->instances_num, sizeof (char *));
    if (prep_area->instances_buffer == NULL)
    {
      ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
      BAIL_OUT (-ENOMEM);
    }
  } /* if (r->instances_num > 0) */

  prep_area->values_pos
    = (size_t *) calloc (r->values_num, sizeof (size_t));
  if (prep_area->values_pos == NULL)
  {
    ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
    BAIL_OUT (-ENOMEM);
  }

  prep_area->values_buffer
    = (char **) calloc (r->values_num, sizeof (char *));
  if (prep_area->values_buffer == NULL)
  {
    ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
    BAIL_OUT (-ENOMEM);
  }

  prep_area->metadata_pos
    = (size_t *) calloc (r->metadata_num, sizeof (size_t));
  if (prep_area->metadata_pos == NULL)
  {
    ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
    BAIL_OUT (-ENOMEM);
  }

  prep_area->metadata_buffer
    = (char **) calloc (r->metadata_num, sizeof (char *));
  if (prep_area->metadata_buffer == NULL)
  {
    ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
    BAIL_OUT (-ENOMEM);
  }

  /* }}} */

  /* Determine the position of the plugin instance column {{{ */
  for (i = 0; i < r->instances_num; i++)
  {
    size_t j;

    for (j = 0; j < column_num; j++)
    {
      if (strcasecmp (r->instances[i], column_names[j]) == 0)
      {
        prep_area->instances_pos[i] = j;
        break;
      }
    }

    if (j >= column_num)
    {
      ERROR ("db query utils: udb_result_prepare_result: "
          "Column `%s' could not be found.",
          r->instances[i]);
      BAIL_OUT (-ENOENT);
    }
  } /* }}} for (i = 0; i < r->instances_num; i++) */


  /* Determine the position of the value columns {{{ */
  for (i = 0; i < r->values_num; i++)
  {
    size_t j;

    for (j = 0; j < column_num; j++)
    {
      if (strcasecmp (r->values[i], column_names[j]) == 0)
      {
        prep_area->values_pos[i] = j;
        break;
      }
    }

    if (j >= column_num)
    {
      ERROR ("db query utils: udb_result_prepare_result: "
          "Column `%s' could not be found.",
          r->values[i]);
      BAIL_OUT (-ENOENT);
    }
  } /* }}} for (i = 0; i < r->values_num; i++) */

  /* Determine the position of the metadata columns {{{ */
  for (i = 0; i < r->metadata_num; i++)
  {
    size_t j;

    for (j = 0; j < column_num; j++)
    {
      if (strcasecmp (r->metadata[i], column_names[j]) == 0)
      {
        prep_area->metadata_pos[i] = j;
        break;
      }
    }

    if (j >= column_num)
    {
      ERROR ("db query utils: udb_result_prepare_result: "
          "Metadata column `%s' could not be found.",
          r->values[i]);
      BAIL_OUT (-ENOENT);
    }
  } /* }}} for (i = 0; i < r->metadata_num; i++) */

#undef BAIL_OUT
  return (0);
} /* }}} int udb_result_prepare_result */
Beispiel #5
0
int main (int argc, char *argv[])
{
    const int q_size = 16;
    struct queue *q;
    struct job *j;
    json_t *attrs;
    json_t *badattrs;
    json_t *o;
    json_t *el;
    json_t *id_o;
    flux_jobid_t id;

    plan (NO_PLAN);

    q = make_test_queue (q_size);
    if (!(attrs = json_pack ("[s]", "id")))
        BAIL_OUT ("json_pack failed");

    /* list_job_array */

    o = list_job_array (q, 0, attrs);
    ok (o != NULL && json_is_array (o),
        "list_job_array returns array");
    ok (json_array_size (o) == q_size,
        "array has expected size");
    json_decref (o);

    o = list_job_array (q, 4, attrs);
    ok (o != NULL && json_is_array (o),
        "list_job_array max_entries=4 returns array");
    ok (json_array_size (o) == 4,
        "array has expected size");
    el = json_array_get (o, 1);
    ok (el != NULL && json_is_object (el),
        "array[1] is an object");
    ok ((id_o = json_object_get (el, "id")) != NULL,
        "array[1] id is set");
    id = json_integer_value (id_o);
    ok (id == 1,
        "array[1] id=1");
    if (id != 1)
        diag ("id=%d", (int)id);
    ok (json_object_size (el) == 1,
        "array[1] size=1");
    json_decref (o);

    errno = 0;
    ok (list_job_array (q, -1, attrs) == NULL && errno == EPROTO,
        "list_job_array max_entries < 0 fails with EPROTO");

    errno = 0;
    ok (list_job_array (q, -1, NULL) == NULL && errno == EPROTO,
        "list_job_array attrs=NULL fails with EPROTO");

    /* list_one_job */

    if (!(j = queue_lookup_by_id (q, 0)))
        BAIL_OUT ("queue_lookup_by_id 0 failed");
    if (!(badattrs = json_pack ("[s]", "foo")))
        BAIL_OUT ("json_pack failed");
    errno = 0;
    ok (list_one_job (j, badattrs) == NULL && errno == EINVAL,
        "list_one_job attrs=[\"foo\"] fails with EINVAL");
    json_decref (badattrs);

    if (!(badattrs = json_pack ("[i]", 42)))
        BAIL_OUT ("json_pack failed");
    errno = 0;
    ok (list_one_job (j, badattrs) == NULL && errno == EPROTO,
        "list_one_job attrs=[42] fails with EPROTO");
    json_decref (badattrs);


    json_decref (attrs);
    queue_destroy (q);

    done_testing ();
}
Beispiel #6
0
int main (int ac, char **av)
{
    int rc;
    struct subprocess_manager *sm;
    struct subprocess *p, *q;
    const char *s;
    char *buf;
    char *args[] = { "hello", NULL };
    char *args2[] = { "goodbye", NULL };
    char *args3[] = { "/bin/true", NULL };
    char *args4[] = { "/bin/sleep", "10", NULL };
    int start_fdcount, end_fdcount;

    start_fdcount = fdcount ();
    diag ("initial fd count %d", start_fdcount);

    plan (NO_PLAN);

    if (!(sm = subprocess_manager_create ()))
        BAIL_OUT ("Failed to create subprocess manager");
    ok (sm != NULL, "create subprocess manager");

    diag ("subprocess accessors tests");
    if (!(p = subprocess_create (sm)))
        BAIL_OUT ("Failed to create subprocess handle: %s", strerror (errno));
    ok (p != NULL, "create subprocess handle");

    rc = subprocess_set_args (p, 1, args);
    ok (rc >= 0, "subprocess_set_args: %s", strerror (errno));

    ok (subprocess_get_argc (p) == 1, "subprocess argc is 1");

    s = subprocess_get_arg (p, 0);
    is (s, "hello", "subprocess argv[0] is 'hello'");

    rc = subprocess_argv_append (p, "foo");
    ok (rc >= 0, "subprocess_arg_append");
    ok (subprocess_get_argc (p) == 2, "subprocess argc is now 2");

    s = subprocess_get_arg (p, 2);
    ok (s == NULL, "subprocess_get_arg() out of bounds returns NULL");

    rc = subprocess_set_args (p, 1, args2);
    ok (rc >= 0, "set_args replaces existing");

    s = subprocess_get_arg (p, 0);
    is (s, "goodbye", "subprocess argv[0] is 'goodbye'");

    rc = subprocess_setenv (p, "FOO", "bar", 1);
    ok (rc >= 0, "subprocess_setenv");

    s = subprocess_getenv (p, "FOO");
    is (s, "bar", "subprocess_getenv works");

    rc = subprocess_setenv (p, "FOO", "bar2", 0);
    ok (rc == -1, "subprocess_setenv without overwrite fails for existing var");
    ok (errno == EEXIST, "and with appropriate errno");

    s = subprocess_getenv (p, "FOO");
    is (s, "bar", "subproces_getenv still shows correct variable");

    subprocess_unsetenv (p, "FOO");
    s = subprocess_getenv (p, "FOO");
    ok (s == NULL, "subproces_getenv fails for unset variable");

    rc = subprocess_setenvf (p, "FOO", 1, "%d", 42);
    ok (rc >= 0, "subprocess_setenvf");

    s = subprocess_getenv (p, "FOO");
    is (s, "42", "subprocess_getenv works after setenvf");

    is (subprocess_state_string (p), "Pending",
        "Unstarted process has state 'Pending'");

    subprocess_destroy (p);
    diag ("fd count after subproc create/destroy %d", fdcount ());

    /* Test running an executable */
    diag ("test subprocess_manager_run");
    p = subprocess_manager_run (sm, 1, args3, NULL);
    ok (p != NULL, "subprocess_manager_run");
    ok (subprocess_pid (p) != (pid_t) -1, "process has valid pid");

    q = subprocess_manager_wait (sm);
    ok (p == q, "subprocess_manager_wait returns correct process");

    ok (subprocess_exited (p), "subprocess has exited after wait returns");
    is (subprocess_state_string (p), "Exited", "State is now 'Exited'");
    ok (subprocess_exit_code (p) == 0, "With expected exit code");
    subprocess_destroy (p);
    q = NULL;

    /*  Test failing program */
    diag ("test expected failure from subprocess_manager_run");
    args3[0] = "/bin/false";
    p = subprocess_manager_run (sm, 1, args3, NULL);
    if (p) {
        ok (p != NULL, "subprocess_manager_run");
        ok (subprocess_pid (p) != (pid_t) -1, "process has valid pid");
        q = subprocess_manager_wait (sm);
        ok (p == q, "subprocess_manager_wait returns correct process");
        is (subprocess_state_string (p), "Exited", "State is now 'Exited'");
        is (subprocess_exit_string (p), "Exited with non-zero status",
                "State is now 'Exited with non-zero status'");
        ok (subprocess_exit_code (p) == 1, "Exit code is 1.");
        subprocess_destroy (p);
        q = NULL;
    }

    diag ("Test signaled program");

    /* Test signaled program */
    p = subprocess_manager_run (sm, 2, args4, NULL);
    ok (p != NULL, "subprocess_manager_run: %s", strerror (errno));
    if (p) {
        ok (subprocess_pid (p) != (pid_t) -1, "process has valid pid");

        ok (subprocess_kill (p, SIGKILL) >= 0, "subprocess_kill");

        q = subprocess_manager_wait (sm);
        ok (p == q, "subprocess_manager_wait returns correct process");
        is (subprocess_state_string (p), "Exited", "State is now 'Exited'");
        is (subprocess_exit_string (p), "Killed", "Exit string is 'Killed'");
        ok (subprocess_signaled (p) == 9, "Killed by signal 9.");
        ok (subprocess_exit_status (p) == 0x9, "Exit status is 0x9 (Killed)");
        ok (subprocess_exit_code (p) == 137, "Exit code is 137 (128+9)");
        subprocess_destroy (p);
    }

    q = NULL;

    diag ("Test fork/exec interface");
    /* Test separate fork/exec interface */
    p = subprocess_create (sm);
    ok (p != NULL, "subprocess_create works");
    ok (subprocess_pid (p) == (pid_t) -1, "Initial pid value is -1");
    ok (subprocess_fork (p) == -1, "fork on unitialized subprocess should fail");
    ok (subprocess_kill (p, 1) == -1, "kill on unitialized subprocess should fail");
    is (subprocess_state_string (p), "Pending",
        "initial subprocess state is 'Pending'");

    ok (subprocess_argv_append (p, "true") >= 0, "set argv");
    ok (subprocess_setenv (p, "PATH", getenv ("PATH"), 1) >= 0, "set dnv");

    ok (subprocess_fork (p) == 0, "subprocess_fork");
    is (subprocess_state_string (p), "Waiting", "subprocess is Waiting");
    ok (subprocess_pid (p) > 0, "subprocess_pid() is valid");

    ok (subprocess_exec (p) == 0, "subprocess_run");
    is (subprocess_state_string (p), "Running", "subprocess is Running");
    q = subprocess_manager_wait (sm);
    ok (q != NULL, "subprocess_manager_wait");
    ok (q == p, "got correct child after wait");

    ok (subprocess_exit_code (p) == 0, "Child exited normally");

    subprocess_destroy (p);
    q = NULL;

    diag ("Test exec failure");
    /* Test exec failure */
    p = subprocess_create (sm);
    ok (p != NULL, "subprocess create");
    ok (subprocess_argv_append (p, "/unlikely/program") >= 0, "set argv");
    ok (subprocess_setenv (p, "PATH", getenv ("PATH"), 1) >= 0, "setnv");

    ok (subprocess_fork (p) == 0, "subprocess_fork");
    rc = subprocess_exec (p);
    ok (rc < 0, "subprocess_exec should fail");
    ok (errno == ENOENT, "errno should be ENOENT");
    is (subprocess_state_string (p), "Exec Failure", "State is Exec Failed");
    is (subprocess_exit_string (p), "Exec Failure", "Exit state is Exec Failed");
    subprocess_destroy (p);

    diag ("Test set working directory");
    /* Test set working directory */
    p = subprocess_create (sm);
    ok (p != NULL, "subprocess create");
    ok (subprocess_get_cwd (p) == NULL, "CWD is not set");
    ok (subprocess_set_cwd (p, "/tmp") >= 0, "Set CWD to /tmp");
    is (subprocess_get_cwd (p), "/tmp", "CWD is now /tmp");
    ok (subprocess_setenv (p, "PATH", getenv ("PATH"), 1) >= 0, "set PATH");
    ok (subprocess_set_command (p, "test `pwd` = '/tmp'" ) >= 0, "Set args");
    ok (subprocess_run (p) >= 0, "subprocess_run");
    is (subprocess_state_string (p), "Running", "subprocess now running");
    q = subprocess_manager_wait (sm);
    ok (q != NULL, "subprocess_manager_wait: %s", strerror (errno));
    ok (q == p, "subprocess_manager_wait() got expected subprocess");
    ok (subprocess_exited (p), "subprocess exited");
    ok (!subprocess_signaled (p), "subprocess didn't die from signal");
    ok (subprocess_exit_code (p) == 0, "subprocess successfully run in /tmp");
    subprocess_destroy (p);

    diag ("Test subprocess_reap interface");
    /* Test subprocess_reap */
    p = subprocess_create (sm);
    q = subprocess_create (sm);

    ok (subprocess_argv_append (p, "/bin/true") >= 0,
        "set argv for first subprocess");
    ok (subprocess_argv_append (q, "/bin/true") >= 0,
        "set argv for second subprocess");
    ok (subprocess_run (p) >= 0, "run process 1");
    ok (subprocess_run (q) >= 0, "run process 2");

    ok (subprocess_reap (q) >= 0, "reap process 2");
    ok (subprocess_exited (q), "process 2 is now exited");
    ok (subprocess_exit_code (q) == 0, "process 2 exited with code 0");

    ok (subprocess_reap (p) >= 0, "reap process 1");
    ok (subprocess_exited (p), "process 1 is now exited");
    ok (subprocess_exit_code (p) == 0, "process 1 exited with code 0");

    subprocess_destroy (p);
    subprocess_destroy (q);

    diag ("Test subprocess I/O");
    /* Test subprocess output */
    p = subprocess_create (sm);
    ok (p != NULL, "subprocess_create");
    ok (subprocess_argv_append (p, "/bin/echo") >= 0,  "subprocess_argv_append");
    ok (subprocess_argv_append (p, "Hello, 123") >= 0, "subprocess_argv_append");

    buf = NULL;
    subprocess_set_context (p, "io", (void *) &buf);
    ok (subprocess_get_context (p, "io") == (void *) &buf, "able to set subprocess context");

    ok (subprocess_set_io_callback (p, testio_cb) >= 0, "set io callback");

    ok (subprocess_run (p) >= 0, "run process with IO");

    ok (subprocess_reap (p) >= 0, "reap process");
    ok (subprocess_flush_io (p) >=0, "flush io");

    ok (subprocess_exited (p) >= 0, "process is now exited");
    ok (subprocess_exit_code (p) == 0, "process exited normally");

    ok (buf != NULL, "io buffer is allocated");
    if (buf) {
        ok (strcmp (buf, "Hello, 123\n") == 0, "io buffer is correct");
        free (buf);
    }
    subprocess_destroy (p);


    /* Test subprocess input */
    diag ("test subprocess stdin");
    p = subprocess_create (sm);
    ok (p != NULL, "subprocess_create");
    ok (subprocess_argv_append (p, "/bin/cat") >= 0,  "subprocess_argv_append");

    buf = NULL;
    subprocess_set_context (p, "io", (void *) &buf);
    ok (subprocess_get_context (p, "io") == (void *) &buf, "able to set subprocess context");

    ok (subprocess_set_io_callback (p, testio_cb) >= 0, "set io callback");

    ok (subprocess_run (p) >= 0, "run process with IO");

    ok (subprocess_write (p, "Hello\n", 7, true) >= 0, "write to subprocess");
    ok (subprocess_reap (p) >= 0, "reap process");
    ok (subprocess_flush_io (p) >= 0, "manually flush io");
    ok (subprocess_io_complete (p) == 1, "io is now complete");

    ok (subprocess_exited (p) >= 0, "process is now exited");
    ok (subprocess_exit_code (p) == 0, "process exited normally");

    ok (buf != NULL, "io buffer is allocated");
    if (buf) {
        ok (strcmp (buf, "Hello\n") == 0, "io buffer is correct");
        free (buf);
    }
    subprocess_destroy (p);
    subprocess_manager_destroy (sm);

    end_fdcount = fdcount ();
    diag ("final fd count %d", end_fdcount);
    ok (start_fdcount == end_fdcount,
        "no file descriptors were leaked");

    done_testing ();
}
Beispiel #7
0
int main(int argc, char** argv)
{
    const char *tmp = getenv ("TMPDIR");
    char file[PATH_MAX];
    char dir[PATH_MAX];
    char dir2[PATH_MAX];
    struct stat sb;
    int fd, len;

    plan (NO_PLAN);

    /* Independent file and dir
     */
    len = snprintf (file, sizeof (file), "%s/cleanup_test.XXXXXX", tmp ? tmp : "/tmp");
    if ((len < 0) || (len >= sizeof (file)))
        BAIL_OUT ("snprintf failed creating tmp file path");
    if (!(fd = mkstemp (file)))
        BAIL_OUT ("could not create tmp file");
    close (fd);

    len = snprintf (dir, sizeof (dir), "%s/cleanup_test.XXXXXX", tmp ? tmp : "/tmp");
    if ((len < 0) || (len >= sizeof (dir)))
        BAIL_OUT ("snprintf failed creating tmp directory");
    if (!mkdtemp (dir))
        BAIL_OUT ("could not create tmp directory");

    cleanup_push_string (cleanup_file, file);
    cleanup_push_string (cleanup_directory, dir);
    cleanup_run ();
    ok (stat (file, &sb) < 0 && errno == ENOENT,
        "cleanup removed independent file");
    ok (stat (dir, &sb) < 0 && errno == ENOENT,
        "cleanup removed independent dir");

    /* This time put file inside directory
     */
    len = snprintf (dir, sizeof (dir), "%s/cleanup_test.XXXXXX", tmp ? tmp : "/tmp");
    if ((len < 0) || (len >= sizeof (dir)))
        BAIL_OUT ("snprintf failed creating tmp directory");
    if (!mkdtemp (dir))
        BAIL_OUT ("could not create tmp directory");

    len = snprintf (file, sizeof (file), "%s/file", dir);
    if ((len < 0) || (len >= sizeof (file)))
        BAIL_OUT ("snprintf failed creating tmp file path");
    if (!(fd = open (file, O_CREAT, 0644)))
        BAIL_OUT ("could not create tmp file");
    close (fd);

    cleanup_push_string (cleanup_directory, dir);
    cleanup_push_string (cleanup_file, file);
    cleanup_run ();
    ok (stat (file, &sb) < 0 && errno == ENOENT,
        "cleanup removed file pushed second");
    ok (stat (dir, &sb) < 0 && errno == ENOENT,
        "cleanup removed dir pushed first");

    /* Same but reverse push order
     */
    len = snprintf (dir, sizeof (dir), "%s/cleanup_test.XXXXXX", tmp ? tmp : "/tmp");
    if ((len < 0) || (len >= sizeof (dir)))
        BAIL_OUT ("snprintf failed creating tmp directory");
    if (!mkdtemp (dir))
        BAIL_OUT ("could not create tmp directory");

    len = snprintf (file, sizeof (file), "%s/file", dir);
    if ((len < 0) || (len >= sizeof (file)))
        BAIL_OUT ("snprintf failed creating tmp file path");
    if (!(fd = open (file, O_CREAT, 0644)))
        BAIL_OUT ("could not create tmp file");
    close (fd);

    cleanup_push_string (cleanup_file, file);
    cleanup_push_string (cleanup_directory, dir);
    cleanup_run ();
    ok (stat (dir, &sb) == 0,
        "cleanup failed to remove dir pushed first");
    ok (stat (file, &sb) < 0 && errno == ENOENT,
        "cleanup removed file pushed second (1 deep)");

    if (rmdir (dir) < 0)
        BAIL_OUT ("rmdir %s failed", dir);

    /* Same but recursive removal
     */
    len = snprintf (dir, sizeof (dir), "%s/cleanup_test.XXXXXX", tmp ? tmp : "/tmp");
    if ((len < 0) || (len >= sizeof (dir)))
        BAIL_OUT ("snprintf failed creating tmp directory");
    if (!mkdtemp (dir))
        BAIL_OUT ("could not create tmp directory");

    len = snprintf (file, sizeof (file), "%s/file", dir);
    if ((len < 0) || (len >= sizeof (file)))
        BAIL_OUT ("snprintf failed creating tmp file path");
    if (!(fd = open (file, O_CREAT, 0644)))
        BAIL_OUT ("could not create tmp file");
    close (fd);

    cleanup_push_string (cleanup_directory_recursive, dir);
    cleanup_run ();

    ok (stat (file, &sb) < 0 && errno == ENOENT,
        "cleanup removed file not pushed (1 deep)");
    ok (stat (dir, &sb) < 0 && errno == ENOENT,
        "cleanup removed pushed dir recursively");

    /* Try couple levels deep
     */
    len = snprintf (dir, sizeof (dir), "%s/cleanup_test.XXXXXX", tmp ? tmp : "/tmp");
    if ((len < 0) || (len >= sizeof (dir)))
        BAIL_OUT ("snprintf failed creating tmp dir path");
    if (!mkdtemp (dir))
        BAIL_OUT ("could not create tmp directory");
    len = snprintf (dir2, sizeof (dir2), "%s/dir", dir);
    if ((len < 0) || (len >= sizeof (dir2)))
        BAIL_OUT ("snprintf failed creating tmp dir path");
    if (mkdir (dir2, 0755) < 0)
        BAIL_OUT ("mkdir failed");

    len = snprintf (file, sizeof (file), "%s/file", dir2);
    if ((len < 0) || (len >= sizeof (file)))
        BAIL_OUT ("snprintf failed creating tmp file path");
    if (!(fd = open (file, O_CREAT, 0644)))
        BAIL_OUT ("could not create tmp file");
    close (fd);

    cleanup_push_string (cleanup_directory_recursive, dir);
    cleanup_run ();

    ok (stat (file, &sb) < 0 && errno == ENOENT,
        "cleanup removed file not pushed (2 deep)");
    ok (stat (dir2, &sb) < 0 && errno == ENOENT,
        "cleanup removed dir not pushed (1 deep)");
    ok (stat (dir, &sb) < 0 && errno == ENOENT,
        "cleanup removed pushed dir recursively");

    done_testing();
}
Beispiel #8
0
int main (int argc, char *argv[])
{
    struct queue *q;
    struct job *job[3];
    struct job *njob[2];
    struct job *j, *j_prev;

    plan (NO_PLAN);

    q = queue_create (true);
    if (!q)
        BAIL_OUT ("could not create queue");
    ok (queue_size (q) == 0,
        "queue_size returns 0");

    /* insert 1,2,3 */

    job[0] = job_create_test (1, FLUX_JOB_PRIORITY_DEFAULT);
    job[1] = job_create_test (2, FLUX_JOB_PRIORITY_DEFAULT);
    job[2] = job_create_test (3, FLUX_JOB_PRIORITY_DEFAULT);
    ok (queue_insert (q, job[0], &job[0]->queue_handle) == 0,
        "queue_insert 1 pri=def");
    ok (queue_insert (q, job[1], &job[1]->queue_handle) == 0,
        "queue_insert 2 pri=def");
    ok (queue_insert (q, job[2], &job[2]->queue_handle) == 0,
        "queue_insert 3 pri=def");

    errno = 0;
    ok (queue_insert (q, job[2], &job[2]->queue_handle) < 0 && errno == EEXIST,
        "queue_insert 3 again fails with EEXIST");

    /* queue size, refcounts */

    ok (queue_size (q) == 3,
        "queue_size returns 3");
    ok (job[0]->refcount == 2 && job[1]->refcount == 2 && job[2]->refcount == 2,
        "queue took reference on inserted jobs");

    /* iterators */

    ok (queue_first (q) == job[0] && queue_next (q) == job[1]
                                  && queue_next (q) == job[2]
                                  && queue_next (q) == NULL,
        "queue iterators return job 1,2,3,NULL");

    /* lookup_by_id */

    ok (queue_lookup_by_id (q, 1) == job[0]
        && queue_lookup_by_id (q, 2) == job[1]
        && queue_lookup_by_id (q, 3) == job[2],
        "queue_lookup_by_id works for all three jobs");
    errno = 0;
    ok (queue_lookup_by_id (q, 42) == NULL && errno == ENOENT,
        "queue_lookupby_id 42 fails with ENOENT");

    /* insert high priority */

    njob[0] = job_create_test (100, FLUX_JOB_PRIORITY_MAX);
    ok (queue_insert (q, njob[0], &njob[0]->queue_handle) == 0,
        "queue_insert 100 pri=max");
    ok (queue_first (q) == njob[0],
        "queue_first returns high priority job");

    /* insert low priority */

    njob[1] = job_create_test (101, FLUX_JOB_PRIORITY_MIN);
    ok (queue_insert (q, njob[1], &njob[1]->queue_handle) == 0,
        "queue_insert 101 pri=min");

    j_prev = NULL;
    j = queue_first (q);
    while (j) {
        j_prev = j;
        j = queue_next (q);
    }
    ok (j_prev == njob[1],
        "iterators find low priority job last");

    /* set high priority and reorder
     *   review: queue contains 100,1,2,3,101
     */
    job[2]->priority = FLUX_JOB_PRIORITY_MAX; // job 3
    queue_reorder (q, job[2], job[2]->queue_handle);
    ok (queue_first (q) == job[2],
        "reorder job 3 pri=max moves that job first");

    /* queue_delete */

    queue_delete (q, njob[0], njob[0]->queue_handle);
    queue_delete (q, njob[1], njob[1]->queue_handle);

    ok (njob[0]->refcount == 1 && njob[1]->refcount == 1,
        "queue_delete dropped reference on jobs");

    errno = 0;
    ok (queue_lookup_by_id (q, 100) == NULL && errno == ENOENT,
        "queue_lookup_by_id on deleted job fails with ENOENT");

    /* destroy */

    queue_destroy (q);
    ok (job[0]->refcount == 1 && job[1]->refcount == 1
                              && job[2]->refcount == 1,
        "queue dropped reference on jobs at destruction");

    job_decref (job[0]);
    job_decref (job[1]);
    job_decref (job[2]);

    job_decref (njob[0]);
    job_decref (njob[1]);

    done_testing ();
}
Beispiel #9
0
static void fatal_err (const char *message, void *arg)
{
    BAIL_OUT ("fatal error: %s", message);
}
Beispiel #10
0
static void
handle_core_signal(int signo)
{
    BAIL_OUT("Signal %d thrown", signo);
}
Beispiel #11
0
int main (int argc, char **argv)
{
    flux_t h;
    heartbeat_t *hb;
    flux_msg_handler_t *w;

    plan (18);

    check_codec ();

    (void)setenv ("FLUX_CONNECTOR_PATH",
                  flux_conf_get ("connector_path", CONF_FLAG_INTREE), 0);
    ok ((h = flux_open ("loop://", 0)) != NULL,
        "opened loop connector");
    if (!h)
        BAIL_OUT ("can't continue without loop handle");
    flux_fatal_set (h, fatal_err, NULL);

    ok ((hb = heartbeat_create ()) != NULL,
        "heartbeat_create works");

    heartbeat_set_flux (hb, h);

    ok (heartbeat_get_rate (hb) == 2.,
        "heartbeat_get_rate returns default of 2s");
    errno = 0;
    ok (heartbeat_set_rate (hb, -1) < 1 && errno == EINVAL,
        "heartbeat_set_rate -1 fails with EINVAL");
    errno = 0;
    ok (heartbeat_set_rate (hb, 1000000) < 1 && errno == EINVAL,
        "heartbeat_set_rate 1000000 fails with EINVAL");
    ok (heartbeat_set_ratestr (hb, "250ms") == 0,
        "heartbeat_set_ratestr 250ms works");
    ok (heartbeat_get_rate (hb) == 0.250,
        "heartbeat_get_rate returns what was set");
    ok (heartbeat_set_rate (hb, 0.1) == 0,
        "heartbeat_set_rate 0.1 works");
    ok (heartbeat_get_rate (hb) == 0.1,
        "heartbeat_get_rate returns what was set");

    ok (heartbeat_get_epoch (hb) == 0,
        "heartbeat_get_epoch works, default is zero");

    w = flux_msg_handler_create (h, FLUX_MATCH_EVENT, heartbeat_event_cb, hb);
    ok (w != NULL,
        "created event watcher");
    flux_msg_handler_start (w);

    ok (heartbeat_start (hb) == 0,
        "heartbeat_start works");

    ok (flux_reactor_run (flux_get_reactor (h), 0) == 0,
        "flux reactor exited normally");

    heartbeat_destroy (hb);
    flux_msg_handler_destroy (w);
    flux_close (h);

    done_testing ();
    return 0;
}
Beispiel #12
0
static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q)
{
	PGresult *res;

	c_psql_user_data_t *data;

	const char *host;

	char **column_names;
	char **column_values;
	int    column_num;

	int rows_num;
	int status;
	int row, col;

	/* The user data may hold parameter information, but may be NULL. */
	data = udb_query_get_user_data (q);

	/* Versions up to `3' don't know how to handle parameters. */
	if (3 <= db->proto_version)
		res = c_psql_exec_query_params (db, q, data);
	else if ((NULL == data) || (0 == data->params_num))
		res = c_psql_exec_query_noparams (db, q);
	else {
		log_err ("Connection to database \"%s\" does not support parameters "
				"(protocol version %d) - cannot execute query \"%s\".",
				db->database, db->proto_version,
				udb_query_get_name (q));
		return -1;
	}

	column_names = NULL;
	column_values = NULL;

#define BAIL_OUT(status) \
	sfree (column_names); \
	sfree (column_values); \
	PQclear (res); \
	return status

	if (PGRES_TUPLES_OK != PQresultStatus (res)) {
		log_err ("Failed to execute SQL query: %s",
				PQerrorMessage (db->conn));
		log_info ("SQL query was: %s",
				udb_query_get_statement (q));
		BAIL_OUT (-1);
	}

	rows_num = PQntuples (res);
	if (1 > rows_num) {
		BAIL_OUT (0);
	}

	column_num = PQnfields (res);
	column_names = (char **) calloc (column_num, sizeof (char *));
	if (NULL == column_names) {
		log_err ("calloc failed.");
		BAIL_OUT (-1);
	}

	column_values = (char **) calloc (column_num, sizeof (char *));
	if (NULL == column_values) {
		log_err ("calloc failed.");
		BAIL_OUT (-1);
	}
	
	for (col = 0; col < column_num; ++col) {
		/* Pointers returned by `PQfname' are freed by `PQclear' via
		 * `BAIL_OUT'. */
		column_names[col] = PQfname (res, col);
		if (NULL == column_names[col]) {
			log_err ("Failed to resolv name of column %i.", col);
			BAIL_OUT (-1);
		}
	}

	if (C_PSQL_IS_UNIX_DOMAIN_SOCKET (db->host)
			|| (0 == strcmp (db->host, "localhost")))
		host = hostname_g;
	else
		host = db->host;

	status = udb_query_prepare_result (q, host, "postgresql",
			db->database, column_names, (size_t) column_num);
	if (0 != status) {
		log_err ("udb_query_prepare_result failed with status %i.",
				status);
		BAIL_OUT (-1);
	}

	for (row = 0; row < rows_num; ++row) {
		for (col = 0; col < column_num; ++col) {
			/* Pointers returned by `PQgetvalue' are freed by `PQclear' via
			 * `BAIL_OUT'. */
			column_values[col] = PQgetvalue (res, row, col);
			if (NULL == column_values[col]) {
				log_err ("Failed to get value at (row = %i, col = %i).",
						row, col);
				break;
			}
		}

		/* check for an error */
		if (col < column_num)
			continue;

		status = udb_query_handle_result (q, column_values);
		if (status != 0) {
			log_err ("udb_query_handle_result failed with status %i.",
					status);
		}
	} /* for (row = 0; row < rows_num; ++row) */

	BAIL_OUT (0);
#undef BAIL_OUT
} /* c_psql_exec_query */
/**
 * @brief Validate iterator
 * @details Uses the iterator to walk the JSON tree and validates that all items is visited in the right order
 *
 * @param jsmn_tokens [description]
 * @param jsmn_len [description]
 *
 * @return [description]
 */
int iterator_validate(jsmntok_t *jsmn_tokens, unsigned int jsmn_len) {

    jsmn_iterator_t stack[1024];

    jsmntok_t *jsmn_value = NULL;
    jsmntok_t *jsmn_identifier = NULL;

    unsigned int jsmn_iterator_index = 1;
    unsigned int stack_index = 0;
    unsigned int iterator_hint = 0;
    int exit_line = 0;
    int ret_value;

#define JSMN_INDEX(_item_) (unsigned int)(_item_ - jsmn_tokens)
#define BAIL_OUT() do { exit_line = __LINE__; goto error_out; } while(0)

    /* Setup root item */
    stack_index = 0;
    if ((ret_value = jsmn_iterator_init(&stack[stack_index], jsmn_tokens, jsmn_len, 0)) < 0) {
        BAIL_OUT();
    }

    /* Set hint to first item */
    iterator_hint = 1;

    /* Index for first item */
    jsmn_iterator_index = 1;

    /* Iterate over all items, only abort on error. We don't pass iterator_hint which means
       that the iterator will fallback to internal function to determine where next object begins*/
    while ((ret_value = jsmn_iterator_next(&stack[stack_index], &jsmn_identifier, &jsmn_value, 0)) >= 0) {
        /* No more items, need to pop stack if possible */
        if (ret_value == 0) {
            /* Back at root item, so bail out */
            if (stack_index == 0)
                break;

            /* parser_pos should point at the index after the current Array/Object,
               we use it to hint to the outer Array/Object where next item is */
            iterator_hint = stack[stack_index].parser_pos;

            /* Pop the stack */
            stack_index--;

            /* Continue using new stack pointer */
            continue;
        }

        /* Validate that iterator hint is correct (need to compensate for Object) */
        if (iterator_hint != JSMN_INDEX(jsmn_value) - (jsmn_identifier ? 1 : 0))
            BAIL_OUT();

        /* We have identifier so we are inside object, add this before the value */
        if (jsmn_identifier) {
            if (jsmn_iterator_index != JSMN_INDEX(jsmn_identifier))
                BAIL_OUT();
            jsmn_iterator_index++;
        }

        if (jsmn_iterator_index != JSMN_INDEX(jsmn_value))
            BAIL_OUT();
        jsmn_iterator_index++;

        /* Always put iterator_hint to the next value, if end of Array/Object it will
           be updated when popping the stack */
        iterator_hint = JSMN_INDEX(jsmn_value) + 1;

        /* Need to handle sublevels before next object */
        if (jsmn_value->type == JSMN_OBJECT || jsmn_value->type == JSMN_ARRAY) {
            if (stack_index + 1 >= countof(stack))
                BAIL_OUT();

            /* Initiate new iterator on the stack */
            if (jsmn_iterator_init(&stack[stack_index + 1], jsmn_tokens, jsmn_len, stack[stack_index].parser_pos) < 0)
                BAIL_OUT();

            /* Update stack pointer */
            stack_index++;
        }
    }

    /* Check for error abort of while loop */
    if (ret_value != 0)
        BAIL_OUT();

    /* Check so we have visited all items */
    if (jsmn_iterator_index != jsmn_len)
        BAIL_OUT();

    return 0;
error_out:
    printf("exit_line: %d\r\n", exit_line);

    if (jsmn_iterator_index != jsmn_len) {
        return (int)jsmn_iterator_index;
    }

    return -100;
}
Beispiel #14
0
int main (int ac, char *av[])
{
    struct idset *ids = NULL;
    struct rnode *n = NULL;

    plan (NO_PLAN);

    if (!(n = rnode_create (0, "0-3")))
        BAIL_OUT ("could not create an rnode object");
    ok (rnode_avail (n) == 4,
        "rnode_avail == 4");

    ok (rnode_alloc (n, 5, &ids) < 0 && errno == ENOSPC,
        "rnode_alloc too many cores returns errno ENOSPC");

    rnode_alloc_and_check (n, 1, "0");
    ok (rnode_avail (n) == 3,
        "rnode_avail == 3");
    rnode_avail_check (n, "1-3");

    rnode_alloc_and_check (n, 1, "1");
    ok (rnode_avail (n) == 2,
        "rnode_avail == 2");
    rnode_avail_check (n, "2-3");

    rnode_alloc_and_check (n, 2, "2-3");
    ok (rnode_avail (n) == 0,
        "rnode_avail == 0");
    rnode_avail_check (n, "");

    ok (rnode_alloc (n, 1, &ids) < 0 && errno == ENOSPC && ids == NULL,
        "rnode_alloc on empty rnode fails with ENOSPC");

    ok (rnode_free (n, "3-4") < 0 && errno == ENOENT,
        "rnode_free with invalid ids fails");
    ok (rnode_avail (n) == 0,
        "rnode_avail still is 0");
    rnode_avail_check (n, "");

    ok (rnode_free (n, "0-1") == 0,
        "rnode_free (0-1) works");
    ok (rnode_avail (n) == 2,
        "rnode_avail now is 2");
    rnode_avail_check (n, "0-1");
    ok (rnode_free (n, "0") < 0 && errno == EEXIST,
        "rnode_free of already available id fails");
    ok (rnode_avail (n) == 2,
        "rnode_avail is still 2");
    ok (rnode_free (n, "3") == 0,
        "rnode_free '3' works");
    rnode_avail_check (n, "0-1,3");

    rnode_alloc_and_check (n, 3, "0-1,3");

    rnode_destroy (n);

    n = rnode_create_count (1, 8);
    if (n == NULL)
        BAIL_OUT ("rnode_create_count failed");
    ok (n->rank == 1, "rnode rank set correctly");
    ok (n != NULL, "rnode_create_count");
    rnode_avail_check (n, "0-7");
    rnode_destroy (n);

    struct idset *idset = idset_decode ("0-3");
    n = rnode_create_idset (3, idset);
    idset_destroy (idset);
    if (n == NULL)
        BAIL_OUT ("rnode_create_idset failed");
    ok (n != NULL, "rnode_create_idset");
    ok (n->rank == 3, "rnode rank set correctly");
    rnode_avail_check (n, "0-3");

    struct idset *alloc = idset_decode ("1,3");
    ok (rnode_alloc_idset (n, alloc) == 0,
        "rnode_alloc_idset (1,3)");
    rnode_avail_check (n, "0,2");
    ok (rnode_alloc_idset (n, alloc) < 0 && errno == EEXIST,
        "rnode_alloc_idset with idset already allocated returns EEXIST");

    ok (rnode_free_idset (n, alloc) == 0,
        "rnode_free_idset (1,3)");
    rnode_avail_check (n, "0-3");

    ok (rnode_free_idset (n, alloc) < 0 && errno == EEXIST,
        "rnode_free_idset with idset already available returns EEXIST");

    idset_destroy (alloc);
    alloc = idset_decode ("4-7");
    ok (rnode_alloc_idset (n, alloc) < 0 && errno == ENOENT,
        "rnode_alloc_idset with invalid ids return ENOENT");
    ok (rnode_free_idset (n, alloc) < 0 && errno == ENOENT,
        "rnode_free_idset with invalid ids return ENOENT");

    idset_destroy (alloc);
    rnode_destroy (n);
    done_testing ();
}
Beispiel #15
0
/* db->db_lock must be locked when calling this function */
static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q,
		udb_query_preparation_area_t *prep_area)
{
	PGresult *res;

	c_psql_user_data_t *data;

	const char *host;

	char **column_names;
	char **column_values;
	int    column_num;

	int rows_num;
	int status;
	int row, col;

	/* The user data may hold parameter information, but may be NULL. */
	data = udb_query_get_user_data (q);

	/* Versions up to `3' don't know how to handle parameters. */
	if (3 <= db->proto_version)
		res = c_psql_exec_query_params (db, q, data);
	else if ((NULL == data) || (0 == data->params_num))
		res = c_psql_exec_query_noparams (db, q);
	else {
		log_err ("Connection to database \"%s\" (%s) does not support "
				"parameters (protocol version %d) - "
				"cannot execute query \"%s\".",
				db->database, db->instance, db->proto_version,
				udb_query_get_name (q));
		return -1;
	}

	/* give c_psql_write() a chance to acquire the lock if called recursively
	 * through dispatch_values(); this will happen if, both, queries and
	 * writers are configured for a single connection */
	pthread_mutex_unlock (&db->db_lock);

	column_names = NULL;
	column_values = NULL;

	if (PGRES_TUPLES_OK != PQresultStatus (res)) {
		pthread_mutex_lock (&db->db_lock);

		if ((CONNECTION_OK != PQstatus (db->conn))
				&& (0 == c_psql_check_connection (db))) {
			PQclear (res);
			return c_psql_exec_query (db, q, prep_area);
		}

		log_err ("Failed to execute SQL query: %s",
				PQerrorMessage (db->conn));
		log_info ("SQL query was: %s",
				udb_query_get_statement (q));
		PQclear (res);
		return -1;
	}

#define BAIL_OUT(status) \
	sfree (column_names); \
	sfree (column_values); \
	PQclear (res); \
	pthread_mutex_lock (&db->db_lock); \
	return status

	rows_num = PQntuples (res);
	if (1 > rows_num) {
		BAIL_OUT (0);
	}

	column_num = PQnfields (res);
	column_names = (char **) calloc (column_num, sizeof (char *));
	if (NULL == column_names) {
		log_err ("calloc failed.");
		BAIL_OUT (-1);
	}

	column_values = (char **) calloc (column_num, sizeof (char *));
	if (NULL == column_values) {
		log_err ("calloc failed.");
		BAIL_OUT (-1);
	}
	
	for (col = 0; col < column_num; ++col) {
		/* Pointers returned by `PQfname' are freed by `PQclear' via
		 * `BAIL_OUT'. */
		column_names[col] = PQfname (res, col);
		if (NULL == column_names[col]) {
			log_err ("Failed to resolve name of column %i.", col);
			BAIL_OUT (-1);
		}
	}

	if (C_PSQL_IS_UNIX_DOMAIN_SOCKET (db->host)
			|| (0 == strcmp (db->host, "127.0.0.1"))
			|| (0 == strcmp (db->host, "localhost")))
		host = hostname_g;
	else
		host = db->host;

	status = udb_query_prepare_result (q, prep_area, host, "postgresql",
			db->instance, column_names, (size_t) column_num, db->interval);
	if (0 != status) {
		log_err ("udb_query_prepare_result failed with status %i.",
				status);
		BAIL_OUT (-1);
	}

	for (row = 0; row < rows_num; ++row) {
		for (col = 0; col < column_num; ++col) {
			/* Pointers returned by `PQgetvalue' are freed by `PQclear' via
			 * `BAIL_OUT'. */
			column_values[col] = PQgetvalue (res, row, col);
			if (NULL == column_values[col]) {
				log_err ("Failed to get value at (row = %i, col = %i).",
						row, col);
				break;
			}
		}

		/* check for an error */
		if (col < column_num)
			continue;

		status = udb_query_handle_result (q, prep_area, column_values);
		if (status != 0) {
			log_err ("udb_query_handle_result failed with status %i.",
					status);
		}
	} /* for (row = 0; row < rows_num; ++row) */

	udb_query_finish_result (q, prep_area);

	BAIL_OUT (0);
#undef BAIL_OUT
} /* c_psql_exec_query */
Beispiel #16
0
int main (int argc, char *argv[])
{
    flux_msg_t *msg;
    flux_t *h;
    flux_reactor_t *reactor;

    plan (NO_PLAN);

    (void)setenv ("FLUX_CONNECTOR_PATH",
                  flux_conf_get ("connector_path", CONF_FLAG_INTREE), 0);
    ok ((h = flux_open ("loop://", FLUX_O_COPROC)) != NULL,
        "opened loop connector");
    if (!h)
        BAIL_OUT ("can't continue without loop handle");
    flux_fatal_set (h, fatal_err, NULL);
    ok ((reactor = flux_get_reactor(h)) != NULL,
       "obtained reactor");
    if (!h)
        BAIL_OUT ("can't continue without reactor");

    ok (flux_msg_handler_addvec (h, htab, NULL) == 0,
        "registered message handlers");
    /* test continues in rpctest_begin_cb() so that rpc calls
     * can sleep while we answer them
     */
    ok ((msg = flux_request_encode ("rpctest.begin", NULL)) != NULL,
        "encoded rpctest.begin request OK");
    ok (flux_send (h, msg, 0) == 0,
        "sent rpctest.begin request");
    ok (flux_reactor_run (reactor, 0) == 0,
        "reactor completed normally");
    flux_msg_destroy (msg);

    /* test _then:  Slightly tricky.
     * Send request.  We're not in a coproc ctx here in main(), so there
     * will be no response, therefore, check will be false.  Register
     * continuation, start reactor.  Response will be received, continuation
     * will be invoked. Continuation stops the reactor.
    */
    flux_rpc_t *r;
    ok ((r = flux_rpc (h, "rpctest.echo", "{}", FLUX_NODEID_ANY, 0)) != NULL,
        "flux_rpc with payload when payload is expected works");
    ok (flux_rpc_check (r) == false,
        "flux_rpc_check says get would block");
    /* reg/unreg _then a couple times for fun */
    ok (flux_rpc_then (r, NULL, 0) == 0,
        "flux_rpc_then with NULL cb works");
    ok (flux_rpc_then (r, then_cb, h) == 0,
        "flux_rpc_then works after NULL");
    ok (flux_rpc_then (r, NULL, 0) == 0,
        "flux_rpc_then with NULL cb after non-NULL works");
    ok (flux_rpc_then (r, then_cb, h) == 0,
        "flux_rpc_then works");
    /* enough of that */
    ok (flux_reactor_run (reactor, 0) == 0,
        "reactor completed normally");
    flux_rpc_destroy (r);

    /* Test a _then corner case:
     * If _check() is called before _then(), a message may have been cached
     * in the flux_rpc_t.  rpctest_thenbug_cb creates this condition.
     * Next, _then continuation is installed, but will reactor call it?
     * This will hang if rpc implementation doesn't return a cached message
     * back to the handle in _then().  Else, continuation will stop reactor.
     */
    ok ((thenbug_r = flux_rpc (h, "rpctest.echo", "{}",
        FLUX_NODEID_ANY, 0)) != NULL,
        "thenbug: sent echo request");
    do {
        if (!(msg = flux_request_encode ("rpctest.thenbug", NULL))
                  || flux_send (h, msg, 0) < 0
                  || flux_reactor_run (reactor, 0) < 0) {
            flux_msg_destroy (msg);
            break;
        }
        flux_msg_destroy (msg);
    } while (!flux_rpc_check (thenbug_r));
    ok (true,
        "thenbug: check says message ready");
    ok (flux_rpc_then (thenbug_r, then_cb, h) == 0,
        "thenbug: registered then - hangs on failure");
    ok (flux_reactor_run (reactor, 0) == 0,
        "reactor completed normally");
    flux_rpc_destroy (thenbug_r);

    flux_msg_handler_delvec (htab);
    flux_close (h);
    done_testing();
    return (0);
}
Beispiel #17
0
static int flush (lcc_connection_t *c, int argc, char **argv)
{
  int timeout = -1;

  lcc_identifier_t *identifiers = NULL;
  int identifiers_num = 0;

  char **plugins = NULL;
  int plugins_num = 0;

  int status;
  int i;

  assert (strcasecmp (argv[0], "flush") == 0);

#define BAIL_OUT(s) \
  do { \
    if (identifiers != NULL) \
      free (identifiers); \
    identifiers_num = 0; \
    if (plugins != NULL) \
      free (plugins); \
    plugins_num = 0; \
    return (s); \
  } while (0)

  for (i = 1; i < argc; ++i) {
    char *key, *value;

    key   = argv[i];
    value = strchr (argv[i], (int)'=');

    if (! value) {
      fprintf (stderr, "ERROR: flush: Invalid option ``%s''.\n", argv[i]);
      BAIL_OUT (-1);
    }

    *value = '\0';
    ++value;

    if (strcasecmp (key, "timeout") == 0) {
      char *endptr = NULL;

      timeout = (int) strtol (value, &endptr, 0);

      if (endptr == value) {
        fprintf (stderr, "ERROR: Failed to parse timeout as number: %s.\n",
            value);
        BAIL_OUT (-1);
      }
      else if ((endptr != NULL) && (*endptr != '\0')) {
        fprintf (stderr, "WARNING: Ignoring trailing garbage after timeout: "
            "%s.\n", endptr);
      }
    }
    else if (strcasecmp (key, "plugin") == 0) {
      status = array_grow ((void *)&plugins, &plugins_num,
          sizeof (*plugins));
      if (status != 0)
        BAIL_OUT (status);

      plugins[plugins_num - 1] = value;
    }
    else if (strcasecmp (key, "identifier") == 0) {
      status = array_grow ((void *)&identifiers, &identifiers_num,
          sizeof (*identifiers));
      if (status != 0)
        BAIL_OUT (status);

      memset (identifiers + (identifiers_num - 1), 0, sizeof (*identifiers));
      status = parse_identifier (c, value,
          identifiers + (identifiers_num - 1));
      if (status != 0)
        BAIL_OUT (status);
    }
    else {
      fprintf (stderr, "ERROR: flush: Unknown option `%s'.\n", key);
      BAIL_OUT (-1);
    }
  }

  if (plugins_num == 0) {
    status = array_grow ((void *)&plugins, &plugins_num, sizeof (*plugins));
    if (status != 0)
      BAIL_OUT (status);

    assert (plugins_num == 1);
    plugins[0] = NULL;
  }

  for (i = 0; i < plugins_num; ++i) {
    if (identifiers_num == 0) {
      status = lcc_flush (c, plugins[i], NULL, timeout);
      if (status != 0)
        fprintf (stderr, "ERROR: Failed to flush plugin `%s': %s.\n",
            (plugins[i] == NULL) ? "(all)" : plugins[i], lcc_strerror (c));
    }
    else {
      int j;

      for (j = 0; j < identifiers_num; ++j) {
        status = lcc_flush (c, plugins[i], identifiers + j, timeout);
        if (status != 0) {
          char id[1024];

          lcc_identifier_to_string (c, id, sizeof (id), identifiers + j);
          fprintf (stderr, "ERROR: Failed to flush plugin `%s', "
              "identifier `%s': %s.\n",
              (plugins[i] == NULL) ? "(all)" : plugins[i],
              id, lcc_strerror (c));
        }
      }
    }
  }

  BAIL_OUT (0);
#undef BAIL_OUT
} /* flush */
Beispiel #18
0
int rpctest_begin_cb (flux_t h, int type, zmsg_t **zmsg, void *arg)
{
    uint32_t nodeid;
    int i, errors;
    int old_count;
    flux_rpc_t *r;
    const char *json_str;

    errno = 0;
    ok (!(r = flux_rpc_multi (h, NULL, "foo", "all", 0)) && errno == EINVAL,
        "flux_rpc_multi [0] with NULL topic fails with EINVAL");
    errno = 0;
    ok (!(r = flux_rpc_multi (h, "bar", "foo", NULL, 0)) && errno == EINVAL,
        "flux_rpc_multi [0] with NULL nodeset fails with EINVAL");
    errno = 0;
    ok (!(r = flux_rpc_multi (h, "bar", "foo", "xyz", 0)) && errno == EINVAL,
        "flux_rpc_multi [0] with bad nodeset fails with EINVAL");

    /* working no-payload RPC */
    old_count = hello_count;
    ok ((r = flux_rpc_multi (h, "rpctest.hello", NULL, "all", 0)) != NULL,
        "flux_rpc_multi [0] with no payload when none is expected works");
    if (!r)
        BAIL_OUT ("can't continue without successful rpc call");
    ok (flux_rpc_check (r) == false,
        "flux_rpc_check says get would block");
    ok (flux_rpc_get (r, NULL, NULL) == 0,
        "flux_rpc_get works");
    ok (hello_count == old_count + 1,
        "rpc was called once");
    flux_rpc_destroy (r);

    /* cause remote EPROTO (unexpected payload) - picked up in _get() */
    ok ((r = flux_rpc_multi (h, "rpctest.hello", "foo", "all", 0)) != NULL,
        "flux_rpc_multi [0] with unexpected payload works, at first");
    ok (flux_rpc_check (r) == false,
        "flux_rpc_check says get would block");
    errno = 0;
    ok (flux_rpc_get (r, NULL, NULL) < 0
        && errno == EPROTO,
        "flux_rpc_get fails with EPROTO");
    flux_rpc_destroy (r);

    /* fake that we have a larger session */
    fake_size = 128;
    char s[16];
    uint32_t size = 0;
    snprintf (s, sizeof (s), "%u", fake_size);
    flux_attr_fake (h, "size", s, FLUX_ATTRFLAG_IMMUTABLE);
    flux_get_size (h, &size);
    cmp_ok (size, "==", fake_size,
        "successfully faked flux_get_size() of %d", fake_size);

    /* repeat working no-payload RPC test (now with 128 nodes) */
    old_count = hello_count;
    ok ((r = flux_rpc_multi (h, "rpctest.hello", NULL, "all", 0)) != NULL,
        "flux_rpc_multi [0-%d] with no payload when none is expected works",
        fake_size - 1);
    ok (flux_rpc_check (r) == false,
        "flux_rpc_check says get would block");
    errors = 0;
    for (i = 0; i < fake_size; i++)
        if (flux_rpc_get (r, NULL, NULL) < 0)
            errors++;
    ok (errors == 0,
        "flux_rpc_get succeded %d times", fake_size);

    cmp_ok (hello_count - old_count, "==", fake_size,
        "rpc was called %d times", fake_size);
    flux_rpc_destroy (r);

    /* same with a subset */
    old_count = hello_count;
    ok ((r = flux_rpc_multi (h, "rpctest.hello", NULL, "[0-63]", 0)) != NULL,
        "flux_rpc_multi [0-%d] with no payload when none is expected works",
        64 - 1);
    ok (flux_rpc_check (r) == false,
        "flux_rpc_check says get would block");
    errors = 0;
    for (i = 0; i < 64; i++)
        if (flux_rpc_get (r, &nodeid, NULL) < 0 || nodeid != i)
            errors++;
    ok (errors == 0,
        "flux_rpc_get succeded %d times, with correct nodeid map", 64);

    cmp_ok (hello_count - old_count, "==", 64,
        "rpc was called %d times", 64);
    flux_rpc_destroy (r);

    /* same with echo payload */
    ok ((r = flux_rpc_multi (h, "rpctest.echo", "foo", "[0-63]", 0)) != NULL,
        "flux_rpc_multi [0-%d] ok",
        64 - 1);
    ok (flux_rpc_check (r) == false,
        "flux_rpc_check says get would block");
    errors = 0;
    for (i = 0; i < 64; i++) {
        if (flux_rpc_get (r, NULL, &json_str) < 0
                || !json_str || strcmp (json_str, "foo") != 0)
            errors++;
    }
    ok (errors == 0,
        "flux_rpc_get succeded %d times, with correct return payload", 64);
    flux_rpc_destroy (r);

    /* detect partial failure without mresponse */
    nodeid_fake_error = 20;
    ok ((r = flux_rpc_multi (h, "rpctest.nodeid", NULL, "[0-63]", 0)) != NULL,
        "flux_rpc_multi [0-%d] ok",
        64 - 1);
    ok (flux_rpc_check (r) == false,
        "flux_rpc_check says get would block");
    for (i = 0; i < 64; i++) {
        if (flux_rpc_get (r, &nodeid, &json_str) < 0)
            break;
    }
    ok (i == 20 && errno == EPERM,
        "flux_rpc_get correctly reports single error");
    flux_rpc_destroy (r);

    /* test _then (still at fake session size of 128) */
    ok ((then_r = flux_rpc_multi (h, "rpctest.hello", NULL, "[0-127]", 0)) != NULL,
        "flux_rpc_multi [0-127] ok");
    ok (flux_rpc_then (then_r, then_cb, h) == 0,
        "flux_rpc_then works");
    /* then_cb stops reactor; results reported, then_r destroyed in main() */

    return 0;
}