static inline void sx_garbage_collect(sxmanager *m) { uint64_t min_csn = sx_csn(m); sxv *gc = NULL; uint32_t count = 0; sxv *next; sxv *v = m->gc; for (; v; v = next) { next = v->gc; assert(v->v->flags & SVGET); assert(sx_vcommitted(v)); if (v->csn > min_csn) { v->gc = gc; gc = v; count++; continue; } sx_untrack(v); sx_vfree(m->r, m->asxv, v); } m->count_gc = count; m->gc = gc; }
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 void sx_rollback_svp(sx *x, ssiter *i, int free) { sxmanager *m = x->manager; 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; /* remove from index and replace head with * a first waiter */ sx_untrack(v); /* translate log version from sxv to svv */ sv_init(&lv->v, &sv_vif, v->v, NULL); if (free) { if (sslikely(! (v->v->flags & SVGET))) gc += sv_vsize((svv*)v->v); sx_vfree(m->r, m->asxv, v); } } ss_quota(m->r->quota, SS_QREMOVE, gc); }
int sx_set(sx *x, sxindex *index, svv *version) { sxmanager *m = x->manager; sr *r = m->r; if (! (version->flags & SVGET)) { x->log_read = -1; } /* allocate mvcc container */ sxv *v = sx_valloc(m->asxv, version); if (ssunlikely(v == NULL)) { ss_quota(r->quota, SS_QREMOVE, sv_vsize(version)); sv_vfree(r, version); return -1; } v->id = x->id; v->index = index; svlogv lv; lv.id = index->dsn; lv.next = UINT32_MAX; sv_init(&lv.v, &sx_vif, v, NULL); /* update concurrent index */ ssrbnode *n = NULL; int rc = sx_match(&index->i, index->r->scheme, sv_vpointer(version), version->size, &n); if (ssunlikely(rc == 0 && n)) { /* exists */ } else { int pos = rc; /* unique */ v->lo = sv_logcount(&x->log); rc = sv_logadd(&x->log, r->a, &lv, index->ptr); if (ssunlikely(rc == -1)) { sr_oom(r->e); goto error; } ss_rbset(&index->i, n, pos, &v->node); return 0; } sxv *head = sscast(n, sxv, node); /* match previous update made by current * transaction */ sxv *own = sx_vmatch(head, x->id); if (ssunlikely(own)) { if (ssunlikely(version->flags & SVUPDATE)) { sr_error(r->e, "%s", "only one update statement is " "allowed per a transaction key"); goto error; } /* replace old document with the new one */ lv.next = sv_logat(&x->log, own->lo)->next; v->lo = own->lo; if (ssunlikely(sx_vaborted(own))) sx_vabort(v); sx_vreplace(own, v); if (sslikely(head == own)) ss_rbreplace(&index->i, &own->node, &v->node); /* update log */ sv_logreplace(&x->log, v->lo, &lv); ss_quota(r->quota, SS_QREMOVE, sv_vsize(own->v)); sx_vfree(r, m->asxv, own); return 0; } /* update log */ v->lo = sv_logcount(&x->log); rc = sv_logadd(&x->log, r->a, &lv, index->ptr); if (ssunlikely(rc == -1)) { sr_oom(r->e); goto error; } /* add version */ sx_vlink(head, v); return 0; error: ss_quota(r->quota, SS_QREMOVE, sv_vsize(v->v)); sx_vfree(r, m->asxv, v); return -1; }
int sx_set(sx *x, sxindex *index, svv *version) { sxmanager *m = x->manager; sr *r = index->r; svlogv lv; lv.index_id = index->dsn; lv.next = UINT32_MAX; lv.v = version; lv.ptr = NULL; /* allocate mvcc container */ sxv *v = sx_valloc(&m->pool, version); if (ssunlikely(v == NULL)) { sv_vunref(r, version); return -1; } v->id = x->id; v->index = index; lv.ptr = v; if (! (sv_vflags(version, index->r) & SVGET)) x->log_read = -1; /* update concurrent index */ ssrbnode *n = NULL; int rc; rc = sx_match(&index->i, index->r->scheme, sv_vpointer(version), 0, &n); if (ssunlikely(rc == 0 && n)) { /* exists */ } else { int pos = rc; /* unique */ v->lo = sv_logcount(x->log); rc = sv_logadd(x->log, r, &lv); if (ssunlikely(rc == -1)) { sr_oom(r->e); goto error; } ss_rbset(&index->i, n, pos, &v->node); return 0; } sxv *head = sscast(n, sxv, node); /* match previous update made by current * transaction */ sxv *own = sx_vmatch(head, x->id); if (ssunlikely(own)) { if (ssunlikely(sv_vflags(version, index->r) & SVUPSERT)) { sr_error(r->e, "%s", "only one upsert statement is " "allowed per a transaction key"); goto error; } /* replace old document with the new one */ lv.next = sv_logat(x->log, own->lo)->next; v->lo = own->lo; if (ssunlikely(sx_vaborted(own))) sx_vabort(v); sx_vreplace(own, v); if (sslikely(head == own)) ss_rbreplace(&index->i, &own->node, &v->node); /* update log */ sv_logreplace(x->log, r, v->lo, &lv); sx_vfree(&m->pool, r, own); return 0; } /* update log */ v->lo = sv_logcount(x->log); rc = sv_logadd(x->log, r, &lv); if (ssunlikely(rc == -1)) { sr_oom(r->e); goto error; } /* add version */ sx_vlink(head, v); return 0; error: sx_vfree(&m->pool, r, v); return -1; }
int sx_set(sx *t, sxindex *index, svv *version) { sxmanager *m = t->manager; /* allocate mvcc container */ sxv *v = sx_valloc(m->asxv, version); if (ssunlikely(v == NULL)) { sv_vfree(m->a, version); return -1; } v->id = t->id; v->index = index; svlogv lv; lv.id = index->dsn; lv.vgc = NULL; lv.next = UINT32_MAX; sv_init(&lv.v, &sx_vif, v, NULL); /* update concurrent index */ ssrbnode *n = NULL; int rc = sx_match(&index->i, index->scheme, sv_vpointer(version), version->size, &n); if (ssunlikely(rc == 0 && n)) { /* exists */ } else { /* unique */ v->lo = sv_logcount(&t->log); if (ssunlikely((sv_logadd(&t->log, m->a, &lv, index->ptr)) == -1)) { rc = sr_oom(index->r->e); } else { ss_rbset(&index->i, n, rc, &v->node); rc = 0; } return rc; } sxv *head = sscast(n, sxv, node); /* match previous update made by current * transaction */ sxv *own = sx_vmatch(head, t->id); if (ssunlikely(own)) { if (ssunlikely(version->flags & SVUPDATE)) { sr_error(index->r->e, "%s", "only one update statement is " "allowed per a transaction key"); sx_vfree(m->a, m->asxv, v); return -1; } /* replace old object with the new one */ lv.next = sv_logat(&t->log, own->lo)->next; v->lo = own->lo; sx_vreplace(own, v); if (sslikely(head == own)) ss_rbreplace(&index->i, &own->node, &v->node); /* update log */ sv_logreplace(&t->log, v->lo, &lv); sx_vfree(m->a, m->asxv, own); return 0; } /* update log */ rc = sv_logadd(&t->log, m->a, &lv, index->ptr); if (ssunlikely(rc == -1)) { sx_vfree(m->a, m->asxv, v); return sr_oom(index->r->e); } /* add version */ sx_vlink(head, v); return 0; }
i->count = 0; i->scheme = NULL; i->ptr = ptr; i->r = r; return 0; } int sx_indexset(sxindex *i, uint32_t dsn, srscheme *scheme) { i->dsn = dsn; i->scheme = scheme; return 0; } ss_rbtruncate(sx_truncate, sx_vfree(((ssa**)arg)[0], ((ssa**)arg)[1], sscast(n, sxv, node))) int sx_indexfree(sxindex *i, sxmanager *m) { ssa *allocators[2] = { m->a, m->asxv }; if (i->i.root) sx_truncate(i->i.root, allocators); return 0; } uint32_t sx_min(sxmanager *m) { ss_spinlock(&m->lock); uint32_t id = 0; if (m->count) { ssrbnode *node = ss_rbmin(&m->i);