Skip to content

Commit

Permalink
deal with rare race condition in balance cache
Browse files Browse the repository at this point in the history
When we create a balance cache, we lock the account, it is possible
for another thread to post a GLTransaction, still uncommitted, that
increases the last transaction ID.

To prevent this without enforcing expensive locks on every account
involving a GLTransaction post, we use a safe window (default to 1000,
can be overriden but we believe 1000 is a safe value for use cases like
jCard) when deciding the MaxID we use for a bcache entry.
  • Loading branch information
ar committed Jun 10, 2016
1 parent 50e4e55 commit 11d56e4
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 6 deletions.
14 changes: 10 additions & 4 deletions modules/minigl/src/main/java/org/jpos/gl/GLSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class GLSession {
public static final short[] LAYER_ZERO = new short[] { 0 };
public static final BigDecimal ZERO = new BigDecimal ("0.00");
public static final BigDecimal Z = new BigDecimal ("0");
private long SAFE_WINDOW = 1000L;

/**
* Construct a GLSession for a given user.
Expand Down Expand Up @@ -1066,10 +1067,9 @@ else if (acct.isFinalAccount()) {
balance[0] = chkp.getBalance();
txnCrit.add (Restrictions.gt ("postDate", chkp.getDate()));
}

} else {
BalanceCache bcache = getBalanceCache (journal, acct, layersCopy);
if (bcache != null) {
if (bcache != null && bcache.getRef() <= maxId) {
balance[0] = bcache.getBalance();
entryCrit.add (Restrictions.gt("id", bcache.getRef()));
}
Expand Down Expand Up @@ -1267,9 +1267,9 @@ else if (acct.isFinalAccount()) {
(Journal journal, Account acct, short[] layers)
throws HibernateException, GLException
{
return createBalanceCache (journal, acct, layers, getMaxGLEntryId());
return createBalanceCache (journal, acct, layers, getSafeMaxGLEntryId());
}
public BigDecimal createBalanceCache
private BigDecimal createBalanceCache
(Journal journal, Account acct, short[] layers, long maxId)
throws HibernateException, GLException
{
Expand Down Expand Up @@ -1768,6 +1768,12 @@ private long getMaxGLEntryId () {
GLEntry entry = (GLEntry) crit.uniqueResult();
return entry != null ? entry.getId() : 0L;
}
private long getSafeMaxGLEntryId() {
return Math.max (getMaxGLEntryId()-SAFE_WINDOW, 0L);
}
public void overrideSafeWindow (long l) {
this.SAFE_WINDOW = l;
}
private void recurseChildren (Account acct, List<Long> list) {
for (Account a : acct.getChildren()) {
if (a instanceof FinalAccount)
Expand Down
5 changes: 3 additions & 2 deletions modules/minigl/src/test/java/org/jpos/gl/BalanceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class BalanceTest extends TestBase {

public void setUp () throws Exception {
super.setUp();
gls.overrideSafeWindow(0L);
tj = gls.getJournal ("TestJournal");
cashUS = gls.getFinalAccount ("TestChart", "111");
cashPesos = gls.getAccount ("TestChart", "112");
Expand All @@ -58,8 +59,8 @@ public void testBalancesAfterCheckpoint() throws Exception {
}
public void testBalanceCache() throws Exception {
final Transaction tx1 = gls.beginTransaction();
gls.createBalanceCache (tj, root, GLSession.LAYER_ZERO, 10);
gls.createBalanceCache (tj, root, new short[] { 858 }, 10);
gls.createBalanceCache (tj, root, GLSession.LAYER_ZERO);
gls.createBalanceCache (tj, root, new short[] { 858 });
tx1.commit ();
}
public void testBalanceCache2() throws Exception {
Expand Down

0 comments on commit 11d56e4

Please # to comment.