From 67fb0adeedc389a869781ad37afca965aa08c2a9 Mon Sep 17 00:00:00 2001
From: "Todd L. Montgomery" <tmont@nard.net>
Date: Thu, 28 Sep 2017 13:40:36 -0700
Subject: [PATCH] [Java]: add configuration of page size for aligning file
 lengths. For #387. Align loss report and CnC file.

---
 .../main/java/io/aeron/CncFileDescriptor.java |  5 +--
 .../java/io/aeron/driver/Configuration.java   | 16 +++++++++
 .../java/io/aeron/driver/MediaDriver.java     | 35 +++++++++++++++++--
 3 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/aeron-client/src/main/java/io/aeron/CncFileDescriptor.java b/aeron-client/src/main/java/io/aeron/CncFileDescriptor.java
index 114565f8e8..09d9da03ad 100644
--- a/aeron-client/src/main/java/io/aeron/CncFileDescriptor.java
+++ b/aeron-client/src/main/java/io/aeron/CncFileDescriptor.java
@@ -96,11 +96,12 @@ public class CncFileDescriptor
      * Compute the length of the cnc file and return it.
      *
      * @param totalLengthOfBuffers in bytes
+     * @param alignment for file length to adhere to
      * @return cnc file length in bytes
      */
-    public static int computeCncFileLength(final int totalLengthOfBuffers)
+    public static int computeCncFileLength(final int totalLengthOfBuffers, final int alignment)
     {
-        return END_OF_METADATA_OFFSET + totalLengthOfBuffers;
+        return align(END_OF_METADATA_OFFSET + totalLengthOfBuffers, alignment);
     }
 
     public static int cncVersionOffset(final int baseOffset)
diff --git a/aeron-driver/src/main/java/io/aeron/driver/Configuration.java b/aeron-driver/src/main/java/io/aeron/driver/Configuration.java
index 702eaa2617..2152cca3d3 100644
--- a/aeron-driver/src/main/java/io/aeron/driver/Configuration.java
+++ b/aeron-driver/src/main/java/io/aeron/driver/Configuration.java
@@ -99,6 +99,22 @@ public class Configuration
      */
     public static final String PERFORM_STORAGE_CHECKS_PROP_NAME = "aeron.perform.storage.checks";
 
+    /**
+     * Property name for page size to align all files to.
+     */
+    public static final String FILE_PAGE_SIZE_PROP_NAME = "aeron.file.page.size";
+
+    /**
+     * Default page size for alignment of all files.
+     */
+    public static final int FILE_PAGE_SIZE_DEFAULT = 4 * 1024;
+
+    /**
+     * Page size for alignment of all files.
+     */
+    public static final int FILE_PAGE_SIZE =
+        getInteger(FILE_PAGE_SIZE_PROP_NAME, FILE_PAGE_SIZE_DEFAULT);
+
     /**
      * Should storage checks should be performed when allocating files.
      */
diff --git a/aeron-driver/src/main/java/io/aeron/driver/MediaDriver.java b/aeron-driver/src/main/java/io/aeron/driver/MediaDriver.java
index 587bcf71f0..b77d5877e7 100644
--- a/aeron-driver/src/main/java/io/aeron/driver/MediaDriver.java
+++ b/aeron-driver/src/main/java/io/aeron/driver/MediaDriver.java
@@ -44,6 +44,7 @@
 import static io.aeron.driver.status.SystemCounterDescriptor.*;
 import static io.aeron.driver.status.SystemCounterDescriptor.CONTROLLABLE_IDLE_STRATEGY;
 import static java.nio.charset.StandardCharsets.US_ASCII;
+import static org.agrona.BitUtil.align;
 import static org.agrona.IoUtil.mapNewFile;
 
 /**
@@ -454,6 +455,7 @@ public static class Context extends CommonContext
         private int initialWindowLength = Configuration.initialWindowLength();
         private int mtuLength = Configuration.MTU_LENGTH;
         private int ipcMtuLength = Configuration.IPC_MTU_LENGTH;
+        private int filePageSize = Configuration.FILE_PAGE_SIZE;
 
         private EpochClock epochClock;
         private NanoClock nanoClock;
@@ -543,8 +545,12 @@ public Context conclude()
                 cncByteBuffer = mapNewFile(
                     cncFile(),
                     CncFileDescriptor.computeCncFileLength(
-                        CONDUCTOR_BUFFER_LENGTH + TO_CLIENTS_BUFFER_LENGTH +
-                            COUNTERS_METADATA_BUFFER_LENGTH + COUNTERS_VALUES_BUFFER_LENGTH + ERROR_BUFFER_LENGTH));
+                        CONDUCTOR_BUFFER_LENGTH +
+                            TO_CLIENTS_BUFFER_LENGTH +
+                            COUNTERS_METADATA_BUFFER_LENGTH +
+                            COUNTERS_VALUES_BUFFER_LENGTH +
+                            ERROR_BUFFER_LENGTH,
+                        filePageSize));
 
                 cncMetaDataBuffer = CncFileDescriptor.createMetaDataBuffer(cncByteBuffer);
                 CncFileDescriptor.fillMetaData(
@@ -689,6 +695,28 @@ public Context performStorageChecks(final boolean performStorageChecks)
             return this;
         }
 
+        /**
+         * Page size for alignment of all files.
+         *
+         * @return page size for alignment of all files.
+         */
+        public int filePageSize()
+        {
+            return filePageSize;
+        }
+
+        /**
+         * Page size for alignment of all files.
+         *
+         * @param filePageSize for alignment of file sizes.
+         * @return this for a fluent API.
+         */
+        public Context filePageSize(final int filePageSize)
+        {
+            this.filePageSize = filePageSize;
+            return this;
+        }
+
         /**
          * Time in nanoseconds an Image will be kept alive for its subscribers to consume it once disconnected.
          *
@@ -1756,7 +1784,8 @@ private void concludeDependantProperties()
 
             if (null == lossReport)
             {
-                lossReportBuffer = mapLossReport(aeronDirectoryName(), Configuration.LOSS_REPORT_BUFFER_LENGTH);
+                lossReportBuffer = mapLossReport(
+                    aeronDirectoryName(), align(Configuration.LOSS_REPORT_BUFFER_LENGTH, filePageSize));
                 lossReport = new LossReport(new UnsafeBuffer(lossReportBuffer));
             }
         }