void st_document_eq(stgenerator *g, sf fmt, void *o, uint32_t seed, uint32_t seed_value) { svv *v = st_svv_seed(g, seed, seed_value); if (ssunlikely(v == NULL)) { t(0); return; } switch (fmt) { case SF_KV: { int i = 0; int size = 0; while (i < g->r->scheme->count) { void *ptr = sp_getstring(o, g->r->scheme->parts[i].name, &size); t( ptr != NULL ); t( size == sf_keysize(sv_vpointer(v), i) ); t( memcmp(ptr, sf_key(sv_vpointer(v), i), size) == 0 ); i++; } void *ptr = sp_getstring(o, "value", &size); if ((g->value_start + g->value_end) > 0) { t( ptr != NULL ); t( size == sf_valuesize(g->r->fmt, sv_vpointer(v), v->size, g->r->scheme->count) ); t( memcmp(ptr, sf_value(g->r->fmt, sv_vpointer(v), g->r->scheme->count), size) == 0 ); } else { t( ptr == NULL ); } break; } case SF_DOCUMENT: { int i = 0; int size = 0; while (i < g->r->scheme->count) { void *ptr = sp_getstring(o, g->r->scheme->parts[i].name, &size); t( ptr != NULL ); t( size == sf_keysize(sv_vpointer(v), i) ); t( memcmp(ptr, sf_key(sv_vpointer(v), i), size) == 0 ); i++; } void *ptr = sp_getstring(o, "value", &size); t( ptr != NULL ); if ((g->value_start + g->value_end) > 0) { int vsize = sf_valuesize(g->r->fmt, ptr, size, g->r->scheme->count); t( vsize == sf_valuesize(g->r->fmt, sv_vpointer(v), v->size, g->r->scheme->count) ); ptr = sf_value(g->r->fmt, ptr, g->r->scheme->count); t( memcmp(ptr, sf_value(g->r->fmt, sv_vpointer(v), g->r->scheme->count), vsize) == 0 ); } break; } } sv_vfree(g->r, v); }
void *st_document_generate(stgenerator *g, sf fmt, stlist *l, void *db, uint32_t seed, uint32_t seed_value) { svv *v = st_svv_seed(g, seed, seed_value); if (ssunlikely(v == NULL)) return NULL; assert(l->svv == 1); int rc = ss_bufadd(&l->list, g->r->a, &v, sizeof(svv**)); if (ssunlikely(rc == -1)) { sv_vfree(g->r, v); return NULL; } void *o = sp_document(db); t( o != NULL ); switch (fmt) { case SF_KV: { int i = 0; while (i < g->r->scheme->count) { rc = sp_setstring(o, g->r->scheme->parts[i].name, sf_key(sv_vpointer(v), i), sf_keysize(sv_vpointer(v), i)); t( rc == 0 ); i++; } if ((g->value_start + g->value_end) > 0) { rc = sp_setstring(o, "value", sf_value(g->r->fmt, sv_vpointer(v), g->r->scheme->count), sf_valuesize(g->r->fmt, sv_vpointer(v), v->size, g->r->scheme->count)); t( rc == 0 ); } break; } case SF_DOCUMENT: { char *vpointer = sv_vpointer(v); int i = 0; while (i < g->r->scheme->count) { rc = sp_setstring(o, g->r->scheme->parts[i].name, sf_key(vpointer, i), sf_keysize(vpointer, i)); t( rc == 0 ); i++; } rc = sp_setstring(o, "value", vpointer, v->size); t( rc == 0 ); break; } } return o; }
uint32_t si_gcv(ssa *a, svv *gc) { uint32_t used = 0; svv *v = gc; while (v) { used += sv_vsize(v); svv *n = v->next; sl *log = (sl*)v->log; if (log) ss_gcsweep(&log->gc, 1); sv_vfree(a, v); v = n; } return used; }
static void addv(sdbuild *b, sr *r, uint64_t lsn, uint8_t flags, int *key) { sfv pv; pv.key = (char*)key; pv.r.size = sizeof(uint32_t); pv.r.offset = 0; svv *v = sv_vbuild(r, &pv, 1, (char*)key, sizeof(uint32_t)); v->lsn = lsn; v->flags = flags; sv vv; sv_init(&vv, &sv_vif, v, NULL); sd_buildadd(b, r, &vv, flags & SVDUP); sv_vfree(r->a, v); }
static void svv_kv(stc *cx) { sra a; sr_aopen(&a, &sr_stda); srkey cmp; sr_keyinit(&cmp); srkeypart *part = sr_keyadd(&cmp, &a); t( sr_keypart_setname(part, &a, "key") == 0 ); t( sr_keypart_set(part, &a, "u32") == 0 ); sr r; sr_init(&r, NULL, &a, NULL, SR_FKV, &cmp, NULL, NULL, NULL); uint32_t key = 123; uint32_t value = 321; srformatv pv; pv.key = (char*)&key; pv.r.size = sizeof(key); pv.r.offset = 0; svv *vv = sv_vbuild(&r, &pv, 1, (char*)&value, sizeof(value)); t( vv != NULL ); vv->flags = SVSET; vv->lsn = 10; sv v; sv_init(&v, &sv_vif, vv, NULL); t( sv_flags(&v) == SVSET ); t( sv_lsn(&v) == 10 ); sv_lsnset(&v, 8); t( sv_lsn(&v) == 8 ); t( *(uint32_t*)sr_formatkey(sv_pointer(&v), 0) == key ); t( sr_formatkey_size(sv_pointer(&v), 0) == sizeof(key) ); t( *(uint32_t*)sr_formatvalue(SR_FKV, &cmp, sv_pointer(&v)) == value ); t( sr_formatvalue_size(SR_FKV, &cmp, sv_pointer(&v), sv_size(&v) ) == sizeof(value) ); sv_vfree(&a, vv); sr_keyfree(&cmp, &a); }
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 half-commit mode */ if (x->state == SXCOMMIT) { for (; ss_iterhas(ss_bufiter, &i); ss_iternext(ss_bufiter, &i)) { svlogv *lv = ss_iterof(ss_bufiter, &i); svv *v = lv->v.v; sv_vfree(m->r, v); } sx_promote(x, SXROLLBACK); return SXROLLBACK; } sx_rollback_svp(x, &i, 1); sx_promote(x, SXROLLBACK); sx_end(x); return SXROLLBACK; }
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 *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; }
/* * sophia database * sphia.org * * Copyright (c) Dmitry Simonenko * BSD License */ #include <libss.h> #include <libsf.h> #include <libsr.h> #include <libss.h> #include <libsv.h> ss_rbtruncate(sv_indextruncate, sv_vfree((ssa*)arg, sscast(n, svv, node))) int sv_indexinit(svindex *i) { i->lsnmin = UINT64_MAX; i->count = 0; i->used = 0; ss_rbinit(&i->i); return 0; } int sv_indexfree(svindex *i, sr *r) { if (i->i.root) sv_indextruncate(i->i.root, r->a); ss_rbinit(&i->i);