mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-05-22 01:22:51 -06:00
cleanup transient revisions only after a transaction is opened
This commit is contained in:
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user