Skip to content

Commit 84b21b1

Browse files
committed
Bug 31834278: Improve recovering from persistence by defering contentious maintenance tasks (merge 14.1.1 -> ce/14.1.1 @81396)
[git-p4: depot-paths = "//dev/coherence-ce/release/coherence-ce-v14.1.1.0/": change = 81397]
1 parent 5290616 commit 84b21b1

File tree

6 files changed

+113
-18
lines changed

6 files changed

+113
-18
lines changed

prj/coherence-core/src/main/java/com/oracle/coherence/persistence/PersistentStore.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import com.oracle.coherence.common.base.Collector;
1010

11+
import com.tangosol.util.NullImplementation;
12+
1113
/**
1214
* PersistentStore represents a persistence facility to store and recover
1315
* key/value pairs. Each key-value pair is namespaced by a numeric "extent"
@@ -91,6 +93,22 @@ public interface PersistentStore<R>
9193
*/
9294
public long[] extents();
9395

96+
/**
97+
* Suggest to this PersistentStore that the caller requires exclusive access
98+
* to this store until {@link AutoCloseable#close() close} is called on the
99+
* returned {@link AutoCloseable}.
100+
* <p>
101+
* Note: the caller <b>must</b> call {@link AutoCloseable#close() close} on
102+
* the returned object
103+
*
104+
* @return an {@link AutoCloseable} object that <b>requires</b> close to be
105+
* called on it when exclusive access is no longer needed
106+
*/
107+
public default AutoCloseable exclusively()
108+
{
109+
return NullImplementation.getAutoCloseable();
110+
}
111+
94112
// ----- store operations -----------------------------------------------
95113

96114
/**

prj/coherence-core/src/main/java/com/tangosol/persistence/AbstractPersistenceManager.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
package com.tangosol.persistence;
88

99
import com.oracle.coherence.common.base.Collector;
10-
1110
import com.oracle.coherence.common.base.Blocking;
11+
1212
import com.oracle.coherence.persistence.AsyncPersistenceException;
1313
import com.oracle.coherence.persistence.ConcurrentAccessException;
1414
import com.oracle.coherence.persistence.FatalAccessException;
@@ -61,6 +61,7 @@
6161

6262
import java.util.concurrent.locks.ReadWriteLock;
6363
import java.util.concurrent.locks.ReentrantReadWriteLock;
64+
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
6465

6566
/**
6667
* Abstract implementation of a ReadBuffer-based PersistentManager.
@@ -1122,6 +1123,16 @@ public long[] extents()
11221123
return al;
11231124
}
11241125

1126+
@Override
1127+
public AutoCloseable exclusively()
1128+
{
1129+
ensureReady();
1130+
1131+
lockWrite();
1132+
1133+
return instantiateExclusiveClosable();
1134+
}
1135+
11251136
/**
11261137
* {@inheritDoc}
11271138
*/
@@ -1371,7 +1382,7 @@ public void abort(Object oToken)
13711382
{
13721383
// guard against any unexpected throwable
13731384
CacheFactory.log("Caught an exception while aborting transaction for token \""
1374-
+ oToken + "\": " + printStackTrace(e), CacheFactory.LOG_ERR);
1385+
+ oToken + "\": " + printStackTrace(e), CacheFactory.LOG_QUIET);
13751386
}
13761387
}
13771388
}
@@ -1648,6 +1659,28 @@ protected void setState(int nState)
16481659
}
16491660
}
16501661

1662+
/**
1663+
* Return true if this store is in exclusive mode.
1664+
*
1665+
* @return true if this store is in exclusive mode
1666+
*/
1667+
protected boolean isExclusive()
1668+
{
1669+
return ((WriteLock) f_lock.writeLock()).isHeldByCurrentThread();
1670+
}
1671+
1672+
/**
1673+
* Return an {@link AutoCloseable} that will transition this PersistentStore
1674+
* out of exclusive mode.
1675+
*
1676+
* @return an AutoCloseable that will transition this PersistentStore
1677+
* out of exclusive mode
1678+
*/
1679+
protected AutoCloseable instantiateExclusiveClosable()
1680+
{
1681+
return this::unlockWrite;
1682+
}
1683+
16511684
// ----- Object methods ---------------------------------------------
16521685

16531686
/**

prj/coherence-core/src/main/java/com/tangosol/persistence/SafePersistenceWrappers.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,23 @@ public long[] extents()
825825
return super.extents();
826826
}
827827

828+
/**
829+
* {@inheritDoc}
830+
*/
831+
public AutoCloseable exclusively()
832+
{
833+
try
834+
{
835+
return getStore().exclusively();
836+
}
837+
catch (Throwable t)
838+
{
839+
onException((T) t);
840+
}
841+
842+
return super.exclusively();
843+
}
844+
828845
/**
829846
* {@inheritDoc}
830847
*/

prj/coherence-core/src/main/java/com/tangosol/persistence/bdb/BerkeleyDBManager.java

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,7 @@ public void commitInternal(Object oToken)
819819
{
820820
throw ensurePersistenceException(e);
821821
}
822+
maintainEnvironment();
822823
}
823824

824825
/**
@@ -835,6 +836,7 @@ public void abortInternal(Object oToken)
835836
{
836837
throw ensurePersistenceException(e);
837838
}
839+
maintainEnvironment();
838840
}
839841

840842
// ----- helpers ----------------------------------------------------
@@ -1083,6 +1085,18 @@ protected Transaction ensureTransaction(Object oToken)
10831085
throw new IllegalArgumentException("illegal token: " + oToken);
10841086
}
10851087

1088+
@Override
1089+
protected AutoCloseable instantiateExclusiveClosable()
1090+
{
1091+
AutoCloseable parent = super.instantiateExclusiveClosable();
1092+
return () ->
1093+
{
1094+
parent.close();
1095+
1096+
maintainEnvironment();
1097+
};
1098+
}
1099+
10861100
/**
10871101
* Perform any necessary maintenance of the underlying BerkeleyDB
10881102
* environment.
@@ -1094,38 +1108,41 @@ protected void maintainEnvironment(ReadBuffer bufKey, ReadBuffer bufValue)
10941108
{
10951109
if (MAINTENANCE_ENABLED)
10961110
{
1097-
// calculate the approximate number of bytes written to the
1098-
// environment by the current operation
1099-
int cbCurrent = bufKey.length();
1100-
if (bufValue != null)
1101-
{
1102-
cbCurrent += bufValue.length();
1103-
}
1104-
1105-
// update the approximate running count of bytes written
1106-
long cbLast = f_cbWritten.getAndAdd(cbCurrent);
1107-
long cbWritten = cbLast + cbCurrent;
1111+
// calculate the approximate number of bytes written to the environment
1112+
// by the current operation and update the running count
1113+
f_cbWritten.getAndAdd(bufKey.length() + (bufValue == null ? 0 : bufValue.length()));
1114+
}
1115+
}
11081116

1117+
/**
1118+
* Perform any necessary maintenance of the underlying BerkeleyDB
1119+
* environment.
1120+
*/
1121+
protected void maintainEnvironment()
1122+
{
1123+
if (MAINTENANCE_ENABLED)
1124+
{
11091125
// determine if maintenance is already in progress
1110-
if (m_fMaintenanceScheduled)
1126+
if (isExclusive() || m_fMaintenanceScheduled)
11111127
{
11121128
// nothing to do
11131129
return;
11141130
}
11151131

1132+
long cbWritten = f_cbWritten.get();
1133+
11161134
// determine if it's time to checkpoint the environment
11171135
boolean fCheckpointRequired = m_cbLastCheckpoint >= CHECKPOINT_INTERVAL;
11181136

11191137
// determine if it's time to clean the environment
11201138
boolean fCleanRequired = m_cbLastClean >= CLEAN_INTERVAL;
11211139

11221140
// determine if it's time to compress the environment
1123-
boolean fCompressRequired = getSafeTimeMillis()
1124-
>= m_ldtLastCompress + COMPRESS_INTERVAL;
1141+
boolean fCompressRequired = getSafeTimeMillis() >= m_ldtLastCompress + COMPRESS_INTERVAL;
11251142

11261143
// determine if it's time to update statistics
11271144
boolean fStatsRequired = f_cChecks.incrementAndGet() == STATS_CHECK_COUNT ||
1128-
(cbWritten >= STATS_CHECK_BYTES && cbLast < STATS_CHECK_BYTES);
1145+
cbWritten >= STATS_CHECK_BYTES;
11291146

11301147
if (fCheckpointRequired || fCleanRequired || fCompressRequired || fStatsRequired)
11311148
{

prj/coherence-core/src/main/java/com/tangosol/util/NullImplementation.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,13 +423,23 @@ public static <R> PersistentStore<R> getPersistentStore(Class<R> clz)
423423
/**
424424
* Factory method: Obtain a null implementation of a {@link ResourceRegistry}.
425425
*
426-
* @return an implementation of ResourceRegistry that does nothing.
426+
* @return an implementation of ResourceRegistry that does nothing
427427
*/
428428
public static ResourceRegistry getResourceRegistry()
429429
{
430430
return NullResourceRegistry.INSTANCE;
431431
}
432432

433+
/**
434+
* Factory method: Obtain a null implementation of an {@link AutoCloseable}.
435+
*
436+
* @return an implementation of an AutoCloseable that does nothing
437+
*/
438+
public static AutoCloseable getAutoCloseable()
439+
{
440+
return () -> {};
441+
}
442+
433443
// ----- inner classes ----------------------------------------------
434444

435445
/**

0 commit comments

Comments
 (0)