/* * sophia database * sphia.org * * Copyright (c) Dmitry Simonenko * BSD License */ #include int sp_gc(sp *s, spepoch *x) { /* * copy all yet active pages from a epoch's * databases picked for the garbage * collecting. */ for (;;) { sp_lock(&s->lockr); spepoch *g = sp_repgc(&s->rep, s->e->gcfactor); sp_unlock(&s->lockr); if (g == NULL) break; int rc; splist *i, *n; sp_listforeach_safe(&g->pages, i, n) { sppage *p = spcast(i, sppage, link); /* map origin page and copy to db file */ sppageh *h = (sppageh*)(g->db.map + p->offset); sp_lock(&x->lock); rc = sp_mapensure(&x->db, sizeof(sppageh) + h->size, s->e->dbgrow); if (spunlikely(rc == -1)) { sp_unlock(&x->lock); return sp_e(s, SPEIO, "failed to remap db file", x->epoch); } sp_unlock(&x->lock); memcpy(x->db.map + x->db.used, h, sizeof(sppageh) + h->size); /* update page location */ sp_lock(&s->locks); sp_listunlink(&p->link); sp_listappend(&x->pages, &p->link); p->epoch = x; p->offset = x->db.used; sp_unlock(&s->locks); /* advance file pointer */ sp_mapuse(&x->db, sizeof(sppageh) + h->size); } /* * remove old files and unlink the epoch * from the repository. */ rc = sp_mapunlink(&g->db); if (spunlikely(rc == -1)) return sp_e(s, SPEIO, "failed to unlink db file", g->epoch); rc = sp_mapclose(&g->db); if (spunlikely(rc == -1)) return sp_e(s, SPEIO, "failed to close db file", g->epoch); sp_lock(&s->lockr); sp_repdetach(&s->rep, g); sp_free(&s->a, g); sp_unlock(&s->lockr); } return 0; }