int se_scheduler_backup(void *arg) { se *e = arg; sescheduler *s = &e->sched; if (ssunlikely(e->conf.backup_path == NULL)) { sr_error(&e->error, "%s", "backup is not enabled"); return -1; } /* begin backup procedure * state 0 * * disable log garbage-collection */ sl_poolgc_enable(&e->lp, 0); ss_mutexlock(&s->lock); if (ssunlikely(s->backup > 0)) { ss_mutexunlock(&s->lock); sl_poolgc_enable(&e->lp, 1); /* in progress */ return 0; } uint64_t bsn = sr_seq(&e->seq, SR_BSNNEXT); s->backup = 1; s->backup_bsn = bsn; ss_mutexunlock(&s->lock); return 0; }
so *sc_readpool_popready(screadpool *p) { ss_mutexlock(&p->lock); if (p->list_ready.n == 0) { ss_mutexunlock(&p->lock); return NULL; } so *o = so_listfirst(&p->list_ready); so_listdel(&p->list_ready, o); ss_mutexunlock(&p->lock); return o; }
int sc_readpool_queue(screadpool *p) { ss_mutexlock(&p->lock); int n = p->list.n; ss_mutexunlock(&p->lock); return n; }
static inline int sc_taskend(sc *s, sctask *t) { ss_mutexlock(&s->lock); scdb *db = t->db; switch (t->plan.plan) { case SI_CHECKPOINT: case SI_COMPACTION: t->gc = 1; break; case SI_BACKUP: case SI_BACKUPEND: db->workers[SC_QBACKUP]--; break; case SI_EXPIRE: db->workers[SC_QEXPIRE]--; t->gc = 1; break; case SI_GC: db->workers[SC_QGC]--; t->gc = 1; break; } if (t->rotate == 1) s->rotate = 0; ss_mutexunlock(&s->lock); return 0; }
int sc_ctl_shutdown(sc *s, si *i) { ss_mutexlock(&s->lock); so_listadd(&s->shutdown, &i->link); ss_mutexunlock(&s->lock); return 0; }
int sc_ctl_lru(sc *s) { ss_mutexlock(&s->lock); s->lru = 1; ss_mutexunlock(&s->lock); return 0; }
int sc_ctl_gc(sc *s) { ss_mutexlock(&s->lock); s->gc = 1; ss_mutexunlock(&s->lock); return 0; }
static int se_complete(sescheduler *s, setask *t) { ss_mutexlock(&s->lock); sedb *db = t->db; if (db) se_dbunref(db, 1); switch (t->plan.plan) { case SI_BRANCH: case SI_AGE: case SI_CHECKPOINT: s->workers_branch--; break; case SI_BACKUP: case SI_BACKUPEND: s->workers_backup--; break; case SI_GC: s->workers_gc--; break; case SI_SHUTDOWN: case SI_DROP: s->workers_gc_db--; so_destroy(&db->o); break; } if (t->rotate == 1) s->rotate = 0; if (t->req) s->req = 0; ss_mutexunlock(&s->lock); return 0; }
void sc_readpool_ready(screadpool *p, so *o) { scread *r = (scread*)o; ss_mutexlock(&p->lock); so_listdel(&p->list_active, &r->o); so_listadd(&p->list_ready, &r->o); ss_mutexunlock(&p->lock); }
static inline void sc_readpool_add(screadpool *p, scread *r) { ss_mutexlock(&p->lock); so_listadd(&p->list, &r->o); ss_condsignal(&p->cond); ss_mutexunlock(&p->lock); }
int sc_ctl_checkpoint(sc *s) { uint64_t lsn = sr_seq(s->r->seq, SR_LSN); ss_mutexlock(&s->lock); s->checkpoint_lsn = lsn; s->checkpoint = 1; ss_mutexunlock(&s->lock); return 0; }
int sc_ctl_snapshot(sc *s) { uint64_t ssn = sr_seq(s->r->seq, SR_SSNNEXT); ss_mutexlock(&s->lock); s->snapshot_ssn = ssn; s->snapshot = 1; ss_mutexunlock(&s->lock); return 0; }
int sc_backupstop(sc *s) { sl_poolgc_enable(s->lp, 1); ss_mutexlock(&s->lock); s->backup = 0; s->backup_bsn_last_complete = 0; ss_mutexunlock(&s->lock); return 0; }
int se_scheduler_gc(void *arg) { se *o = arg; sescheduler *s = &o->sched; ss_mutexlock(&s->lock); s->gc = 1; ss_mutexunlock(&s->lock); return 0; }
so *sc_readpool_pop(screadpool *p, int block) { ss_mutexlock(&p->lock); if (p->list.n == 0) { if (! block) goto empty; ss_condwait(&p->cond, &p->lock); if (p->list.n == 0) goto empty; } so *o = so_listfirst(&p->list); so_listdel(&p->list, o); so_listadd(&p->list_active, o); ss_mutexunlock(&p->lock); return o; empty: ss_mutexunlock(&p->lock); return NULL; }
int se_scheduler_add(sescheduler *s , void *db) { ss_mutexlock(&s->lock); se *e = (se*)s->env; int count = s->count + 1; void **i = ss_malloc(&e->a, count * sizeof(void*)); if (ssunlikely(i == NULL)) { ss_mutexunlock(&s->lock); return -1; } memcpy(i, s->i, s->count * sizeof(void*)); i[s->count] = db; void *iprev = s->i; s->i = i; s->count = count; ss_mutexunlock(&s->lock); if (iprev) ss_free(&e->a, iprev); return 0; }
int se_scheduler_snapshot(void *arg) { se *o = arg; sescheduler *s = &o->sched; uint64_t ssn = sr_seq(&o->seq, SR_SSNNEXT); ss_mutexlock(&s->lock); s->snapshot_ssn = ssn; s->snapshot = 1; ss_mutexunlock(&s->lock); return 0; }
int se_scheduler_checkpoint(void *arg) { se *o = arg; sescheduler *s = &o->sched; uint64_t lsn = sr_seq(&o->seq, SR_LSN); ss_mutexlock(&s->lock); s->checkpoint_lsn = lsn; s->checkpoint = 1; ss_mutexunlock(&s->lock); return 0; }
int sc_ctl_backup_event(sc *s) { int event = 0; ss_mutexlock(&s->lock); if (ssunlikely(s->backup_events > 0)) { s->backup_events--; event = 1; } ss_mutexunlock(&s->lock); return event; }
static int sc_schedule(sc *s, sctask *task) { int rc; ss_mutexlock(&s->lock); task->db = sc_current(s); sc_periodic(s, task); rc = sc_do(s, task); sc_next(s); ss_mutexunlock(&s->lock); return rc; }
int sc_backupstart(sc *s) { /* begin backup procedure * state 0 * * disable log garbage-collection */ sl_poolgc_enable(s->lp, 0); ss_mutexlock(&s->lock); if (ssunlikely(s->backup > 0)) { ss_mutexunlock(&s->lock); sl_poolgc_enable(s->lp, 1); /* in progress */ return 1; } uint64_t bsn = sr_seq(s->r->seq, SR_BSNNEXT); s->backup = 1; s->backup_bsn = bsn; ss_mutexunlock(&s->lock); return 0; }
int sc_backupend(sc *s, scworker *w) { /* * a. rotate log file * b. copy log files * c. enable log gc * d. rename <bsn.incomplete> into <bsn> * e. set last backup, set COMPLETE */ /* force log rotation */ ss_trace(&w->trace, "%s", "log rotation for backup"); int rc = sl_poolrotate(s->lp); if (ssunlikely(rc == -1)) return -1; /* copy log files */ ss_trace(&w->trace, "%s", "log files backup"); char path[1024]; snprintf(path, sizeof(path), "%s/%" PRIu32 ".incomplete/log", s->backup_path, s->backup_bsn); rc = sl_poolcopy(s->lp, path, &w->dc.c); if (ssunlikely(rc == -1)) return -1; /* complete backup */ snprintf(path, sizeof(path), "%s/%" PRIu32 ".incomplete", s->backup_path, s->backup_bsn); char newpath[1024]; snprintf(newpath, sizeof(newpath), "%s/%" PRIu32, s->backup_path, s->backup_bsn); rc = ss_vfsrename(s->r->vfs, path, newpath); if (ssunlikely(rc == -1)) { sr_error(s->r->e, "backup directory '%s' rename error: %s", path, strerror(errno)); return -1; } /* enable log gc */ sl_poolgc_enable(s->lp, 1); /* complete */ ss_mutexlock(&s->lock); s->backup_bsn_last = s->backup_bsn; s->backup_bsn_last_complete = 1; s->backup_in_progress = 0; s->backup = 0; s->backup_bsn = 0; ss_mutexunlock(&s->lock); return 0; }
int se_scheduler_del(sescheduler *s, void *db) { if (ssunlikely(s->i == NULL)) return 0; ss_mutexlock(&s->lock); se *e = (se*)s->env; int count = s->count - 1; if (ssunlikely(count == 0)) { s->count = 0; ss_free(&e->a, s->i); s->i = NULL; ss_mutexunlock(&s->lock); return 0; } void **i = ss_malloc(&e->a, count * sizeof(void*)); if (ssunlikely(i == NULL)) { ss_mutexunlock(&s->lock); return -1; } int j = 0; int k = 0; while (j < s->count) { if (s->i[j] == db) { j++; continue; } i[k] = s->i[j]; k++; j++; } void *iprev = s->i; s->i = i; s->count = count; if (ssunlikely(s->rr >= s->count)) s->rr = 0; ss_mutexunlock(&s->lock); ss_free(&e->a, iprev); return 0; }
int sc_backupbegin(sc *s) { /* * a. create backup_path/<bsn.incomplete> directory * b. create database directories * c. create log directory */ char path[1024]; snprintf(path, sizeof(path), "%s/%" PRIu32 ".incomplete", s->backup_path, s->backup_bsn); int rc = ss_vfsmkdir(s->r->vfs, path, 0755); if (ssunlikely(rc == -1)) { sr_error(s->r->e, "backup directory '%s' create error: %s", path, strerror(errno)); return -1; } int i = 0; while (i < s->count) { scdb *db = &s->i[i]; snprintf(path, sizeof(path), "%s/%" PRIu32 ".incomplete/%s", s->backup_path, s->backup_bsn, db->index->scheme.name); rc = ss_vfsmkdir(s->r->vfs, path, 0755); if (ssunlikely(rc == -1)) { sr_error(s->r->e, "backup directory '%s' create error: %s", path, strerror(errno)); return -1; } i++; } snprintf(path, sizeof(path), "%s/%" PRIu32 ".incomplete/log", s->backup_path, s->backup_bsn); rc = ss_vfsmkdir(s->r->vfs, path, 0755); if (ssunlikely(rc == -1)) { sr_error(s->r->e, "backup directory '%s' create error: %s", path, strerror(errno)); return -1; } ss_mutexlock(&s->lock); s->backup = 2; s->backup_in_progress = s->count; i = 0; while (i < s->count) { sc_task_backup(&s->i[i]); i++; } ss_mutexunlock(&s->lock); return 0; }
int se_scheduler(sescheduler *s, seworker *w) { setask task; int rc = se_schedule(s, &task, w); int job = rc; if (task.rotate) { rc = se_rotate(s, w); if (ssunlikely(rc == -1)) goto error; } if (task.req) { rc = se_dispatch(s, w, &task); if (ssunlikely(rc == -1)) { goto error; } } se *e = (se*)s->env; if (task.backup_complete) se_reqonbackup(e); if (job) { rc = se_run(&task, w); if (ssunlikely(rc == -1)) { if (task.plan.plan != SI_BACKUP && task.plan.plan != SI_BACKUPEND) { se_dbmalfunction(task.db); goto error; } ss_mutexlock(&s->lock); se_backuperror(s); ss_mutexunlock(&s->lock); } } if (task.gc) { rc = se_gc(s, w); if (ssunlikely(rc == -1)) goto error; } se_complete(s, &task); ss_trace(&w->trace, "%s", "sleep"); return job; error: ss_trace(&w->trace, "%s", "malfunction"); return -1; }
static int se_schedule(sescheduler *s, setask *task, seworker *w) { ss_trace(&w->trace, "%s", "schedule"); si_planinit(&task->plan); uint64_t now = ss_utime(); se *e = (se*)s->env; sedb *db; srzone *zone = se_zoneof(e); assert(zone != NULL); task->checkpoint_complete = 0; task->backup_complete = 0; task->rotate = 0; task->req = 0; task->gc = 0; task->db = NULL; ss_mutexlock(&s->lock); /* asynchronous reqs dispatcher */ if (s->req == 0) { switch (zone->async) { case 2: if (se_reqqueue(e) == 0) break; case 1: s->req = 1; task->req = zone->async; ss_mutexunlock(&s->lock); return 0; } } /* log gc and rotation */ if (s->rotate == 0) { task->rotate = 1; s->rotate = 1; } /* checkpoint */ int in_progress = 0; int rc; checkpoint: if (s->checkpoint) { task->plan.plan = SI_CHECKPOINT; task->plan.a = s->checkpoint_lsn; rc = se_schedule_plan(s, &task->plan, &db); switch (rc) { case 1: s->workers_branch++; se_dbref(db, 1); task->db = db; task->gc = 1; ss_mutexunlock(&s->lock); return 1; case 2: /* work in progress */ in_progress = 1; break; case 0: /* complete checkpoint */ s->checkpoint = 0; s->checkpoint_lsn_last = s->checkpoint_lsn; s->checkpoint_lsn = 0; task->checkpoint_complete = 1; break; } } /* apply zone policy */ switch (zone->mode) { case 0: /* compact_index */ case 1: /* compact_index + branch_count prio */ assert(0); break; case 2: /* checkpoint */ { if (in_progress) { ss_mutexunlock(&s->lock); return 0; } uint64_t lsn = sr_seq(&e->seq, SR_LSN); s->checkpoint_lsn = lsn; s->checkpoint = 1; goto checkpoint; } default: /* branch + compact */ assert(zone->mode == 3); } /* database shutdown-drop */ if (s->workers_gc_db < zone->gc_db_prio) { ss_spinlock(&e->dblock); db = NULL; if (ssunlikely(e->db_shutdown.n > 0)) { db = (sedb*)so_listfirst(&e->db_shutdown); if (se_dbgarbage(db)) { so_listdel(&e->db_shutdown, &db->o); } else { db = NULL; } } ss_spinunlock(&e->dblock); if (ssunlikely(db)) { if (db->dropped) task->plan.plan = SI_DROP; else task->plan.plan = SI_SHUTDOWN; s->workers_gc_db++; se_dbref(db, 1); task->db = db; ss_mutexunlock(&s->lock); return 1; } } /* backup */ if (s->backup && (s->workers_backup < zone->backup_prio)) { /* backup procedure. * * state 0 (start) * ------- * * a. disable log gc * b. mark to start backup (state 1) * * state 1 (background, delayed start) * ------- * * a. create backup_path/<bsn.incomplete> directory * b. create database directories * c. create log directory * d. state 2 * * state 2 (background, copy) * ------- * * a. schedule and execute node backup which bsn < backup_bsn * b. state 3 * * state 3 (background, completion) * ------- * * a. rotate log file * b. copy log files * c. enable log gc, schedule gc * d. rename <bsn.incomplete> into <bsn> * e. set last backup, set COMPLETE * */ if (s->backup == 1) { /* state 1 */ rc = se_backupstart(s); if (ssunlikely(rc == -1)) { se_backuperror(s); goto backup_error; } s->backup = 2; } /* state 2 */ task->plan.plan = SI_BACKUP; task->plan.a = s->backup_bsn; rc = se_schedule_plan(s, &task->plan, &db); switch (rc) { case 1: s->workers_backup++; se_dbref(db, 1); task->db = db; ss_mutexunlock(&s->lock); return 1; case 2: /* work in progress */ break; case 0: /* state 3 */ rc = se_backupcomplete(s, w); if (ssunlikely(rc == -1)) { se_backuperror(s); goto backup_error; } s->backup_events++; task->gc = 1; task->backup_complete = 1; break; } backup_error:; } /* garbage-collection */ if (s->gc) { if (s->workers_gc < zone->gc_prio) { task->plan.plan = SI_GC; task->plan.a = sx_vlsn(&e->xm); task->plan.b = zone->gc_wm; rc = se_schedule_plan(s, &task->plan, &db); switch (rc) { case 1: s->workers_gc++; se_dbref(db, 1); task->db = db; ss_mutexunlock(&s->lock); return 1; case 2: /* work in progress */ break; case 0: /* state 3 */ s->gc = 0; s->gc_last = now; break; } } } else { if (zone->gc_prio && zone->gc_period) { if ( (now - s->gc_last) >= ((uint64_t)zone->gc_period * 1000000) ) { s->gc = 1; } } } /* index aging */ if (s->age) { if (s->workers_branch < zone->branch_prio) { task->plan.plan = SI_AGE; task->plan.a = zone->branch_age * 1000000; /* ms */ task->plan.b = zone->branch_age_wm; rc = se_schedule_plan(s, &task->plan, &db); switch (rc) { case 1: s->workers_branch++; se_dbref(db, 1); task->db = db; ss_mutexunlock(&s->lock); return 1; case 0: s->age = 0; s->age_last = now; break; } } } else { if (zone->branch_prio && zone->branch_age_period) { if ( (now - s->age_last) >= ((uint64_t)zone->branch_age_period * 1000000) ) { s->age = 1; } } } /* branching */ if (s->workers_branch < zone->branch_prio) { /* schedule branch task using following * priority: * * a. peek node with the largest in-memory index * which is equal or greater then branch * watermark. * If nothing is found, stick to b. * * b. peek node with the largest in-memory index, * which has oldest update time. * * c. if no branch work is needed, schedule a * compaction job * */ task->plan.plan = SI_BRANCH; task->plan.a = zone->branch_wm; rc = se_schedule_plan(s, &task->plan, &db); if (rc == 1) { s->workers_branch++; se_dbref(db, 1); task->db = db; task->gc = 1; ss_mutexunlock(&s->lock); return 1; } } /* compaction */ task->plan.plan = SI_COMPACT; task->plan.a = zone->compact_wm; task->plan.b = zone->compact_mode; rc = se_schedule_plan(s, &task->plan, &db); if (rc == 1) { se_dbref(db, 1); task->db = db; ss_mutexunlock(&s->lock); return 1; } ss_mutexunlock(&s->lock); return 0; }
int se_scheduler_branch(void *arg) { sedb *db = arg; se *e = se_of(&db->o); srzone *z = se_zoneof(e); seworker stub; se_workerstub_init(&stub); int rc; while (1) { uint64_t vlsn = sx_vlsn(&e->xm); siplan plan = { .explain = SI_ENONE, .plan = SI_BRANCH, .a = z->branch_wm, .b = 0, .c = 0, .node = NULL }; rc = si_plan(&db->index, &plan); if (rc == 0) break; rc = si_execute(&db->index, &stub.dc, &plan, vlsn); if (ssunlikely(rc == -1)) break; } se_workerstub_free(&stub, &db->r); return rc; } int se_scheduler_compact(void *arg) { sedb *db = arg; se *e = se_of(&db->o); srzone *z = se_zoneof(e); seworker stub; se_workerstub_init(&stub); int rc; while (1) { uint64_t vlsn = sx_vlsn(&e->xm); siplan plan = { .explain = SI_ENONE, .plan = SI_COMPACT, .a = z->compact_wm, .b = z->compact_mode, .c = 0, .node = NULL }; rc = si_plan(&db->index, &plan); if (rc == 0) break; rc = si_execute(&db->index, &stub.dc, &plan, vlsn); if (ssunlikely(rc == -1)) break; } se_workerstub_free(&stub, &db->r); return rc; } int se_scheduler_checkpoint(void *arg) { se *o = arg; sescheduler *s = &o->sched; uint64_t lsn = sr_seq(&o->seq, SR_LSN); ss_mutexlock(&s->lock); s->checkpoint_lsn = lsn; s->checkpoint = 1; ss_mutexunlock(&s->lock); return 0; }
int se_scheduler_branch(void *arg) { sedb *db = arg; se *e = se_of(&db->o); srzone *z = se_zoneof(e); seworker *w = se_workerpool_pop(&e->sched.workers, &e->r); if (ssunlikely(w == NULL)) return -1; int rc; while (1) { uint64_t vlsn = sx_vlsn(&e->xm); uint64_t vlsn_lru = si_lru_vlsn(&db->index); siplan plan = { .explain = SI_ENONE, .plan = SI_BRANCH, .a = z->branch_wm, .b = 0, .c = 0, .node = NULL }; rc = si_plan(&db->index, &plan); if (rc == 0) break; rc = si_execute(&db->index, &w->dc, &plan, vlsn, vlsn_lru); if (ssunlikely(rc == -1)) break; } se_workerpool_push(&e->sched.workers, w); return rc; } int se_scheduler_compact(void *arg) { sedb *db = arg; se *e = se_of(&db->o); srzone *z = se_zoneof(e); seworker *w = se_workerpool_pop(&e->sched.workers, &e->r); if (ssunlikely(w == NULL)) return -1; int rc; while (1) { uint64_t vlsn = sx_vlsn(&e->xm); uint64_t vlsn_lru = si_lru_vlsn(&db->index); siplan plan = { .explain = SI_ENONE, .plan = SI_COMPACT, .a = z->compact_wm, .b = z->compact_mode, .c = 0, .node = NULL }; rc = si_plan(&db->index, &plan); if (rc == 0) break; rc = si_execute(&db->index, &w->dc, &plan, vlsn, vlsn_lru); if (ssunlikely(rc == -1)) break; } se_workerpool_push(&e->sched.workers, w); return rc; } int se_scheduler_compact_index(void *arg) { sedb *db = arg; se *e = se_of(&db->o); srzone *z = se_zoneof(e); seworker *w = se_workerpool_pop(&e->sched.workers, &e->r); if (ssunlikely(w == NULL)) return -1; int rc; while (1) { uint64_t vlsn = sx_vlsn(&e->xm); uint64_t vlsn_lru = si_lru_vlsn(&db->index); siplan plan = { .explain = SI_ENONE, .plan = SI_COMPACT_INDEX, .a = z->branch_wm, .b = 0, .c = 0, .node = NULL }; rc = si_plan(&db->index, &plan); if (rc == 0) break; rc = si_execute(&db->index, &w->dc, &plan, vlsn, vlsn_lru); if (ssunlikely(rc == -1)) break; } se_workerpool_push(&e->sched.workers, w); return rc; } int se_scheduler_anticache(void *arg) { se *o = arg; sescheduler *s = &o->sched; uint64_t asn = sr_seq(&o->seq, SR_ASNNEXT); ss_mutexlock(&s->lock); s->anticache_asn = asn; s->anticache_storage = o->conf.anticache; s->anticache = 1; ss_mutexunlock(&s->lock); return 0; }
int sc_ctl_branch(sc *s, uint64_t vlsn, si *index) { sr *r = s->r; int rc = sr_statusactive(r->status); if (ssunlikely(rc == 0)) return 0; srzone *z = sr_zoneof(r); scworker *w = sc_workerpool_pop(&s->wp, r); if (ssunlikely(w == NULL)) return -1; while (1) { uint64_t vlsn_lru = si_lru_vlsn(index); siplan plan = { .explain = SI_ENONE, .plan = SI_BRANCH, .a = z->branch_wm, .b = 0, .c = 0, .node = NULL }; rc = si_plan(index, &plan); if (rc == 0) break; rc = si_execute(index, &w->dc, &plan, vlsn, vlsn_lru); if (ssunlikely(rc == -1)) break; } sc_workerpool_push(&s->wp, w); return rc; } int sc_ctl_compact(sc *s, uint64_t vlsn, si *index) { sr *r = s->r; int rc = sr_statusactive(r->status); if (ssunlikely(rc == 0)) return 0; srzone *z = sr_zoneof(r); scworker *w = sc_workerpool_pop(&s->wp, r); if (ssunlikely(w == NULL)) return -1; while (1) { uint64_t vlsn_lru = si_lru_vlsn(index); siplan plan = { .explain = SI_ENONE, .plan = SI_COMPACT, .a = z->compact_wm, .b = z->compact_mode, .c = 0, .node = NULL }; rc = si_plan(index, &plan); if (rc == 0) break; rc = si_execute(index, &w->dc, &plan, vlsn, vlsn_lru); if (ssunlikely(rc == -1)) break; } sc_workerpool_push(&s->wp, w); return rc; } int sc_ctl_compact_index(sc *s, uint64_t vlsn, si *index) { sr *r = s->r; int rc = sr_statusactive(r->status); if (ssunlikely(rc == 0)) return 0; srzone *z = sr_zoneof(r); scworker *w = sc_workerpool_pop(&s->wp, r); if (ssunlikely(w == NULL)) return -1; while (1) { uint64_t vlsn_lru = si_lru_vlsn(index); siplan plan = { .explain = SI_ENONE, .plan = SI_COMPACT_INDEX, .a = z->branch_wm, .b = 0, .c = 0, .node = NULL }; rc = si_plan(index, &plan); if (rc == 0) break; rc = si_execute(index, &w->dc, &plan, vlsn, vlsn_lru); if (ssunlikely(rc == -1)) break; } sc_workerpool_push(&s->wp, w); return rc; } int sc_ctl_anticache(sc *s) { uint64_t asn = sr_seq(s->r->seq, SR_ASNNEXT); ss_mutexlock(&s->lock); s->anticache_asn = asn; s->anticache_storage = s->anticache_limit; s->anticache = 1; ss_mutexunlock(&s->lock); return 0; }
void sc_readpool_wakeup(screadpool *p) { ss_mutexlock(&p->lock); ss_condsignal(&p->cond); ss_mutexunlock(&p->lock); }