From 61b67f57ac854903affc7dd6fefb9c8b7035e9b7 Mon Sep 17 00:00:00 2001
From: izabel <izabel>
Date: Tue, 23 Mar 2010 20:25:35 +0000
Subject: [PATCH] [LMS-1452] use highwater mark; allow schedule at midnight

SVN: 15240
---
 .../cisd/etlserver/MaintenancePlugin.java     |  6 +-
 .../etlserver/MaintenanceTaskParameters.java  | 50 +++++++++++++++
 .../server/plugins/demo/DemoArchiver.java     |  4 +-
 .../AbstractArchiverProcessingPlugin.java     | 26 +++++++-
 .../standard/HighWaterMarkChecker.java        | 62 +++++++++++++++++++
 .../plugins/standard/IStatusChecker.java      | 13 ++++
 6 files changed, 155 insertions(+), 6 deletions(-)
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/HighWaterMarkChecker.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IStatusChecker.java

diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/MaintenancePlugin.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/MaintenancePlugin.java
index f03004c4cc9..9c870437ece 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/MaintenancePlugin.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/MaintenancePlugin.java
@@ -21,8 +21,8 @@ public class MaintenancePlugin
             this.task = ClassUtils.create(IMaintenanceTask.class, parameters.getClassName());
         } catch (Exception ex)
         {
-            throw new ConfigurationFailureException("Cannot find the plugin class '" + parameters.getClassName()
-                    + "'", CheckedExceptionTunnel.unwrapIfNecessary(ex));
+            throw new ConfigurationFailureException("Cannot find the plugin class '"
+                    + parameters.getClassName() + "'", CheckedExceptionTunnel.unwrapIfNecessary(ex));
         }
         task.setUp(parameters.getPluginName(), parameters.getProperties());
     }
@@ -38,6 +38,6 @@ public class MaintenancePlugin
                 {
                     task.execute();
                 }
-            }, 0L, parameters.getIntervalSeconds() * 1000);
+            }, parameters.getStartDate(), parameters.getIntervalSeconds() * 1000);
     }
 }
\ No newline at end of file
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/MaintenanceTaskParameters.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/MaintenanceTaskParameters.java
index 84c221445bc..46713143495 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/MaintenanceTaskParameters.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/MaintenanceTaskParameters.java
@@ -16,8 +16,17 @@
 
 package ch.systemsx.cisd.etlserver;
 
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
 import java.util.Properties;
 
+import org.apache.commons.lang.StringUtils;
+
+import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
 import ch.systemsx.cisd.common.utilities.PropertyUtils;
 
 /**
@@ -25,12 +34,16 @@ import ch.systemsx.cisd.common.utilities.PropertyUtils;
  */
 public class MaintenanceTaskParameters
 {
+    private static final String TIME_FORMAT = "hh:mm";
+
     private static final int ONE_DAY_IN_SEC = 60 * 60 * 24;
 
     private static final String CLASS_KEY = "class";
 
     private static final String INTERVAL_KEY = "interval";
 
+    private static final String START_KEY = "start";
+
     private final String pluginName;
 
     private final long interval;
@@ -39,12 +52,44 @@ public class MaintenanceTaskParameters
 
     private final Properties properties;
 
+    private final Date startDate;
+
     public MaintenanceTaskParameters(Properties properties, String pluginName)
     {
         this.properties = properties;
         this.pluginName = pluginName;
         interval = PropertyUtils.getLong(properties, INTERVAL_KEY, ONE_DAY_IN_SEC);
         className = PropertyUtils.getMandatoryProperty(properties, CLASS_KEY);
+        startDate = extractStartDate(PropertyUtils.getProperty(properties, START_KEY));
+    }
+
+    private static Date extractStartDate(String timeOrNull)
+    {
+        try
+        {
+            if (StringUtils.isBlank(timeOrNull))
+            {
+                return GregorianCalendar.getInstance().getTime();
+            }
+            DateFormat format = new SimpleDateFormat(TIME_FORMAT);
+            Date parsedDate = format.parse(timeOrNull);
+            Calendar rightHourAndMinutes1970 = GregorianCalendar.getInstance();
+            rightHourAndMinutes1970.setTime(parsedDate);
+            Calendar result = GregorianCalendar.getInstance();
+            result.set(Calendar.HOUR_OF_DAY, rightHourAndMinutes1970.get(Calendar.HOUR_OF_DAY));
+            result.set(Calendar.MINUTE, rightHourAndMinutes1970.get(Calendar.MINUTE));
+            Calendar now = GregorianCalendar.getInstance();
+            if (now.after(result))
+            {
+                result.add(Calendar.DAY_OF_MONTH, 1);
+            }
+            return result.getTime();
+        } catch (ParseException ex)
+        {
+            throw new ConfigurationFailureException(String.format(
+                    "Start date <%s> does not match the required format <%s>", timeOrNull,
+                    TIME_FORMAT));
+        }
     }
 
     public long getIntervalSeconds()
@@ -66,4 +111,9 @@ public class MaintenanceTaskParameters
     {
         return properties;
     }
+
+    public Date getStartDate()
+    {
+        return startDate;
+    }
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/demo/DemoArchiver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/demo/DemoArchiver.java
index a0464ee807b..509af5bba2a 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/demo/DemoArchiver.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/demo/DemoArchiver.java
@@ -21,6 +21,7 @@ import java.util.Properties;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.AbstractArchiverProcessingPlugin;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard.HighWaterMarkChecker;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
 
 /**
@@ -32,7 +33,8 @@ public class DemoArchiver extends AbstractArchiverProcessingPlugin
 
     public DemoArchiver(Properties properties, File storeRoot)
     {
-        super(properties, storeRoot);
+        super(properties, storeRoot, new HighWaterMarkChecker(storeRoot), new HighWaterMarkChecker(
+                storeRoot));
     }
 
     @Override
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractArchiverProcessingPlugin.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractArchiverProcessingPlugin.java
index 36b7ad43b30..26b9b1b41e3 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractArchiverProcessingPlugin.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/AbstractArchiverProcessingPlugin.java
@@ -38,7 +38,6 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription;
  * 
  * @author Piotr Buczek
  */
-// TODO 2010-03-19, PTR: check HighWaterMark
 public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastorePlugin implements
         IArchiverTask
 {
@@ -48,9 +47,16 @@ public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastore
 
     private static final long serialVersionUID = 1L;
 
-    public AbstractArchiverProcessingPlugin(Properties properties, File storeRoot)
+    private final IStatusChecker archivePrerequisiteOrNull;
+
+    private final IStatusChecker unarchivePrerequisiteOrNull;
+
+    public AbstractArchiverProcessingPlugin(Properties properties, File storeRoot,
+            IStatusChecker archivePrerequisiteOrNull, IStatusChecker unarchivePrerequisiteOrNull)
     {
         super(properties, storeRoot);
+        this.archivePrerequisiteOrNull = archivePrerequisiteOrNull;
+        this.unarchivePrerequisiteOrNull = unarchivePrerequisiteOrNull;
     }
 
     abstract protected void archive(DatasetDescription dataset) throws UserFailureException;
@@ -67,6 +73,14 @@ public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastore
 
                         public Status handle(DatasetDescription dataset)
                         {
+                            if (archivePrerequisiteOrNull != null)
+                            {
+                                Status status = archivePrerequisiteOrNull.check();
+                                if (status.isError())
+                                {
+                                    return status;
+                                }
+                            }
                             try
                             {
                                 archive(dataset);
@@ -90,6 +104,14 @@ public abstract class AbstractArchiverProcessingPlugin extends AbstractDatastore
 
                         public Status handle(DatasetDescription dataset)
                         {
+                            if (unarchivePrerequisiteOrNull != null)
+                            {
+                                Status status = unarchivePrerequisiteOrNull.check();
+                                if (status.isError())
+                                {
+                                    return status;
+                                }
+                            }
                             try
                             {
                                 unarchive(dataset);
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/HighWaterMarkChecker.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/HighWaterMarkChecker.java
new file mode 100644
index 00000000000..6b3502ad504
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/HighWaterMarkChecker.java
@@ -0,0 +1,62 @@
+package ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard;
+
+import java.io.File;
+import java.io.Serializable;
+
+import ch.systemsx.cisd.common.exceptions.Status;
+import ch.systemsx.cisd.common.highwatermark.HighwaterMarkWatcher;
+import ch.systemsx.cisd.common.highwatermark.HostAwareFile;
+import ch.systemsx.cisd.common.highwatermark.HostAwareFileWithHighwaterMark;
+import ch.systemsx.cisd.common.highwatermark.HighwaterMarkWatcher.HighwaterMarkState;
+import ch.systemsx.cisd.common.utilities.PropertyUtils;
+import ch.systemsx.cisd.openbis.dss.generic.shared.utils.PropertyParametersUtil;
+
+/**
+ * Checks if the space available is larger than specified value.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class HighWaterMarkChecker implements IStatusChecker, Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    private final long highWaterMark;
+
+    private final File highWaterMarkPath;
+
+    /**
+     * Loads the high water mark value from global properties -
+     * {@link HostAwareFileWithHighwaterMark#HIGHWATER_MARK_PROPERTY_KEY}.
+     */
+    public HighWaterMarkChecker(File path)
+    {
+        this(PropertyUtils.getLong(PropertyParametersUtil.loadServiceProperties(),
+                HostAwareFileWithHighwaterMark.HIGHWATER_MARK_PROPERTY_KEY, -1L), path);
+    }
+
+    public HighWaterMarkChecker(long archiveHighWaterMark, File archiveHighWaterMarkPath)
+    {
+        this.highWaterMark = archiveHighWaterMark;
+        this.highWaterMarkPath = archiveHighWaterMarkPath;
+    }
+
+    public Status check()
+    {
+        HighwaterMarkWatcher w = new HighwaterMarkWatcher(highWaterMark);
+        HighwaterMarkState state = w.getHighwaterMarkState(new HostAwareFile(highWaterMarkPath));
+        if (HighwaterMarkWatcher.isBelow(state))
+        {
+            String canonicalPath = highWaterMarkPath.getPath();
+            String mark = HighwaterMarkWatcher.displayKilobyteValue(state.getHighwaterMark());
+            String space = HighwaterMarkWatcher.displayKilobyteValue(state.getFreeSpace());
+            String message =
+                    String.format("Free space on '%s': %s, highwater mark: %s.", canonicalPath,
+                            space, mark);
+            return Status.createError(message);
+        } else
+        {
+            return Status.OK;
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IStatusChecker.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IStatusChecker.java
new file mode 100644
index 00000000000..ad708037c9f
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/IStatusChecker.java
@@ -0,0 +1,13 @@
+package ch.systemsx.cisd.openbis.dss.generic.server.plugins.standard;
+
+import ch.systemsx.cisd.common.exceptions.Status;
+
+/**
+ * Checks the status.
+ * 
+ * @author Izabela Adamczyk
+ */
+public interface IStatusChecker
+{
+    Status check();
+}
\ No newline at end of file
-- 
GitLab