jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r1494530 - /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
Date Wed, 19 Jun 2013 10:10:44 GMT
Author: jukka
Date: Wed Jun 19 10:10:44 2013
New Revision: 1494530

URL: http://svn.apache.org/r1494530
Log:
OAK-876: SegmentMK: File backend restart problem due to missing padding

Add a padding record at the end of a data tar file when needed.

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java?rev=1494530&r1=1494529&r2=1494530&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
Wed Jun 19 10:10:44 2013
@@ -55,12 +55,20 @@ public class FileStore implements Segmen
 
     private static final long JOURNAL_MAGIC = 0xdf36544212c0cb24L;
 
+    private static final long PADDING_MAGIC = 0x786da7779516c12L;
+
     private static final String JOURNALS_UUID = new UUID(0, 0).toString();
 
+    private static final String PADDING_UUID = new UUID(-1, -1).toString();
+
     private static final long FILE_SIZE = 256 * 1024 * 1024;
 
     private static final String FILE_NAME_FORMAT = "data%05d.tar";
 
+    private static final int SEGMENT_SIZE = 0x200; // 512
+
+    private static final byte[] PADDING_BYTES = new byte[SEGMENT_SIZE];
+
     private final Map<String, Journal> journals = Maps.newHashMap();
 
     private final File directory;
@@ -121,11 +129,11 @@ public class FileStore implements Segmen
             rw = f.getChannel().map(READ_WRITE, 0, size);
             ro = rw.asReadOnlyBuffer();
 
-            while (ro.remaining() >= 4 * 0x200) {
+            while (ro.remaining() >= 4 * SEGMENT_SIZE) {
                 // skip tar header and get the magic bytes; TODO: verify?
-                long magic = ro.getLong(ro.position() + 0x200);
+                long magic = ro.getLong(ro.position() + SEGMENT_SIZE);
                 if (magic == SEGMENT_MAGIC) {
-                    ro.position(ro.position() + 0x200 + 8);
+                    ro.position(ro.position() + SEGMENT_SIZE + 8);
 
                     int length = ro.getInt();
                     int count = ro.getInt();
@@ -151,7 +159,7 @@ public class FileStore implements Segmen
                     // advance to next entry in the file
                     ro.position((ro.position() + length + 0x1ff) & ~0x1ff);
                 } else if (magic == JOURNAL_MAGIC) {
-                    ro.position(ro.position() + 0x200 + 8);
+                    ro.position(ro.position() + SEGMENT_SIZE + 8);
 
                     int count = ro.getInt();
                     for (int i = 0; i < count; i++) {
@@ -167,6 +175,8 @@ public class FileStore implements Segmen
 
                     // advance to next entry in the file
                     ro.position((ro.position() + 0x1ff) & ~0x1ff);
+                } else if (magic == PADDING_MAGIC) {
+                    return true;
                 } else {
                     // still space for more segments: position the write
                     // buffer at this point and return false to stop looking
@@ -228,8 +238,10 @@ public class FileStore implements Segmen
         ByteBuffer buffer = ro.slice();
         ro.limit(rw.limit());
 
-        rw.position((rw.position() + 0x1ff) & ~0x1ff);
-        ro.position(rw.position());
+        int n = rw.position() % SEGMENT_SIZE;
+        if (n > 0) {
+            rw.put(PADDING_BYTES, 0, SEGMENT_SIZE - n);
+        }
 
         Segment segment = new Segment(
                 this, segmentId, buffer,
@@ -265,12 +277,31 @@ public class FileStore implements Segmen
             rw.putLong(head.getSegmentId().getLeastSignificantBits());
             rw.putInt(head.getOffset());
         }
-        rw.position((rw.position() + 0x1ff) & ~0x1ff);
+
+        int n = rw.position() % SEGMENT_SIZE;
+        if (n > 0) {
+            rw.put(PADDING_BYTES, 0, SEGMENT_SIZE - n);
+        }
     }
 
     private void prepare(int size) {
-        if (0x200 + ((size + 0x1ff) & ~0x1ff) + 2 * 0x200 > rw.remaining()) {
+        int segments = (size + SEGMENT_SIZE - 1) / SEGMENT_SIZE;
+        if ((1 + segments + 2) * SEGMENT_SIZE > rw.remaining()) {
+            if (rw.remaining() >= 3 * SEGMENT_SIZE) {
+                // Add a padding entry to avoid problems during reopening
+                rw.put(createTarHeader(
+                        PADDING_UUID,
+                        rw.remaining() - 3 * SEGMENT_SIZE));
+                if (rw.remaining() > 2 * SEGMENT_SIZE) {
+                    rw.putLong(PADDING_MAGIC);
+                    rw.put(PADDING_BYTES, 0, SEGMENT_SIZE - 8);
+                }
+            }
+            while (rw.remaining() > 0) {
+                rw.put(PADDING_BYTES);
+            }
             rw.force();
+
             String name = String.format(FILE_NAME_FORMAT, ++index);
             File file = new File(directory, name);
             try {
@@ -288,73 +319,55 @@ public class FileStore implements Segmen
     }
 
     private static byte[] createTarHeader(String name, int length) {
-        byte[] header = new byte[] {
-                // File name
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0,
-                // File mode
-                '0', '0', '0', '0', '4', '0', '0', 0,
-                // User's numeric user ID
-                '0', '0', '0', '0', '0', '0', '0', 0,
-                // Group's numeric user ID
-                '0', '0', '0', '0', '0', '0', '0', 0,
-                // File size in bytes (octal basis)
-                '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',  0,
-                // Last modification time in numeric Unix time format (octal)
-                '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',  0,
-                // Checksum for header record
-                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
-                // Type flag
-                '0',
-                // Name of linked file
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0,
-                // unused
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-        };
+        byte[] header = new byte[SEGMENT_SIZE];
 
+        // File name
         byte[] n = name.getBytes(UTF_8);
         System.arraycopy(n, 0, header, 0, n.length);
 
-        byte[] l = Integer.toOctalString(length).getBytes(UTF_8);
-        System.arraycopy(l, 0, header, 124 + 11 - l.length, l.length);
+        // File mode
+        System.arraycopy(
+                String.format("%07o", 0400).getBytes(UTF_8), 0,
+                header, 100, 7);
+
+        // User's numeric user ID
+        System.arraycopy(
+                String.format("%07o", 0).getBytes(UTF_8), 0,
+                header, 108, 7);
+
+        // Group's numeric user ID
+        System.arraycopy(
+                String.format("%07o", 0).getBytes(UTF_8), 0,
+                header, 116, 7);
+
+        // File size in bytes (octal basis)
+        System.arraycopy(
+                String.format("%011o", length).getBytes(UTF_8), 0,
+                header, 124, 11);
 
+        // Last modification time in numeric Unix time format (octal)
         long time = System.currentTimeMillis() / 1000;
-        byte[] t = Long.toOctalString(time).getBytes(UTF_8);
-        System.arraycopy(t, 0, header, 136 + 11 - t.length, t.length);
+        System.arraycopy(
+                String.format("%011o", time).getBytes(UTF_8), 0,
+                header, 136, 11);
+
+        // Checksum for header record
+        System.arraycopy(
+                new byte[] { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, 0,
+                header, 148, 8);
+
+        // Type flag
+        header[156] = '0';
 
+        // Compute checksum
         int checksum = 0;
         for (int i = 0; i < header.length; i++) {
             checksum += header[i] & 0xff;
         }
-        byte[] c = Integer.toOctalString(checksum).getBytes(UTF_8);
-        System.arraycopy(c, 0, header, 148 + 6 - c.length, c.length);
-        header[148 + 6] = 0;
+        System.arraycopy(
+                String.format("%06o", checksum).getBytes(UTF_8), 0,
+                header, 148, 6);
+        header[154] = 0;
 
         return header;
     }



Mime
View raw message