This is an automated email from the ASF dual-hosted git repository.
andor pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zookeeper.git
The following commit(s) were added to refs/heads/master by this push:
new 0cf36616d ZOOKEEPER-4829: Support DatadirCleanup in minutes
0cf36616d is described below
commit 0cf36616dffe3164bf46b3b8c627f6cc5e37e8c8
Author: puru <[email protected]>
AuthorDate: Tue Aug 27 15:32:16 2024 -0700
ZOOKEEPER-4829: Support DatadirCleanup in minutes
Reviewers: anmolnar
Author: purushah
Closes #2178 from purushah/ZOOKEEPER-4829
---
.../java/org/apache/zookeeper/common/Time.java | 44 ++++++++++++++++++++++
.../zookeeper/server/DatadirCleanupManager.java | 21 +++++------
.../embedded/ZooKeeperServerEmbeddedImpl.java | 4 +-
.../zookeeper/server/quorum/QuorumPeerConfig.java | 13 +++++--
.../zookeeper/server/quorum/QuorumPeerMain.java | 2 +-
.../java/org/apache/zookeeper/common/TimeTest.java | 28 ++++++++++++++
6 files changed, 94 insertions(+), 18 deletions(-)
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/common/Time.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/common/Time.java
index 08891f73a..9abe4d6a8 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/common/Time.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/common/Time.java
@@ -22,6 +22,12 @@ import java.util.Date;
public class Time {
+ public static final int MILLISECOND = 1;
+ public static final int SECOND = 1000 * MILLISECOND;
+ public static final int MINUTE = 60 * SECOND;
+ public static final int HOUR = 60 * MINUTE;
+ public static final int DAY = 24 * HOUR;
+
/**
* Returns time in milliseconds as does System.currentTimeMillis(),
* but uses elapsed time from an arbitrary epoch more like
System.nanoTime().
@@ -51,4 +57,42 @@ public class Time {
return new Date(wallTime);
}
+ /** Parse a string as a time interval. An interval is specified as an
+ * integer with an optional suffix. No suffix means milliseconds, s, m,
+ * h, d indicates seconds, minutes, hours, and days respectively.
+ * As a special case, "ms" means milliseconds.
+ * @param str the interval string
+ * @return interval in milliseconds
+ */
+
+ public static int parseTimeInterval(String str) {
+ try {
+ int len = str.length();
+ char suffix = str.charAt(len - 1);
+ if (Character.isDigit(suffix)) {
+ return Integer.parseInt(str);
+ } else {
+ if (str.endsWith("ms") || str.endsWith("MS")) {
+ return Integer.parseInt(str.substring(0, len - 2));
+ } else {
+ String numstr = str.substring(0, len - 1);
+ switch (Character.toUpperCase(suffix)) {
+ case 'S':
+ return Integer.parseInt(numstr) * SECOND;
+ case 'M':
+ return Integer.parseInt(numstr) * MINUTE;
+ case 'H':
+ return Integer.parseInt(numstr) * HOUR;
+ case 'D':
+ return Integer.parseInt(numstr) * DAY;
+ default:
+ throw new NumberFormatException("Illegal time interval
suffix: " + str);
+ }
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ throw new NumberFormatException("empty string");
+ }
+ }
+
}
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/DatadirCleanupManager.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/DatadirCleanupManager.java
index 2f9e75783..5504519af 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/DatadirCleanupManager.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/DatadirCleanupManager.java
@@ -21,7 +21,6 @@ package org.apache.zookeeper.server;
import java.io.File;
import java.util.Timer;
import java.util.TimerTask;
-import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -53,7 +52,7 @@ public class DatadirCleanupManager {
private final int snapRetainCount;
- private final int purgeInterval;
+ private final int purgeIntervalInMs;
private Timer timer;
@@ -70,13 +69,13 @@ public class DatadirCleanupManager {
* @param purgeInterval
* purge interval in hours
*/
- public DatadirCleanupManager(File snapDir, File dataLogDir, int
snapRetainCount, int purgeInterval) {
+ public DatadirCleanupManager(File snapDir, File dataLogDir, int
snapRetainCount, int purgeIntervalInMs) {
this.snapDir = snapDir;
this.dataLogDir = dataLogDir;
this.snapRetainCount = snapRetainCount;
- this.purgeInterval = purgeInterval;
+ this.purgeIntervalInMs = purgeIntervalInMs;
LOG.info("autopurge.snapRetainCount set to {}", snapRetainCount);
- LOG.info("autopurge.purgeInterval set to {}", purgeInterval);
+ LOG.info("autopurge.purgeInterval set to {}", purgeIntervalInMs);
}
/**
@@ -97,14 +96,14 @@ public class DatadirCleanupManager {
return;
}
// Don't schedule the purge task with zero or negative purge interval.
- if (purgeInterval <= 0) {
+ if (purgeIntervalInMs <= 0) {
LOG.info("Purge task is not scheduled.");
return;
}
timer = new Timer("PurgeTask", true);
TimerTask task = new PurgeTask(dataLogDir, snapDir, snapRetainCount);
- timer.scheduleAtFixedRate(task, 0,
TimeUnit.HOURS.toMillis(purgeInterval));
+ timer.scheduleAtFixedRate(task, 0, purgeIntervalInMs);
purgeTaskStatus = PurgeTaskStatus.STARTED;
}
@@ -175,12 +174,12 @@ public class DatadirCleanupManager {
}
/**
- * Returns purge interval in hours.
+ * Returns purge interval in milliseconds.
*
- * @return the purge interval in hours.
+ * @return the purge interval in milliseconds.
*/
- public int getPurgeInterval() {
- return purgeInterval;
+ public int getPurgeIntervalInMs() {
+ return purgeIntervalInMs;
}
/**
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/embedded/ZooKeeperServerEmbeddedImpl.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/embedded/ZooKeeperServerEmbeddedImpl.java
index 189c3b45a..60070e66f 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/embedded/ZooKeeperServerEmbeddedImpl.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/embedded/ZooKeeperServerEmbeddedImpl.java
@@ -119,7 +119,7 @@ class ZooKeeperServerEmbeddedImpl implements
ZooKeeperServerEmbedded {
// Start and schedule the the purge task
purgeMgr = new DatadirCleanupManager(config
.getDataDir(), config.getDataLogDir(), config
- .getSnapRetainCount(), config.getPurgeInterval());
+ .getSnapRetainCount(), config.getPurgeIntervalInMs());
purgeMgr.start();
thread = new Thread("zkservermainrunner") {
@@ -155,7 +155,7 @@ class ZooKeeperServerEmbeddedImpl implements
ZooKeeperServerEmbedded {
};
purgeMgr = new DatadirCleanupManager(config
.getDataDir(), config.getDataLogDir(), config
- .getSnapRetainCount(), config.getPurgeInterval());
+ .getSnapRetainCount(), config.getPurgeIntervalInMs());
purgeMgr.start();
thread = new Thread("zkservermainrunner") {
@Override
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
index d72d84443..0e9c82d4d 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
@@ -44,6 +44,7 @@ import
org.apache.zookeeper.common.AtomicFileWritingIdiom.WriterStatement;
import org.apache.zookeeper.common.ClientX509Util;
import org.apache.zookeeper.common.PathUtils;
import org.apache.zookeeper.common.StringUtils;
+import org.apache.zookeeper.common.Time;
import org.apache.zookeeper.metrics.impl.DefaultMetricsProvider;
import org.apache.zookeeper.server.ZooKeeperServer;
import org.apache.zookeeper.server.auth.ProviderRegistry;
@@ -104,7 +105,7 @@ public class QuorumPeerConfig {
protected QuorumVerifier quorumVerifier = null, lastSeenQuorumVerifier =
null;
protected int snapRetainCount = 3;
- protected int purgeInterval = 0;
+ protected int purgeIntervalInMs = 0;
protected boolean syncEnabled = true;
protected String initialConfig;
@@ -336,7 +337,11 @@ public class QuorumPeerConfig {
} else if (key.equals("autopurge.snapRetainCount")) {
snapRetainCount = Integer.parseInt(value);
} else if (key.equals("autopurge.purgeInterval")) {
- purgeInterval = Integer.parseInt(value);
+ if (Character.isDigit(value.charAt(value.length() - 1))) {
+ purgeIntervalInMs = Time.parseTimeInterval(value) *
Time.HOUR; // default is hours for backward compatibility
+ } else {
+ purgeIntervalInMs = Time.parseTimeInterval(value);
+ }
} else if (key.equals("standaloneEnabled")) {
setStandaloneEnabled(parseBoolean(key, value));
} else if (key.equals("reconfigEnabled")) {
@@ -898,8 +903,8 @@ public class QuorumPeerConfig {
return snapRetainCount;
}
- public int getPurgeInterval() {
- return purgeInterval;
+ public int getPurgeIntervalInMs() {
+ return purgeIntervalInMs;
}
public boolean getSyncEnabled() {
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
index 0cad9ae8f..8a5bb9ccd 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
@@ -130,7 +130,7 @@ public class QuorumPeerMain {
config.getDataDir(),
config.getDataLogDir(),
config.getSnapRetainCount(),
- config.getPurgeInterval());
+ config.getPurgeIntervalInMs());
purgeMgr.start();
if (args.length == 1 && config.isDistributed()) {
diff --git
a/zookeeper-server/src/test/java/org/apache/zookeeper/common/TimeTest.java
b/zookeeper-server/src/test/java/org/apache/zookeeper/common/TimeTest.java
index bd8ace79b..cc60055a5 100644
--- a/zookeeper-server/src/test/java/org/apache/zookeeper/common/TimeTest.java
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/common/TimeTest.java
@@ -18,6 +18,7 @@
package org.apache.zookeeper.common;
+import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Calendar;
import java.util.Date;
@@ -101,4 +102,31 @@ public class TimeTest extends ClientBase {
assertEquals(calculatedDate, realDate);
}
+ @Test
+ public void testParseTimeInterval() throws Exception {
+ assertEquals(0, Time.parseTimeInterval("0"));
+ assertEquals(0, Time.parseTimeInterval("0s"));
+ assertEquals(0, Time.parseTimeInterval("0m"));
+ assertEquals(0, Time.parseTimeInterval("0h"));
+ assertEquals(0, Time.parseTimeInterval("0d"));
+ assertEquals(1000, Time.parseTimeInterval("1000"));
+ assertEquals(Time.SECOND, Time.parseTimeInterval("1s"));
+ assertEquals(Time.MINUTE, Time.parseTimeInterval("1m"));
+ assertEquals(Time.HOUR, Time.parseTimeInterval("1h"));
+ assertEquals(Time.DAY, Time.parseTimeInterval("1d"));
+ assertEquals(1234, Time.parseTimeInterval("1234ms"));
+ assertEquals(Time.parseTimeInterval("60s"),
Time.parseTimeInterval("1m"));
+ assertEquals(Time.parseTimeInterval("120m"),
Time.parseTimeInterval("2h"));
+ assertEquals(Time.parseTimeInterval("72h"),
Time.parseTimeInterval("3d"));
+ try {
+ Time.parseTimeInterval("2x");
+ fail("should have thrown NumberFormatException");
+ } catch (NumberFormatException e) {
+ }
+ try {
+ Time.parseTimeInterval("");
+ fail("should have thrown NumberFormatException");
+ } catch (NumberFormatException e) {
+ }
+ }
}