static inline int si_recovercomplete(sitrack *track, sr *r, si *index, ssbuf *buf) { /* prepare and build primary index */ ss_bufreset(buf); ssrbnode *p = ss_rbmin(&track->i); while (p) { sinode *n = sscast(p, sinode, node); int rc = ss_bufadd(buf, r->a, &n, sizeof(sinode*)); if (ssunlikely(rc == -1)) return sr_oom_malfunction(r->e); p = ss_rbnext(&track->i, p); } ssiter i; ss_iterinit(ss_bufiterref, &i); ss_iteropen(ss_bufiterref, &i, buf, sizeof(sinode*)); while (ss_iterhas(ss_bufiterref, &i)) { sinode *n = ss_iterof(ss_bufiterref, &i); if (n->recover & SI_RDB_REMOVE) { int rc = si_nodefree(n, r, 1); if (ssunlikely(rc == -1)) return -1; ss_iternext(ss_bufiterref, &i); continue; } n->recover = SI_RDB; si_insert(index, n); si_plannerupdate(&index->p, SI_COMPACT|SI_BRANCH|SI_TEMP, n); ss_iternext(ss_bufiterref, &i); } return 0; }
int si_profiler(siprofiler *p) { uint64_t memory_used = 0; ssrbnode *pn; sinode *n; pn = ss_rbmin(&p->i->i); while (pn) { n = sscast(pn, sinode, node); p->total_node_count++; p->count += n->i0.count; p->count += n->i1.count; memory_used += n->i0.used; memory_used += n->i1.used; p->count += n->index.h->keys; p->count_dup += n->index.h->dupkeys; int indexsize = sd_indexsize_ext(n->index.h); p->total_node_size += indexsize + n->index.h->total; p->total_node_origin_size += indexsize + n->index.h->totalorigin; p->total_page_count += n->index.h->count; pn = ss_rbnext(&p->i->i, pn); } p->memory_used = memory_used; p->read_disk = p->i->read_disk; p->read_cache = p->i->read_cache; return 0; }
int si_profiler(siprofiler *p) { uint32_t temperature_total = 0; uint64_t memory_used = 0; ssrbnode *pn; sinode *n; pn = ss_rbmin(&p->i->i); while (pn) { n = sscast(pn, sinode, node); if (p->temperature_max < n->temperature) p->temperature_max = n->temperature; if (p->temperature_min > n->temperature) p->temperature_min = n->temperature; temperature_total += n->temperature; p->total_node_count++; p->count += n->i0.count; p->count += n->i1.count; p->total_branch_count += n->branch_count; if (p->total_branch_max < n->branch_count) p->total_branch_max = n->branch_count; if (n->branch_count < 20) p->histogram_branch[n->branch_count]++; else p->histogram_branch_20plus++; memory_used += n->i0.used; memory_used += n->i1.used; sibranch *b = n->branch; while (b) { p->count += b->index.h->keys; p->count_dup += b->index.h->dupkeys; int indexsize = sd_indexsize_ext(b->index.h); p->total_snapshot_size += indexsize; p->total_node_size += indexsize + b->index.h->total; p->total_node_origin_size += indexsize + b->index.h->totalorigin; p->total_page_count += b->index.h->count; if (b->index.h->extensions & SD_INDEXEXT_AMQF) { p->total_amqf_size += sizeof(sdindexamqf) + sd_indexamqf(&b->index)->size; } b = b->next; } pn = ss_rbnext(&p->i->i, pn); } if (p->total_node_count > 0) { p->total_branch_avg = p->total_branch_count / p->total_node_count; p->temperature_avg = temperature_total / p->total_node_count; } p->memory_used = memory_used; p->read_disk = p->i->read_disk; p->read_cache = p->i->read_cache; si_profiler_histogram_branch(p); si_profiler_histogram_temperature(p); return 0; }
static inline void si_recoversize(si *i) { ssrbnode *pn = ss_rbmin(&i->i); while (pn) { sinode *n = sscast(pn, sinode, node); i->size += si_nodesize(n); pn = ss_rbnext(&i->i, pn); } }
static inline uint64_t sx_csn(sxmanager *m) { uint64_t csn = UINT64_MAX; if (m->count_rw == 0) return csn; ssrbnode *p = ss_rbmin(&m->i); sx *min = NULL; while (p) { min = sscast(p, sx, node); if (min->type == SXRO) { p = ss_rbnext(&m->i, p); continue; } break; } assert(min != NULL); return min->csn; }
int si_snapshot(si *index, siplan *plan) { sr *r = index->r; ssfile file; ss_fileinit(&file, r->vfs); /* prepare to take snapshot */ sdsnapshot snapshot; sd_snapshot_init(&snapshot); int rc = ss_bufensure(&snapshot.buf, r->a, 1 * 1024 * 1024); if (ssunlikely(rc == -1)) goto error_oom; rc = sd_snapshot_begin(&snapshot, r); if (ssunlikely(rc == -1)) goto error_oom; /* save node index image */ si_lock(index); ssrbnode *p = NULL; while ((p = ss_rbnext(&index->i, p))) { sinode *n = sscast(p, sinode, node); rc = sd_snapshot_add(&snapshot, r, n->self.id.id, n->file.size, n->branch_count, n->temperature_reads); if (ssunlikely(rc == -1)) { si_unlock(index); goto error_oom; } sibranch *b = &n->self; while (b) { rc = sd_snapshot_addbranch(&snapshot, r, b->index.h); if (ssunlikely(rc == -1)) { si_unlock(index); goto error_oom; } b = b->link; } } sd_snapshot_commit(&snapshot, r, index->lru_v, index->lru_steps, index->lru_intr_lsn, index->lru_intr_sum, index->read_disk, index->read_cache); si_unlock(index); /* create snapshot.inprogress */ char path[PATH_MAX]; snprintf(path, sizeof(path), "%s/index.incomplete", index->scheme->path); rc = ss_filenew(&file, path); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "index file '%s' create error: %s", path, strerror(errno)); goto error; } rc = ss_filewrite(&file, snapshot.buf.s, ss_bufused(&snapshot.buf)); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "index file '%s' write error: %s", path, strerror(errno)); goto error; } SS_INJECTION(r->i, SS_INJECTION_SI_SNAPSHOT_0, ss_fileclose(&file); sd_snapshot_free(&snapshot, r); sr_malfunction(r->e, "%s", "error injection"); return -1); /* sync snapshot file */ if (index->scheme->sync) { rc = ss_filesync(&file); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "index file '%s' sync error: %s", path, strerror(errno)); goto error; } } /* remove old snapshot file (if exists) */ snprintf(path, sizeof(path), "%s/index", index->scheme->path); ss_vfsunlink(r->vfs, path); SS_INJECTION(r->i, SS_INJECTION_SI_SNAPSHOT_1, ss_fileclose(&file); sd_snapshot_free(&snapshot, r); sr_malfunction(r->e, "%s", "error injection"); return -1); /* rename snapshot.incomplete to snapshot */ rc = ss_filerename(&file, path); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "index file '%s' rename error: %s", ss_pathof(&file.path), strerror(errno)); goto error; } SS_INJECTION(r->i, SS_INJECTION_SI_SNAPSHOT_2, ss_fileclose(&file); sd_snapshot_free(&snapshot, r); sr_malfunction(r->e, "%s", "error injection"); return -1); /* close snapshot file */ rc = ss_fileclose(&file); if (ssunlikely(rc == -1)) { sr_malfunction(r->e, "index file '%s' close error: %s", path, strerror(errno)); goto error; } sd_snapshot_free(&snapshot, r); /* finish index snapshot */ si_lock(index); index->snapshot = plan->a; index->snapshot_run = 0; si_unlock(index); return 0; error_oom: sr_oom(r->e); error: ss_fileclose(&file); sd_snapshot_free(&snapshot, r); return -1; }