int se_document_create(sedocument *o, uint8_t flags) { sedb *db = (sedb*)o->o.parent; se *e = se_of(&db->o); assert(o->created == 0); assert(o->v == NULL); /* create document from raw data */ if (o->raw) { o->v = sv_vbuildraw(db->r, o->raw); if (ssunlikely(o->v == NULL)) return sr_oom(&e->error); o->created = 1; return 0; } /* ensure all keys are set */ if (ssunlikely(o->fields_count_keys != db->scheme->scheme.keys_count)) return sr_error(&e->error, "%s", "incomplete key"); /* set auto fields */ uint32_t timestamp = UINT32_MAX; if (db->scheme->scheme.has_timestamp) { timestamp = ss_timestamp(); sf_autoset(&db->scheme->scheme, o->fields, ×tamp); } o->v = sv_vbuild(db->r, o->fields); if (ssunlikely(o->v == NULL)) return sr_oom(&e->error); sf_flagsset(db->r->scheme, sv_vpointer(o->v), flags); o->created = 1; return 0; }
static inline int sd_indexadd_keyvalue(sdindex *i, sr *r, sdbuild *build, sdindexpage *p, char *min, char *max) { assert(r->scheme->count <= 8); /* min */ sfv kv[8]; uint64_t offset; int total = 0; int part = 0; while (part < r->scheme->count) { /* read keytab offset */ min += ss_leb128read(min, &offset); /* read key */ sfv *k = &kv[part]; char *key = build->k.s + sd_buildref(build)->k + offset; uint64_t keysize; key += ss_leb128read(key, &keysize); k->key = key; k->r.size = keysize; k->r.offset = 0; total += keysize; part++; } p->sizemin = total + (r->scheme->count * sizeof(sfref)); int rc = ss_bufensure(&i->v, r->a, p->sizemin); if (ssunlikely(rc == -1)) return sr_oom(r->e); sf_write(SF_KV, i->v.p, kv, r->scheme->count, NULL, 0); ss_bufadvance(&i->v, p->sizemin); /* max */ total = 0; part = 0; while (part < r->scheme->count) { /* read keytab offset */ max += ss_leb128read(max, &offset); /* read key */ sfv *k = &kv[part]; char *key = build->k.s + sd_buildref(build)->k + offset; uint64_t keysize; key += ss_leb128read(key, &keysize); k->key = key; k->r.size = keysize; k->r.offset = 0; total += keysize; part++; } p->sizemax = total + (r->scheme->count * sizeof(sfref)); rc = ss_bufensure(&i->v, r->a, p->sizemax); if (ssunlikely(rc == -1)) return sr_oom(r->e); sf_write(SF_KV, i->v.p, kv, r->scheme->count, NULL, 0); ss_bufadvance(&i->v, p->sizemax); return 0; }
int sx_get(sx *t, sxindex *index, sv *key, sv *result) { sxmanager *m = t->manager; ssrbnode *n = NULL; int rc = sx_match(&index->i, index->scheme, sv_pointer(key), sv_size(key), &n); if (! (rc == 0 && n)) { rc = 0; goto done; } sxv *head = sscast(n, sxv, node); sxv *v = sx_vmatch(head, t->id); if (v == NULL) { rc = 0; goto done; } if (ssunlikely((v->v->flags & SVDELETE) > 0)) { rc = 2; goto done; } sv vv; sv_init(&vv, &sv_vif, v->v, NULL); svv *ret = sv_vdup(m->a, &vv); if (ssunlikely(ret == NULL)) { rc = sr_oom(index->r->e); } else { sv_init(result, &sv_vif, ret, NULL); rc = 1; } done: return rc; }
int sd_indexcommit(sdindex *i, sr *r, sdid *id, ssqf *qf, uint64_t offset) { int size = ss_bufused(&i->v); int size_extension = 0; int extensions = 0; if (qf) { extensions = SD_INDEXEXT_AMQF; size_extension += sizeof(sdindexamqf); size_extension += qf->qf_table_size; } int rc = ss_bufensure(&i->i, r->a, size + size_extension); if (ssunlikely(rc == -1)) return sr_oom(r->e); memcpy(i->i.p, i->v.s, size); ss_bufadvance(&i->i, size); if (qf) { sdindexamqf *qh = (sdindexamqf*)(i->i.p); qh->q = qf->qf_qbits; qh->r = qf->qf_rbits; qh->entries = qf->qf_entries; qh->size = qf->qf_table_size; ss_bufadvance(&i->i, sizeof(sdindexamqf)); memcpy(i->i.p, qf->qf_table, qf->qf_table_size); ss_bufadvance(&i->i, qf->qf_table_size); } ss_buffree(&i->v, r->a); i->h = sd_indexheader(i); i->h->offset = offset; i->h->id = *id; i->h->extension = size_extension; i->h->extensions = extensions; i->h->crc = ss_crcs(r->crc, i->h, sizeof(sdindexheader), 0); return 0; }
int sd_indexbegin(sdindex *i, sr *r) { int rc = ss_bufensure(&i->i, r->a, sizeof(sdindexheader)); if (ssunlikely(rc == -1)) return sr_oom(r->e); sdindexheader *h = sd_indexheader(i); sr_version(&h->version); h->crc = 0; h->size = 0; h->sizevmax = 0; h->count = 0; h->keys = 0; h->total = 0; h->totalorigin = 0; h->extension = 0; h->extensions = 0; h->lsnmin = UINT64_MAX; h->lsnmax = 0; h->tsmin = 0; h->offset = 0; h->dupkeys = 0; h->dupmin = UINT64_MAX; memset(h->reserve, 0, sizeof(h->reserve)); sd_idinit(&h->id, 0, 0, 0); i->h = NULL; ss_bufadvance(&i->i, sizeof(sdindexheader)); return 0; }
int sr_meta_write(srmeta *m, srmetastmt *s) { if (m->flags & SR_RO) { sr_error(s->r->e, "%s is read-only", s->path); return -1; } switch (m->type) { case SS_U32: if (s->valuetype == SS_I64) { *((uint32_t*)m->value) = *(int64_t*)s->value; } else if (s->valuetype == SS_U32) { *((uint32_t*)m->value) = *(uint32_t*)s->value; } else if (s->valuetype == SS_U64) { *((uint32_t*)m->value) = *(uint64_t*)s->value; } else { goto bad_type; } break; case SS_U64: if (s->valuetype == SS_I64) { *((uint64_t*)m->value) = *(int64_t*)s->value; } else if (s->valuetype == SS_U32) { *((uint64_t*)m->value) = *(uint32_t*)s->value; } else if (s->valuetype == SS_U64) { *((uint64_t*)m->value) = *(uint64_t*)s->value; } else { goto bad_type; } break; case SS_STRINGPTR: { char **string = m->value; if (s->valuetype == SS_STRING) { char *sz = s->value; if (s->valuesize > 0) { sz = ss_malloc(s->r->a, s->valuesize); if (ssunlikely(sz == NULL)) return sr_oom(s->r->e); memcpy(sz, s->value, s->valuesize); } if (*string) ss_free(s->r->a, *string); *string = sz; } else { goto bad_type; } break; } default: assert(0); return -1; } return 0; bad_type: return sr_error(s->r->e, "bad meta write type (%s) for (%s) %s", ss_typeof(s->valuetype), ss_typeof(m->type), s->path); }
static inline int si_readdup(siread *q, sv *result) { svv *v = sv_vdup(q->r, result); if (ssunlikely(v == NULL)) return sr_oom(q->r->e); sv_init(&q->result, &sv_vif, v, NULL); return 1; }
int se_document_createkey(sedocument *o) { sedb *db = (sedb*)o->o.parent; se *e = se_of(&db->o); if (o->created) return 0; assert(o->v == NULL); /* set prefix */ if (o->prefix) { if (db->scheme->scheme.keys[0]->type != SS_STRING) return sr_error(&e->error, "%s", "prefix search is only " "supported for a string key"); void *copy = ss_malloc(&e->a, o->prefix_size); if (ssunlikely(copy == NULL)) return sr_oom(&e->error); memcpy(copy, o->prefix, o->prefix_size); o->prefix_copy = copy; } /* set unspecified min/max keys, depending on * iteration order */ if (ssunlikely(o->fields_count_keys != db->scheme->scheme.keys_count)) { if (o->prefix && o->fields_count_keys == 0) { memset(o->fields, 0, sizeof(o->fields)); o->fields[0].pointer = o->prefix; o->fields[0].size = o->prefix_size; } sf_limitapply(&db->limit, &db->scheme->scheme, o->fields, o->order); o->fields_count = db->scheme->scheme.fields_count; o->fields_count_keys = db->scheme->scheme.keys_count; } o->v = sv_vbuild(db->r, o->fields); if (ssunlikely(o->v == NULL)) return sr_oom(&e->error); sf_flagsset(db->r->scheme, sv_vpointer(o->v), SVGET); o->created = 1; return 0; }
int sd_schemebegin(sdscheme *c, sr *r) { int rc = ss_bufensure(&c->buf, r->a, sizeof(sdschemeheader)); if (ssunlikely(rc == -1)) return sr_oom(r->e); sdschemeheader *h = (sdschemeheader*)c->buf.s; memset(h, 0, sizeof(sdschemeheader)); ss_bufadvance(&c->buf, sizeof(sdschemeheader)); return 0; }
int sd_indexcommit(sdindex *i, sr *r, sdid *id, ssqf *qf, uint32_t align, uint64_t offset) { int size = ss_bufused(&i->v); int size_extension = 0; int extensions = 0; if (qf) { extensions = SD_INDEXEXT_AMQF; size_extension += sizeof(sdindexamqf); size_extension += qf->qf_table_size; } /* calculate index align for direct_io */ int size_meta = size + size_extension + sizeof(sdindexheader); int size_align = 0; if (align) { size_align += align - ((offset + size_meta + ss_bufused(&i->i)) % align); size_meta += size_align; } int rc = ss_bufensure(&i->i, r->a, size_meta); if (ssunlikely(rc == -1)) return sr_oom(r->e); /* min/max pairs */ memcpy(i->i.p, i->v.s, size); ss_bufadvance(&i->i, size); /* extension */ if (qf) { sdindexamqf *qh = (sdindexamqf*)(i->i.p); qh->q = qf->qf_qbits; qh->r = qf->qf_rbits; qh->entries = qf->qf_entries; qh->size = qf->qf_table_size; ss_bufadvance(&i->i, sizeof(sdindexamqf)); memcpy(i->i.p, qf->qf_table, qf->qf_table_size); ss_bufadvance(&i->i, qf->qf_table_size); } ss_buffree(&i->v, r->a); sdindexheader *h = &i->build; /* align */ if (size_align) { h->align = size_align; memset(i->i.p, 0, size_align); ss_bufadvance(&i->i, size_align); } /* header */ h->offset = offset; h->id = *id; h->extension = size_extension; h->extensions = extensions; h->crc = ss_crcs(r->crc, h, sizeof(sdindexheader), 0); memcpy(i->i.p, &i->build, sizeof(sdindexheader)); ss_bufadvance(&i->i, sizeof(sdindexheader)); i->h = sd_indexheader(i); return 0; }
static int se_dbscheme_init(sedb *db, char *name, int size) { se *e = se_of(&db->o); /* database id */ uint32_t id = sr_seq(&e->seq, SR_DSN); sr_seq(&e->seq, SR_DSNNEXT); /* prepare index scheme */ sischeme *scheme = db->scheme; if (size == 0) size = strlen(name); scheme->name = ss_malloc(&e->a, size + 1); if (ssunlikely(scheme->name == NULL)) goto error; memcpy(scheme->name, name, size); scheme->name[size] = 0; scheme->id = id; scheme->sync = 2; scheme->mmap = 0; scheme->storage = SI_SCACHE; scheme->node_size = 64 * 1024 * 1024; scheme->node_compact_load = 0; scheme->node_page_size = 128 * 1024; scheme->node_page_checksum = 1; scheme->compression_copy = 0; scheme->compression_cold = 0; scheme->compression_cold_if = &ss_nonefilter; scheme->compression_hot = 0; scheme->compression_hot_if = &ss_nonefilter; scheme->temperature = 0; scheme->expire = 0; scheme->amqf = 0; scheme->fmt_storage = SF_RAW; scheme->lru = 0; scheme->lru_step = 128 * 1024; scheme->buf_gc_wm = 1024 * 1024; scheme->storage_sz = ss_strdup(&e->a, "cache"); if (ssunlikely(scheme->storage_sz == NULL)) goto error; scheme->compression_cold_sz = ss_strdup(&e->a, scheme->compression_cold_if->name); if (ssunlikely(scheme->compression_cold_sz == NULL)) goto error; scheme->compression_hot_sz = ss_strdup(&e->a, scheme->compression_hot_if->name); if (ssunlikely(scheme->compression_hot_sz == NULL)) goto error; sf_upsertinit(&scheme->fmt_upsert); sf_schemeinit(&scheme->scheme); return 0; error: sr_oom(&e->error); return -1; }
int sd_indexcopy(sdindex *i, sr *r, sdindexheader *h) { int size = sd_indexsize_ext(h); int rc = ss_bufensure(&i->i, r->a, size); if (ssunlikely(rc == -1)) return sr_oom(r->e); memcpy(i->i.s, (char*)h, size); ss_bufadvance(&i->i, size); i->h = sd_indexheader(i); return 0; }
int sd_indexcopy(sdindex *i, sr *r, sdindexheader *h) { int size = sd_indexsize_ext(h); int rc = ss_bufensure(&i->i, r->a, size); if (ssunlikely(rc == -1)) return sr_oom(r->e); char *start = (char*)h - (h->align + h->size + h->extension); memcpy(i->i.s, start, size); ss_bufadvance(&i->i, size); i->h = sd_indexheader(i); return 0; }
int sd_indexadd(sdindex *i, sr *r, sdbuild *build, uint64_t offset) { int rc = ss_bufensure(&i->i, r->a, sizeof(sdindexpage)); if (ssunlikely(rc == -1)) return sr_oom(r->e); sdpageheader *ph = sd_buildheader(build); int size = ph->size + sizeof(sdpageheader); int sizeorigin = ph->sizeorigin + sizeof(sdpageheader); /* prepare page header */ sdindexpage *p = (sdindexpage*)i->i.p; p->offset = offset; p->offsetindex = ss_bufused(&i->v); p->lsnmin = ph->lsnmin; p->lsnmax = ph->lsnmax; p->size = size; p->sizeorigin = sizeorigin; p->sizemin = 0; p->sizemax = 0; /* copy keys */ if (ssunlikely(ph->count > 0)) { char *min = sd_buildmin(build, r); char *max = sd_buildmax(build, r); rc = sd_indexadd_raw(i, r, p, min, max); if (ssunlikely(rc == -1)) return -1; } /* update index info */ sdindexheader *h = &i->build; h->count++; h->size += sizeof(sdindexpage) + p->sizemin + p->sizemax; h->keys += ph->count; h->total += size; h->totalorigin += sizeorigin; if (build->vmax > h->sizevmax) h->sizevmax = build->vmax; if (ph->lsnmin < h->lsnmin) h->lsnmin = ph->lsnmin; if (ph->lsnmax > h->lsnmax) h->lsnmax = ph->lsnmax; if (ph->tsmin < h->tsmin) h->tsmin = ph->tsmin; h->dupkeys += ph->countdup; if (ph->lsnmindup < h->dupmin) h->dupmin = ph->lsnmindup; ss_bufadvance(&i->i, sizeof(sdindexpage)); return 0; }
so *sc_readpool_new(screadpool *p, so *o, int add) { scread *r = (scread*)o; scread *n = ss_malloc(p->r->a, sizeof(scread)); if (ssunlikely(r == NULL)) { sr_oom(p->r->e); return NULL; } memcpy(n, r, sizeof(*r)); if (add) { sc_readpool_add(p, n); } return &r->o; }
static inline int sd_indexadd_raw(sdindex *i, sr *r, sdindexpage *p, char *min, char *max) { /* reformat document to exclude non-key fields */ p->sizemin = sf_comparable_size(r->scheme, min); p->sizemax = sf_comparable_size(r->scheme, max); int rc = ss_bufensure(&i->v, r->a, p->sizemin + p->sizemax); if (ssunlikely(rc == -1)) return sr_oom(r->e); sf_comparable_write(r->scheme, min, i->v.p); ss_bufadvance(&i->v, p->sizemin); sf_comparable_write(r->scheme, max, i->v.p); ss_bufadvance(&i->v, p->sizemax); return 0; }
int sd_buildbegin(sdbuild *b, sr *r, int crc, int compress, int compress_dup) { b->crc = crc; b->compress = compress; b->compress_dup = compress_dup; int rc; if (compress_dup && b->tracker.size == 0) { rc = ss_htinit(&b->tracker, r->a, 32768); if (ssunlikely(rc == -1)) return sr_oom(r->e); } rc = ss_bufensure(&b->list, r->a, sizeof(sdbuildref)); if (ssunlikely(rc == -1)) return sr_oom(r->e); sdbuildref *ref = (sdbuildref*)ss_bufat(&b->list, sizeof(sdbuildref), b->n); ref->m = ss_bufused(&b->m); ref->msize = 0; ref->v = ss_bufused(&b->v); ref->vsize = 0; ref->k = ss_bufused(&b->k); ref->ksize = 0; ref->c = ss_bufused(&b->c); ref->csize = 0; rc = ss_bufensure(&b->m, r->a, sizeof(sdpageheader)); if (ssunlikely(rc == -1)) return sr_oom(r->e); sdpageheader *h = sd_buildheader(b); memset(h, 0, sizeof(*h)); h->lsnmin = UINT64_MAX; h->lsnmindup = UINT64_MAX; memset(h->reserve, 0, sizeof(h->reserve)); ss_bufadvance(&b->list, sizeof(sdbuildref)); ss_bufadvance(&b->m, sizeof(sdpageheader)); return 0; }
static inline int sd_buildadd_raw(sdbuild *b, sr *r, sv *v) { uint64_t lsn = sv_lsn(v); uint32_t size = sv_size(v); uint32_t sizemeta = ss_leb128size(size) + ss_leb128size(lsn); int rc = ss_bufensure(&b->v, r->a, sizemeta + size); if (ssunlikely(rc == -1)) return sr_oom(r->e); ss_bufadvance(&b->v, ss_leb128write(b->v.p, size)); ss_bufadvance(&b->v, ss_leb128write(b->v.p, lsn)); memcpy(b->v.p, sv_pointer(v), size); ss_bufadvance(&b->v, size); return 0; }
static inline int sd_indexadd_raw(sdindex *i, sr *r, sdindexpage *p, char *min, char *max) { /* calculate sizes */ p->sizemin = sf_keytotal(min, r->scheme->count); p->sizemax = sf_keytotal(max, r->scheme->count); /* prepare buffer */ int rc = ss_bufensure(&i->v, r->a, p->sizemin + p->sizemax); if (ssunlikely(rc == -1)) return sr_oom(r->e); /* reformat key document to exclude value */ rc = sf_keycopy(i->v.p, min, r->scheme->count); assert(rc == p->sizemin); (void)rc; ss_bufadvance(&i->v, p->sizemin); rc = sf_keycopy(i->v.p, max, r->scheme->count); assert(rc == p->sizemax); (void)rc; ss_bufadvance(&i->v, p->sizemax); return 0; }
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 sd_buildadd(sdbuild *b, sr *r, sv *v, uint32_t flags) { /* prepare object metadata */ int rc = ss_bufensure(&b->m, r->a, sizeof(sdv)); if (ssunlikely(rc == -1)) return sr_oom(r->e); sdpageheader *h = sd_buildheader(b); sdv *sv = (sdv*)b->m.p; sv->flags = sv_flags(v) | flags; sv->offset = ss_bufused(&b->v) - sd_buildref(b)->v; ss_bufadvance(&b->m, sizeof(sdv)); /* copy object */ switch (r->fmt_storage) { case SF_SKEYVALUE: rc = sd_buildadd_keyvalue(b, r, v); break; case SF_SRAW: rc = sd_buildadd_raw(b, r, v); break; } if (ssunlikely(rc == -1)) return -1; /* update page header */ h->count++; uint32_t size = sizeof(sdv) + sv_size(v) + sizeof(sfref) * r->scheme->count; if (size > b->vmax) b->vmax = size; uint64_t lsn = sv_lsn(v); if (lsn > h->lsnmax) h->lsnmax = lsn; if (lsn < h->lsnmin) h->lsnmin = lsn; if (sv->flags & SVDUP) { h->countdup++; if (lsn < h->lsnmindup) h->lsnmindup = lsn; } return 0; }
static int se_dbscheme_init(sedb *db, char *name, int size) { se *e = se_of(&db->o); /* database id */ uint32_t id = sr_seq(&e->seq, SR_DSN); sr_seq(&e->seq, SR_DSNNEXT); /* prepare index scheme */ sischeme *scheme = db->scheme; if (size == 0) size = strlen(name); scheme->name = ss_malloc(&e->a, size + 1); if (ssunlikely(scheme->name == NULL)) goto error; memcpy(scheme->name, name, size); scheme->name[size] = 0; scheme->id = id; scheme->sync = 1; scheme->mmap = 1; scheme->direct_io = 0; scheme->direct_io_page_size = 4096; scheme->direct_io_buffer_size = 8 * 1024 * 1024; scheme->compression = 0; scheme->compression_if = &ss_nonefilter; scheme->expire = 0; scheme->buf_gc_wm = 1024 * 1024; scheme->compression_sz = ss_strdup(&e->a, scheme->compression_if->name); if (ssunlikely(scheme->compression_sz == NULL)) goto error; sf_upsertinit(&scheme->upsert); sf_schemeinit(&scheme->scheme); return 0; error: sr_oom(&e->error); return -1; }
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; }
int sr_conf_serialize(srconf *m, srconfstmt *s) { char buf[128]; char name_function[] = "function"; char name_object[] = "object"; void *value = NULL; srconfdump v = { .type = m->type }; switch (m->type) { case SS_U32: v.valuesize = snprintf(buf, sizeof(buf), "%" PRIu32, sscastu32(m->value)); v.valuesize += 1; value = buf; break; case SS_U64: v.valuesize = snprintf(buf, sizeof(buf), "%" PRIu64, sscastu64(m->value)); v.valuesize += 1; value = buf; break; case SS_I64: v.valuesize = snprintf(buf, sizeof(buf), "%" PRIi64, sscasti64(m->value)); v.valuesize += 1; value = buf; break; case SS_STRING: { char *string = m->value; if (string) { v.valuesize = strlen(string) + 1; value = string; } else { v.valuesize = 0; } break; } case SS_STRINGPTR: { char **string = (char**)m->value; if (*string) { v.valuesize = strlen(*string) + 1; value = *string; } else { v.valuesize = 0; } v.type = SS_STRING; break; } case SS_OBJECT: v.type = SS_STRING; v.valuesize = sizeof(name_object); value = name_object; break; case SS_FUNCTION: v.type = SS_STRING; v.valuesize = sizeof(name_function); value = name_function; break; default: return -1; } char name[128]; v.keysize = snprintf(name, sizeof(name), "%s", s->path); v.keysize += 1; ssbuf *p = s->serialize; int size = sizeof(v) + v.keysize + v.valuesize; int rc = ss_bufensure(p, s->r->a, size); if (ssunlikely(rc == -1)) return sr_oom(s->r->e); memcpy(p->p, &v, sizeof(v)); memcpy(p->p + sizeof(v), name, v.keysize); memcpy(p->p + sizeof(v) + v.keysize, value, v.valuesize); ss_bufadvance(p, size); return 0; } static inline int sr_confexec_serialize(srconf *c, srconfstmt *stmt, char *root) { char path[256]; while (c) { if (root) snprintf(path, sizeof(path), "%s.%s", root, c->key); else snprintf(path, sizeof(path), "%s", c->key); int rc; if (c->flags & SR_NS) { rc = sr_confexec_serialize(c->value, stmt, path); if (ssunlikely(rc == -1)) return -1; } else { stmt->path = path; rc = c->function(c, stmt); if (ssunlikely(rc == -1)) return -1; stmt->path = NULL; } c = c->next; } return 0; }
static int se_dbscheme_set(sedb *db) { se *e = se_of(&db->o); sischeme *s = si_scheme(db->index); /* set default scheme */ int rc; if (s->scheme.fields_count == 0) { sffield *field = sf_fieldnew(&e->a, "key"); if (ssunlikely(field == NULL)) return sr_oom(&e->error); rc = sf_fieldoptions(field, &e->a, "string,key(0)"); if (ssunlikely(rc == -1)) { sf_fieldfree(field, &e->a); return sr_oom(&e->error); } rc = sf_schemeadd(&s->scheme, &e->a, field); if (ssunlikely(rc == -1)) { sf_fieldfree(field, &e->a); return sr_oom(&e->error); } field = sf_fieldnew(&e->a, "value"); if (ssunlikely(field == NULL)) return sr_oom(&e->error); rc = sf_fieldoptions(field, &e->a, "string"); if (ssunlikely(rc == -1)) { sf_fieldfree(field, &e->a); return sr_oom(&e->error); } rc = sf_schemeadd(&s->scheme, &e->a, field); if (ssunlikely(rc == -1)) { sf_fieldfree(field, &e->a); return sr_oom(&e->error); } } /* validate scheme and set keys */ rc = sf_schemevalidate(&s->scheme, &e->a); if (ssunlikely(rc == -1)) { sr_error(&e->error, "incomplete scheme", s->name); return -1; } /* validate io settings */ if (s->mmap && s->direct_io) { sr_error(&e->error, "%s", "incompatible options: mmap and direct_io"); return -1; } /* compression */ s->compression_if = ss_filterof(s->compression_sz); if (ssunlikely(s->compression_if == NULL)) { sr_error(&e->error, "unknown compression type '%s'", s->compression_sz); return -1; } s->compression = s->compression_if != &ss_nonefilter; /* path */ if (s->path == NULL) { char path[1024]; snprintf(path, sizeof(path), "%s/%s", e->rep_conf->path, s->name); s->path = ss_strdup(&e->a, path); if (ssunlikely(s->path == NULL)) return sr_oom(&e->error); } /* backup path */ s->path_backup = e->rep_conf->path_backup; if (e->rep_conf->path_backup) { s->path_backup = ss_strdup(&e->a, e->rep_conf->path_backup); if (ssunlikely(s->path_backup == NULL)) return sr_oom(&e->error); } /* compaction settings */ sicompaction *c = &s->compaction; /* convert periodic times from sec to usec */ c->gc_period_us = c->gc_period * 1000000; c->expire_period_us = c->expire_period * 1000000; /* .. */ db->r->scheme = &s->scheme; db->r->upsert = &s->upsert; db->r->stat = &db->stat; db->r->av = &db->a; db->r->ptr = db->index; return 0; }
static int se_dbscheme_set(sedb *db) { se *e = se_of(&db->o); sischeme *s = si_scheme(db->index); /* set default scheme */ int rc; if (s->scheme.fields_count == 0) { sffield *field = sf_fieldnew(&e->a, "key"); if (ssunlikely(field == NULL)) return sr_oom(&e->error); rc = sf_fieldoptions(field, &e->a, "string,key(0)"); if (ssunlikely(rc == -1)) { sf_fieldfree(field, &e->a); return sr_oom(&e->error); } rc = sf_schemeadd(&s->scheme, &e->a, field); if (ssunlikely(rc == -1)) { sf_fieldfree(field, &e->a); return sr_oom(&e->error); } field = sf_fieldnew(&e->a, "value"); if (ssunlikely(field == NULL)) return sr_oom(&e->error); rc = sf_fieldoptions(field, &e->a, "string"); if (ssunlikely(rc == -1)) { sf_fieldfree(field, &e->a); return sr_oom(&e->error); } rc = sf_schemeadd(&s->scheme, &e->a, field); if (ssunlikely(rc == -1)) { sf_fieldfree(field, &e->a); return sr_oom(&e->error); } } /* validate scheme and set keys */ rc = sf_schemevalidate(&s->scheme, &e->a); if (ssunlikely(rc == -1)) { sr_error(&e->error, "incomplete scheme", s->name); return -1; } /* storage */ if (strcmp(s->storage_sz, "cache") == 0) { s->storage = SI_SCACHE; } else if (strcmp(s->storage_sz, "anti-cache") == 0) { s->storage = SI_SANTI_CACHE; } else if (strcmp(s->storage_sz, "in-memory") == 0) { s->storage = SI_SIN_MEMORY; } else { sr_error(&e->error, "unknown storage type '%s'", s->storage_sz); return -1; } /* compression_copy */ if (s->compression_copy) { s->fmt_storage = SF_SPARSE; } /* compression cold */ s->compression_cold_if = ss_filterof(s->compression_cold_sz); if (ssunlikely(s->compression_cold_if == NULL)) { sr_error(&e->error, "unknown compression type '%s'", s->compression_cold_sz); return -1; } s->compression_cold = s->compression_cold_if != &ss_nonefilter; /* compression hot */ s->compression_hot_if = ss_filterof(s->compression_hot_sz); if (ssunlikely(s->compression_hot_if == NULL)) { sr_error(&e->error, "unknown compression type '%s'", s->compression_hot_sz); return -1; } s->compression_hot = s->compression_hot_if != &ss_nonefilter; /* path */ if (s->path == NULL) { char path[1024]; snprintf(path, sizeof(path), "%s/%s", e->conf.path, s->name); s->path = ss_strdup(&e->a, path); if (ssunlikely(s->path == NULL)) return sr_oom(&e->error); } /* backup path */ s->path_backup = e->conf.backup_path; if (e->conf.backup_path) { s->path_backup = ss_strdup(&e->a, e->conf.backup_path); if (ssunlikely(s->path_backup == NULL)) return sr_oom(&e->error); } db->r->scheme = &s->scheme; db->r->fmt_storage = s->fmt_storage; db->r->fmt_upsert = &s->fmt_upsert; return 0; }
int sr_conf_read(srconf *m, srconfstmt *s) { switch (m->type) { case SS_U32: s->valuesize = sizeof(uint32_t); if (s->valuetype == SS_I64) { sscasti64(s->value) = sscastu32(m->value); } else if (s->valuetype == SS_U32) { sscastu32(s->value) = sscastu32(m->value); } else if (s->valuetype == SS_U64) { sscastu64(s->value) = sscastu32(m->value); } else { goto bad_type; } break; case SS_U64: s->valuesize = sizeof(uint64_t); if (s->valuetype == SS_I64) { sscasti64(s->value) = sscastu64(m->value); } else if (s->valuetype == SS_U32) { sscastu32(s->value) = sscastu64(m->value); } else if (s->valuetype == SS_U64) { sscastu64(s->value) = sscastu64(m->value); } else { goto bad_type; } break; case SS_STRING: { if (s->valuetype != SS_STRING) goto bad_type; char **result = s->value; *result = NULL; s->valuesize = 0; char *string = m->value; if (string == NULL) break; int size = strlen(string) + 1; s->valuesize = size; *result = malloc(size); if (ssunlikely(*result == NULL)) return sr_oom(s->r->e); memcpy(*result, string, size); break; } case SS_STRINGPTR: { if (s->valuetype != SS_STRING) goto bad_type; char **result = s->value; *result = NULL; s->valuesize = 0; char **string = m->value; if (*string == NULL) break; int size = strlen(*string) + 1; s->valuesize = size; *result = malloc(size); if (ssunlikely(*result == NULL)) return sr_oom(s->r->e); memcpy(*result, *string, size); break; } case SS_OBJECT: if (s->valuetype != SS_STRING) goto bad_type; *(void**)s->value = m->value; s->valuesize = sizeof(void*); break; default: goto bad_type; } return 0; bad_type: return sr_error(s->r->e, "configuration read bad type (%s) -> (%s) %s", ss_typeof(s->valuetype), ss_typeof(m->type), s->path); }
static inline int sd_buildadd_keyvalue(sdbuild *b, sr *r, sv *v) { /* calculate key size */ uint32_t keysize = 0; int i = 0; while (i < r->scheme->count) { keysize += sv_keysize(v, r, i); i++; } uint32_t valuesize = sv_valuesize(v, r); uint32_t size = keysize + valuesize; /* prepare buffer */ uint64_t lsn = sv_lsn(v); uint32_t sizemeta = ss_leb128size(size) + ss_leb128size(lsn); int rc = ss_bufensure(&b->v, r->a, sizemeta); if (ssunlikely(rc == -1)) return sr_oom(r->e); /* write meta */ ss_bufadvance(&b->v, ss_leb128write(b->v.p, size)); ss_bufadvance(&b->v, ss_leb128write(b->v.p, lsn)); /* write key-parts */ i = 0; for (; i < r->scheme->count; i++) { uint32_t partsize = sv_keysize(v, r, i); char *part = sv_key(v, r, i); int offsetstart = ss_bufused(&b->k); int offset = (offsetstart - sd_buildref(b)->k); /* match a key copy */ int is_duplicate = 0; uint32_t hash = 0; int pos = 0; if (b->compress_dup) { hash = ss_fnv(part, partsize); pos = sd_buildsearch(&b->tracker, hash, part, partsize, b); if (b->tracker.i[pos]) { is_duplicate = 1; sdbuildkey *ref = sscast(b->tracker.i[pos], sdbuildkey, node); offset = ref->offset; } } /* offset */ rc = ss_bufensure(&b->v, r->a, ss_leb128size(offset)); if (ssunlikely(rc == -1)) return sr_oom(r->e); ss_bufadvance(&b->v, ss_leb128write(b->v.p, offset)); if (is_duplicate) continue; /* copy key */ int partsize_meta = ss_leb128size(partsize); rc = ss_bufensure(&b->k, r->a, partsize_meta + partsize); if (ssunlikely(rc == -1)) return sr_oom(r->e); ss_bufadvance(&b->k, ss_leb128write(b->k.p, partsize)); memcpy(b->k.p, part, partsize); ss_bufadvance(&b->k, partsize); /* add key reference */ if (b->compress_dup) { if (ssunlikely(ss_htisfull(&b->tracker))) { rc = ss_htresize(&b->tracker, r->a); if (ssunlikely(rc == -1)) return sr_oom(r->e); } sdbuildkey *ref = ss_malloc(r->a, sizeof(sdbuildkey)); if (ssunlikely(rc == -1)) return sr_oom(r->e); ref->node.hash = hash; ref->offset = offset; ref->offsetstart = offsetstart + partsize_meta; ref->size = partsize; ss_htset(&b->tracker, pos, &ref->node); } } /* write value */ rc = ss_bufensure(&b->v, r->a, valuesize); if (ssunlikely(rc == -1)) return sr_oom(r->e); memcpy(b->v.p, sv_value(v, r), valuesize); ss_bufadvance(&b->v, valuesize); return 0; }
int si_compaction(si *index, sdc *c, siplan *plan, uint64_t vlsn) { sr *r = &index->r; sinode *node = plan->node; assert(node->flags & SI_LOCK); si_lock(index); svindex *vindex; vindex = si_noderotate(node); si_unlock(index); uint64_t size_stream = vindex->used; ssiter vindex_iter; ss_iterinit(sv_indexiter, &vindex_iter); ss_iteropen(sv_indexiter, &vindex_iter, &index->r, vindex, SS_GTE, NULL); /* prepare direct_io stream */ int rc; if (index->scheme.direct_io) { rc = sd_ioprepare(&c->io, r, index->scheme.direct_io, index->scheme.direct_io_page_size, index->scheme.direct_io_buffer_size); if (ssunlikely(rc == -1)) return sr_oom(r->e); } /* prepare for compaction */ svmerge merge; sv_mergeinit(&merge); rc = sv_mergeprepare(&merge, r, 1 + 1); if (ssunlikely(rc == -1)) return -1; svmergesrc *s; s = sv_mergeadd(&merge, &vindex_iter); sdcbuf *cbuf = &c->e; s = sv_mergeadd(&merge, NULL); sdreadarg arg = { .from_compaction = 1, .io = &c->io, .index = &node->index, .buf = &cbuf->a, .buf_read = &c->d, .index_iter = &cbuf->index_iter, .page_iter = &cbuf->page_iter, .use_mmap = index->scheme.mmap, .use_mmap_copy = 0, .use_compression = index->scheme.compression, .use_direct_io = index->scheme.direct_io, .direct_io_page_size = index->scheme.direct_io_page_size, .compression_if = index->scheme.compression_if, .has = 0, .has_vlsn = 0, .o = SS_GTE, .mmap = &node->map, .file = &node->file, .r = r }; ss_iterinit(sd_read, &s->src); rc = ss_iteropen(sd_read, &s->src, &arg, NULL); if (ssunlikely(rc == -1)) return -1; size_stream += sd_indextotal(&node->index); ssiter i; ss_iterinit(sv_mergeiter, &i); ss_iteropen(sv_mergeiter, &i, r, &merge, SS_GTE); rc = si_merge(index, c, node, vlsn, &i, size_stream, sd_indexkeys(&node->index)); sv_mergefree(&merge, r->a); return rc; }
int sr_conf_write(srconf *m, srconfstmt *s) { if (m->flags & SR_RO) { sr_error(s->r->e, "%s is read-only", s->path); return -1; } switch (m->type) { case SS_U32: if (s->valuetype == SS_I64) { sscastu32(m->value) = sscasti64(s->value); } else if (s->valuetype == SS_U32) { sscastu32(m->value) = sscastu32(s->value); } else if (s->valuetype == SS_U64) { sscastu32(m->value) = sscastu64(s->value); } else { goto bad_type; } break; case SS_U64: if (s->valuetype == SS_I64) { sscastu64(m->value) = sscasti64(s->value); } else if (s->valuetype == SS_U32) { sscastu64(m->value) = sscastu32(s->value); } else if (s->valuetype == SS_U64) { sscastu64(m->value) = sscastu64(s->value); } else { goto bad_type; } break; case SS_STRINGPTR: { char **string = m->value; if (s->valuetype == SS_STRING) { char *sz = s->value; if (s->valuesize > 0) { sz = ss_malloc(s->r->a, s->valuesize); if (ssunlikely(sz == NULL)) return sr_oom(s->r->e); memcpy(sz, s->value, s->valuesize); } if (*string) ss_free(s->r->a, *string); *string = sz; } else { goto bad_type; } break; } default: goto bad_type; } return 0; bad_type: return sr_error(s->r->e, "configuration write bad type (%s) for (%s) %s", ss_typeof(s->valuetype), ss_typeof(m->type), s->path); }