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; }
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 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 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) { /* 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_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 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_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; }
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 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; }
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; }
int si_noderead(sinode *n, sr *r, ssbuf *dest) { int rc = ss_bufensure(dest, r->a, n->file.size); if (ssunlikely(rc == -1)) return sr_oom_malfunction(r->e); rc = ss_filepread(&n->file, 0, dest->s, n->file.size); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "db file '%s' read error: %s", ss_pathof(&n->file.path), strerror(errno)); return -1; } ss_bufadvance(dest, n->file.size); return 0; }
int sw_dirread(ssbuf *list, ssa *a, swdirtype *types, char *dir) { DIR *d = opendir(dir); if (ssunlikely(d == NULL)) return -1; struct dirent *de; while ((de = readdir(d))) { if (ssunlikely(de->d_name[0] == '.')) continue; ssize_t id = sw_diridof(de->d_name); if (ssunlikely(id == -1)) goto error; char *ext = strstr(de->d_name, "."); if (ssunlikely(ext == NULL)) goto error; ext++; swdirtype *type = sw_dirtypeof(types, ext); if (ssunlikely(type == NULL)) continue; swdirid *n = sw_dirmatch(list, id); if (n) { n->mask |= type->mask; type->count++; continue; } int rc = ss_bufensure(list, a, sizeof(swdirid)); if (ssunlikely(rc == -1)) goto error; n = (swdirid*)list->p; ss_bufadvance(list, sizeof(swdirid)); n->id = id; n->mask = type->mask; type->count++; } closedir(d); if (ssunlikely(ss_bufused(list) == 0)) return 0; int n = ss_bufused(list) / sizeof(swdirid); qsort(list->s, n, sizeof(swdirid), sw_dircmp); return n; error: closedir(d); return -1; }
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 inline int sd_buildcompress(sdbuild *b, sr *r) { /* reserve header */ int rc = ss_bufensure(&b->c, r->a, sizeof(sdpageheader)); if (ssunlikely(rc == -1)) return -1; ss_bufadvance(&b->c, sizeof(sdpageheader)); /* compression (including meta-data) */ sdbuildref *ref = sd_buildref(b); ssfilter f; rc = ss_filterinit(&f, (ssfilterif*)r->compression, r->a, SS_FINPUT); if (ssunlikely(rc == -1)) return -1; rc = ss_filterstart(&f, &b->c); if (ssunlikely(rc == -1)) goto error; rc = ss_filternext(&f, &b->c, b->m.s + ref->m + sizeof(sdpageheader), ref->msize - sizeof(sdpageheader)); if (ssunlikely(rc == -1)) goto error; rc = ss_filternext(&f, &b->c, b->v.s + ref->v, ref->vsize); if (ssunlikely(rc == -1)) goto error; rc = ss_filternext(&f, &b->c, b->k.s + ref->k, ref->ksize); if (ssunlikely(rc == -1)) goto error; rc = ss_filtercomplete(&f, &b->c); if (ssunlikely(rc == -1)) goto error; ss_filterfree(&f); return 0; error: ss_filterfree(&f); return -1; }
static inline sibranch* si_branchcreate(si *index, sdc *c, sinode *parent, svindex *vindex, uint64_t vlsn) { sr *r = index->r; svmerge vmerge; sv_mergeinit(&vmerge); int rc = sv_mergeprepare(&vmerge, r, 1); if (ssunlikely(rc == -1)) return NULL; svmergesrc *s = sv_mergeadd(&vmerge, NULL); ss_iterinit(sv_indexiterraw, &s->src); ss_iteropen(sv_indexiterraw, &s->src, vindex); ssiter i; ss_iterinit(sv_mergeiter, &i); ss_iteropen(sv_mergeiter, &i, r, &vmerge, SS_GTE, 1); /* merge iter is not used */ sdmergeconf mergeconf = { .size_stream = UINT32_MAX, .size_node = UINT64_MAX, .size_page = index->scheme->node_page_size, .checksum = index->scheme->node_page_checksum, .compression = index->scheme->compression, .compression_key = index->scheme->compression_key, .offset = parent->file.size, .vlsn = vlsn, .save_delete = 1 }; sdmerge merge; sd_mergeinit(&merge, r, &i, &c->build, &mergeconf); rc = sd_merge(&merge); if (ssunlikely(rc == -1)) { sv_mergefree(&vmerge, r->a); sr_oom_malfunction(r->e); goto error; } assert(rc == 1); sv_mergefree(&vmerge, r->a); sibranch *branch = si_branchnew(r); if (ssunlikely(branch == NULL)) goto error; sdid id = { .parent = parent->self.id.id, .flags = SD_IDBRANCH, .id = sr_seq(r->seq, SR_NSNNEXT) }; rc = sd_mergecommit(&merge, &id); if (ssunlikely(rc == -1)) goto error; si_branchset(branch, &merge.index); rc = sd_commit(&c->build, r, &branch->index, &parent->file); if (ssunlikely(rc == -1)) { si_branchfree(branch, r); return NULL; } SS_INJECTION(r->i, SS_INJECTION_SI_BRANCH_0, sr_malfunction(r->e, "%s", "error injection"); si_branchfree(branch, r); return NULL); if (index->scheme->sync) { rc = si_nodesync(parent, r); if (ssunlikely(rc == -1)) { si_branchfree(branch, r); return NULL; } } if (index->scheme->mmap) { ss_mmapinit(&parent->map_swap); rc = ss_mmap(&parent->map_swap, parent->file.fd, parent->file.size, 1); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "db file '%s' mmap error: %s", parent->file.file, strerror(errno)); return NULL; } } return branch; error: sd_mergefree(&merge); return NULL; } int si_branch(si *index, sdc *c, siplan *plan, uint64_t vlsn) { sr *r = index->r; sinode *n = plan->node; assert(n->flags & SI_LOCK); si_lock(index); if (ssunlikely(n->used == 0)) { si_nodeunlock(n); si_unlock(index); return 0; } svindex *i; i = si_noderotate(n); si_unlock(index); sd_creset(c); sibranch *branch = si_branchcreate(index, c, n, i, vlsn); if (ssunlikely(branch == NULL)) return -1; /* commit */ si_lock(index); branch->next = n->branch; n->branch = branch; n->branch_count++; uint32_t used = sv_indexused(i); n->used -= used; ss_quota(r->quota, SS_QREMOVE, used); svindex swap = *i; si_nodeunrotate(n); si_nodeunlock(n); si_plannerupdate(&index->p, SI_BRANCH|SI_COMPACT, n); ssmmap swap_map = n->map; n->map = n->map_swap; memset(&n->map_swap, 0, sizeof(n->map_swap)); si_unlock(index); /* gc */ if (index->scheme->mmap) { int rc = ss_munmap(&swap_map); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "db file '%s' munmap error: %s", n->file.file, strerror(errno)); return -1; } } si_nodegc_index(r, &swap); return 1; } static inline char* si_noderead(si *index, ssbuf *dest, sinode *node) { sr *r = index->r; if (index->scheme->mmap) { return node->map.p; } int rc = ss_bufensure(dest, r->a, node->file.size); if (ssunlikely(rc == -1)) { sr_oom_malfunction(r->e); return NULL; } rc = ss_filepread(&node->file, 0, dest->s, node->file.size); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "db file '%s' read error: %s", node->file.file, strerror(errno)); return NULL; } ss_bufadvance(dest, node->file.size); return dest->s; }
static inline int si_recoversnapshot(si *i, sr *r, sdsnapshot *s) { /* recovery stages: snapshot (1) ok snapshot.incomplete (2) remove snapshot.incomplete snapshot (3) remove snapshot.incomplete, load snapshot snapshot.incomplete */ /* recover snapshot file (crash recover) */ int snapshot = 0; int snapshot_incomplete = 0; char path[1024]; snprintf(path, sizeof(path), "%s/index", i->scheme->path); snapshot = ss_vfsexists(r->vfs, path); snprintf(path, sizeof(path), "%s/index.incomplete", i->scheme->path); snapshot_incomplete = ss_vfsexists(r->vfs, path); int rc; if (snapshot_incomplete) { rc = ss_vfsunlink(r->vfs, path); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "index file '%s' unlink error: %s", path, strerror(errno)); return -1; } } if (! snapshot) return 0; /* read snapshot file */ snprintf(path, sizeof(path), "%s/index", i->scheme->path); ssize_t size = ss_vfssize(r->vfs, path); if (ssunlikely(size == -1)) { sr_malfunction(r->e, "index file '%s' read error: %s", path, strerror(errno)); return -1; } rc = ss_bufensure(&s->buf, r->a, size); if (ssunlikely(rc == -1)) return sr_oom_malfunction(r->e); ssfile file; ss_fileinit(&file, r->vfs); rc = ss_fileopen(&file, path); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "index file '%s' open error: %s", path, strerror(errno)); return -1; } rc = ss_filepread(&file, 0, s->buf.s, size); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "index file '%s' read error: %s", path, strerror(errno)); ss_fileclose(&file); return -1; } ss_bufadvance(&s->buf, size); ss_fileclose(&file); 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; char *max; min = sd_buildminkey(build); min += ss_leb128skip(min); min += ss_leb128skip(min); max = sd_buildmaxkey(build); max += ss_leb128skip(max); max += ss_leb128skip(max); switch (r->fmt_storage) { case SF_SRAW: rc = sd_indexadd_raw(i, r, p, min, max); break; case SF_SKEYVALUE: rc = sd_indexadd_keyvalue(i, r, build, p, min, max); break; } if (ssunlikely(rc == -1)) return -1; } /* update index info */ sdindexheader *h = sd_indexheader(i); 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; h->dupkeys += ph->countdup; if (ph->lsnmindup < h->dupmin) h->dupmin = ph->lsnmindup; ss_bufadvance(&i->i, sizeof(sdindexpage)); 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 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; }