int si_nodeseal(sinode *n, sr *r, siconf *conf) { srpath path; sr_pathAB(&path, conf->path, n->self.id.parent, n->self.id.id, ".db.seal"); int rc = sr_filerename(&n->file, path.path); if (srunlikely(rc == -1)) { sr_malfunction(r->e, "db file '%s' rename error: %s", n->file.file, strerror(errno)); } return rc; }
int si_nodecreate(sinode *n, sr *r, siconf *conf, sdid *id, sdindex *i, sdbuild *build) { si_branchset(&n->self, i); srpath path; sr_pathAB(&path, conf->path, id->parent, id->id, ".db.incomplete"); int rc = sr_filenew(&n->file, path.path); if (srunlikely(rc == -1)) { sr_malfunction(r->e, "db file '%s' create error: %s", path.path, strerror(errno)); return -1; } rc = sd_buildwrite(build, r, &n->self.index, &n->file); if (srunlikely(rc == -1)) return -1; n->branch = &n->self; n->branch_count++; return 0; }
static inline int si_trackdir(sitrack *track, sr *r, si *i) { DIR *dir = opendir(i->conf->path); if (srunlikely(dir == NULL)) { sr_malfunction(r->e, "directory '%s' open error: %s", i->conf->path, strerror(errno)); return -1; } struct dirent *de; while ((de = readdir(dir))) { if (srunlikely(de->d_name[0] == '.')) continue; uint32_t id_parent = 0; uint32_t id = 0; int rc = si_process(de->d_name, &id, &id_parent); if (srunlikely(rc == -1)) continue; /* skip unknown file */ si_tracknsn(track, id_parent); si_tracknsn(track, id); sinode *head, *node; srpath path; switch (rc) { case SI_RDB_DBI: case SI_RDB_DBSEAL: { /* find parent node and mark it as having * incomplete compaction process */ head = si_trackget(track, id_parent); if (srlikely(head == NULL)) { head = si_nodenew(r); if (srunlikely(head == NULL)) goto error; head->self.id.id = id_parent; head->recover = SI_RDB_UNDEF; si_trackset(track, head); } head->recover |= rc; /* remove any incomplete file made during compaction */ if (rc == SI_RDB_DBI) { sr_pathAB(&path, i->conf->path, id_parent, id, ".db.incomplete"); rc = sr_fileunlink(path.path); if (srunlikely(rc == -1)) { sr_malfunction(r->e, "db file '%s' unlink error: %s", path.path, strerror(errno)); goto error; } continue; } assert(rc == SI_RDB_DBSEAL); /* recover 'sealed' node */ node = si_nodenew(r); if (srunlikely(node == NULL)) goto error; node->recover = SI_RDB_DBSEAL; sr_pathAB(&path, i->conf->path, id_parent, id, ".db.seal"); rc = si_nodeopen(node, r, &path); if (srunlikely(rc == -1)) { si_nodefree(node, r, 0); goto error; } si_trackset(track, node); si_trackmetrics(track, node); continue; } } assert(rc == SI_RDB); /* recover node */ node = si_nodenew(r); if (srunlikely(node == NULL)) goto error; node->recover = SI_RDB; sr_pathA(&path, i->conf->path, id, ".db"); rc = si_nodeopen(node, r, &path); if (srunlikely(rc == -1)) { si_nodefree(node, r, 0); goto error; } si_trackmetrics(track, node); /* track node */ head = si_trackget(track, id); if (srlikely(head == NULL)) { si_trackset(track, node); } else { /* replace a node previously created by a * incomplete compaction. */ if (! (head->recover & SI_RDB_UNDEF)) { sr_malfunction(r->e, "corrupted database repository: %s", i->conf->path); goto error; } si_trackreplace(track, head, node); head->recover &= ~SI_RDB_UNDEF; node->recover |= head->recover; si_nodefree(head, r, 0); } } closedir(dir); return 0; error: closedir(dir); return -1; }