Bladeren bron

ZOOKEEPER-4829: Support DatadirCleanup in minutes

Reviewers: anmolnar
Author: purushah
Closes #2178 from purushah/ZOOKEEPER-4829
puru 8 maanden geleden
bovenliggende
commit
0cf36616df

+ 44 - 0
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");
+        }
+    }
+
 }

+ 10 - 11
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;
     }
 
     /**

+ 2 - 2
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

+ 9 - 4
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() {

+ 1 - 1
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()) {

+ 28 - 0
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) {
+        }
+    }
 }