vbp_task(struct worker *wrk, void *priv) { struct vbp_target *vt; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CAST_OBJ_NOTNULL(vt, priv, VBP_TARGET_MAGIC); AN(vt->running); AN(vt->req); assert(vt->req_len > 0); vbp_start_poke(vt); vbp_poke(vt); vbp_has_poked(vt); VBP_Update_Backend(vt); Lck_Lock(&vbp_mtx); if (vt->running < 0) { assert(vt->heap_idx == BINHEAP_NOIDX); vbp_delete(vt); } else { vt->running = 0; if (vt->heap_idx != BINHEAP_NOIDX) { vt->due = VTIM_real() + vt->interval; binheap_delete(vbp_heap, vt->heap_idx); binheap_insert(vbp_heap, vt); } } Lck_Unlock(&vbp_mtx); }
vbp_thread(struct worker *wrk, void *priv) { vtim_real now, nxt; struct vbp_target *vt; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); AZ(priv); Lck_Lock(&vbp_mtx); while (1) { now = VTIM_real(); vt = binheap_root(vbp_heap); if (vt == NULL) { nxt = 8.192 + now; (void)Lck_CondWait(&vbp_cond, &vbp_mtx, nxt); } else if (vt->due > now) { nxt = vt->due; vt = NULL; (void)Lck_CondWait(&vbp_cond, &vbp_mtx, nxt); } else { binheap_delete(vbp_heap, vt->heap_idx); vt->due = now + vt->interval; if (!vt->running) { vt->running = 1; vt->task.func = vbp_task; vt->task.priv = vt; if (Pool_Task_Any(&vt->task, TASK_QUEUE_REQ)) vt->running = 0; } binheap_insert(vbp_heap, vt); } } NEEDLESS(Lck_Unlock(&vbp_mtx)); NEEDLESS(return NULL); }
void EXP_Rearm(const struct object *o) { struct objcore *oc; CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC); oc = o->objcore; if (oc == NULL) return; CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); Lck_Lock(&exp_mtx); /* * The hang-man might have this object of the binheap while * tending to a timer. If so, we do not muck with it here. */ if (oc->timer_idx != BINHEAP_NOIDX && update_object_when(o)) { /* * XXX: this could possibly be optimized by shuffling * XXX: up or down, but that leaves some very nasty * XXX: corner cases, such as shuffling all the way * XXX: down the left half, then back up the right half. */ assert(oc->timer_idx != BINHEAP_NOIDX); binheap_delete(exp_heap, oc->timer_idx); assert(oc->timer_idx == BINHEAP_NOIDX); binheap_insert(exp_heap, oc); assert(oc->timer_idx != BINHEAP_NOIDX); } Lck_Unlock(&exp_mtx); if (o->smp_object != NULL) SMP_TTLchanged(o); }
int Wait_HeapDelete(const struct waiter *w, const struct waited *wp) { CHECK_OBJ_NOTNULL(w, WAITER_MAGIC); CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC); if (wp->idx == BINHEAP_NOIDX) return (0); binheap_delete(w->heap, wp->idx); return (1); }
static void * exp_timer(struct sess *sp, void *priv) { struct objcore *oc; struct object *o; double t; struct objcore_head *lru; (void)priv; AZ(sleep(10)); /* XXX: Takes time for VCL to arrive */ VCL_Get(&sp->vcl); t = TIM_real(); while (1) { Lck_Lock(&exp_mtx); oc = binheap_root(exp_heap); CHECK_OBJ_ORNULL(oc, OBJCORE_MAGIC); if (oc == NULL || oc->timer_when > t) { /* XXX: > or >= ? */ Lck_Unlock(&exp_mtx); WSL_Flush(sp->wrk, 0); WRK_SumStat(sp->wrk); AZ(sleep(1)); VCL_Refresh(&sp->vcl); t = TIM_real(); continue; } o = oc->obj; CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(o->objhead, OBJHEAD_MAGIC); assert(oc->flags & OC_F_ONLRU); assert(oc->timer_idx != BINHEAP_NOIDX); binheap_delete(exp_heap, oc->timer_idx); assert(oc->timer_idx == BINHEAP_NOIDX); lru = STV_lru(o->objstore); AN(lru); VTAILQ_REMOVE(lru, o->objcore, lru_list); oc->flags &= ~OC_F_ONLRU; { /* Sanity checking */ struct objcore *oc2 = binheap_root(exp_heap); if (oc2 != NULL) { assert(oc2->timer_idx != BINHEAP_NOIDX); assert(oc2->timer_when >= oc->timer_when); } } VSL_stats->n_expired++; Lck_Unlock(&exp_mtx); WSL(sp->wrk, SLT_ExpKill, 0, "%u %d", o->xid, (int)(o->ttl - t)); HSH_Deref(sp->wrk, &o); } }
static void exp_inbox(struct exp_priv *ep, struct objcore *oc, unsigned flags) { CHECK_OBJ_NOTNULL(ep, EXP_PRIV_MAGIC); CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); assert(oc->refcnt > 0); VSLb(&ep->vsl, SLT_ExpKill, "EXP_Inbox flg=%x p=%p e=%.9f f=0x%x", flags, oc, oc->timer_when, oc->flags); if (flags & OC_EF_REMOVE) { if (!(flags & OC_EF_INSERT)) { assert(oc->timer_idx != BINHEAP_NOIDX); binheap_delete(ep->heap, oc->timer_idx); } assert(oc->timer_idx == BINHEAP_NOIDX); assert(oc->refcnt > 0); AZ(oc->exp_flags); ObjSendEvent(ep->wrk, oc, OEV_EXPIRE); (void)HSH_DerefObjCore(ep->wrk, &oc, 0); return; } if (flags & OC_EF_MOVE) { oc->timer_when = EXP_WHEN(oc); ObjSendEvent(ep->wrk, oc, OEV_TTLCHG); } VSLb(&ep->vsl, SLT_ExpKill, "EXP_When p=%p e=%.9f f=0x%x", oc, oc->timer_when, flags); /* * XXX: There are some pathological cases here, were we * XXX: insert or move an expired object, only to find out * XXX: the next moment and rip them out again. */ if (flags & OC_EF_INSERT) { assert(oc->timer_idx == BINHEAP_NOIDX); binheap_insert(exphdl->heap, oc); assert(oc->timer_idx != BINHEAP_NOIDX); } else if (flags & OC_EF_MOVE) { assert(oc->timer_idx != BINHEAP_NOIDX); binheap_reorder(exphdl->heap, oc->timer_idx); assert(oc->timer_idx != BINHEAP_NOIDX); } else { WRONG("Objcore state wrong in inbox"); } }
static double exp_expire(struct exp_priv *ep, double now) { struct objcore *oc; CHECK_OBJ_NOTNULL(ep, EXP_PRIV_MAGIC); oc = binheap_root(ep->heap); if (oc == NULL) return (now + 355./113.); VSLb(&ep->vsl, SLT_ExpKill, "EXP_expire p=%p e=%.9f f=0x%x", oc, oc->timer_when - now, oc->flags); CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); /* Ready ? */ if (oc->timer_when > now) return (oc->timer_when); VSC_C_main->n_expired++; Lck_Lock(&ep->mtx); if (oc->exp_flags & OC_EF_POSTED) { oc->exp_flags |= OC_EF_REMOVE; oc = NULL; } else { oc->exp_flags &= ~OC_EF_REFD; } Lck_Unlock(&ep->mtx); if (oc != NULL) { if (!(oc->flags & OC_F_DYING)) HSH_Kill(oc); /* Remove from binheap */ assert(oc->timer_idx != BINHEAP_NOIDX); binheap_delete(ep->heap, oc->timer_idx); assert(oc->timer_idx == BINHEAP_NOIDX); CHECK_OBJ_NOTNULL(oc->objhead, OBJHEAD_MAGIC); VSLb(&ep->vsl, SLT_ExpKill, "EXP_Expired x=%u t=%.0f", ObjGetXID(ep->wrk, oc), EXP_Ttl(NULL, oc) - now); ObjSendEvent(ep->wrk, oc, OEV_EXPIRE); (void)HSH_DerefObjCore(ep->wrk, &oc, 0); } return (0); }
void VBP_Control(const struct backend *be, int enable) { struct vbp_target *vt; CHECK_OBJ_NOTNULL(be, BACKEND_MAGIC); vt = be->probe; CHECK_OBJ_NOTNULL(vt, VBP_TARGET_MAGIC); vbp_reset(vt); VBP_Update_Backend(vt); Lck_Lock(&vbp_mtx); if (enable) { assert(vt->heap_idx == BINHEAP_NOIDX); vt->due = VTIM_real(); binheap_insert(vbp_heap, vt); AZ(pthread_cond_signal(&vbp_cond)); } else { assert(vt->heap_idx != BINHEAP_NOIDX); binheap_delete(vbp_heap, vt->heap_idx); } Lck_Unlock(&vbp_mtx); }
int main(int argc, char *argv[]) { binheap_t h; int32_t a[1024]; int32_t i, j, r; int32_t parent, child; binheap_node_t *nodes[1024]; for (i = 0; i < 1024; i++) { a[i] = 1024 - i; } binheap_init(&h, compare_int, NULL); for (i = 0; i < 1024; i++) { binheap_insert(&h, a + i); } for (i = 0; i < 1024; i++) { parent = (i - 1) / 2; child = (2 * i) + 1; if (!i) { if (*(int *) h.array[i]->datum > *(int *) h.array[child]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child + 1]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d %4d\n", h.array[i]->index, *(int *) h.array[i]->datum, *(int *) h.array[child]->datum, *(int *) h.array[child + 1]->datum); } else if (i < (h.size - 1) / 2) { if (*(int *) h.array[i]->datum < *(int *) h.array[parent]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child + 1]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d %4d %4d\n", h.array[i]->index, *(int *) h.array[parent]->datum, *(int *) h.array[i]->datum, *(int *) h.array[child]->datum, *(int *) h.array[child + 1]->datum); } else { if (*(int *) h.array[i]->datum < *(int *) h.array[parent]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d\n", h.array[i]->index, *(int *) h.array[parent]->datum, *(int *) h.array[i]->datum); } } binheap_delete(&h); binheap_init_from_array(&h, a, sizeof (*a), 1024, compare_int, NULL); for (i = 0; i < 1024; i++) { parent = (i - 1) / 2; child = (2 * i) + 1; if (!i) { if (*(int *) h.array[i]->datum > *(int *) h.array[child]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child + 1]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d %4d\n", h.array[i]->index, *(int *) h.array[i]->datum, *(int *) h.array[child]->datum, *(int *) h.array[child + 1]->datum); } else if (i < (h.size - 1) / 2) { if (*(int *) h.array[i]->datum < *(int *) h.array[parent]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child + 1]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d %4d %4d\n", h.array[i]->index, *(int *) h.array[parent]->datum, *(int *) h.array[i]->datum, *(int *) h.array[child]->datum, *(int *) h.array[child + 1]->datum); } else { if (*(int *) h.array[i]->datum < *(int *) h.array[parent]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d\n", h.array[i]->index, *(int *) h.array[parent]->datum, *(int *) h.array[i]->datum); } } while (!binheap_is_empty(&h)) { binheap_remove_min(&h); for (i = 0; i < h.size; i++) { parent = (i - 1) / 2; child = (2 * i) + 1; if (h.size == 1) { printf("%4d: %4d\n", h.array[i]->index, *(int *) h.array[i]->datum); } else if (!i) { if (*(int *) h.array[i]->datum > *(int *) h.array[child]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child + 1]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d %4d\n", h.array[i]->index, *(int *) h.array[i]->datum, *(int *) h.array[child]->datum, *(int *) h.array[child + 1]->datum); } else if (i < (h.size - 1) / 2) { if (*(int *) h.array[i]->datum < *(int *) h.array[parent]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child + 1]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d %4d %4d\n", h.array[i]->index, *(int *) h.array[parent]->datum, *(int *) h.array[i]->datum, *(int *) h.array[child]->datum, *(int *) h.array[child + 1]->datum); } else { if (*(int *) h.array[i]->datum < *(int *) h.array[parent]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d\n", h.array[i]->index, *(int *) h.array[parent]->datum, *(int *) h.array[i]->datum); } } } binheap_delete(&h); binheap_init(&h, compare_int, NULL); for (i = 0; i < 1024; i++) { nodes[i] = binheap_insert(&h, a + i); } for (i = 0; i < 1024; i++) { printf("%d\n", *(int *) nodes[i]->datum); } for (j = 0; j < 1; j++) { r = 1020; a[r] = 0; binheap_decrease_key(&h, nodes[r]); for (i = 0; i < h.size; i++) { parent = (i - 1) / 2; child = (2 * i) + 1; if (h.size == 1) { printf("%4d: %4d\n", h.array[i]->index, *(int *) h.array[i]->datum); } else if (!i) { if (*(int *) h.array[i]->datum > *(int *) h.array[child]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child + 1]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d %4d\n", h.array[i]->index, *(int *) h.array[i]->datum, *(int *) h.array[child]->datum, *(int *) h.array[child + 1]->datum); } else if (i < (h.size - 1) / 2) { if (*(int *) h.array[i]->datum < *(int *) h.array[parent]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child]->datum || *(int *) h.array[i]->datum > *(int *) h.array[child + 1]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d %4d %4d\n", h.array[i]->index, *(int *) h.array[parent]->datum, *(int *) h.array[i]->datum, *(int *) h.array[child]->datum, *(int *) h.array[child + 1]->datum); } else { if (*(int *) h.array[i]->datum < *(int *) h.array[parent]->datum) { printf("Error follows:\n"); } printf("%4d: %4d %4d\n", h.array[i]->index, *(int *) h.array[parent]->datum, *(int *) h.array[i]->datum); } } } binheap_delete(&h); return 0; }