From 1b09e7293f579a2c3be439ad78905387a17bd910 Mon Sep 17 00:00:00 2001 From: krangelov Date: Fri, 10 Sep 2021 11:39:54 +0200 Subject: [PATCH] implemented pgf_free_revision --- src/runtime/c/pgf/db.cxx | 25 +++++++++++++++++++------ src/runtime/c/pgf/db.h | 2 +- src/runtime/c/pgf/pgf.cxx | 17 ++++++++++++++++- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/runtime/c/pgf/db.cxx b/src/runtime/c/pgf/db.cxx index 6a26b602a..44bc78a04 100644 --- a/src/runtime/c/pgf/db.cxx +++ b/src/runtime/c/pgf/db.cxx @@ -312,14 +312,23 @@ PgfDB::PgfDB(const char* filepath, int flags, int mode) { if (ms == MAP_FAILED) throw pgf_systemerror(errno, filepath); - if (is_new) { - init_state(file_size); - } - int res = pthread_rwlock_init(&rwlock, NULL); if (res != 0) { throw pgf_systemerror(errno); } + + if (is_new) { + init_state(file_size); + } else { + // 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()); + } + } } PGF_INTERNAL @@ -994,14 +1003,18 @@ void PgfDB::link_transient_revision(ref pgf) } PGF_INTERNAL -void PgfDB::unlink_transient_revision(ref pgf) +bool PgfDB::unlink_transient_revision(ref pgf) { if (pgf->next != 0) pgf->next->prev = pgf->prev; if (pgf->prev != 0) pgf->prev->next = pgf->next; - else + else if (current_db->ms->transient_revisions == pgf) current_db->ms->transient_revisions = pgf->next; + else + return false; + + return true; } DB_scope::DB_scope(PgfDB *db, DB_scope_mode tp) diff --git a/src/runtime/c/pgf/db.h b/src/runtime/c/pgf/db.h index 810510e80..ac8e0558b 100644 --- a/src/runtime/c/pgf/db.h +++ b/src/runtime/c/pgf/db.h @@ -82,7 +82,7 @@ public: static PGF_INTERNAL_DECL void set_revision(ref pgf); static PGF_INTERNAL_DECL ref revision2pgf(PgfRevision revision); static PGF_INTERNAL_DECL void link_transient_revision(ref pgf); - static PGF_INTERNAL_DECL void unlink_transient_revision(ref pgf); + static PGF_INTERNAL_DECL bool unlink_transient_revision(ref pgf); PGF_INTERNAL_DECL static void sync(); diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index b6737c4b4..21ae51a7e 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -156,8 +156,23 @@ void pgf_free(PgfDB *db) } PGF_API_DECL -void pgf_free_revision(PgfDB *pgf, PgfRevision revision) +void pgf_free_revision(PgfDB *db, PgfRevision revision) { + try { + DB_scope scope(db, READER_SCOPE); + ref pgf = PgfDB::revision2pgf(revision); + + if (PgfDB::unlink_transient_revision(pgf)) { + namespace_release(pgf->gflags); + PgfDB::free(pgf->abstract.name); + namespace_release(pgf->abstract.aflags); + namespace_release(pgf->abstract.funs); + namespace_release(pgf->abstract.cats); + PgfDB::free(pgf); + } + } catch (std::runtime_error& e) { + // silently ignore and hope for the best + } } PGF_API