static inline int si_qgetindex(siquery *q, sinode *node) { svindex *second; svindex *first = si_nodeindex_priority(node, &second); ssiter i; ss_iterinit(sv_indexiter, &i); int rc; if (first->count > 0) { rc = ss_iteropen(sv_indexiter, &i, q->r, first, SS_GTE, q->key, q->keysize); if (rc) { goto result; } } if (sslikely(second == NULL || !second->count)) return 0; rc = ss_iteropen(sv_indexiter, &i, q->r, second, SS_GTE, q->key, q->keysize); if (! rc) { return 0; } result:; sv *v = ss_iterof(sv_indexiter, &i); assert(v != NULL); svv *visible = v->v; if (sslikely(! q->has)) { visible = sv_visible((svv*)v->v, q->vlsn); if (visible == NULL) return 0; } sv vret; sv_init(&vret, &sv_vif, visible, NULL); return si_qgetresult(q, &vret, 0); }
static int si_redistribute_index(si *index, sr *r, sdc *c, sinode *node) { svindex *vindex = si_nodeindex(node); ssiter i; ss_iterinit(sv_indexiter, &i); ss_iteropen(sv_indexiter, &i, r, vindex, SS_GTE, NULL, 0); while (ss_iterhas(sv_indexiter, &i)) { sv *v = ss_iterof(sv_indexiter, &i); int rc = ss_bufadd(&c->b, r->a, &v->v, sizeof(svv**)); if (ssunlikely(rc == -1)) return sr_oom_malfunction(r->e); ss_iternext(sv_indexiter, &i); } if (ssunlikely(ss_bufused(&c->b) == 0)) return 0; uint64_t now = ss_utime(); ss_iterinit(ss_bufiterref, &i); ss_iteropen(ss_bufiterref, &i, &c->b, sizeof(svv*)); while (ss_iterhas(ss_bufiterref, &i)) { svv *v = ss_iterof(ss_bufiterref, &i); si_redistribute_set(index, r, now, v); ss_iternext(ss_bufiterref, &i); } return 0; }
static int si_redistribute(si *index, sr *r, sdc *c, sinode *node, ssbuf *result) { (void)index; svindex *vindex = si_nodeindex(node); ssiter i; ss_iterinit(sv_indexiter, &i); ss_iteropen(sv_indexiter, &i, r, vindex, SS_GTE, NULL, 0); while (ss_iterhas(sv_indexiter, &i)) { sv *v = ss_iterof(sv_indexiter, &i); int rc = ss_bufadd(&c->b, r->a, &v->v, sizeof(svv**)); if (ssunlikely(rc == -1)) return sr_oom_malfunction(r->e); ss_iternext(sv_indexiter, &i); } if (ssunlikely(ss_bufused(&c->b) == 0)) return 0; ss_iterinit(ss_bufiterref, &i); ss_iteropen(ss_bufiterref, &i, &c->b, sizeof(svv*)); ssiter j; ss_iterinit(ss_bufiterref, &j); ss_iteropen(ss_bufiterref, &j, result, sizeof(sinode*)); sinode *prev = ss_iterof(ss_bufiterref, &j); ss_iternext(ss_bufiterref, &j); while (1) { sinode *p = ss_iterof(ss_bufiterref, &j); if (p == NULL) { assert(prev != NULL); while (ss_iterhas(ss_bufiterref, &i)) { svv *v = ss_iterof(ss_bufiterref, &i); v->next = NULL; sv_indexset(&prev->i0, r, v); ss_iternext(ss_bufiterref, &i); } break; } while (ss_iterhas(ss_bufiterref, &i)) { svv *v = ss_iterof(ss_bufiterref, &i); v->next = NULL; sdindexpage *page = sd_indexmin(&p->self.index); int rc = sr_compare(r->scheme, sv_vpointer(v), v->size, sd_indexpage_min(&p->self.index, page), page->sizemin); if (ssunlikely(rc >= 0)) break; sv_indexset(&prev->i0, r, v); ss_iternext(ss_bufiterref, &i); } if (ssunlikely(! ss_iterhas(ss_bufiterref, &i))) break; prev = p; ss_iternext(ss_bufiterref, &j); } assert(ss_iterof(ss_bufiterref, &i) == NULL); return 0; }
static void sv_mergeiter_merge_dup_a_chain(void) { stlist vlista; stlist vlistb; st_listinit(&vlista, 0); st_listinit(&vlistb, 0); int key = 7; int i = 0; int lsn = 5; while (i < 5) { st_sv(&st_r.g, &vlista, lsn, 0 | ((i > 0) ? SVDUP: 0), key); i++; lsn--; } ssiter ita; ss_iterinit(ss_bufiterref, &ita); ss_iteropen(ss_bufiterref, &ita, &vlista.list, sizeof(sv*)); ssiter itb; ss_iterinit(ss_bufiterref, &itb); ss_iteropen(ss_bufiterref, &itb, &vlistb.list, sizeof(sv*)); svmerge m; sv_mergeinit(&m); sv_mergeprepare(&m, &st_r.r, 2); svmergesrc *s = sv_mergeadd(&m, NULL); t(s != NULL); s->src = ita; s = sv_mergeadd(&m, NULL); t(s != NULL); s->src = itb; ssiter merge; ss_iterinit(sv_mergeiter, &merge); ss_iteropen(sv_mergeiter, &merge, &st_r.r, &m, SS_GTE); i = 0; while (ss_iteratorhas(&merge)) { sv *v = (sv*)ss_iteratorof(&merge); t( *(int*)sv_key(v, &st_r.r, 0) == key ); if (i == 0) { t( sv_flags(v) == 0 ); } else { t( (sv_flags(v) | sv_mergeisdup(&merge)) == (0|SVDUP) ); } ss_iteratornext(&merge); i++; } t( i == 5 ); ss_iteratorclose(&merge); sv_mergefree(&m, &st_r.a); st_listfree(&vlista, &st_r.r); st_listfree(&vlistb, &st_r.r); }
static void sv_mergeiter_merge_ba(void) { stlist vlista; stlist vlistb; st_listinit(&vlista, 0); st_listinit(&vlistb, 0); int i = 0; while (i < 5) { st_sv(&st_r.g, &vlista, i, 0, i); i++; } while (i < 10) { st_sv(&st_r.g, &vlistb, i, 0, i); i++; } ssiter ita; ss_iterinit(ss_bufiterref, &ita); ss_iteropen(ss_bufiterref, &ita, &vlista.list, sizeof(sv*)); ssiter itb; ss_iterinit(ss_bufiterref, &itb); ss_iteropen(ss_bufiterref, &itb, &vlistb.list, sizeof(sv*)); svmerge m; sv_mergeinit(&m); sv_mergeprepare(&m, &st_r.r, 3); svmergesrc *s = sv_mergeadd(&m, NULL); t(s != NULL); s->src = ita; s = sv_mergeadd(&m, NULL); t(s != NULL); s->src = itb; ssiter merge; ss_iterinit(sv_mergeiter, &merge); ss_iteropen(sv_mergeiter, &merge, &st_r.r, &m, SS_GTE); i = 0; while (ss_iteratorhas(&merge)) { sv *v = (sv*)ss_iteratorof(&merge); t( *(int*)sv_key(v, &st_r.r, 0) == i ); t( sv_lsn(v) == i ); t( sv_flags(v) == 0 ); ss_iteratornext(&merge); i++; } t( i == 10 ); ss_iteratorclose(&merge); sv_mergefree(&m, &st_r.a); st_listfree(&vlista, &st_r.r); st_listfree(&vlistb, &st_r.r); }
int si_compact(si *index, sr *r, sdc *c, siplan *plan, uint64_t vlsn) { sinode *node = plan->node; assert(node->flags & SI_LOCK); /* read node file */ sd_creset(c); int rc = si_noderead(r, &c->c, node); if (ssunlikely(rc == -1)) return -1; /* prepare for compaction */ rc = sd_censure(c, r, node->branch_count); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "%s", "memory allocation failed"); return -1; } svmerge merge; sv_mergeinit(&merge); rc = sv_mergeprepare(&merge, r, node->branch_count); if (ssunlikely(rc == -1)) return -1; uint32_t size_stream = 0; sdcbuf *cbuf = c->head; sibranch *b = node->branch; while (b) { svmergessc *s = sv_mergeadd(&merge, NULL); rc = ss_bufensure(&cbuf->b, r->a, b->index.h->sizevmax); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "%s", "memory allocation failed"); return -1; } size_stream += sd_indextotal(&b->index); ss_iterinit(sd_iter, &s->ssc); ss_iteropen(sd_iter, &s->ssc, r, &b->index, c->c.s, 0, index->scheme->compression, &cbuf->a, &cbuf->b); cbuf = cbuf->next; b = b->next; } ssiter i; ss_iterinit(sv_mergeiter, &i); ss_iteropen(sv_mergeiter, &i, r, &merge, SS_GTE); rc = si_compaction(index, r, c, vlsn, node, &i, size_stream); if (ssunlikely(rc == -1)) { sv_mergefree(&merge, r->a); return -1; } sv_mergefree(&merge, r->a); return 0; }
static inline int sx_deadlock_in(sxmanager *m, sslist *mark, sx *t, sx *p) { if (p->deadlock.next != &p->deadlock) return 0; ss_listappend(mark, &p->deadlock); ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &p->log.buf, sizeof(svlogv)); for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); sxv *v = lv->v.v; if (v->prev == NULL) continue; do { sx *n = sx_find(m, v->id); assert(n != NULL); if (ssunlikely(n == t)) return 1; int rc = sx_deadlock_in(m, mark, t, n); if (ssunlikely(rc == 1)) return 1; v = v->prev; } while (v); } return 0; }
static void sv_indexiter_iterate1(void) { svindex i; t( sv_indexinit(&i) == 0 ); int j = 0; while (j < 16) { svv *v = st_svv(&st_r.g, NULL, j, 0, j); t( sv_indexset(&i, &st_r.r, v) == 0 ); j++; } ssiter it; ss_iterinit(sv_indexiter, &it); ss_iteropen(sv_indexiter, &it, &st_r.r, &i, SS_GTE, NULL, 0); j = 0; while (ss_iteratorhas(&it)) { sv *v = ss_iteratorof(&it); t( sv_lsn(v) == j ); ss_iteratornext(&it); j++; } t( j == 16 ); sv_indexfree(&i, &st_r.r); }
sxstate sx_rollback(sx *x) { sxmanager *m = x->manager; ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &x->log.buf, sizeof(svlogv)); /* support log free after commit and half-commit mode */ if (x->state == SXCOMMIT) { int gc = 0; for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); svv *v = lv->v.v; int size = sv_vsize(v); if (sv_vunref(m->r, v)) gc += size; } ss_quota(m->r->quota, SS_QREMOVE, gc); sx_promote(x, SXROLLBACK); return SXROLLBACK; } sx_rollback_svp(x, &i, 1); sx_promote(x, SXROLLBACK); sx_end(x); return SXROLLBACK; }
static inline void sx_rollback_index(sx *t, int translate) { ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &t->log.buf, sizeof(svlogv)); for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); sxv *v = lv->v.v; /* remove from index and replace head with * a first waiter */ if (v->prev) goto unlink; sxindex *i = v->index; if (v->next == NULL) ss_rbremove(&i->i, &v->node); else ss_rbreplace(&i->i, &v->node, &v->next->node); unlink: sx_vunlink(v); /* translate log version from sxv to svv */ if (translate) { sv_init(&lv->v, &sv_vif, v->v, NULL); lv->vgc = v; } } }
sxstate sx_commit(sx *t) { assert(t->s == SXPREPARE); if (t->complete) goto complete; ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &t->log.buf, sizeof(svlogv)); for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); sxv *v = lv->v.v; /* mark waiters as aborted */ sx_vabortwaiters(v); /* remove from concurrent index and replace * head with a first waiter */ sxindex *i = v->index; if (v->next == NULL) ss_rbremove(&i->i, &v->node); else ss_rbreplace(&i->i, &v->node, &v->next->node); /* unlink version */ sx_vunlink(v); /* translate log version from sxv to svv */ sv_init(&lv->v, &sv_vif, v->v, NULL); lv->vgc = v; } complete: t->s = SXCOMMIT; sx_end(t); return SXCOMMIT; }
sxstate sx_prepare(sx *t, sxpreparef prepare, void *arg) { ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &t->log.buf, sizeof(svlogv)); sxstate s = SXPREPARE; for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); sxv *v = lv->v.v; /* cancelled by a concurrent commited * transaction */ if (v->v->flags & SVABORT) { s = SXROLLBACK; goto done; } /* concurrent update in progress */ if (v->prev != NULL) { s = SXLOCK; goto done; } /* check that new key has not been committed by * a concurrent transaction */ if (prepare) { sxindex *i = v->index; s = prepare(t, &lv->v, arg, i->ptr); if (ssunlikely(s != SXPREPARE)) goto done; } } done: t->s = s; return s; }
void sx_gc(sx *t, sr *r) { sxmanager *m = t->manager; ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &t->log.buf, sizeof(svlogv)); if (sslikely(t->s == SXCOMMIT)) { for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); sxv *v = lv->vgc; ss_free(m->asxv, v); } } else if (t->s == SXROLLBACK) { int gc = 0; for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); sxv *v = lv->v.v; gc += sv_vsize((svv*)v->v); sx_vfree(m->a, m->asxv, v); } ss_quota(r->quota, SS_QREMOVE, gc); } sv_logfree(&t->log, m->a); t->s = SXUNDEF; }
static inline int si_recovercomplete(sitrack *track, sr *r, si *index, ssbuf *buf) { /* prepare and build primary index */ ss_bufreset(buf); ssrbnode *p = ss_rbmin(&track->i); while (p) { sinode *n = sscast(p, sinode, node); int rc = ss_bufadd(buf, r->a, &n, sizeof(sinode*)); if (ssunlikely(rc == -1)) return sr_oom_malfunction(r->e); p = ss_rbnext(&track->i, p); } ssiter i; ss_iterinit(ss_bufiterref, &i); ss_iteropen(ss_bufiterref, &i, buf, sizeof(sinode*)); while (ss_iterhas(ss_bufiterref, &i)) { sinode *n = ss_iterof(ss_bufiterref, &i); if (n->recover & SI_RDB_REMOVE) { int rc = si_nodefree(n, r, 1); if (ssunlikely(rc == -1)) return -1; ss_iternext(ss_bufiterref, &i); continue; } n->recover = SI_RDB; si_insert(index, n); si_plannerupdate(&index->p, SI_COMPACT|SI_BRANCH|SI_TEMP, n); ss_iternext(ss_bufiterref, &i); } return 0; }
static inline int si_noderecover(sinode *n, sr *r, sdsnapshotnode *sn, int in_memory) { /* fast recover from snapshot file */ if (sn) { n->temperature_reads = sn->temperature_reads; if (! in_memory) return si_noderecover_snapshot(n, r, sn); } /* recover branches */ ssiter i; ss_iterinit(sd_recover, &i); ss_iteropen(sd_recover, &i, r, &n->file); int first = 1; int rc; while (ss_iteratorhas(&i)) { sdindexheader *h = ss_iteratorof(&i); sibranch *b; if (first) { b = &n->self; } else { b = si_branchnew(r); if (ssunlikely(b == NULL)) goto error; } sdindex index; sd_indexinit(&index); rc = sd_indexcopy(&index, r, h); if (ssunlikely(rc == -1)) goto error; si_branchset(b, &index); if (in_memory) { rc = si_branchload(b, r, &n->file); if (ssunlikely(rc == -1)) goto error; } b->next = n->branch; n->branch = b; n->branch_count++; first = 0; ss_iteratornext(&i); } rc = sd_recover_complete(&i); if (ssunlikely(rc == -1)) goto error; ss_iteratorclose(&i); n->in_memory = in_memory; return 0; error: ss_iteratorclose(&i); return -1; }
static inline int si_noderecover(sinode *n, sr *r, int in_memory) { /* recover branches */ ssiter i; ss_iterinit(sd_recover, &i); ss_iteropen(sd_recover, &i, r, &n->file); int first = 1; int rc; while (ss_iteratorhas(&i)) { sdindexheader *h = ss_iteratorof(&i); sibranch *b; if (first) { b = &n->self; } else { b = si_branchnew(r); if (ssunlikely(b == NULL)) goto error; } sdindex index; sd_indexinit(&index); rc = sd_indexcopy(&index, r, h); if (ssunlikely(rc == -1)) goto error; si_branchset(b, &index); if (in_memory) { char *start = (char*)h - h->total - sizeof(sdseal); char *end = start + sizeof(sdseal) + h->total + sizeof(sdindexheader) + h->size + h->extension; int branch_size = end - start; rc = ss_blobensure(&b->copy, branch_size); if (ssunlikely(rc == -1)) { sr_oom_malfunction(r->e); goto error; } memcpy(b->copy.p, start, branch_size); } b->next = n->branch; n->branch = b; n->branch_count++; first = 0; ss_iteratornext(&i); } rc = sd_recover_complete(&i); if (ssunlikely(rc == -1)) goto error; ss_iteratorclose(&i); return 0; error: ss_iteratorclose(&i); return -1; }
sxstate sx_rollback(sx *x) { assert(x->state != SX_COMMIT); ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &x->log->buf, sizeof(svlogv)); sx_rollback_svp(x, &i, 1); sx_promote(x, SX_ROLLBACK); sx_end(x); return SX_ROLLBACK; }
static void freelog(svlog *log, sr *c) { ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &log->buf, sizeof(svlogv)); for (; ss_iteratorhas(&i); ss_iteratornext(&i)) { svlogv *v = ss_iteratorof(&i); ss_free(c->a, v->v.v); } sv_logfree(log, c->a); }
static int si_readcommited_branch(sr *r, sibranch *b, sv *v) { ssiter i; ss_iterinit(sd_indexiter, &i); ss_iteropen(sd_indexiter, &i, r, &b->index, SS_GTE, sv_pointer(v), sv_size(v)); sdindexpage *page = ss_iterof(sd_indexiter, &i); if (page == NULL) return 0; return page->lsnmax >= sv_lsn(v); }
static void sv_indexiter_iterate0(void) { svindex i; t( sv_indexinit(&i) == 0 ); int keyb = 3; int keya = 7; int keyc = 15; svv *h = st_svv(&st_r.g, NULL, 0, 0, keyb); t( sv_indexset(&i, &st_r.r, h) == 0 ); svv *p = st_svv(&st_r.g, NULL, 2, 0, keyc); t( sv_indexset(&i, &st_r.r, p) == 0 ); svv *va = st_svv(&st_r.g, NULL, 1, 0, keya); t( sv_indexset(&i, &st_r.r, va) == 0 ); svv *vb = st_svv(&st_r.g, NULL, 2, 0, keya); t( sv_indexset(&i, &st_r.r, vb) == 0 ); svv *vc = st_svv(&st_r.g, NULL, 3, 0, keya); t( sv_indexset(&i, &st_r.r, vc) == 0 ); ssiter it; ss_iterinit(sv_indexiter, &it); ss_iteropen(sv_indexiter, &it, &st_r.r, &i, SS_GTE, NULL, 0); t( ss_iteratorhas(&it) != 0 ); sv *v = ss_iteratorof(&it); t( v->v == h ); ss_iteratornext(&it); v = ss_iteratorof(&it); t( v->v == vc ); ss_iteratornext(&it); v = ss_iteratorof(&it); t( v->v == vb ); ss_iteratornext(&it); v = ss_iteratorof(&it); t( v->v == va ); ss_iteratornext(&it); v = ss_iteratorof(&it); t( v->v == p ); ss_iteratornext(&it); v = ss_iteratorof(&it); t( v == NULL ); sv_indexfree(&i, &st_r.r); }
static void sd_v_test(void) { sdbuild b; sd_buildinit(&b); t( sd_buildbegin(&b, &st_r.r, 1, 0, 0) == 0); int i = 7; int j = 8; addv(&b, &st_r.r, 3, 0, &i); addv(&b, &st_r.r, 4, 0, &j); sd_buildend(&b, &st_r.r); ssbuf buf; ss_bufinit(&buf); ssbuf xfbuf; ss_bufinit(&xfbuf); t( ss_bufensure(&xfbuf, &st_r.a, 1024) == 0 ); t( sd_commitpage(&b, &st_r.r, &buf) == 0 ); sdpageheader *h = (sdpageheader*)buf.s; sdpage page; sd_pageinit(&page, h); ssiter it; ss_iterinit(sd_pageiter, &it); ss_iteropen(sd_pageiter, &it, &st_r.r, &xfbuf, &page, SS_GTE, NULL, 0); t( ss_iteratorhas(&it) != 0 ); sv *v = ss_iteratorof(&it); t( v != NULL ); t( *(int*)sv_key(v, &st_r.r, 0) == i ); t( sv_lsn(v) == 3 ); t( sv_flags(v) == 0 ); ss_iteratornext(&it); t( ss_iteratorhas(&it) != 0 ); v = ss_iteratorof(&it); t( v != NULL ); t( *(int*)sv_key(v, &st_r.r, 0) == j ); t( sv_lsn(v) == 4 ); t( sv_flags(v) == 0 ); ss_iteratornext(&it); v = ss_iteratorof(&it); t( v == NULL ); sd_buildfree(&b, &st_r.r); ss_buffree(&buf, &st_r.a); ss_buffree(&xfbuf, &st_r.a); }
static int si_splitfree(ssbuf *result, sr *r) { ssiter i; ss_iterinit(ss_bufiterref, &i); ss_iteropen(ss_bufiterref, &i, result, sizeof(sinode*)); while (ss_iterhas(ss_bufiterref, &i)) { sinode *p = ss_iterof(ss_bufiterref, &i); si_nodefree(p, r, 0); ss_iternext(ss_bufiterref, &i); } return 0; }
static void sv_indexiter_lte_empty(void) { svindex i; t( sv_indexinit(&i) == 0 ); ssiter it; ss_iterinit(sv_indexiter, &it); ss_iteropen(sv_indexiter, &it, &st_r.r, &i, SS_LTE, NULL, 0); t( ss_iteratorhas(&it) == 0 ); sv *v = ss_iteratorof(&it); t( v == NULL ); sv_indexfree(&i, &st_r.r); }
static void sv_indexiter_lt_eq(void) { svindex i; t( sv_indexinit(&i) == 0 ); int keya = 7; int keyb = 5; int keyc = 2; svv *va = st_svv(&st_r.g, NULL, 0, 0, keya); t( sv_indexset(&i, &st_r.r, va) == 0 ); svv *vb = st_svv(&st_r.g, NULL, 0, 0, keyb); t( sv_indexset(&i, &st_r.r, vb) == 0 ); svv *vc = st_svv(&st_r.g, NULL, 0, 0, keyc); t( sv_indexset(&i, &st_r.r, vc) == 0 ); ssiter it; ss_iterinit(sv_indexiter, &it); ss_iteropen(sv_indexiter, &it, &st_r.r, &i, SS_LT, sv_vpointer(va), va->size); t( ss_iteratorhas(&it) != 0 ); sv *v = ss_iteratorof(&it); t( v->v == vb ); ss_iterinit(sv_indexiter, &it); ss_iteropen(sv_indexiter, &it, &st_r.r, &i, SS_LT, sv_vpointer(vb), vb->size); t( ss_iteratorhas(&it) != 0 ); v = ss_iteratorof(&it); t( v->v == vc ); ss_iterinit(sv_indexiter, &it); ss_iteropen(sv_indexiter, &it, &st_r.r, &i, SS_LT, sv_vpointer(vc), vc->size); t( ss_iteratorhas(&it) == 0 ); v = ss_iteratorof(&it); t( v == NULL ); sv_indexfree(&i, &st_r.r); }
static inline void si_redistribute_set(si *index, sr *r, svv *v) { /* match node */ ssiter i; ss_iterinit(si_iter, &i); ss_iteropen(si_iter, &i, r, index, SS_GTE, sv_vpointer(v)); sinode *node = ss_iterof(si_iter, &i); assert(node != NULL); /* update node */ svindex *vindex = si_nodeindex(node); sv_indexset(vindex, r, v); node->used += sv_vsize(v, &index->r); /* schedule node */ si_plannerupdate(&index->p, node); }
static void sv_indexiter_gte_empty(void) { svindex i; t( sv_indexinit(&i) == 0 ); svv *key = st_svv(&st_r.g, &st_r.gc, 0, 0, 7); ssiter it; ss_iterinit(sv_indexiter, &it); ss_iteropen(sv_indexiter, &it, &st_r.r, &i, SS_GTE, sv_vpointer(key), key->size); t( ss_iteratorhas(&it) == 0 ); sv *v = ss_iteratorof(&it); t( v == NULL ); sv_indexfree(&i, &st_r.r); }
sxstate sx_commit(sx *x) { if (x->state == SX_COMMIT) return SX_COMMIT; assert(x->state == SX_PREPARE); sxmanager *m = x->manager; ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &x->log->buf, sizeof(svlogv)); uint64_t csn = ++m->csn; for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); sxv *v = lv->ptr; if ((int)v->lo == x->log_read) break; /* abort conflict reader */ if (v->prev && !sx_vcommitted(v->prev)) { sxindex *i = v->prev->index; assert(sv_vflags(v->prev->v, i->r) & SVGET); sx_vabort(v->prev); } /* abort waiters */ sx_vabort_all(v->next); /* mark stmt as commited */ sx_vcommit(v, csn); lv->ptr = NULL; /* schedule read stmt for gc */ sxindex *i = v->index; if (sv_vflags(v->v, i->r) & SVGET) { sv_vref(v->v); v->gc = m->gc; m->gc = v; m->count_gc++; } else { sx_untrack(v); sx_vpool_push(&m->pool, v); } } /* rollback latest reads */ sx_rollback_svp(x, &i, 0); sx_promote(x, SX_COMMIT); sx_end(x); return SX_COMMIT; }
sxstate sx_commit(sx *x) { assert(x->state == SXPREPARE); sxmanager *m = x->manager; ssiter i; ss_iterinit(ss_bufiter, &i); ss_iteropen(ss_bufiter, &i, &x->log.buf, sizeof(svlogv)); uint64_t csn = ++m->csn; for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); sxv *v = lv->v.v; if ((int)v->lo == x->log_read) break; /* abort conflict reader */ if (v->prev && !sx_vcommitted(v->prev)) { assert(v->prev->v->flags & SVGET); sx_vabort(v->prev); } /* abort waiters */ sx_vabort_all(v->next); /* mark stmt as commited */ sx_vcommit(v, csn); /* translate log version from sxv to svv */ sv_init(&lv->v, &sv_vif, v->v, NULL); /* schedule read stmt for gc */ if (v->v->flags & SVGET) { sv_vref(v->v); v->gc = m->gc; m->gc = v; m->count_gc++; } else { sx_untrack(v); ss_free(m->asxv, v); } } /* rollback latest reads */ sx_rollback_svp(x, &i, 0); sx_promote(x, SXCOMMIT); sx_end(x); return SXCOMMIT; }
static inline void si_redistribute_set(si *index, sr *r, uint64_t now, svv *v) { index->update_time = now; /* match node */ ssiter i; ss_iterinit(si_iter, &i); ss_iteropen(si_iter, &i, r, index, SS_ROUTE, sv_vpointer(v), v->size); sinode *node = ss_iterof(si_iter, &i); assert(node != NULL); /* update node */ svindex *vindex = si_nodeindex(node); sv_indexset(vindex, r, v); node->update_time = index->update_time; node->used += sv_vsize(v); /* schedule node */ si_plannerupdate(&index->p, SI_BRANCH, node); }
static inline int si_tracksnapshot(sitrack *track, sr *r, si *i, sdsnapshot *s) { /* read snapshot */ ssiter iter; ss_iterinit(sd_snapshotiter, &iter); int rc; rc = ss_iteropen(sd_snapshotiter, &iter, r, s); if (ssunlikely(rc == -1)) return -1; for (; ss_iterhas(sd_snapshotiter, &iter); ss_iternext(sd_snapshotiter, &iter)) { sdsnapshotnode *n = ss_iterof(sd_snapshotiter, &iter); /* skip updated nodes */ sspath path; ss_path(&path, i->scheme->path, n->id, ".db"); rc = ss_vfsexists(r->vfs, path.path); if (! rc) continue; uint64_t size = ss_vfssize(r->vfs, path.path); if (size != n->size_file) continue; /* recover node */ sinode *node = si_nodenew(r); if (ssunlikely(node == NULL)) return -1; node->recover = SI_RDB; rc = si_nodeopen(node, r, i->scheme, &path, n); if (ssunlikely(rc == -1)) { si_nodefree(node, r, 0); return -1; } si_trackmetrics(track, node); si_trackset(track, node); } /* recover index temperature (read stats) */ sdsnapshotheader *h = sd_snapshot_header(s); i->read_cache = h->read_cache; i->read_disk = h->read_disk; i->lru_v = h->lru_v; i->lru_steps = h->lru_steps; return 0; }