static int vlog_cb_func(struct VSL_data *vsl, struct VSL_transaction * const trans[], void *priv) { int i; struct vlog_req_priv *vrp = priv; struct VSL_transaction *t; for (i = 0; (t = trans[i]) != NULL && vrp->entries < vrp->limit; ++i) { while (VSL_Next(t->c) && vrp->entries < vrp->limit) { if (!VSL_Match(vsl, t->c)) { continue; } if (vrp->entries != 0) VSB_printf(vrp->answer,","); VSB_printf(vrp->answer,"\n"); VSB_printf(vrp->answer, "{ \"vxid\": \"%u\", " "\"tag\": \"%s\", \"type\": \"%s\", \"reason\": \"%s\", " "\"value\": ", t->vxid, VSL_tags[VSL_TAG(t->c->rec.ptr)], vsl_t_names[t->type], vsl_r_names[t->reason]); VSB_quote(vrp->answer, VSL_CDATA(t->c->rec.ptr), strlen(VSL_CDATA(t->c->rec.ptr)), 0); VSB_printf(vrp->answer,"}"); vrp->entries++; } } return (0); }
int vslq_runquery(const struct vslq_query *query, struct VSL_transaction * const ptrans[]) { struct VSL_transaction *t; struct VSL_cursor *c; int i, len; const char *data; CHECK_OBJ_NOTNULL(query, VSLQ_QUERY_MAGIC); AN(query->regex); t = ptrans[0]; while (t) { c = t->c; while (1) { i = VSL_Next(c); if (i == 0) break; assert(i == 1); AN(c->rec.ptr); len = VSL_LEN(c->rec.ptr); data = VSL_CDATA(c->rec.ptr); i = VRE_exec(query->regex, data, len, 0, 0, NULL, 0, NULL); if (i != VRE_ERROR_NOMATCH) { AZ(VSL_ResetCursor(c)); return (1); } } AZ(VSL_ResetCursor(c)); t = *++ptrans; } return (0); }
static int vsl_match_IX(struct VSL_data *vsl, const vslf_list *list, const struct VSL_cursor *c) { enum VSL_tag_e tag; const char *cdata; int len; const struct vslf *vslf; (void)vsl; tag = VSL_TAG(c->rec.ptr); cdata = VSL_CDATA(c->rec.ptr); len = VSL_LEN(c->rec.ptr); VTAILQ_FOREACH(vslf, list, list) { CHECK_OBJ_NOTNULL(vslf, VSLF_MAGIC); if (vslf->tag >= 0 && vslf->tag != tag) continue; if (VRE_exec(vslf->vre, cdata, len, 0, 0, NULL, 0, NULL) >= 0) return (1); }
accumulate(struct VSL_data *vsl, struct VSL_transaction * const pt[], void *priv) { struct top *tp, t; unsigned int u; unsigned tag; const char *b, *e, *p; unsigned len; struct VSL_transaction *tr; (void)priv; for (tr = pt[0]; tr != NULL; tr = *++pt) { while ((1 == VSL_Next(tr->c))) { if (!VSL_Match(vsl, tr->c)) continue; tag = VSL_TAG(tr->c->rec.ptr); b = VSL_CDATA(tr->c->rec.ptr); e = b + VSL_LEN(tr->c->rec.ptr); u = 0; for (p = b; p <= e; p++) { if (*p == '\0') break; if (f_flag && (*p == ':' || isspace(*p))) break; u += *p; } len = p - b; if (len == 0) continue; t.hash = u; t.tag = tag; t.clen = len; t.rec_data = VSL_CDATA(tr->c->rec.ptr); AZ(pthread_mutex_lock(&mtx)); tp = VRB_FIND(t_key, &h_key, &t); if (tp) { VRB_REMOVE(t_order, &h_order, tp); tp->count += 1.0; /* Reinsert to rebalance */ VRB_INSERT(t_order, &h_order, tp); } else { ntop++; tp = calloc(sizeof *tp, 1); assert(tp != NULL); tp->hash = u; tp->count = 1.0; tp->clen = len; tp->tag = tag; tp->rec_buf = strdup(t.rec_data); tp->rec_data = tp->rec_buf; AN(tp->rec_data); VRB_INSERT(t_key, &h_key, tp); VRB_INSERT(t_order, &h_order, tp); } AZ(pthread_mutex_unlock(&mtx)); } } return (0); }
static int /*__match_proto__ (VSLQ_dispatch_f)*/ accumulate(struct VSL_data *vsl, struct VSL_transaction * const pt[], void *priv) { int i, tag, skip, match, hit; unsigned u; double value = 0; struct VSL_transaction *tr; double t; const char *tsp; (void)vsl; (void)priv; for (tr = pt[0]; tr != NULL; tr = *++pt) { if (tr->reason == VSL_r_esi) /* Skip ESI requests */ continue; hit = 0; skip = 0; match = 0; tsp = NULL; while (skip == 0) { i = VSL_Next(tr->c); if (i == -3) { /* overrun - need to skip forward */ AZ(pthread_mutex_lock(&mtx)); vsl_to = vsl_t0 = vsl_ts = 0; t0 = VTIM_mono(); AZ(pthread_mutex_unlock(&mtx)); break; } if (i != 1) break; /* get the value we want and register if it's a hit */ tag = VSL_TAG(tr->c->rec.ptr); switch (tag) { case SLT_Hit: hit = 1; break; case SLT_VCL_return: if (!strcasecmp(VSL_CDATA(tr->c->rec.ptr), "restart") || !strcasecmp(VSL_CDATA(tr->c->rec.ptr), "retry")) skip = 1; break; case SLT_Timestamp: tsp = VSL_CDATA(tr->c->rec.ptr); /* FALLTHROUGH */ default: if (tag != match_tag) break; if (active_profile->prefix && strncmp(VSL_CDATA(tr->c->rec.ptr), active_profile->prefix, strlen(active_profile->prefix)) != 0) break; i = sscanf(VSL_CDATA(tr->c->rec.ptr), format, &value); if (i != 1) break; match = 1; break; } } if (skip || !match) continue; /* select bucket */ i = HIST_RES * (log(value) / log_ten); if (i < hist_low * HIST_RES) i = hist_low * HIST_RES; if (i >= hist_high * HIST_RES) i = hist_high * HIST_RES - 1; i -= hist_low * HIST_RES; assert(i >= 0); assert(i < hist_buckets); AZ(pthread_mutex_lock(&mtx)); /* * only parse the last tsp seen in this transaction - * it should be the latest. */ if (tsp) upd_vsl_ts(tsp); /* phase out old data */ if (nhist == HIST_N) { u = rr_hist[next_hist]; if (u >= hist_buckets) { u -= hist_buckets; assert(u < hist_buckets); assert(bucket_hit[u] > 0); bucket_hit[u]--; } else { assert(bucket_miss[u] > 0); bucket_miss[u]--; } } else { ++nhist; } /* phase in new data */ if (hit) { bucket_hit[i]++; rr_hist[next_hist] = i + hist_buckets; } else { bucket_miss[i]++; rr_hist[next_hist] = i; } if (++next_hist == HIST_N) { next_hist = 0; } AZ(pthread_mutex_unlock(&mtx)); } if (vsl_ts < vsl_to) return (0); t = VTIM_mono(); AZ(pthread_mutex_lock(&mtx)); if (vsl_t0 == 0) vsl_to = vsl_t0 = vsl_ts; assert(t > t0); vsl_to = vsl_t0 + (t - t0) * timebend; if (vsl_ts > vsl_to) { double when = VTIM_real() + vsl_ts - vsl_to; struct timespec ts; ts.tv_nsec = (long)(modf(when, &t) * 1e9); ts.tv_sec = (long)t; i = pthread_cond_timedwait(&timebend_cv, &mtx, &ts); assert(i == 0 || i == ETIMEDOUT); } AZ(pthread_mutex_unlock(&mtx)); return (0); }