static int se_schedule_plan(sescheduler *s, siplan *plan, sedb **dbret) { int start = s->rr; int limit = s->count; int i = start; int rc_inprogress = 0; int rc; *dbret = NULL; first_half: while (i < limit) { sedb *db = s->i[i]; if (ssunlikely(! se_dbactive(db))) { i++; continue; } rc = si_plan(&db->index, plan); switch (rc) { case 1: s->rr = i; *dbret = db; return 1; case 2: rc_inprogress = rc; case 0: break; } i++; } if (i > start) { i = 0; limit = start; goto first_half; } s->rr = 0; return rc_inprogress; }
static inline int sc_plan(sc *s, sctask *task, int id) { scdb *db = sc_current(s); uint32_t prio = s->prio[id]; if (db->workers[id] >= prio) return SI_PRETRY; return si_plan(db->index, &task->plan); }
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 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; }
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; }
static inline siplannerrc sc_do(sc *s, sctask *task) { siplannerrc rc; scdb *db = task->db; sicompaction *c = &db->index->scheme.compaction; ss_trace(&task->w->trace, "%s", "schedule"); /* checkpoint */ if (db->checkpoint) { task->plan.plan = SI_CHECKPOINT; task->plan.a = db->checkpoint_vlsn; rc = si_plan(db->index, &task->plan); switch (rc) { case SI_PMATCH: return rc; case SI_PNONE: sc_task_checkpoint_done(db, task->time); break; case SI_PRETRY: break; } } /* node delayed gc */ task->plan.plan = SI_NODEGC; rc = si_plan(db->index, &task->plan); if (rc == SI_PMATCH) return rc; /* backup */ if (db->backup) { /* 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 * */ /* state 2 */ task->plan.plan = SI_BACKUP; task->plan.a = s->backup_bsn; rc = sc_plan(s, task, SC_QBACKUP); switch (rc) { case SI_PMATCH: db->workers[SC_QBACKUP]++; task->db = db; return SI_PMATCH; case SI_PNONE: sc_task_backup_done(task->db); assert(s->backup_in_progress > 0); s->backup_in_progress--; /* state 3 */ if (s->backup_in_progress == 0) task->backup = 1; break; case SI_PRETRY: break; } } /* expire */ if (db->expire) { task->plan.plan = SI_EXPIRE; task->plan.a = db->index->scheme.expire; rc = sc_plan(s, task, SC_QEXPIRE); switch (rc) { case SI_PMATCH: db->workers[SC_QEXPIRE]++; return SI_PMATCH; case SI_PNONE: sc_task_expire_done(db, task->time); break; case SI_PRETRY: break; } } /* garbage-collection */ if (db->gc) { task->plan.plan = SI_GC; task->plan.a = task->vlsn; task->plan.b = c->gc_wm; rc = sc_plan(s, task, SC_QGC); switch (rc) { case SI_PMATCH: db->workers[SC_QGC]++; return SI_PMATCH; case SI_PNONE: sc_task_gc_done(db, task->time); break; case SI_PRETRY: break; } } /* compaction */ task->plan.plan = SI_COMPACTION; rc = si_plan(db->index, &task->plan); if (rc == SI_PMATCH) return SI_PMATCH; si_planinit(&task->plan); return SI_PNONE; }