Ejemplo n.º 1
0
  bool evaluate(struct w_query_ctx* ctx, const watchman_file* file) override {
    w_clock_t clock;
    struct w_query_since since;
    time_t tval = 0;

    w_clockspec_eval(ctx->root, spec.get(), &since);

    switch (field) {
      case since_what::SINCE_OCLOCK:
      case since_what::SINCE_CCLOCK:
        clock = (field == since_what::SINCE_OCLOCK) ? file->otime : file->ctime;
        if (since.is_timestamp) {
          return since.timestamp > clock.timestamp;
        }
        if (since.clock.is_fresh_instance) {
          return file->exists;
        }
        return clock.ticks > since.clock.ticks;
      case since_what::SINCE_MTIME:
        tval = file->stat.mtime.tv_sec;
        break;
      case since_what::SINCE_CTIME:
        tval = file->stat.ctime.tv_sec;
        break;
    }

    assert(since.is_timestamp);
    return tval > since.timestamp;
  }
Ejemplo n.º 2
0
static bool eval_since(struct w_query_ctx *ctx,
    struct watchman_file *file,
    void *data)
{
  struct since_term *term = data;
  w_clock_t clock;
  struct w_query_since since;
  time_t tval = 0;

  w_clockspec_eval(ctx->root, term->spec, &since);

  switch (term->field) {
    case SINCE_OCLOCK:
    case SINCE_CCLOCK:
      clock = (term->field == SINCE_OCLOCK) ? file->otime : file->ctime;
      if (since.is_timestamp) {
        return w_timeval_compare(since.timestamp, clock.tv) > 0;
      }
      if (since.clock.is_fresh_instance) {
        return file->exists;
      }
      return clock.ticks > since.clock.ticks;
    case SINCE_MTIME:
      tval = file->st.st_mtime;
      break;
    case SINCE_CTIME:
      tval = file->st.st_ctime;
      break;
  }

  assert(since.is_timestamp);
  return tval > since.timestamp.tv_sec;
}
Ejemplo n.º 3
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.º 4
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;
}