forked from GitHub/gf-core
Revisions now correspond to revision_entry:s in the database.
This commit is contained in:
@@ -394,7 +394,7 @@ txn_t PgfDB::get_txn_id() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
void PgfDB::register_revision(object o)
|
object PgfDB::register_revision(object o, txn_t txn_id)
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pthread_mutex_lock(&ms->mutex);
|
pthread_mutex_lock(&ms->mutex);
|
||||||
@@ -403,7 +403,7 @@ void PgfDB::register_revision(object o)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
revision_entry *free_entry = NULL;
|
revision_entry *found_entry = NULL;
|
||||||
|
|
||||||
#ifdef DEBUG_MEMORY_ALLOCATOR
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
fprintf(stderr, "revisions");
|
fprintf(stderr, "revisions");
|
||||||
@@ -413,8 +413,8 @@ void PgfDB::register_revision(object o)
|
|||||||
for (size_t i = 0; i < ms->n_revisions; i++) {
|
for (size_t i = 0; i < ms->n_revisions; i++) {
|
||||||
revision_entry *entry = &ms->revisions[i];
|
revision_entry *entry = &ms->revisions[i];
|
||||||
if (entry->ref_count == 0) {
|
if (entry->ref_count == 0) {
|
||||||
if (free_entry == NULL)
|
if (found_entry == NULL)
|
||||||
free_entry = entry;
|
found_entry = entry;
|
||||||
} else {
|
} else {
|
||||||
#ifdef DEBUG_MEMORY_ALLOCATOR
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
fprintf(stderr, " %ld:%s(%016lx):%ld",
|
fprintf(stderr, " %ld:%s(%016lx):%ld",
|
||||||
@@ -427,7 +427,8 @@ void PgfDB::register_revision(object o)
|
|||||||
if (entry->pid == pid &&
|
if (entry->pid == pid &&
|
||||||
entry->o == o) {
|
entry->o == o) {
|
||||||
entry->ref_count++;
|
entry->ref_count++;
|
||||||
entry->txn_id = ms->curr_txn_id;
|
entry->txn_id = txn_id;
|
||||||
|
found_entry = entry;
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,7 +438,7 @@ void PgfDB::register_revision(object o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
if (free_entry == NULL) {
|
if (found_entry == NULL) {
|
||||||
size_t n_max = (page_size-sizeof(malloc_state))/sizeof(revision_entry);
|
size_t n_max = (page_size-sizeof(malloc_state))/sizeof(revision_entry);
|
||||||
if (ms->n_revisions >= n_max) {
|
if (ms->n_revisions >= n_max) {
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@@ -447,36 +448,52 @@ void PgfDB::register_revision(object o)
|
|||||||
#endif
|
#endif
|
||||||
throw pgf_error("Too many retained database revisions");
|
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;
|
found_entry->pid = pid;
|
||||||
free_entry->o = o;
|
found_entry->o = o;
|
||||||
free_entry->ref_count = 1;
|
found_entry->ref_count = 1;
|
||||||
free_entry->txn_id = ms->curr_txn_id;
|
found_entry->txn_id = txn_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_MEMORY_ALLOCATOR
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
fprintf(stderr, " minimal %ld\n", ms->min_txn_id);
|
fprintf(stderr, " minimal %ld\n", ms->min_txn_id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
done:
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pthread_mutex_unlock(&ms->mutex);
|
pthread_mutex_unlock(&ms->mutex);
|
||||||
#else
|
#else
|
||||||
ReleaseMutex(hMutex);
|
ReleaseMutex(hMutex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return (found_entry - ms->revisions) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PGF_INTERNAL
|
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
|
#ifndef _WIN32
|
||||||
pthread_mutex_lock(&ms->mutex);
|
pthread_mutex_lock(&ms->mutex);
|
||||||
#else
|
#else
|
||||||
WaitForSingleObject(hMutex, INFINITE);
|
WaitForSingleObject(hMutex, INFINITE);
|
||||||
#endif
|
#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
|
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||||
fprintf(stderr, "revisions");
|
fprintf(stderr, "revisions");
|
||||||
#endif
|
#endif
|
||||||
@@ -492,17 +509,7 @@ void PgfDB::unregister_revision(object o)
|
|||||||
entry->o & ~MALLOC_ALIGN_MASK,
|
entry->o & ~MALLOC_ALIGN_MASK,
|
||||||
entry->ref_count);
|
entry->ref_count);
|
||||||
#endif
|
#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)
|
if (ms->min_txn_id > entry->txn_id)
|
||||||
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
|
PGF_INTERNAL
|
||||||
ref<PgfPGF> PgfDB::revision2pgf(PgfRevision revision)
|
ref<PgfPGF> PgfDB::revision2pgf(PgfRevision revision, size_t *p_txn_id)
|
||||||
{
|
{
|
||||||
if (revision == 0 || ref<PgfPGF>::get_tag(revision) != PgfPGF::tag)
|
if (revision == 0 || revision-1 >= ms->n_revisions)
|
||||||
throw pgf_error("Invalid revision");
|
throw pgf_error("Invalid revision");
|
||||||
|
|
||||||
ref<PgfPGF> pgf = ref<PgfPGF>::untagged(revision);
|
revision_entry *entry = &ms->revisions[revision-1];
|
||||||
|
if (entry->ref_count == 0)
|
||||||
|
throw pgf_error("Invalid revision");
|
||||||
|
|
||||||
|
if (ref<PgfPGF>::get_tag(entry->o) != PgfPGF::tag)
|
||||||
|
throw pgf_error("Invalid revision");
|
||||||
|
|
||||||
|
ref<PgfPGF> pgf = ref<PgfPGF>::untagged(entry->o);
|
||||||
if (pgf.as_object() >= top)
|
if (pgf.as_object() >= top)
|
||||||
throw pgf_error("Invalid revision");
|
throw pgf_error("Invalid revision");
|
||||||
|
|
||||||
|
if (p_txn_id != NULL)
|
||||||
|
*p_txn_id = entry->txn_id;
|
||||||
|
|
||||||
return pgf;
|
return pgf;
|
||||||
}
|
}
|
||||||
|
|
||||||
PGF_INTERNAL
|
PGF_INTERNAL
|
||||||
ref<PgfConcr> PgfDB::revision2concr(PgfConcrRevision revision)
|
ref<PgfConcr> PgfDB::revision2concr(PgfConcrRevision revision, size_t *p_txn_id)
|
||||||
{
|
{
|
||||||
if (revision == 0 || ref<PgfConcr>::get_tag(revision) != PgfConcr::tag)
|
if (revision == 0 || revision-1 >= ms->n_revisions)
|
||||||
throw pgf_error("Invalid revision");
|
throw pgf_error("Invalid revision");
|
||||||
|
|
||||||
ref<PgfConcr> concr = ref<PgfConcr>::untagged(revision);
|
revision_entry *entry = &ms->revisions[revision-1];
|
||||||
|
if (entry->ref_count == 0)
|
||||||
|
throw pgf_error("Invalid revision");
|
||||||
|
|
||||||
|
if (ref<PgfPGF>::get_tag(entry->o) != PgfConcr::tag)
|
||||||
|
throw pgf_error("Invalid revision");
|
||||||
|
|
||||||
|
ref<PgfConcr> concr = ref<PgfConcr>::untagged(entry->o);
|
||||||
if (concr.as_object() >= top)
|
if (concr.as_object() >= top)
|
||||||
throw pgf_error("Invalid revision");
|
throw pgf_error("Invalid revision");
|
||||||
|
|
||||||
|
if (p_txn_id != NULL)
|
||||||
|
*p_txn_id = entry->txn_id;
|
||||||
|
|
||||||
return concr;
|
return concr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,11 +115,11 @@ public:
|
|||||||
PGF_INTERNAL_DECL void cleanup_revisions();
|
PGF_INTERNAL_DECL void cleanup_revisions();
|
||||||
|
|
||||||
PGF_INTERNAL_DECL object get_active_revision();
|
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 void unregister_revision(object o);
|
||||||
|
|
||||||
PGF_INTERNAL_DECL ref<PgfPGF> revision2pgf(PgfRevision revision);
|
PGF_INTERNAL_DECL ref<PgfPGF> revision2pgf(PgfRevision revision, size_t *p_txn_id = NULL);
|
||||||
PGF_INTERNAL_DECL ref<PgfConcr> revision2concr(PgfConcrRevision revision);
|
PGF_INTERNAL_DECL ref<PgfConcr> revision2concr(PgfConcrRevision revision, size_t *p_txn_id = NULL);
|
||||||
|
|
||||||
PGF_INTERNAL_DECL void start_transaction();
|
PGF_INTERNAL_DECL void start_transaction();
|
||||||
PGF_INTERNAL_DECL void commit(object o);
|
PGF_INTERNAL_DECL void commit(object o);
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ PgfDB *pgf_read_pgf(const char* fpath,
|
|||||||
PgfReader rdr(in);
|
PgfReader rdr(in);
|
||||||
ref<PgfPGF> pgf = rdr.read_pgf();
|
ref<PgfPGF> 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());
|
db->commit(pgf.as_object());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path,
|
|||||||
PgfReader rdr(in);
|
PgfReader rdr(in);
|
||||||
ref<PgfPGF> pgf = rdr.read_pgf();
|
ref<PgfPGF> 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());
|
db->commit(pgf.as_object());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ PgfDB *pgf_read_ngf(const char *fpath,
|
|||||||
db->cleanup_revisions();
|
db->cleanup_revisions();
|
||||||
|
|
||||||
ref<PgfPGF> pgf = db->get_active_revision();
|
ref<PgfPGF> pgf = db->get_active_revision();
|
||||||
db->register_revision(*revision = pgf.tagged());
|
*revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
db->ref_count++;
|
db->ref_count++;
|
||||||
@@ -186,7 +186,7 @@ PgfDB *pgf_new_ngf(PgfText *abstract_name,
|
|||||||
pgf->abstract.funs = 0;
|
pgf->abstract.funs = 0;
|
||||||
pgf->abstract.cats = 0;
|
pgf->abstract.cats = 0;
|
||||||
pgf->concretes = 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());
|
db->commit(pgf.as_object());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,8 +260,7 @@ PGF_API_DECL
|
|||||||
void pgf_free_revision(PgfDB *db, PgfRevision revision)
|
void pgf_free_revision(PgfDB *db, PgfRevision revision)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
ref<PgfPGF> pgf = db->revision2pgf(revision);
|
db->unregister_revision(revision);
|
||||||
db->unregister_revision(pgf.tagged());
|
|
||||||
db->ref_count--;
|
db->ref_count--;
|
||||||
} catch (std::runtime_error& e) {
|
} catch (std::runtime_error& e) {
|
||||||
// silently ignore and hope for the best
|
// silently ignore and hope for the best
|
||||||
@@ -276,8 +275,7 @@ void pgf_free_concr_revision(PgfDB *db, PgfConcrRevision revision)
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
DB_scope scope(db, READER_SCOPE);
|
DB_scope scope(db, READER_SCOPE);
|
||||||
ref<PgfConcr> concr = db->revision2concr(revision);
|
db->unregister_revision(revision);
|
||||||
db->unregister_revision(concr.tagged());
|
|
||||||
db->ref_count--;
|
db->ref_count--;
|
||||||
} catch (std::runtime_error& e) {
|
} catch (std::runtime_error& e) {
|
||||||
// silently ignore and hope for the best
|
// silently ignore and hope for the best
|
||||||
@@ -316,6 +314,7 @@ void pgf_iter_categories(PgfDB *db, PgfRevision revision,
|
|||||||
struct PgfItorConcrHelper : PgfItor
|
struct PgfItorConcrHelper : PgfItor
|
||||||
{
|
{
|
||||||
PgfDB *db;
|
PgfDB *db;
|
||||||
|
txn_t txn_id;
|
||||||
PgfItor *itor;
|
PgfItor *itor;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -324,9 +323,9 @@ void iter_concretes_helper(PgfItor *itor, PgfText *key, object value, PgfExn *er
|
|||||||
{
|
{
|
||||||
PgfItorConcrHelper* helper = (PgfItorConcrHelper*) itor;
|
PgfItorConcrHelper* helper = (PgfItorConcrHelper*) itor;
|
||||||
ref<PgfConcr> concr = value;
|
ref<PgfConcr> concr = value;
|
||||||
helper->db->register_revision(concr.tagged());
|
object rev = helper->db->register_revision(concr.tagged(), helper->txn_id);
|
||||||
helper->db->ref_count++;
|
helper->db->ref_count++;
|
||||||
helper->itor->fn(helper->itor, key, concr.tagged(), err);
|
helper->itor->fn(helper->itor, key, rev, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
PGF_API
|
PGF_API
|
||||||
@@ -334,13 +333,16 @@ void pgf_iter_concretes(PgfDB *db, PgfRevision revision,
|
|||||||
PgfItor *itor, PgfExn *err)
|
PgfItor *itor, PgfExn *err)
|
||||||
{
|
{
|
||||||
PGF_API_BEGIN {
|
PGF_API_BEGIN {
|
||||||
|
size_t txn_id;
|
||||||
|
|
||||||
DB_scope scope(db, READER_SCOPE);
|
DB_scope scope(db, READER_SCOPE);
|
||||||
ref<PgfPGF> pgf = db->revision2pgf(revision);
|
ref<PgfPGF> pgf = db->revision2pgf(revision, &txn_id);
|
||||||
|
|
||||||
PgfItorConcrHelper helper;
|
PgfItorConcrHelper helper;
|
||||||
helper.fn = iter_concretes_helper;
|
helper.fn = iter_concretes_helper;
|
||||||
helper.db = db;
|
helper.db = db;
|
||||||
helper.itor = itor;
|
helper.txn_id = txn_id;
|
||||||
|
helper.itor = itor;
|
||||||
|
|
||||||
namespace_iter(pgf->concretes, &helper, err);
|
namespace_iter(pgf->concretes, &helper, err);
|
||||||
} PGF_API_END
|
} PGF_API_END
|
||||||
@@ -1075,10 +1077,10 @@ PgfRevision pgf_start_transaction(PgfDB *db, PgfRevision revision,
|
|||||||
new_pgf->abstract.cats = pgf->abstract.cats;
|
new_pgf->abstract.cats = pgf->abstract.cats;
|
||||||
new_pgf->concretes = pgf->concretes;
|
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++;
|
db->ref_count++;
|
||||||
return new_pgf.tagged();
|
return rev;
|
||||||
} PGF_API_END
|
} PGF_API_END
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1100,8 +1102,7 @@ PGF_API
|
|||||||
void pgf_rollback_transaction(PgfDB *db, PgfRevision revision)
|
void pgf_rollback_transaction(PgfDB *db, PgfRevision revision)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
ref<PgfPGF> pgf = db->revision2pgf(revision);
|
db->unregister_revision(revision);
|
||||||
db->unregister_revision(pgf.tagged());
|
|
||||||
db->rollback();
|
db->rollback();
|
||||||
db->ref_count--;
|
db->ref_count--;
|
||||||
} catch (std::runtime_error& e) {
|
} catch (std::runtime_error& e) {
|
||||||
@@ -1118,11 +1119,12 @@ PgfRevision pgf_checkout_revision(PgfDB *db, PgfExn *err)
|
|||||||
PGF_API_BEGIN {
|
PGF_API_BEGIN {
|
||||||
DB_scope scope(db, WRITER_SCOPE);
|
DB_scope scope(db, WRITER_SCOPE);
|
||||||
ref<PgfPGF> pgf = db->get_active_revision();
|
ref<PgfPGF> pgf = db->get_active_revision();
|
||||||
|
object rev = 0;
|
||||||
if (pgf != 0) {
|
if (pgf != 0) {
|
||||||
db->register_revision(pgf.tagged());
|
rev = db->register_revision(pgf.tagged(), PgfDB::get_txn_id());
|
||||||
db->ref_count++;
|
db->ref_count++;
|
||||||
}
|
}
|
||||||
return pgf.tagged();
|
return rev;
|
||||||
} PGF_API_END
|
} PGF_API_END
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1248,14 +1250,14 @@ PgfConcrRevision pgf_create_concrete(PgfDB *db, PgfRevision revision,
|
|||||||
concr->next = 0;
|
concr->next = 0;
|
||||||
memcpy(&concr->name, name, sizeof(PgfText)+name->size+1);
|
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<PgfConcr> concrs =
|
Namespace<PgfConcr> concrs =
|
||||||
namespace_insert(pgf->concretes, concr);
|
namespace_insert(pgf->concretes, concr);
|
||||||
pgf->concretes = concrs;
|
pgf->concretes = concrs;
|
||||||
|
|
||||||
db->ref_count++;
|
db->ref_count++;
|
||||||
return concr.tagged();
|
return rev;
|
||||||
} PGF_API_END
|
} PGF_API_END
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1285,14 +1287,14 @@ PgfConcrRevision pgf_clone_concrete(PgfDB *db, PgfRevision revision,
|
|||||||
clone->next = 0;
|
clone->next = 0;
|
||||||
memcpy(&clone->name, name, sizeof(PgfText)+name->size+1);
|
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<PgfConcr> concrs =
|
Namespace<PgfConcr> concrs =
|
||||||
namespace_insert(pgf->concretes, clone);
|
namespace_insert(pgf->concretes, clone);
|
||||||
pgf->concretes = concrs;
|
pgf->concretes = concrs;
|
||||||
|
|
||||||
db->ref_count++;
|
db->ref_count++;
|
||||||
return clone.tagged();
|
return rev;
|
||||||
} PGF_API_END
|
} PGF_API_END
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user