From 3a21267f1626f6571fd56dcf2e97c7ff51b6cbb3 Mon Sep 17 00:00:00 2001 From: cotton-ben Date: Fri, 3 Jul 2020 12:40:23 -0400 Subject: [PATCH] built a hack'd mock impl (incomplete) of off-heap ChronicleStampedLock.java --- .../revelations/ChronicleStampedLock.java | 110 +++++++++++++++++- .../acid/revelations/DirtyReadOffender.java | 13 ++- .../acid/revelations/DirtyReadVictim.java | 29 ++--- 3 files changed, 132 insertions(+), 20 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/ChronicleStampedLock.java b/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/ChronicleStampedLock.java index 8749e4631..9f2059899 100644 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/ChronicleStampedLock.java +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/ChronicleStampedLock.java @@ -3,7 +3,6 @@ package net.openhft.chronicle.map.fromdocs.acid.revelations; import net.openhft.chronicle.map.ChronicleMap; import net.openhft.chronicle.map.fromdocs.BondVOInterface; - import java.io.IOException; import java.util.concurrent.locks.StampedLock; @@ -16,4 +15,113 @@ import static net.openhft.chronicle.values.Values.newNativeReference; */ public class ChronicleStampedLock extends StampedLock { + ChronicleMap chm; + BondVOInterface offHeapLock = newNativeReference(BondVOInterface.class); + BondVOInterface lastWriterT = newNativeReference(BondVOInterface.class); + { + try { + chm = DirtyReadTolerance.offHeap( + "C:\\Users\\buddy\\dev\\shm\\OPERAND_CHRONICLE_MAP" + ); + chm.acquireUsing("Stamp ", offHeapLock); //mock'd + chm.acquireUsing("LastWriterTime ", lastWriterT); + System.out.println( + " ,@t=" + System.currentTimeMillis() + + " ChronicleStampedLock constructed" + + "," + ); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public long tryOptimisticRead() { + long l = 0; + + offHeapLock = chm.get("Stamp "); + do { + l = offHeapLock.getEntryLockState(); + } while (l < 0L); // wait until any holding Writer unlocks + + offHeapLock.setEntryLockState(0L); + + chm.put("Stamp ", offHeapLock); + System.out.println( + " ,@t=" + System.currentTimeMillis() + + " ChronicleStampedLock tryOptmisticRead() returned stamp=" + + l + + "," + ); + long t = System.currentTimeMillis(); + return (t); + } + + @Override + public boolean validate(long stamp) { + offHeapLock = chm.get("Stamp "); + lastWriterT = chm.get("LastWriterTime "); + boolean ret = false; + if (lastWriterT.getEntryLockState() > stamp) { + ret = Boolean.FALSE; + } else + ret = Boolean.TRUE; + System.out.println( + " ,@t=" + System.currentTimeMillis() + + " ChronicleStampedLock validate(" + + stamp + ") returned =[" + + ret + "] " + + "," + ); + System.out.println( + " ,@t=" + System.currentTimeMillis() + + " ChronicleStampedLock LastWriterT=[" + + lastWriterT.getEntryLockState() + "] " + + "," + ); + return ret; + } + + @Override + public long tryWriteLock() { + long l = 0; + + offHeapLock = chm.get("Stamp "); + lastWriterT = chm.get("LastWriterTime "); + do { + l = offHeapLock.getEntryLockState(); + } while (l != 0L); + + long t = System.currentTimeMillis(); + offHeapLock.setEntryLockState(-t); //negative ==> Writer holds StampedLock + lastWriterT.setEntryLockState(t); + chm.put("Stamp ", offHeapLock); + chm.put("LastWriterTime ", lastWriterT); + System.out.println( + " ,@t=" + t + + " ChronicleStampedLock tryWriteLock() returned stamp=" + + offHeapLock.getEntryLockState() + + "," + ); + return (offHeapLock.getEntryLockState()); + } + + @Override + public void unlockWrite(long stamp) { + System.out.println( + " ,@t=" + System.currentTimeMillis() + + " ChronicleStampedLock unlockWrite(" + stamp + ") unlocking..," + ); + offHeapLock = chm.get("Stamp "); + offHeapLock.setEntryLockState(0L); + chm.put("Stamp ", offHeapLock); + System.out.println( + " ,@t=" + System.currentTimeMillis() + + " ChronicleStampedLock unlockWrite(" + + stamp + + ") unlocked. set to Zero" + + "," + ); + } + } diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/DirtyReadOffender.java b/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/DirtyReadOffender.java index 50ea01e4d..c756c2c81 100644 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/DirtyReadOffender.java +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/DirtyReadOffender.java @@ -24,10 +24,11 @@ public class DirtyReadOffender { " @t=" + System.currentTimeMillis() + " DirtyReadOffender established chm " ); + StampedLock offHeapLock = new ChronicleStampedLock(); BondVOInterface bond = newNativeReference(BondVOInterface.class); - BondVOInterface cslMock = newNativeReference(BondVOInterface.class); + //BondVOInterface cslMock = newNativeReference(BondVOInterface.class); chm.acquireUsing("369604101", bond); - chm.acquireUsing("Offender ", cslMock); // mock ChronicleStampLock + //chm.acquireUsing("Offender ", cslMock); // mock ChronicleStampLock System.out.println( " @t=" + System.currentTimeMillis() + " DirtyReadOffender sleeping "+sleepT+" seconds " @@ -49,7 +50,7 @@ public class DirtyReadOffender { " @t=" + System.currentTimeMillis() + " DirtyReadOffender ACQUIRING offHeapLock.writeLock();" ); - StampedLock offHeapLock = new ChronicleStampedLock(); + while ((stamp = offHeapLock.tryWriteLock()) == 0) { ; } @@ -66,8 +67,8 @@ public class DirtyReadOffender { ); bond.setCoupon(newCoupon); chm.put("369604101", bond); - cslMock.setEntryLockState(System.currentTimeMillis()); //mock'd - chm.put("Offender ",cslMock); //mock'd + //cslMock.setEntryLockState(System.currentTimeMillis()); //mock'd + // chm.put("Offender ",cslMock); //mock'd System.out.println( " @t=" + System.currentTimeMillis() + " DirtyReadOffender coupon=["+ @@ -79,7 +80,7 @@ public class DirtyReadOffender { System.out.println( " @t=" + System.currentTimeMillis() + " DirtyReadOffender called " + - "offHeapLock.unlockWrite(stamp);" + "offHeapLock.unlockWrite("+stamp+");" ); } /** diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/DirtyReadVictim.java b/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/DirtyReadVictim.java index eab91325b..53d80ed70 100644 --- a/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/DirtyReadVictim.java +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/acid/revelations/DirtyReadVictim.java @@ -14,7 +14,6 @@ public class DirtyReadVictim { try { String isoLevel = args[0]; long sleepMock = Long.parseLong(args[1]); - /** * ben.cotton@rutgers.edu START */ @@ -24,23 +23,26 @@ public class DirtyReadVictim { ); Double coupon = 0.00; BondVOInterface bond = newNativeReference(BondVOInterface.class); - BondVOInterface cslMock = newNativeReference(BondVOInterface.class); //mock'd + //BondVOInterface cslMock = newNativeReference(BondVOInterface.class); //mock'd long stamp = 0; System.out.println( " ,,@t=" + System.currentTimeMillis() + " DirtyReadVictim ENTERING offHeapLock.tryOptimisticRead()" ); StampedLock offHeapLock = new ChronicleStampedLock(); - while ((stamp = offHeapLock.tryOptimisticRead()) == 0) { + while ((stamp = offHeapLock.tryOptimisticRead()) < 0) { ; } System.out.println( " ,,@t=" + System.currentTimeMillis() + - " DirtyReadVictim ENTERED offHeapLock.tryOptimisticRead()" + " DirtyReadVictim ENTERED offHeapLock.tryOptimisticRead() " + + " stamp=[" + + stamp + + "]" ); try { chm.acquireUsing("369604101", bond); - chm.acquireUsing("Offender ", cslMock); //mock'd + //chm.acquireUsing("Offender ", cslMock); //mock'd System.out.println( " ,,@t=" + System.currentTimeMillis() + " DirtyReadVictim calling chm.get('369604101').getCoupon()" @@ -53,24 +55,22 @@ public class DirtyReadVictim { ); System.out.println( " ,,@t=" + System.currentTimeMillis() + - " DirtyReadVictim sleeping "+sleepMock+" seconds" + " DirtyReadVictim sleeping " + sleepMock + " seconds" ); - cslMock.setEntryLockState(0); - chm.put("Offender ", cslMock); //mock'd + Thread.sleep(sleepMock * 1_000); System.out.println( " ,,@t=" + System.currentTimeMillis() + " DirtyReadVictim awakening" ); - //cslMock = (BondVOInterface) chm.get("Offender "); //mock'd - cslMock = (BondVOInterface) chm.get("Offender "); //mock'd } finally { - if (offHeapLock.validate(stamp) && (cslMock.getEntryLockState() == 0)) { + if (offHeapLock.validate(stamp)) { System.out.println( " ,,@t=" + System.currentTimeMillis() + " DirtyReadVictim OPTIMISTICALLY_READ coupon=" + - coupon + " " + coupon + " " + + "stamp = [" + stamp + "]" ); } else { @@ -78,13 +78,16 @@ public class DirtyReadVictim { " ,,@t=" + System.currentTimeMillis() + " DirtyReadVictim FAILED offHeapLock.validate(stamp) " + " must apply PESSIMISTIC_POLICY (dirty read endured)" + - " coupon=[" + coupon + "] is *DIRTY*. " + " coupon=[" + coupon + "] is *DIRTY*. " + + " stamp = [" + stamp + "]" ); + } System.out.println( " ,,@t=" + System.currentTimeMillis() + " DirtyReadVictim EXITED offHeapLock.tryOptimisticRead()" ); + } /** * ben.cotton@rutgers.edu END