From 8f8a94c28e26c0b46a43e89d566c941994645de7 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 13 Apr 2014 23:25:31 -0500 Subject: Add the concept of "deferred postings" This is pretty much exclusively for allowing one to use balance assertions with replicated transactions across multiple files. --- src/account.cc | 15 +++++++++++++++ src/account.h | 17 ++++++++++------- src/journal.cc | 17 ++++++++++++++++- src/post.h | 1 + src/textual.cc | 6 ++++++ src/xact.cc | 5 ++++- 6 files changed, 52 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/account.cc b/src/account.cc index 4b3a4e97..a702cf11 100644 --- a/src/account.cc +++ b/src/account.cc @@ -139,6 +139,21 @@ void account_t::add_post(post_t * post) } } +void account_t::add_deferred_post(const string& uuid, post_t * post) +{ + if (! deferred_posts) + deferred_posts = deferred_posts_map_t(); + + deferred_posts_map_t::iterator i = deferred_posts->find(uuid); + if (i == deferred_posts->end()) { + posts_list lst; + lst.push_back(post); + deferred_posts->insert(deferred_posts_map_t::value_type(uuid, lst)); + } else { + (*i).second.push_back(post); + } +} + bool account_t::remove_post(post_t * post) { // It's possible that 'post' wasn't yet in this account, but try to diff --git a/src/account.h b/src/account.h index f6f764cc..3ce93fba 100644 --- a/src/account.h +++ b/src/account.h @@ -52,6 +52,7 @@ class post_t; typedef std::list posts_list; typedef std::map accounts_map; +typedef std::map deferred_posts_map_t; class account_t : public supports_flags<>, public scope_t { @@ -61,13 +62,14 @@ class account_t : public supports_flags<>, public scope_t #define ACCOUNT_GENERATED 0x04 // account never actually existed public: - account_t * parent; - string name; - optional note; - unsigned short depth; - accounts_map accounts; - posts_list posts; - optional value_expr; + account_t * parent; + string name; + optional note; + unsigned short depth; + accounts_map accounts; + posts_list posts; + optional deferred_posts; + optional value_expr; mutable string _fullname; #if DOCUMENT_MODEL @@ -136,6 +138,7 @@ public: } void add_post(post_t * post); + void add_deferred_post(const string& uuid, post_t * post); bool remove_post(post_t * post); posts_list::iterator posts_begin() { diff --git a/src/journal.cc b/src/journal.cc index ef35722c..94a535d7 100644 --- a/src/journal.cc +++ b/src/journal.cc @@ -385,9 +385,24 @@ bool journal_t::add_xact(xact_t * xact) // will have been performed by extend_xact, so asserts can still be // applied to it. if (optional ref = xact->get_tag(_("UUID"))) { + std::string uuid = ref->to_string(); std::pair result - = checksum_map.insert(checksum_map_t::value_type(ref->to_string(), xact)); + = checksum_map.insert(checksum_map_t::value_type(uuid, xact)); if (! result.second) { + // This UUID has been seen before; apply any postings which the + // earlier version may have deferred. + foreach (post_t * post, xact->posts) { + account_t * acct = post->account; + if (acct->deferred_posts) { + deferred_posts_map_t::iterator + i = acct->deferred_posts->find(uuid); + if (i != acct->deferred_posts->end()) { + foreach (post_t * rpost, (*i).second) + acct->add_post(rpost); + } + } + } + // jww (2012-02-27): Confirm that the xact in // (*result.first).second is exact match in its significant // details to xact. diff --git a/src/post.h b/src/post.h index 379844dc..51a75ade 100644 --- a/src/post.h +++ b/src/post.h @@ -60,6 +60,7 @@ public: #define POST_COST_FIXATED 0x0200 // cost is fixed using = indicator #define POST_COST_VIRTUAL 0x0400 // cost is virtualized: (@) #define POST_ANONYMIZED 0x0800 // a temporary, anonymous posting +#define POST_DEFERRED 0x1000 // the account was specified with xact_t * xact; // only set for posts of regular xacts account_t * account; diff --git a/src/textual.cc b/src/textual.cc index fa84d6de..6f8f0492 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -1432,6 +1432,12 @@ post_t * instance_t::parse_post(char * line, } p++; e--; } + else if (*p == '<' && *(e - 1) == '>') { + post->add_flags(POST_DEFERRED); + DEBUG("textual.parse", "line " << context.linenum << ": " + << "Parsed a deferred account name"); + p++; e--; + } string name(p, static_cast(e - p)); DEBUG("textual.parse", "line " << context.linenum << ": " diff --git a/src/xact.cc b/src/xact.cc index 58d2ac33..c7a9c6e3 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -393,7 +393,10 @@ bool xact_base_t::finalize() some_null = true; } - post->account->add_post(post); + if (post->has_flags(POST_DEFERRED)) + post->account->add_deferred_post(id(), post); + else + post->account->add_post(post); post->xdata().add_flags(POST_EXT_VISITED); post->account->xdata().add_flags(ACCOUNT_EXT_VISITED); -- cgit v1.2.3