From d66cf23811a210586d17ca61c1841acc66f4a941 Mon Sep 17 00:00:00 2001 From: Krasimir Angelov Date: Mon, 23 May 2022 13:59:03 +0200 Subject: [PATCH] Revisions now correspond to revision_entry:s in the database. --- src/runtime/c/pgf/db.cxx | 87 +++++++++++++++++++++++++-------------- src/runtime/c/pgf/db.h | 6 +-- src/runtime/c/pgf/pgf.cxx | 50 +++++++++++----------- 3 files changed, 86 insertions(+), 57 deletions(-) diff --git a/src/runtime/c/pgf/db.cxx b/src/runtime/c/pgf/db.cxx index 36bfc8a4b..0222bed1b 100644 --- a/src/runtime/c/pgf/db.cxx +++ b/src/runtime/c/pgf/db.cxx @@ -394,7 +394,7 @@ txn_t PgfDB::get_txn_id() { } PGF_INTERNAL -void PgfDB::register_revision(object o) +object PgfDB::register_revision(object o, txn_t txn_id) { #ifndef _WIN32 pthread_mutex_lock(&ms->mutex); @@ -403,7 +403,7 @@ void PgfDB::register_revision(object o) #endif bool found = false; - revision_entry *free_entry = NULL; + revision_entry *found_entry = NULL; #ifdef DEBUG_MEMORY_ALLOCATOR fprintf(stderr, "revisions"); @@ -413,8 +413,8 @@ void PgfDB::register_revision(object o) for (size_t i = 0; i < ms->n_revisions; i++) { revision_entry *entry = &ms->revisions[i]; if (entry->ref_count == 0) { - if (free_entry == NULL) - free_entry = entry; + if (found_entry == NULL) + found_entry = entry; } else { #ifdef DEBUG_MEMORY_ALLOCATOR fprintf(stderr, " %ld:%s(%016lx):%ld", @@ -427,7 +427,8 @@ void PgfDB::register_revision(object o) if (entry->pid == pid && entry->o == o) { entry->ref_count++; - entry->txn_id = ms->curr_txn_id; + entry->txn_id = txn_id; + found_entry = entry; found = true; } @@ -437,7 +438,7 @@ void PgfDB::register_revision(object o) } if (!found) { - if (free_entry == NULL) { + if (found_entry == NULL) { size_t n_max = (page_size-sizeof(malloc_state))/sizeof(revision_entry); if (ms->n_revisions >= n_max) { #ifndef _WIN32 @@ -447,36 +448,52 @@ void PgfDB::register_revision(object o) #endif throw pgf_error("Too many retained database revisions"); } - free_entry = &ms->revisions[ms->n_revisions++]; + found_entry = &ms->revisions[ms->n_revisions++]; } - free_entry->pid = pid; - free_entry->o = o; - free_entry->ref_count = 1; - free_entry->txn_id = ms->curr_txn_id; + found_entry->pid = pid; + found_entry->o = o; + found_entry->ref_count = 1; + found_entry->txn_id = txn_id; } #ifdef DEBUG_MEMORY_ALLOCATOR fprintf(stderr, " minimal %ld\n", ms->min_txn_id); #endif -done: #ifndef _WIN32 pthread_mutex_unlock(&ms->mutex); #else ReleaseMutex(hMutex); #endif + + return (found_entry - ms->revisions) + 1; } PGF_INTERNAL -void PgfDB::unregister_revision(object o) +void PgfDB::unregister_revision(object revision) { + if (revision == 0 || revision-1 >= ms->n_revisions) + throw pgf_error("Invalid revision"); + + revision_entry *entry = &ms->revisions[revision-1]; + if (entry->ref_count == 0) + throw pgf_error("Invalid revision"); + #ifndef _WIN32 pthread_mutex_lock(&ms->mutex); #else WaitForSingleObject(hMutex, INFINITE); #endif + if (--entry->ref_count == 0) { + // Maybe this was the last revision in the list. + // Decrement n_revisions if possible. + while (ms->revisions[ms->n_revisions-1].ref_count == 0){ + ms->n_revisions--; + } + } + #ifdef DEBUG_MEMORY_ALLOCATOR fprintf(stderr, "revisions"); #endif @@ -492,17 +509,7 @@ void PgfDB::unregister_revision(object o) entry->o & ~MALLOC_ALIGN_MASK, entry->ref_count); #endif - if (entry->pid == pid && entry->o == o) { - if (--entry->ref_count == 0) { - // Maybe this was the last revision in the list. - // Decrement n_revisions if possible. - while (ms->revisions[ms->n_revisions-1].ref_count == 0){ - ms->n_revisions--; - } - continue; // We skip the update of min_txn_id - } - } - + if (ms->min_txn_id > entry->txn_id) ms->min_txn_id = entry->txn_id; } @@ -1228,28 +1235,48 @@ void PgfDB::free_internal(object o, size_t bytes) } PGF_INTERNAL -ref PgfDB::revision2pgf(PgfRevision revision) +ref PgfDB::revision2pgf(PgfRevision revision, size_t *p_txn_id) { - if (revision == 0 || ref::get_tag(revision) != PgfPGF::tag) + if (revision == 0 || revision-1 >= ms->n_revisions) throw pgf_error("Invalid revision"); - ref pgf = ref::untagged(revision); + revision_entry *entry = &ms->revisions[revision-1]; + if (entry->ref_count == 0) + throw pgf_error("Invalid revision"); + + if (ref::get_tag(entry->o) != PgfPGF::tag) + throw pgf_error("Invalid revision"); + + ref pgf = ref::untagged(entry->o); if (pgf.as_object() >= top) throw pgf_error("Invalid revision"); + if (p_txn_id != NULL) + *p_txn_id = entry->txn_id; + return pgf; } PGF_INTERNAL -ref PgfDB::revision2concr(PgfConcrRevision revision) +ref PgfDB::revision2concr(PgfConcrRevision revision, size_t *p_txn_id) { - if (revision == 0 || ref::get_tag(revision) != PgfConcr::tag) + if (revision == 0 || revision-1 >= ms->n_revisions) throw pgf_error("Invalid revision"); - ref concr = ref::untagged(revision); + revision_entry *entry = &ms->revisions[revision-1]; + if (entry->ref_count == 0) + throw pgf_error("Invalid revision"); + + if (ref::get_tag(entry->o) != PgfConcr::tag) + throw pgf_error("Invalid revision"); + + ref concr = ref::untagged(entry->o); if (concr.as_object() >= top) throw pgf_error("Invalid revision"); + if (p_txn_id != NULL) + *p_txn_id = entry->txn_id; + return concr; } diff --git a/src/runtime/c/pgf/db.h b/src/runtime/c/pgf/db.h index 6d7e50412..e76ba90a2 100644 --- a/src/runtime/c/pgf/db.h +++ b/src/runtime/c/pgf/db.h @@ -115,11 +115,11 @@ public: PGF_INTERNAL_DECL void cleanup_revisions(); PGF_INTERNAL_DECL object get_active_revision(); - PGF_INTERNAL_DECL void register_revision(object o); + PGF_INTERNAL_DECL object register_revision(object o, txn_t txn_id); PGF_INTERNAL_DECL void unregister_revision(object o); - PGF_INTERNAL_DECL ref revision2pgf(PgfRevision revision); - PGF_INTERNAL_DECL ref revision2concr(PgfConcrRevision revision); + PGF_INTERNAL_DECL ref revision2pgf(PgfRevision revision, size_t *p_txn_id = NULL); + PGF_INTERNAL_DECL ref revision2concr(PgfConcrRevision revision, size_t *p_txn_id = NULL); PGF_INTERNAL_DECL void start_transaction(); PGF_INTERNAL_DECL void commit(object o); diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index 6f5cda890..f93e2888d 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -59,7 +59,7 @@ PgfDB *pgf_read_pgf(const char* fpath, PgfReader rdr(in); ref pgf = rdr.read_pgf(); - db->register_revision(*revision = pgf.tagged()); + *revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()); db->commit(pgf.as_object()); } @@ -106,7 +106,7 @@ PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path, PgfReader rdr(in); ref pgf = rdr.read_pgf(); - db->register_revision(*revision = pgf.tagged()); + *revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()); db->commit(pgf.as_object()); } @@ -141,7 +141,7 @@ PgfDB *pgf_read_ngf(const char *fpath, db->cleanup_revisions(); ref pgf = db->get_active_revision(); - db->register_revision(*revision = pgf.tagged()); + *revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()); } db->ref_count++; @@ -186,7 +186,7 @@ PgfDB *pgf_new_ngf(PgfText *abstract_name, pgf->abstract.funs = 0; pgf->abstract.cats = 0; pgf->concretes = 0; - db->register_revision(*revision = pgf.tagged()); + *revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()); db->commit(pgf.as_object()); } @@ -260,8 +260,7 @@ PGF_API_DECL void pgf_free_revision(PgfDB *db, PgfRevision revision) { try { - ref pgf = db->revision2pgf(revision); - db->unregister_revision(pgf.tagged()); + db->unregister_revision(revision); db->ref_count--; } catch (std::runtime_error& e) { // silently ignore and hope for the best @@ -276,8 +275,7 @@ void pgf_free_concr_revision(PgfDB *db, PgfConcrRevision revision) { try { DB_scope scope(db, READER_SCOPE); - ref concr = db->revision2concr(revision); - db->unregister_revision(concr.tagged()); + db->unregister_revision(revision); db->ref_count--; } catch (std::runtime_error& e) { // silently ignore and hope for the best @@ -316,6 +314,7 @@ void pgf_iter_categories(PgfDB *db, PgfRevision revision, struct PgfItorConcrHelper : PgfItor { PgfDB *db; + txn_t txn_id; PgfItor *itor; }; @@ -324,9 +323,9 @@ void iter_concretes_helper(PgfItor *itor, PgfText *key, object value, PgfExn *er { PgfItorConcrHelper* helper = (PgfItorConcrHelper*) itor; ref concr = value; - helper->db->register_revision(concr.tagged()); + object rev = helper->db->register_revision(concr.tagged(), helper->txn_id); helper->db->ref_count++; - helper->itor->fn(helper->itor, key, concr.tagged(), err); + helper->itor->fn(helper->itor, key, rev, err); } PGF_API @@ -334,13 +333,16 @@ void pgf_iter_concretes(PgfDB *db, PgfRevision revision, PgfItor *itor, PgfExn *err) { PGF_API_BEGIN { + size_t txn_id; + DB_scope scope(db, READER_SCOPE); - ref pgf = db->revision2pgf(revision); + ref pgf = db->revision2pgf(revision, &txn_id); PgfItorConcrHelper helper; - helper.fn = iter_concretes_helper; - helper.db = db; - helper.itor = itor; + helper.fn = iter_concretes_helper; + helper.db = db; + helper.txn_id = txn_id; + helper.itor = itor; namespace_iter(pgf->concretes, &helper, err); } PGF_API_END @@ -1075,10 +1077,10 @@ PgfRevision pgf_start_transaction(PgfDB *db, PgfRevision revision, new_pgf->abstract.cats = pgf->abstract.cats; new_pgf->concretes = pgf->concretes; - db->register_revision(new_pgf.tagged()); + object rev = db->register_revision(new_pgf.tagged(), PgfDB::get_txn_id()); db->ref_count++; - return new_pgf.tagged(); + return rev; } PGF_API_END return 0; @@ -1100,8 +1102,7 @@ PGF_API void pgf_rollback_transaction(PgfDB *db, PgfRevision revision) { try { - ref pgf = db->revision2pgf(revision); - db->unregister_revision(pgf.tagged()); + db->unregister_revision(revision); db->rollback(); db->ref_count--; } catch (std::runtime_error& e) { @@ -1118,11 +1119,12 @@ PgfRevision pgf_checkout_revision(PgfDB *db, PgfExn *err) PGF_API_BEGIN { DB_scope scope(db, WRITER_SCOPE); ref pgf = db->get_active_revision(); + object rev = 0; if (pgf != 0) { - db->register_revision(pgf.tagged()); + rev = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()); db->ref_count++; } - return pgf.tagged(); + return rev; } PGF_API_END return 0; @@ -1248,14 +1250,14 @@ PgfConcrRevision pgf_create_concrete(PgfDB *db, PgfRevision revision, concr->next = 0; memcpy(&concr->name, name, sizeof(PgfText)+name->size+1); - db->register_revision(concr.tagged()); + object rev = db->register_revision(concr.tagged(), PgfDB::get_txn_id()); Namespace concrs = namespace_insert(pgf->concretes, concr); pgf->concretes = concrs; db->ref_count++; - return concr.tagged(); + return rev; } PGF_API_END return 0; } @@ -1285,14 +1287,14 @@ PgfConcrRevision pgf_clone_concrete(PgfDB *db, PgfRevision revision, clone->next = 0; memcpy(&clone->name, name, sizeof(PgfText)+name->size+1); - db->register_revision(clone.tagged()); + object rev = db->register_revision(clone.tagged(), PgfDB::get_txn_id()); Namespace concrs = namespace_insert(pgf->concretes, clone); pgf->concretes = concrs; db->ref_count++; - return clone.tagged(); + return rev; } PGF_API_END return 0; }