sxstate sx_set_autocommit(sxmanager *m, sxindex *index, sx *x, svv *v) { if (sslikely(m->count_rw == 0)) { sx_init(m, x); svlogv lv; lv.id = index->dsn; lv.next = UINT32_MAX; sv_init(&lv.v, &sv_vif, v, NULL); sv_logadd(&x->log, m->r->a, &lv, index->ptr); sr_seq(m->r->seq, SR_TSNNEXT); return SXCOMMIT; } sx_begin(m, x, SXRW, 0); int rc = sx_set(x, index, v); if (ssunlikely(rc == -1)) { sx_rollback(x); return SXROLLBACK; } sxstate s = sx_prepare(x, NULL, NULL); if (sslikely(s == SXPREPARE)) sx_commit(x); else if (s == SXLOCK) sx_rollback(x); return s; }
sxstate sx_set_autocommit(sxmanager *m, sxindex *index, sx *x, svlog *log, svv *v) { if (sslikely(m->count_rw == 0)) { sx_init(m, x, log); svlogv lv; lv.index_id = index->dsn; lv.next = UINT32_MAX; lv.v = v; lv.ptr = NULL; sv_logadd(x->log, index->r, &lv); sr_seq(index->r->seq, SR_TSNNEXT); sx_promote(x, SX_COMMIT); return SX_COMMIT; } sx_begin(m, x, SX_RW, log, 0); int rc = sx_set(x, index, v); if (ssunlikely(rc == -1)) { sx_rollback(x); return SX_ROLLBACK; } sxstate s = sx_prepare(x, NULL, NULL); switch (s) { case SX_PREPARE: s = sx_commit(x); break; case SX_LOCK: s = sx_rollback(x); break; case SX_ROLLBACK: break; default: assert(0); } return s; }
static inline int se_txwrite(setx *t, sev *o, uint8_t flags) { se *e = se_of(&t->o); sedb *db = se_cast(o->o.parent, sedb*, SEDB); /* validate req */ if (ssunlikely(t->t.state == SXPREPARE)) { sr_error(&e->error, "%s", "transaction is in 'prepare' state (read-only)"); goto error; } /* validate database status */ int status = se_status(&db->status); switch (status) { case SE_SHUTDOWN: if (ssunlikely(! se_dbvisible(db, t->t.id))) { sr_error(&e->error, "%s", "database is invisible for the transaction"); goto error; } break; case SE_RECOVER: case SE_ONLINE: break; default: goto error; } if (flags == SVUPDATE && !sf_updatehas(&db->scheme.fmt_update)) flags = 0; /* prepare object */ svv *v; int rc = se_dbv(db, o, 0, &v); if (ssunlikely(rc == -1)) goto error; v->flags = flags; v->log = o->log; sv vp; sv_init(&vp, &sv_vif, v, NULL); so_destroy(&o->o); /* ensure quota */ int size = sizeof(svv) + sv_size(&vp); ss_quota(&e->quota, SS_QADD, size); /* concurrent index only */ rc = sx_set(&t->t, &db->coindex, v); if (ssunlikely(rc == -1)) { ss_quota(&e->quota, SS_QREMOVE, size); return -1; } return 0; error: so_destroy(&o->o); return -1; }
static inline int se_txwrite(setx *t, sedocument *o, uint8_t flags) { se *e = se_of(&t->o); sedb *db = se_cast(o->o.parent, sedb*, SEDB); int auto_close = o->created <= 1; /* validate database status */ if (ssunlikely(! se_active(e))) goto error; /* ensure memory quota */ int rc; rc = sr_quota(&e->quota, &e->stat); if (ssunlikely(rc)) { sr_error(&e->error, "%s", "memory quota limit reached"); goto error; } /* create document */ rc = se_document_create(o); if (ssunlikely(rc == -1)) goto error; rc = se_document_validate(o, &db->o, flags); if (ssunlikely(rc == -1)) goto error; svv *v = o->v.v; sv_vref(v); v->log = o->log; /* destroy document object */ if (auto_close) so_destroy(&o->o); /* concurrent index only */ rc = sx_set(&t->t, &db->coindex, v); if (ssunlikely(rc == -1)) return -1; return 0; error: if (auto_close) so_destroy(&o->o); return -1; }
int sx_get(sx *x, sxindex *index, sv *key, sv *result) { sxmanager *m = x->manager; ssrbnode *n = NULL; int rc; rc = sx_match(&index->i, index->r->scheme, sv_pointer(key), sv_size(key), &n); if (! (rc == 0 && n)) goto add; sxv *head = sscast(n, sxv, node); sxv *v = sx_vmatch(head, x->id); if (v == NULL) goto add; if (ssunlikely((v->v->flags & SVGET) > 0)) return 0; if (ssunlikely((v->v->flags & SVDELETE) > 0)) return 2; sv vv; sv_init(&vv, &sv_vif, v->v, NULL); svv *ret = sv_vdup(m->r, &vv); if (ssunlikely(ret == NULL)) { rc = sr_oom(m->r->e); } else { sv_init(result, &sv_vif, ret, NULL); rc = 1; } return rc; add: /* track a start of the latest read sequence in the * transactional log */ if (x->log_read == -1) x->log_read = sv_logcount(&x->log); rc = sx_set(x, index, key->v); if (ssunlikely(rc == -1)) return -1; sv_vref((svv*)key->v); return 0; }
int sx_get(sx *x, sxindex *index, svv *key, svv **result) { ssrbnode *n = NULL; int rc; rc = sx_match(&index->i, index->r->scheme, sv_vpointer(key), 0, &n); if (! (rc == 0 && n)) goto add; sxv *head = sscast(n, sxv, node); sxv *v = sx_vmatch(head, x->id); if (v == NULL) goto add; if (ssunlikely(sv_vflags(v->v, index->r) & SVGET)) return 0; if (ssunlikely(sv_vflags(v->v, index->r) & SVDELETE)) return 2; *result = sv_vbuildraw(index->r, sv_vpointer(v->v)); if (ssunlikely(*result == NULL)) { sr_oom(index->r->e); rc = -1; } else { rc = 1; } return rc; add: /* track a start of the latest read sequence in the * transactional log */ if (x->log_read == -1) x->log_read = sv_logcount(x->log); rc = sx_set(x, index, key); if (ssunlikely(rc == -1)) return -1; sv_vref(key); return 0; }