From cd2c6aa32ae464da85676c820d42462fec25f1d5 Mon Sep 17 00:00:00 2001 From: Krasimir Angelov Date: Wed, 29 Dec 2021 14:52:21 +0100 Subject: [PATCH] cleanup transient revisions only after a transaction is opened --- src/runtime/c/pgf/db.cxx | 68 +++++++++++++++++++-------------------- src/runtime/c/pgf/db.h | 5 +-- src/runtime/c/pgf/pgf.cxx | 2 ++ 3 files changed, 39 insertions(+), 36 deletions(-) diff --git a/src/runtime/c/pgf/db.cxx b/src/runtime/c/pgf/db.cxx index 62dff3dcc..140efc1af 100644 --- a/src/runtime/c/pgf/db.cxx +++ b/src/runtime/c/pgf/db.cxx @@ -502,7 +502,6 @@ struct PGF_INTERNAL_DECL malloc_state PGF_INTERNAL PgfDB::PgfDB(const char* filepath, int flags, int mode) { bool is_new = false; - bool is_first = false; fd = -1; ms = NULL; @@ -655,34 +654,7 @@ PgfDB::PgfDB(const char* filepath, int flags, int mode) { throw pgf_error("Invalid file content"); } - register_process(&is_first); - - 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 pgf = ms->transient_revisions; - ref next = pgf->next; - PgfPGF::release(pgf); - PgfDB::free(pgf); - ms->transient_revisions = next; - } - - while (ms->transient_concr_revisions != 0) { - ref concr = ms->transient_concr_revisions; - ref 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; - } - } + register_process(); } } @@ -725,7 +697,7 @@ PgfDB::~PgfDB() } PGF_INTERNAL -void PgfDB::register_process(bool *is_first) +void PgfDB::register_process() { process_entry *pentry = &ms->p; object *plast = NULL; @@ -768,10 +740,7 @@ void PgfDB::register_process(bool *is_first) } } - if (plast == NULL) { - *is_first = true; - } else { - *is_first = false; + if (plast != NULL) { *plast = malloc_internal(sizeof(process_entry)); pentry = (process_entry*) ptr(ms,*plast); 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 pgf = ms->transient_revisions; + ref next = pgf->next; + PgfPGF::release(pgf); + PgfDB::free(pgf); + ms->transient_revisions = next; + } + + while (ms->transient_concr_revisions != 0) { + ref concr = ms->transient_concr_revisions; + ref 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 ref PgfDB::get_revision(PgfText *name) { diff --git a/src/runtime/c/pgf/db.h b/src/runtime/c/pgf/db.h index 16d702bbf..d1725588a 100644 --- a/src/runtime/c/pgf/db.h +++ b/src/runtime/c/pgf/db.h @@ -90,6 +90,8 @@ public: current_db->free_internal(o.as_object()); } + PGF_INTERNAL_DECL void cleanup_revisions(); + static PGF_INTERNAL_DECL ref get_revision(PgfText *name); static PGF_INTERNAL_DECL void set_revision(ref pgf); @@ -111,10 +113,9 @@ private: PGF_INTERNAL_DECL object malloc_internal(size_t bytes); 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 lock(DB_scope_mode m); PGF_INTERNAL_DECL void unlock(); diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index 10246eb32..182535a8f 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -144,6 +144,8 @@ PgfDB *pgf_read_ngf(const char *fpath, { DB_scope scope(db, WRITER_SCOPE); + db->cleanup_revisions(); + ref pgf = PgfDB::get_revision(master); Node::add_value_ref(pgf); *revision = pgf.as_object();