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; }
static inline int sd_buildcompress(sdbuild *b, sr *r) { /* reserve header */ int rc = sr_bufensure(&b->c, r->a, sizeof(sdpageheader)); if (srunlikely(rc == -1)) return -1; sr_bufadvance(&b->c, sizeof(sdpageheader)); /* compression (including meta-data) */ sdbuildref *ref = sd_buildref(b); srfilter f; rc = sr_filterinit(&f, (srfilterif*)r->compression, r, SR_FINPUT); if (srunlikely(rc == -1)) return -1; rc = sr_filterstart(&f, &b->c); if (srunlikely(rc == -1)) goto error; rc = sr_filternext(&f, &b->c, b->k.s + ref->k + sizeof(sdpageheader), ref->ksize - sizeof(sdpageheader)); if (srunlikely(rc == -1)) goto error; rc = sr_filternext(&f, &b->c, b->v.s + ref->v, ref->vsize); if (srunlikely(rc == -1)) goto error; rc = sr_filtercomplete(&f, &b->c); if (srunlikely(rc == -1)) goto error; sr_filterfree(&f); return 0; error: sr_filterfree(&f); return -1; }
int sd_buildadd(sdbuild *b, sr *r, sv *v, uint32_t flags) { /* prepare metadata reference */ int rc = sr_bufensure(&b->k, r->a, sizeof(sdv)); if (srunlikely(rc == -1)) return sr_error(r->e, "%s", "memory allocation failed"); sdpageheader *h = sd_buildheader(b); sdv *sv = (sdv*)b->k.p; sv->lsn = sv_lsn(v); sv->flags = sv_flags(v) | flags; sv->size = sv_size(v); sv->offset = sr_bufused(&b->v) - sd_buildref(b)->v; /* copy object */ rc = sr_bufensure(&b->v, r->a, sv->size); if (srunlikely(rc == -1)) return sr_error(r->e, "%s", "memory allocation failed"); memcpy(b->v.p, sv_pointer(v), sv->size); sr_bufadvance(&b->v, sv->size); sr_bufadvance(&b->k, sizeof(sdv)); /* update page header */ h->count++; h->size += sv->size + sizeof(sdv); if (sv->lsn > h->lsnmax) h->lsnmax = sv->lsn; if (sv->lsn < h->lsnmin) h->lsnmin = sv->lsn; if (sv->flags & SVDUP) { h->countdup++; if (sv->lsn < h->lsnmindup) h->lsnmindup = sv->lsn; } return 0; }
int sd_buildend(sdbuild *b, sr *r) { /* update sizes */ sdbuildref *ref = sd_buildref(b); ref->ksize = sr_bufused(&b->k) - ref->k; ref->vsize = sr_bufused(&b->v) - ref->v; ref->csize = 0; /* calculate data crc (non-compressed) */ sdpageheader *h = sd_buildheader(b); uint32_t crc = 0; if (srlikely(b->crc)) { crc = sr_crcp(r->crc, b->k.s + ref->k, ref->ksize, 0); crc = sr_crcp(r->crc, b->v.s + ref->v, ref->vsize, crc); } h->crcdata = crc; /* compression */ if (b->compress) { int rc = sd_buildcompress(b, r); if (srunlikely(rc == -1)) return -1; ref->csize = sr_bufused(&b->c) - ref->c; } /* update page header */ h->sizeorigin = h->size; if (b->compress) h->size = ref->csize - sizeof(sdpageheader); h->crc = sr_crcs(r->crc, h, sizeof(sdpageheader), 0); if (b->compress) memcpy(b->c.s + ref->c, h, sizeof(sdpageheader)); return 0; }
int sd_commitpage(sdbuild *b, sr *r, srbuf *buf) { sdbuildref *ref = sd_buildref(b); /* compressed */ uint32_t size = sr_bufused(&b->c); int rc; if (size > 0) { rc = sr_bufensure(buf, r->a, ref->csize); if (srunlikely(rc == -1)) return -1; memcpy(buf->p, b->c.s, ref->csize); sr_bufadvance(buf, ref->csize); return 0; } /* not compressed */ assert(ref->ksize != 0); rc = sr_bufensure(buf, r->a, ref->ksize + ref->vsize); if (srunlikely(rc == -1)) return -1; memcpy(buf->p, b->k.s + ref->k, ref->ksize); sr_bufadvance(buf, ref->ksize); memcpy(buf->p, b->v.s + ref->v, ref->vsize); sr_bufadvance(buf, ref->vsize); 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 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; }