You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ju...@apache.org on 2014/01/29 18:45:24 UTC

svn commit: r1562522 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/ oak-http/src/main/java/org/apache/jackrabbit/oak/http/segment/

Author: jukka
Date: Wed Jan 29 17:45:24 2014
New Revision: 1562522

URL: http://svn.apache.org/r1562522
Log:
OAK-1309: TarMK master-slave clustering

Add a basic HTTP interface to SegmentStore

Added:
    jackrabbit/oak/trunk/oak-http/src/main/java/org/apache/jackrabbit/oak/http/segment/
    jackrabbit/oak/trunk/oak-http/src/main/java/org/apache/jackrabbit/oak/http/segment/SegmentServlet.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStore.java
    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/Segment.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java?rev=1562522&r1=1562521&r2=1562522&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java Wed Jan 29 17:45:24 2014
@@ -24,9 +24,13 @@ import static com.google.common.collect.
 import static org.apache.jackrabbit.oak.plugins.segment.SegmentIdFactory.isDataSegmentId;
 import static org.apache.jackrabbit.oak.plugins.segment.SegmentWriter.BLOCK_SIZE;
 
+import java.io.IOException;
+import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
 import java.util.Arrays;
 import java.util.List;
 import java.util.UUID;
@@ -218,6 +222,20 @@ public class Segment {
         return data.remaining();
     }
 
+    /**
+     * Writes this segment to the given output stream.
+     *
+     * @param stream stream to which this segment will be written
+     * @throws IOException on an IO error
+     */
+    public void writeTo(OutputStream stream) throws IOException {
+        ByteBuffer buffer = data.duplicate();
+        WritableByteChannel channel = Channels.newChannel(stream);
+        while (buffer.hasRemaining()) {
+            channel.write(buffer);
+        }
+    }
+
     byte readByte(int offset) {
         return data.get(pos(offset, 1));
     }
@@ -240,12 +258,14 @@ public class Segment {
      * @param uuid segment identifier
      * @return identified segment
      */
+    @Nonnull
     Segment getSegment(UUID uuid) {
         if (equal(uuid, this.uuid)) {
             return this; // optimization for the common case (OAK-1031)
-        } else {
-            return store.readSegment(uuid);
         }
+        Segment segment = store.readSegment(uuid);
+        checkState(segment != null); // sanity check
+        return segment;
     }
 
     /**

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java?rev=1562522&r1=1562521&r2=1562522&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java Wed Jan 29 17:45:24 2014
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.plugin
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
 import static java.lang.System.currentTimeMillis;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
@@ -76,6 +77,7 @@ public class SegmentNodeStore implements
     public SegmentNodeStore(SegmentStore store, String journal) {
         this.store = store;
         this.journal = store.getJournal(journal);
+        checkState(this.journal != null);
         this.head = new AtomicReference<SegmentNodeState>(new SegmentNodeState(
                 store.getWriter().getDummySegment(), this.journal.getHead()));
         this.changeDispatcher = new ChangeDispatcher(getRoot());

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStore.java?rev=1562522&r1=1562521&r2=1562522&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStore.java Wed Jan 29 17:45:24 2014
@@ -16,15 +16,30 @@
  */
 package org.apache.jackrabbit.oak.plugins.segment;
 
-import javax.annotation.Nullable;
 import java.util.UUID;
 
+import javax.annotation.CheckForNull;
+
 public interface SegmentStore {
 
     SegmentWriter getWriter();
 
+    /**
+     * Returns the named journal.
+     *
+     * @param name journal name
+     * @return named journal, or {@code null} if not found
+     */
+    @CheckForNull
     Journal getJournal(String name);
 
+    /**
+     * Reads the identified segment from this store.
+     *
+     * @param segmentId segment identifier
+     * @return identified segment, or {@code null} if not found
+     */
+    @CheckForNull
     Segment readSegment(UUID segmentId);
 
     /**

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=1562522&r1=1562521&r2=1562522&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 Jan 29 17:45:24 2014
@@ -277,19 +277,12 @@ public class FileStore extends AbstractS
 
     @Override @Nonnull
     protected Segment loadSegment(UUID id) {
-        for (TarFile file : dataFiles) {
-            try {
-                ByteBuffer buffer = file.readEntry(id);
-                if (buffer != null) {
-                    return createSegment(id, buffer);
-                }
-            } catch (IOException e) {
-                throw new RuntimeException(
-                        "Failed to access data file " + file, e);
-            }
+        LinkedList<TarFile> files = dataFiles;
+        if (isBulkSegmentId(id)) {
+            files = bulkFiles;
         }
 
-        for (TarFile file : bulkFiles) {
+        for (TarFile file : files) {
             try {
                 ByteBuffer buffer = file.readEntry(id);
                 if (buffer != null) {
@@ -297,7 +290,7 @@ public class FileStore extends AbstractS
                 }
             } catch (IOException e) {
                 throw new RuntimeException(
-                        "Failed to access bulk file " + file, e);
+                        "Failed to access file " + file, e);
             }
         }
 

Added: jackrabbit/oak/trunk/oak-http/src/main/java/org/apache/jackrabbit/oak/http/segment/SegmentServlet.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-http/src/main/java/org/apache/jackrabbit/oak/http/segment/SegmentServlet.java?rev=1562522&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-http/src/main/java/org/apache/jackrabbit/oak/http/segment/SegmentServlet.java (added)
+++ jackrabbit/oak/trunk/oak-http/src/main/java/org/apache/jackrabbit/oak/http/segment/SegmentServlet.java Wed Jan 29 17:45:24 2014
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jackrabbit.oak.http.segment;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.UUID;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.jackrabbit.oak.plugins.segment.Journal;
+import org.apache.jackrabbit.oak.plugins.segment.RecordId;
+import org.apache.jackrabbit.oak.plugins.segment.Segment;
+import org.apache.jackrabbit.oak.plugins.segment.SegmentStore;
+
+import com.google.common.io.ByteStreams;
+
+public abstract class SegmentServlet extends HttpServlet {
+
+    protected abstract SegmentStore getSegmentStore();
+
+    private UUID getSegmentId(String info) {
+        try {
+            return UUID.fromString(info);
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+    }
+
+    private RecordId getRecordId(BufferedReader reader) throws IOException {
+        try {
+            return RecordId.fromString(reader.readLine());
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+    }
+
+    @Override
+    protected void doGet(
+            HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        String info = request.getPathInfo();
+        if (info == null) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+        } else if (info.startsWith("/s/")) {
+            doGetSegment(info.substring(3, info.length()), response);
+        } else if (info.startsWith("/j/")) {
+            doGetJournal(info.substring(3, info.length()), response);
+        } else {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+        }
+    }
+
+    @Override
+    protected void doPut(
+            HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        String info = request.getPathInfo();
+        if (info == null) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+        } else if (info.startsWith("/s/")) {
+            doPutSegment(info.substring(3, info.length()), request, response);
+        } else if (info.startsWith("/j/")) {
+            doPutJournal(info.substring(3, info.length()), request, response);
+        } else {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+        }
+    }
+
+    private void doGetSegment(
+            String info, HttpServletResponse response)
+            throws ServletException, IOException {
+        UUID uuid = getSegmentId(info);
+        if (uuid == null) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+
+        Segment segment = getSegmentStore().readSegment(uuid);
+        if (segment == null) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+
+        response.setContentType("application/octet-stream");
+        segment.writeTo(response.getOutputStream());
+    }
+
+    private void doPutSegment(
+            String info,
+            HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        UUID uuid = getSegmentId(info);
+        if (uuid == null) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+        } else if (getSegmentStore().readSegment(uuid) != null) {
+            // can't modify an existing segment
+            response.sendError(HttpServletResponse.SC_FORBIDDEN);
+        } else {
+            // TODO: sanity check the segment data?
+            byte[] data = ByteStreams.toByteArray(request.getInputStream());
+            getSegmentStore().writeSegment(uuid, data, 0, data.length);
+            response.setStatus(HttpServletResponse.SC_OK);
+        }
+    }
+
+    private void doGetJournal(
+            String info, HttpServletResponse response)
+            throws ServletException, IOException {
+        Journal journal = getSegmentStore().getJournal(info);
+        if (journal == null) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+
+        response.setContentType("text/plain; charset=UTF-8");
+        response.getWriter().write(journal.getHead().toString());
+    }
+
+    private void doPutJournal(
+            String info,
+            HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        Journal journal = getSegmentStore().getJournal(info);
+        if (journal == null) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+
+        RecordId head = getRecordId(request.getReader());
+        if (head == null) {
+            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+            return;
+        }
+
+        if (journal.setHead(journal.getHead(), head)) {
+            response.setStatus(HttpServletResponse.SC_OK);
+        } else {
+            response.sendError(HttpServletResponse.SC_CONFLICT);
+        }
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-http/src/main/java/org/apache/jackrabbit/oak/http/segment/SegmentServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native