diff --git a/common/source/java/ch/systemsx/cisd/common/highwatermark/AlwaysAboveFreeSpaceProvider.java b/common/source/java/ch/systemsx/cisd/common/highwatermark/AlwaysAboveFreeSpaceProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..6e455aa6902c28738ddfcea96dd90ff32e5c4d73
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/highwatermark/AlwaysAboveFreeSpaceProvider.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.highwatermark;
+
+import java.io.File;
+import java.io.IOException;
+
+import ch.systemsx.cisd.common.highwatermark.HighwaterMarkWatcher.IFreeSpaceProvider;
+
+/**
+ * An <code>IFreeSpaceProvider</code> implementation which returns {@link Long#MAX_VALUE} as free
+ * space value.
+ * <p>
+ * Therefore the free space available will never be below the <i>high water mark</i>.
+ * </p>
+ * 
+ * @author Christian Ribeaud
+ */
+public final class AlwaysAboveFreeSpaceProvider implements IFreeSpaceProvider
+{
+
+    /** The only instance of this class. */
+    public final static IFreeSpaceProvider INSTANCE = new AlwaysAboveFreeSpaceProvider();
+
+    private AlwaysAboveFreeSpaceProvider()
+    {
+        // Can not be instantiated.
+    }
+
+    //
+    // IFreeSpaceProvider
+    //
+
+    public final long freeSpaceKb(final File path) throws IOException
+    {
+        return Long.MAX_VALUE;
+    }
+
+}
diff --git a/common/source/java/ch/systemsx/cisd/common/highwatermark/RemoteFreeSpaceProvider.java b/common/source/java/ch/systemsx/cisd/common/highwatermark/RemoteFreeSpaceProvider.java
index 151537cb6d5c99ae3fdce9572dcbb9e540c5ec20..c9aa4bdcf4b182aef1472790b0071b90feed4573 100644
--- a/common/source/java/ch/systemsx/cisd/common/highwatermark/RemoteFreeSpaceProvider.java
+++ b/common/source/java/ch/systemsx/cisd/common/highwatermark/RemoteFreeSpaceProvider.java
@@ -21,9 +21,13 @@ import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
 
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.time.DateUtils;
 import org.apache.log4j.Logger;
 
 import ch.systemsx.cisd.common.highwatermark.HighwaterMarkWatcher.IFreeSpaceProvider;
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.process.ProcessExecutionHelper;
 import ch.systemsx.cisd.common.process.ProcessResult;
 
@@ -35,29 +39,77 @@ import ch.systemsx.cisd.common.process.ProcessResult;
  */
 public final class RemoteFreeSpaceProvider implements IFreeSpaceProvider
 {
+    private static final String DF_COMMAND_TEMPLATE = "df -k %s";
+
+    private static final Logger machineLog =
+            LogFactory.getLogger(LogCategory.MACHINE, RemoteFreeSpaceProvider.class);
+
+    private static final Logger operationLog =
+            LogFactory.getLogger(LogCategory.OPERATION, RemoteFreeSpaceProvider.class);
+
+    private static final long MILLIS_TO_WAIT_FOR_COMPLETION = 2 * DateUtils.MILLIS_PER_SECOND;
+
     private final File sshExecutable;
 
     private final String host;
 
+    private final long millisToWaitForCompletion = MILLIS_TO_WAIT_FOR_COMPLETION;
+
     public RemoteFreeSpaceProvider(final String host, final File sshExecutable)
     {
+        assert host != null : "Unspecified host";
+        assert sshExecutable != null : "Unspecified ssh executable";
         this.host = host;
         this.sshExecutable = sshExecutable;
     }
 
+    private final static long parseKbytes(final String freeSpaceInKb, final String dfCommand)
+            throws IOException
+    {
+        try
+        {
+            final long kBytes = Long.parseLong(freeSpaceInKb);
+            if (kBytes < 0)
+            {
+                throw new IOException(String.format(
+                        "Command line '%s' did not find free space in response.", dfCommand));
+            }
+            return kBytes;
+        } catch (final NumberFormatException ex)
+        {
+            throw new IOException(String.format(
+                    "Command line '%s' did not return numeric data as expected.", dfCommand));
+        }
+    }
+
     //
     // IFreeSpaceProvider
     //
 
-    public final long freeSpaceKb(final File path) throws IOException
+    public final long freeSpaceKb(final File file) throws IOException
     {
-        final List<String> command =
-                Arrays.asList(sshExecutable.getPath(), host, "df -k " + path.getPath() + "");
-        Logger rootLogger = Logger.getRootLogger();
-        System.out.println(command);
+        assert file != null : "Unspecified remote file.";
+        final String path = file.getPath();
+        assert StringUtils.isNotEmpty(path) : "Empty path.";
+        final String dfCommand = String.format(DF_COMMAND_TEMPLATE, path);
+        final List<String> command = Arrays.asList(sshExecutable.getPath(), host, dfCommand);
         final ProcessResult processResult =
-                ProcessExecutionHelper.run(command, 2000L, rootLogger, rootLogger);
-        System.out.println(processResult.getProcessOutput());
-        return 0L;
+                ProcessExecutionHelper.run(command, millisToWaitForCompletion, operationLog,
+                        machineLog);
+        processResult.log();
+        final List<String> processOutput = processResult.getProcessOutput();
+        if (processOutput.size() >= 2)
+        {
+            final String output = processOutput.get(1);
+            final String[] split = StringUtils.split(output, ' ');
+            if (split.length >= 4)
+            {
+                // The column 'avail' (3th column) interests us.
+                return parseKbytes(split[3], dfCommand);
+            }
+        }
+        throw new IOException(String.format(
+                "Command line '%s' did not return info as expected. Response was '%s'", dfCommand,
+                processOutput));
     }
 }
\ No newline at end of file
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/highwatermark/RemoteFreeSpaceProviderTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/highwatermark/RemoteFreeSpaceProviderTest.java
index 91081ae427c7542ca161634cbf9f929fdf0da293..2511ec873d78fba3920319cc37299b9e9b37b0ee 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/highwatermark/RemoteFreeSpaceProviderTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/highwatermark/RemoteFreeSpaceProviderTest.java
@@ -23,7 +23,6 @@ import java.io.IOException;
 
 import org.testng.annotations.Test;
 
-import ch.systemsx.cisd.common.highwatermark.RemoteFreeSpaceProvider;
 import ch.systemsx.cisd.common.utilities.OSUtilities;
 
 /**