Ejemplo n.º 1
0
bool w_query_execute(
    w_query *query,
    w_root_t *root,
    w_query_res *res,
    w_query_generator generator,
    void *gendata)
{
  struct w_query_ctx ctx;

  memset(&ctx, 0, sizeof(ctx));
  ctx.query = query;
  ctx.root = root;

  memset(res, 0, sizeof(*res));

  if (query->sync_timeout && !w_root_sync_to_now(root, query->sync_timeout)) {
    ignore_result(asprintf(&res->errmsg, "synchronization failed: %s\n",
        strerror(errno)));
    return false;
  }

  /* The first stage of execution is generation.
   * We generate a series of file inputs to pass to
   * the query executor.
   *
   * We evaluate each of the generators one after the
   * other.  If multiple generators are used, it is
   * possible and expected that the same file name
   * will be evaluated multiple times if those generators
   * both emit the same file.
   */

  // Lock the root and begin generation
  w_root_lock(root);
  res->root_number = root->number;
  res->ticks = root->ticks;

  // Evaluate the cursor for this root
  w_clockspec_eval(root, query->since_spec, &ctx.since);

  res->is_fresh_instance = !ctx.since.is_timestamp &&
    ctx.since.clock.is_fresh_instance;

  if (!(res->is_fresh_instance && query->empty_on_fresh_instance)) {
    if (!generator) {
      generator = default_generators;
    }

    generator(query, root, &ctx, gendata);
  }

  w_root_unlock(root);

  if (ctx.wholename) {
    w_string_delref(ctx.wholename);
  }
  res->results = ctx.results;
  res->num_results = ctx.num_results;

  return true;
}
Ejemplo n.º 2
0
bool w_query_execute(
    w_query *query,
    w_root_t *root,
    w_query_res *res,
    w_query_generator generator,
    void *gendata)
{
  struct w_query_ctx ctx;
  w_perf_t sample;
  int64_t num_walked = 0;

  memset(&ctx, 0, sizeof(ctx));
  ctx.query = query;
  ctx.root = root;

  memset(res, 0, sizeof(*res));

  w_perf_start(&sample, "query_execute");

  if (query->sync_timeout && !w_root_sync_to_now(root, query->sync_timeout)) {
    ignore_result(asprintf(&res->errmsg, "synchronization failed: %s\n",
        strerror(errno)));
    return false;
  }

  /* The first stage of execution is generation.
   * We generate a series of file inputs to pass to
   * the query executor.
   *
   * We evaluate each of the generators one after the
   * other.  If multiple generators are used, it is
   * possible and expected that the same file name
   * will be evaluated multiple times if those generators
   * both emit the same file.
   */

  // Lock the root and begin generation
  if (!w_root_lock_with_timeout(root, "w_query_execute", query->lock_timeout)) {
    ignore_result(asprintf(&res->errmsg, "couldn't acquire root lock within "
                                         "lock_timeout of %dms. root is "
                                         "currently busy (%s)\n",
                           query->lock_timeout, root->lock_reason));
    return false;
  }
  res->root_number = root->number;
  res->ticks = root->ticks;

  // Evaluate the cursor for this root
  w_clockspec_eval(root, query->since_spec, &ctx.since);

  res->is_fresh_instance = !ctx.since.is_timestamp &&
    ctx.since.clock.is_fresh_instance;

  if (!(res->is_fresh_instance && query->empty_on_fresh_instance)) {
    if (!generator) {
      generator = default_generators;
    }

    generator(query, root, &ctx, gendata, &num_walked);
  }

  if (w_perf_finish(&sample)) {
    w_perf_add_root_meta(&sample, root);
    w_perf_add_meta(&sample, "query_execute",
                    json_pack("{s:b, s:i, s:i, s:O}",                   //
                              "fresh_instance", res->is_fresh_instance, //
                              "num_results", ctx.num_results,           //
                              "num_walked", num_walked,                 //
                              "query", ctx.query->query_spec           //
                              ));
    w_perf_log(&sample);
  }
  w_root_unlock(root);
  w_perf_destroy(&sample);

  if (ctx.wholename) {
    w_string_delref(ctx.wholename);
  }
  if (ctx.last_parent_path) {
    w_string_delref(ctx.last_parent_path);
  }
  res->results = ctx.results;
  res->num_results = ctx.num_results;

  return true;
}