cleanup transient revisions only after a transaction is opened

This commit is contained in:
Krasimir Angelov
2021-12-29 14:52:21 +01:00
parent f118e644d9
commit cd2c6aa32a
3 changed files with 39 additions and 36 deletions

View File

@@ -502,7 +502,6 @@ struct PGF_INTERNAL_DECL malloc_state
PGF_INTERNAL PGF_INTERNAL
PgfDB::PgfDB(const char* filepath, int flags, int mode) { PgfDB::PgfDB(const char* filepath, int flags, int mode) {
bool is_new = false; bool is_new = false;
bool is_first = false;
fd = -1; fd = -1;
ms = NULL; ms = NULL;
@@ -655,34 +654,7 @@ PgfDB::PgfDB(const char* filepath, int flags, int mode) {
throw pgf_error("Invalid file content"); throw pgf_error("Invalid file content");
} }
register_process(&is_first); register_process();
if (is_first) {
// We must make sure that left-over transient revisions are
// released. This may happen if a client process was killed
// or if the garbadge collector has not managed to run
// pgf_release_revision() before the process ended.
while (ms->transient_revisions != 0) {
pgf_free_revision(this, ms->transient_revisions.as_object());
ref<PgfPGF> pgf = ms->transient_revisions;
ref<PgfPGF> next = pgf->next;
PgfPGF::release(pgf);
PgfDB::free(pgf);
ms->transient_revisions = next;
}
while (ms->transient_concr_revisions != 0) {
ref<PgfConcr> concr = ms->transient_concr_revisions;
ref<PgfConcr> next = concr->next;
concr->ref_count -= concr->ref_count_ex;
if (!concr->ref_count) {
PgfConcr::release(concr);
PgfDB::free(concr);
}
ms->transient_concr_revisions = next;
}
}
} }
} }
@@ -725,7 +697,7 @@ PgfDB::~PgfDB()
} }
PGF_INTERNAL PGF_INTERNAL
void PgfDB::register_process(bool *is_first) void PgfDB::register_process()
{ {
process_entry *pentry = &ms->p; process_entry *pentry = &ms->p;
object *plast = NULL; object *plast = NULL;
@@ -768,10 +740,7 @@ void PgfDB::register_process(bool *is_first)
} }
} }
if (plast == NULL) { if (plast != NULL) {
*is_first = true;
} else {
*is_first = false;
*plast = malloc_internal(sizeof(process_entry)); *plast = malloc_internal(sizeof(process_entry));
pentry = (process_entry*) ptr(ms,*plast); pentry = (process_entry*) ptr(ms,*plast);
pentry->next = 0; pentry->next = 0;
@@ -809,6 +778,37 @@ void PgfDB::unregister_process()
} }
} }
void PgfDB::cleanup_revisions()
{
if (ms->p.next == 0) {
// The first process that opens this file makes sure that
// left-over transient revisions are released.
// They may be left-over of a client process that was killed
// or if the garbadge collector has not managed to run
// pgf_release_revision() before the process ended.
while (ms->transient_revisions != 0) {
pgf_free_revision(this, ms->transient_revisions.as_object());
ref<PgfPGF> pgf = ms->transient_revisions;
ref<PgfPGF> next = pgf->next;
PgfPGF::release(pgf);
PgfDB::free(pgf);
ms->transient_revisions = next;
}
while (ms->transient_concr_revisions != 0) {
ref<PgfConcr> concr = ms->transient_concr_revisions;
ref<PgfConcr> next = concr->next;
concr->ref_count -= concr->ref_count_ex;
if (!concr->ref_count) {
PgfConcr::release(concr);
PgfDB::free(concr);
}
ms->transient_concr_revisions = next;
}
}
}
PGF_INTERNAL PGF_INTERNAL
ref<PgfPGF> PgfDB::get_revision(PgfText *name) ref<PgfPGF> PgfDB::get_revision(PgfText *name)
{ {

View File

@@ -90,6 +90,8 @@ public:
current_db->free_internal(o.as_object()); current_db->free_internal(o.as_object());
} }
PGF_INTERNAL_DECL void cleanup_revisions();
static PGF_INTERNAL_DECL ref<PgfPGF> get_revision(PgfText *name); static PGF_INTERNAL_DECL ref<PgfPGF> get_revision(PgfText *name);
static PGF_INTERNAL_DECL void set_revision(ref<PgfPGF> pgf); static PGF_INTERNAL_DECL void set_revision(ref<PgfPGF> pgf);
@@ -111,10 +113,9 @@ private:
PGF_INTERNAL_DECL object malloc_internal(size_t bytes); PGF_INTERNAL_DECL object malloc_internal(size_t bytes);
PGF_INTERNAL_DECL void free_internal(object o); PGF_INTERNAL_DECL void free_internal(object o);
PGF_INTERNAL_DECL void register_process(bool *is_first); PGF_INTERNAL_DECL void register_process();
PGF_INTERNAL_DECL void unregister_process(); PGF_INTERNAL_DECL void unregister_process();
PGF_INTERNAL_DECL void lock(DB_scope_mode m); PGF_INTERNAL_DECL void lock(DB_scope_mode m);
PGF_INTERNAL_DECL void unlock(); PGF_INTERNAL_DECL void unlock();

View File

@@ -144,6 +144,8 @@ PgfDB *pgf_read_ngf(const char *fpath,
{ {
DB_scope scope(db, WRITER_SCOPE); DB_scope scope(db, WRITER_SCOPE);
db->cleanup_revisions();
ref<PgfPGF> pgf = PgfDB::get_revision(master); ref<PgfPGF> pgf = PgfDB::get_revision(master);
Node<PgfPGF>::add_value_ref(pgf); Node<PgfPGF>::add_value_ref(pgf);
*revision = pgf.as_object(); *revision = pgf.as_object();