Enforce regular file access on Windows in offline compaction
@@ -25,6 +25,7 @@ import java.util.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;
+import com.google.common.base.StandardSystemProperty;
import com.google.common.base.Stopwatch;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
@@ -35,6 +36,46 @@ import org.apache.jackrabbit.oak.run.commons.Command;
class CompactCommand implements Command {
+ private enum FileAccessMode {
+
+ ARCH_DEPENDENT(null, "default access mode"),
+ MEMORY_MAPPED(true, "memory mapped access mode"),
+ REGULAR(false, "regular access mode"),
+ REGULAR_ENFORCED(false, "enforced regular access mode");
+
+ private final Boolean memoryMapped;
+
+ private final String description;
+
+ FileAccessMode(Boolean memoryMapped, String description) {
+ this.memoryMapped = memoryMapped;
+ this.description = description;
+ }
+
+ Boolean getMemoryMapped() {
+ return memoryMapped;
+ }
+
+ @Override
+ public String toString() {
+ return description;
+ }
+
+ }
+
+ private static FileAccessMode getFileAccessMode(Boolean arg, String os) {
+ if (os != null && os.toLowerCase().contains("windows")) {
+ return FileAccessMode.REGULAR_ENFORCED;
+ }
+ if (arg == null) {
+ return FileAccessMode.ARCH_DEPENDENT;
+ }
+ if (arg) {
+ return FileAccessMode.MEMORY_MAPPED;
+ }
+ return FileAccessMode.REGULAR;
+ }
+
@Override
public void execute(String... args) throws Exception {
OptionParser parser = new OptionParser();
@@ -42,8 +83,10 @@ class CompactCommand implements Command {
"Path to segment store (required)").ofType(String.class);
OptionSpec<Boolean> mmapArg = parser.accepts("mmap",
"Use memory mapped access if true, use file access if false. " +
- "If not specified memory mapped access is used on 64 bit systems " +
- "and file access is used on 32 bit systems.")
+ "If not specified, memory mapped access is used on 64 bit " +
+ "systems and file access is used on 32 bit systems. On " +
+ "Windows, regular file access is always enforced and this " +
+ "option is ignored.")
.withOptionalArg()
.ofType(Boolean.class);
OptionSpec<Boolean> forceArg = parser.accepts("force",
@@ -69,15 +112,12 @@ class CompactCommand implements Command {
Set<String> afterLs = newHashSet();
Stopwatch watch = Stopwatch.createStarted();
- Boolean mmap = mmapArg.value(options);
- System.out.println("Compacting " + directory);
- if (mmap == null) {
- System.out.println("With default access mode");
- } else if (mmap) {
- System.out.println("With memory mapped access");
- } else {
- System.out.println("With file access");
- }
+ FileAccessMode fileAccessMode = getFileAccessMode(
+ mmapArg.value(options),
+ StandardSystemProperty.OS_NAME.value()
+ );
+
+ System.out.println("Compacting " + directory + " with " + fileAccessMode);
boolean force = isTrue(forceArg.value(options));
@@ -90,7 +130,7 @@ class CompactCommand implements Command {
System.out.println(" -> compacting");
try {
- SegmentTarUtils.compact(directory, mmap, force);
+ SegmentTarUtils.compact(directory, fileAccessMode.getMemoryMapped(), force);
success = true;
} catch (Throwable e) {
System.out.println("Compaction failure stack trace:");
