Skip to content

Commit 2470c73

Browse files
committed
Enhancement Request 36481554 - [36431573->24.09] ENH: Improve cleaning persistence files on disk to reflect to the cache sizes (merge main -> ce/main @ 108275)
[git-p4: depot-paths = "//dev/coherence-ce/main/": change = 108299]
1 parent bb95291 commit 2470c73

File tree

6 files changed

+288
-4
lines changed

6 files changed

+288
-4
lines changed

prj/coherence-core-components/src/main/java/com/tangosol/coherence/component/util/daemon/queueProcessor/service/grid/PartitionedService.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,11 @@ public abstract class PartitionedService
633633
private int __m_TransferThreshold;
634634
private static com.tangosol.util.ListMap __mapChildren;
635635

636+
/**
637+
* The interval (in milliseconds) between scheduling two maintenance tasks.
638+
*/
639+
protected static final int MAINTENANCE_INTERVAL = 120000;
640+
636641
// Static initializer
637642
static
638643
{
@@ -2299,6 +2304,14 @@ public void exitPartition(int nPartition)
22992304
ctrlPart.exit();
23002305
}
23012306
}
2307+
2308+
protected void scheduleEnvironmentMaintenance()
2309+
{
2310+
if (isRunning())
2311+
{
2312+
getDaemonPool().schedule(new MaintenanceTask(), MAINTENANCE_INTERVAL);
2313+
}
2314+
}
23022315

23032316
/**
23042317
* Finalize the startup sequence for this service member. This method is
@@ -7100,6 +7113,10 @@ public void onServiceStarted()
71007113
setPartitionEvents(new LocalCache(LocalCache.DEFAULT_UNITS, 3600000));
71017114

71027115
finalizeStartup();
7116+
if (isActivePersistence())
7117+
{
7118+
scheduleEnvironmentMaintenance();
7119+
}
71037120
}
71047121

71057122
// Declared at the super level
@@ -33780,4 +33797,30 @@ protected void onCompletion()
3378033797
}
3378133798
}
3378233799
}
33800+
33801+
// ----- inner class: MaintenanceTask -------------------------------
33802+
33803+
/**
33804+
* Task used to perform necessary maintenance of the underlying environment.
33805+
*/
33806+
public class MaintenanceTask implements Runnable
33807+
{
33808+
// ----- Runnable interface -----------------------------------------
33809+
33810+
public void run()
33811+
{
33812+
try
33813+
{
33814+
PersistenceManager manager = getPersistenceManager();
33815+
if (manager != null)
33816+
{
33817+
manager.maintainEnvironment();
33818+
}
33819+
}
33820+
finally
33821+
{
33822+
scheduleEnvironmentMaintenance();
33823+
}
33824+
}
33825+
}
3378333826
}

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
2-
* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2+
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
33
*
44
* Licensed under the Universal Permissive License v 1.0 as shown at
5-
* http://oss.oracle.com/licenses/upl.
5+
* https://oss.oracle.com/licenses/upl.
66
*/
77
package com.oracle.coherence.persistence;
88

@@ -283,4 +283,11 @@ public default void writeSafe(String sId)
283283
* @return a PersistenceTools implementation
284284
*/
285285
public PersistenceTools getPersistenceTools();
286+
287+
/**
288+
* Perform any necessary maintenance of the underlying environment.
289+
*/
290+
public default void maintainEnvironment()
291+
{
292+
}
286293
}

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2022, Oracle and/or its affiliates.
2+
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
33
*
44
* Licensed under the Universal Permissive License v 1.0 as shown at
55
* https://oss.oracle.com/licenses/upl.
@@ -713,6 +713,21 @@ public void release()
713713
}
714714
}
715715

716+
/**
717+
* {@inheritDoc}
718+
*/
719+
public void maintainEnvironment()
720+
{
721+
try
722+
{
723+
getManager().maintainEnvironment();
724+
}
725+
catch (Throwable t)
726+
{
727+
onException((T) t);
728+
}
729+
}
730+
716731
// ----- Object methods ---------------------------------------------
717732

718733
/**

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

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2022, Oracle and/or its affiliates.
2+
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
33
*
44
* Licensed under the Universal Permissive License v 1.0 as shown at
55
* https://oss.oracle.com/licenses/upl.
@@ -151,6 +151,16 @@ protected String getStorageFormat()
151151
return "BDB";
152152
}
153153

154+
@Override
155+
public synchronized void maintainEnvironment()
156+
{
157+
Map<String, BerkeleyDBStore> map = getPersistentStoreMap();
158+
for (BerkeleyDBStore store : map.values())
159+
{
160+
store.maintainEnvironment();
161+
}
162+
}
163+
154164
/**
155165
* {@inheritDoc}
156166
*/
@@ -687,6 +697,7 @@ protected void moveExtentInternal(long lOldExtentId, long lNewExtentId)
687697
protected void truncateExtentInternal(long lExtentId)
688698
{
689699
truncateDatabase(lExtentId);
700+
m_ltdLastErase = getSafeTimeMillis();
690701
}
691702

692703
/**
@@ -1150,6 +1161,10 @@ protected void maintainEnvironment(ReadBuffer bufKey, ReadBuffer bufValue)
11501161
// calculate the approximate number of bytes written to the environment
11511162
// by the current operation and update the running count
11521163
f_cbWritten.getAndAdd(bufKey.length() + (bufValue == null ? 0 : bufValue.length()));
1164+
if (bufValue == null)
1165+
{
1166+
m_ltdLastErase = getSafeTimeMillis();
1167+
}
11531168
}
11541169
}
11551170

@@ -1183,6 +1198,12 @@ protected void maintainEnvironment()
11831198
boolean fStatsRequired = f_cChecks.incrementAndGet() == STATS_CHECK_COUNT ||
11841199
cbWritten >= STATS_CHECK_BYTES;
11851200

1201+
if (m_ltdLastErase != 0 && (getSafeTimeMillis() > m_ltdLastErase + 60000))
1202+
{
1203+
fCheckpointRequired = true;
1204+
fCleanRequired = true;
1205+
}
1206+
11861207
if (fCheckpointRequired || fCleanRequired || fCompressRequired || fStatsRequired)
11871208
{
11881209
synchronized (this)
@@ -1343,6 +1364,10 @@ public Object getAssociatedKey()
13431364
protected void reset()
13441365
{
13451366
BerkeleyDBStore store = BerkeleyDBStore.this;
1367+
if (f_fCheckpoint && f_fClean)
1368+
{
1369+
store.m_ltdLastErase = 0;
1370+
}
13461371
store.f_cChecks.set(0);
13471372
store.f_cbWritten.set(0L);
13481373
store.m_fMaintenanceScheduled = false;
@@ -1424,6 +1449,11 @@ protected void reset()
14241449
* BerkeleyDB environment since statistics were last updated.
14251450
*/
14261451
protected final AtomicLong f_cbWritten = new AtomicLong();
1452+
1453+
/**
1454+
* The last time a key was erased.
1455+
*/
1456+
protected volatile long m_ltdLastErase;
14271457
}
14281458

14291459

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Universal Permissive License v 1.0 as shown at
5+
* https://oss.oracle.com/licenses/upl.
6+
*/
7+
package persistence;
8+
9+
import com.oracle.bedrock.testsupport.deferred.Eventually;
10+
11+
import com.oracle.coherence.testing.AbstractFunctionalTest;
12+
13+
import com.tangosol.io.FileHelper;
14+
15+
import com.tangosol.net.CacheFactory;
16+
import com.tangosol.net.NamedCache;
17+
18+
import java.io.File;
19+
import java.io.IOException;
20+
21+
import java.util.concurrent.TimeUnit;
22+
23+
import org.junit.AfterClass;
24+
import org.junit.Before;
25+
import org.junit.BeforeClass;
26+
import org.junit.Test;
27+
28+
import static com.oracle.bedrock.deferred.DeferredHelper.within;
29+
import static org.hamcrest.CoreMatchers.is;
30+
import static org.hamcrest.number.OrderingComparison.lessThan;
31+
32+
/**
33+
* Test BerkeleyDB environment maintenance.
34+
*/
35+
public class BerkeleyDBCleanupTests
36+
extends AbstractFunctionalTest
37+
{
38+
39+
// ----- test lifecycle -------------------------------------------------
40+
41+
/**
42+
* Initialize the test class.
43+
*/
44+
@BeforeClass
45+
public static void _startup()
46+
{
47+
try
48+
{
49+
s_fileActive = FileHelper.createTempDir();
50+
s_fileSnapshot = FileHelper.createTempDir();
51+
s_fileTrash = FileHelper.createTempDir();
52+
}
53+
catch (IOException e)
54+
{
55+
throw ensureRuntimeException(e);
56+
}
57+
}
58+
59+
/**
60+
* Shutdown the test class.
61+
*/
62+
@AfterClass
63+
public static void shutdown()
64+
{
65+
try
66+
{
67+
FileHelper.deleteDir(s_fileActive);
68+
FileHelper.deleteDir(s_fileSnapshot);
69+
FileHelper.deleteDir(s_fileTrash);
70+
}
71+
catch (IOException e)
72+
{
73+
// ignore
74+
}
75+
}
76+
77+
@Before
78+
public void beforeTests()
79+
{
80+
CacheFactory.shutdown();
81+
}
82+
83+
// ----- tests ----------------------------------------------------------
84+
85+
@Test
86+
public void test() throws InterruptedException
87+
{
88+
try
89+
{
90+
System.setProperty("test.persistence.active.dir", s_fileActive.getAbsolutePath());
91+
System.setProperty("test.persistence.snapshot.dir", s_fileSnapshot.getAbsolutePath());
92+
System.setProperty("test.persistence.trash.dir", s_fileTrash.getAbsolutePath());
93+
System.setProperty("coherence.cacheconfig", CFG_FILE);
94+
System.setProperty("coherence.override", "common-tangosol-coherence-override.xml");
95+
System.setProperty("je.log.fileMax", "1000000");
96+
97+
NamedCache cache = getNamedCache("simple-persistent-1");
98+
char[] val = new char[1_000_000];
99+
for (int i = 0; i < 100; i++)
100+
{
101+
cache.put(i, val);
102+
}
103+
104+
long size = FileHelper.sizeDir(s_fileActive);
105+
cache.clear();
106+
Eventually.assertDeferred(() -> FileHelper.sizeDir(s_fileActive), is(lessThan(size / 5)), within(2, TimeUnit.MINUTES));
107+
}
108+
finally
109+
{
110+
CacheFactory.shutdown();
111+
}
112+
}
113+
114+
// ----- accessors ------------------------------------------------------
115+
116+
/**
117+
* {@inheritDoc}
118+
*/
119+
public String getCacheConfigPath()
120+
{
121+
return CFG_FILE;
122+
}
123+
124+
/**
125+
* {@inheritDoc}
126+
*/
127+
public static String getProjectName()
128+
{
129+
return "persistence";
130+
}
131+
132+
// ----- constants ------------------------------------------------------
133+
134+
protected static final String CFG_FILE = "cleanup-bdb-cache-config.xml";
135+
136+
// ----- data members ---------------------------------------------------
137+
138+
private static File s_fileActive;
139+
private static File s_fileSnapshot;
140+
private static File s_fileTrash;
141+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
4+
5+
Licensed under the Universal Permissive License v 1.0 as shown at
6+
https://oss.oracle.com/licenses/upl.
7+
-->
8+
<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
10+
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config coherence-cache-config.xsd">
11+
12+
<caching-scheme-mapping>
13+
<cache-mapping>
14+
<cache-name>simple-persistent*</cache-name>
15+
<scheme-name>simple-persistence</scheme-name>
16+
</cache-mapping>
17+
</caching-scheme-mapping>
18+
19+
<caching-schemes>
20+
<distributed-scheme>
21+
<scheme-name>simple-persistence</scheme-name>
22+
<service-name>DistributedCachePersistence</service-name>
23+
<thread-count-min system-property="test.threads">1</thread-count-min>
24+
<partition-count system-property="coherence.distributed.partitions">3</partition-count>
25+
<backup-count system-property="test.backupcount">1</backup-count>
26+
<backing-map-scheme>
27+
<transient>{transient false}</transient>
28+
<local-scheme/>
29+
</backing-map-scheme>
30+
<persistence>
31+
<environment system-property="test.persistent-environment">simple-bdb-environment</environment>
32+
</persistence>
33+
<partitioned-quorum-policy-scheme>
34+
<class-name>persistence.AbstractSimplePersistenceTests$QuorumPolicy</class-name>
35+
</partitioned-quorum-policy-scheme>
36+
<autostart>true</autostart>
37+
<async-backup system-property="test.asyncbackup">false</async-backup>
38+
</distributed-scheme>
39+
40+
<invocation-scheme>
41+
<scheme-name>InvocationService</scheme-name>
42+
<service-name>InvocationService</service-name>
43+
<thread-count>5</thread-count>
44+
<guardian-timeout>500000</guardian-timeout>
45+
<autostart>true</autostart>
46+
</invocation-scheme>
47+
</caching-schemes>
48+
</cache-config>

0 commit comments

Comments
 (0)