static bool subscription_generator( w_query *query, w_root_t *root, struct w_query_ctx *ctx, void *gendata) { struct watchman_file *f; struct watchman_client_subscription *sub = gendata; w_log(W_LOG_DBG, "running subscription %s %p\n", sub->name->buf, sub); // Walk back in time until we hit the boundary for (f = root->latest_file; f; f = f->next) { if (ctx->since.is_timestamp && w_timeval_compare(f->otime.tv, ctx->since.timestamp) < 0) { break; } if (!ctx->since.is_timestamp && f->otime.ticks <= ctx->since.clock.ticks) { break; } if (!w_query_process_file(query, ctx, f)) { return false; } } return true; }
static bool trigger_generator( w_query *query, w_root_t *root, struct w_query_ctx *ctx, void *gendata) { struct watchman_file *f; struct watchman_trigger_command *cmd = gendata; w_log(W_LOG_DBG, "assessing trigger %s %p\n", cmd->triggername->buf, cmd); // Walk back in time until we hit the boundary for (f = root->latest_file; f; f = f->next) { if (ctx->since.is_timestamp && w_timeval_compare(f->otime.tv, ctx->since.timestamp) < 0) { break; } if (!ctx->since.is_timestamp && f->otime.ticks <= ctx->since.clock.ticks) { break; } if (!w_query_file_matches_relative_root(ctx, f)) { continue; } if (!w_query_process_file(query, ctx, f)) { return false; } } return true; }
static bool time_generator( w_query *query, w_root_t *root, struct w_query_ctx *ctx) { struct watchman_file *f; // Walk back in time until we hit the boundary for (f = root->latest_file; f; f = f->next) { if (ctx->since.is_timestamp && w_timeval_compare(f->otime.tv, ctx->since.timestamp) < 0) { break; } if (!ctx->since.is_timestamp && f->otime.ticks < ctx->since.clock.ticks) { break; } if (!w_query_process_file(query, ctx, f)) { return false; } } return true; }
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; }
static bool eval_since(struct w_query_ctx *ctx, struct watchman_file *file, void *data) { struct since_term *term = data; w_clock_t clock; time_t tval = 0; unused_parameter(ctx); switch (term->field) { case SINCE_OCLOCK: case SINCE_CCLOCK: clock = (term->field == SINCE_OCLOCK) ? file->otime : file->ctime; if (term->spec.is_timestamp) { return w_timeval_compare(term->spec.tv, clock.tv) > 0; } return clock.ticks > term->spec.ticks; case SINCE_ATIME: tval = file->st.st_atime; break; case SINCE_MTIME: tval = file->st.st_mtime; break; case SINCE_CTIME: tval = file->st.st_ctime; break; } return tval > term->spec.tv.tv_sec; }
bool w_query_process_file( w_query *query, struct w_query_ctx *ctx, struct watchman_file *file) { struct watchman_rule_match *m; if (ctx->wholename) { w_string_delref(ctx->wholename); ctx->wholename = NULL; } ctx->file = file; // For fresh instances, only return files that currently exist. if (!ctx->since.is_timestamp && ctx->since.clock.is_fresh_instance && !file->exists) { return true; } // We produce an output for this file if there is no expression, // or if the expression matched. if (query->expr && !w_query_expr_evaluate(query->expr, ctx, file)) { // No matched return true; } // Need more room? if (ctx->num_results + 1 > ctx->num_allocd) { uint32_t new_num = ctx->num_allocd ? ctx->num_allocd * 2 : 64; struct watchman_rule_match *res; res = realloc(ctx->results, new_num * sizeof(*res)); if (!res) { w_log(W_LOG_ERR, "out of memory while capturing matches!\n"); return false; } ctx->results = res; ctx->num_allocd = new_num; } m = &ctx->results[ctx->num_results++]; m->root_number = ctx->root->number; m->relname = w_query_ctx_get_wholename(ctx); if (!m->relname) { w_log(W_LOG_ERR, "out of memory while capturing matches!\n"); return false; } w_string_addref(m->relname); m->file = file; if (ctx->since.is_timestamp) { m->is_new = w_timeval_compare(ctx->since.timestamp, file->ctime.tv) > 0; } else if (ctx->since.clock.is_fresh_instance) { m->is_new = true; } else { m->is_new = file->ctime.ticks > ctx->since.clock.ticks; } return true; }