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 ch...@apache.org on 2014/04/09 08:08:33 UTC

svn commit: r1585896 - in /jackrabbit/oak/trunk/oak-run: ./ src/main/java/org/apache/jackrabbit/oak/benchmark/ src/main/java/org/apache/jackrabbit/oak/fixture/ src/main/java/org/apache/jackrabbit/oak/run/

Author: chetanm
Date: Wed Apr  9 06:08:32 2014
New Revision: 1585896

URL: http://svn.apache.org/r1585896
Log:
OAK-1702 - Create a benchmark for Full text search

-- Added two new fixtures Oak-Mongo-FDS, Oak-Tar-FDS
-- FullTextSearchTest benchmarks full text query performance
-- Two profile added to pom.xml to create oak-run with lucene3 (oak-run-jr2) and lucene4(oak-run-oak) jars

Added:
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/FullTextSearchTest.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/JcrCustomizer.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-run/README.md
    jackrabbit/oak/trunk/oak-run/pom.xml
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/OakFixture.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/OakRepositoryFixture.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java

Modified: jackrabbit/oak/trunk/oak-run/README.md
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/README.md?rev=1585896&r1=1585895&r2=1585896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/README.md (original)
+++ jackrabbit/oak/trunk/oak-run/README.md Wed Apr  9 06:08:32 2014
@@ -83,17 +83,19 @@ repository backend.
 The optional fixture argument allows to specify the repository implementation
 to be used. The following fixtures are currently supported:
 
-| Fixture     | Description                                           |
-|-------------|-------------------------------------------------------|
-| Jackrabbit  | Jackrabbit with the default embedded Derby  bundle PM |
-| Oak-Memory  | Oak with default in-memory storage                    |
-| Oak-MemoryNS| Oak with default in-memory NodeStore                  |
-| Oak-MemoryMK| Oak with default in-memory MicroKernel                |
-| Oak-Mongo   | Oak with the default Mongo backend                    |
-| Oak-MongoNS | Oak with the Mongo NodeStore                          |
-| Oak-MongoMK | Oak with the Mongo MicroKernel                        |
-| Oak-Tar     | Oak with the Tar backend (aka Segment NodeStore)      |
-| Oak-H2      | Oak with the MK using embedded H2 database            |
+| Fixture       | Description                                           |
+|---------------|-------------------------------------------------------|
+| Jackrabbit    | Jackrabbit with the default embedded Derby  bundle PM |
+| Oak-Memory    | Oak with default in-memory storage                    |
+| Oak-MemoryNS  | Oak with default in-memory NodeStore                  |
+| Oak-MemoryMK  | Oak with default in-memory MicroKernel                |
+| Oak-Mongo     | Oak with the default Mongo backend                    |
+| Oak-Mongo-FDS | Oak with the default Mongo backend and FileDataStore  |
+| Oak-MongoNS   | Oak with the Mongo NodeStore                          |
+| Oak-MongoMK   | Oak with the Mongo MicroKernel                        |
+| Oak-Tar       | Oak with the Tar backend (aka Segment NodeStore)      |
+| Oak-Tar-FDS   | Oak with the Tar backend and FileDataStore            |
+| Oak-H2        | Oak with the MK using embedded H2 database            |
 
 
 Depending on the fixture the following options are available:
@@ -178,17 +180,18 @@ that we used to produce earlier.
 
 Finally the benchmark runner supports the following repository fixtures:
 
-| Fixture     | Description                                           |
-|-------------|-------------------------------------------------------|
-| Jackrabbit  | Jackrabbit with the default embedded Derby  bundle PM |
-| Oak-Memory  | Oak with default in-memory storage                    |
-| Oak-MemoryNS| Oak with default in-memory NodeStore                  |
-| Oak-MemoryMK| Oak with default in-memory MicroKernel                |
-| Oak-Mongo   | Oak with the default Mongo backend                    |
-| Oak-MongoNS | Oak with the Mongo NodeStore                          |
-| Oak-MongoMK | Oak with the Mongo MicroKernel                        |
-| Oak-Tar     | Oak with the Tar backend (aka Segment NodeStore)      |
-| Oak-H2      | Oak with the MK using embedded H2 database            |
+| Fixture       | Description                                           |
+|---------------|-------------------------------------------------------|
+| Jackrabbit    | Jackrabbit with the default embedded Derby  bundle PM |
+| Oak-Memory    | Oak with default in-memory storage                    |
+| Oak-MemoryNS  | Oak with default in-memory NodeStore                  |
+| Oak-MemoryMK  | Oak with default in-memory MicroKernel                |
+| Oak-Mongo     | Oak with the default Mongo backend                    |
+| Oak-Mongo-FDS | Oak with the default Mongo backend and FileDataStore  |
+| Oak-MongoNS   | Oak with the Mongo NodeStore                          |
+| Oak-MongoMK   | Oak with the Mongo MicroKernel                        |
+| Oak-Tar       | Oak with the Tar backend (aka Segment NodeStore)      |
+| Oak-H2        | Oak with the MK using embedded H2 database            |
 
 
 Once started, the benchmark runner will execute each listed test case

Modified: jackrabbit/oak/trunk/oak-run/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/pom.xml?rev=1585896&r1=1585895&r2=1585896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-run/pom.xml Wed Apr  9 06:08:32 2014
@@ -53,6 +53,9 @@
                 <includes>
                   <include>*</include>
                 </includes>
+                <excludes>
+                  <exclude>${lucene.exclude}</exclude>
+                </excludes>
               </artifactSet>
               <filters>
                 <filter>
@@ -136,6 +139,11 @@
     </dependency>
     <dependency>
       <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>oak-lucene</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jackrabbit</groupId>
       <artifactId>oak-mk-remote</artifactId>
       <version>${project.version}</version>
     </dependency>
@@ -157,6 +165,12 @@
       <groupId>org.apache.jackrabbit</groupId>
       <artifactId>jackrabbit-core</artifactId>
       <version>${jackrabbit.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.lucene</groupId>
+          <artifactId>lucene-core</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.jackrabbit</groupId>
@@ -201,4 +215,64 @@
     </dependency>
     
   </dependencies>
+
+  <profiles>
+    <profile>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+      </activation>
+      <id>oak-run-jr2</id>
+      <properties>
+        <lucene.exclude>org.apache.jackrabbit:oak-lucene</lucene.exclude>
+      </properties>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.lucene</groupId>
+          <artifactId>lucene-core</artifactId>
+          <version>3.6.0</version>
+        </dependency>
+      </dependencies>
+    </profile>
+    <profile>
+      <id>oak-run-oak</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <properties>
+        <!--
+        Lucene classes are already part of oak-lucene so exclude
+        them in maven-shade-plugin. Otherwise it causes duplicate
+        classes warning
+        -->
+        <lucene.exclude>org.apache.lucene:*</lucene.exclude>
+      </properties>
+      <dependencies>
+        <!--
+         oak-lucene embeds the Lucene jar. However when running in IDE
+         the IDE use the module classpath. So need to explicitly list the
+         lucene jars
+        -->
+        <dependency>
+          <groupId>org.apache.lucene</groupId>
+          <artifactId>lucene-core</artifactId>
+          <version>${lucene.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.lucene</groupId>
+          <artifactId>lucene-analyzers-common</artifactId>
+          <version>${lucene.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.lucene</groupId>
+          <artifactId>lucene-queryparser</artifactId>
+          <version>${lucene.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.lucene</groupId>
+          <artifactId>lucene-queries</artifactId>
+          <version>${lucene.version}</version>
+        </dependency>
+      </dependencies>
+    </profile>
+  </profiles>
 </project>

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java?rev=1585896&r1=1585895&r2=1585896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java Wed Apr  9 06:08:32 2014
@@ -133,7 +133,7 @@ abstract class AbstractTest extends Benc
         }
         for (RepositoryFixture fixture : fixtures) {
             try {
-                Repository[] cluster = fixture.setUpCluster(1);
+                Repository[] cluster = createRepository(fixture);
                 try {
                     runTest(fixture, cluster[0], concurrencyLevels);
                 } finally {
@@ -435,4 +435,11 @@ abstract class AbstractTest extends Benc
         threads.add(thread);
     }
 
+    /**
+     * Customize the repository creation process by custom fixture handling
+     */
+    protected Repository[] createRepository(RepositoryFixture fixture) throws Exception {
+        return fixture.setUpCluster(1);
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java?rev=1585896&r1=1585895&r2=1585896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java Wed Apr  9 06:08:32 2014
@@ -89,6 +89,11 @@ public class BenchmarkRunner {
                         host.value(options), port.value(options),
                         dbName.value(options), dropDBAfterTest.value(options),
                         cacheSize * MB),
+                OakRepositoryFixture.getMongoWithFDS(
+                        host.value(options), port.value(options),
+                        dbName.value(options), dropDBAfterTest.value(options),
+                        cacheSize * MB,
+                        base.value(options)),
                 OakRepositoryFixture.getMongoNS(
                         host.value(options), port.value(options),
                         dbName.value(options), dropDBAfterTest.value(options),
@@ -98,6 +103,8 @@ public class BenchmarkRunner {
                         dbName.value(options), dropDBAfterTest.value(options),
                         cacheSize * MB),
                 OakRepositoryFixture.getTar(
+                        base.value(options), 256, cacheSize, mmap.value(options)),
+                OakRepositoryFixture.getTarWithBlobStore(
                         base.value(options), 256, cacheSize, mmap.value(options))
         };
         Benchmark[] allBenchmarks = new Benchmark[] {
@@ -200,7 +207,10 @@ public class BenchmarkRunner {
                     flatStructure.value(options)),
             new GetPrincipalTest(
                     numberOfUsers.value(options),
-                    flatStructure.value(options))
+                    flatStructure.value(options)),
+            new FullTextSearchTest(
+                    wikipedia.value(options),
+                    report.value(options))
         };
 
         Set<String> argset = Sets.newHashSet(options.nonOptionArguments());

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/FullTextSearchTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/FullTextSearchTest.java?rev=1585896&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/FullTextSearchTest.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/FullTextSearchTest.java Wed Apr  9 06:08:32 2014
@@ -0,0 +1,178 @@
+/*
+ * 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.benchmark;
+
+import java.io.File;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.Session;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.RowIterator;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.stream.StreamSource;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.apache.jackrabbit.oak.fixture.JcrCustomizer;
+import org.apache.jackrabbit.oak.fixture.OakRepositoryFixture;
+import org.apache.jackrabbit.oak.fixture.RepositoryFixture;
+import org.apache.jackrabbit.oak.jcr.Jcr;
+import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexEditorProvider;
+import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexProvider;
+import org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneInitializerHelper;
+import org.apache.jackrabbit.util.Text;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+public class FullTextSearchTest extends AbstractTest {
+    private int maxSampleSize = 100;
+    private final File dump;
+    private final boolean doReport;
+    private List<String> sampleSet;
+    private Random random;
+    private Reader reader;
+
+    public FullTextSearchTest(File dump, boolean doReport) {
+        this.dump = dump;
+        this.doReport = doReport;
+    }
+
+    @Override
+    public void beforeSuite() throws Exception {
+        random = new Random(42); //fixed seed
+        Session importSession = loginWriter();
+        sampleSet = importWikipedia(importSession);
+        reader = new Reader();
+    }
+
+    @Override
+    protected void runTest() throws Exception {
+        reader.call();
+    }
+
+    private class Reader implements Callable<Boolean> {
+        private final Session session = loginWriter();
+        private final String word = Text.escapeIllegalJcrChars(sampleSet.get(random.nextInt(sampleSet.size())));
+
+        @SuppressWarnings("deprecation")
+        @Override
+        public Boolean call() throws Exception {
+            QueryManager qm = session.getWorkspace().getQueryManager();
+            Query q = qm.createQuery("/jcr:root//*[jcr:contains(@text, '" + word + "')] order by jcr:score()", Query.XPATH);
+            QueryResult r = q.execute();
+            RowIterator it = r.getRows();
+            checkArgument(it.hasNext(), "Not able to find entry with text [%s]", word);
+            return it.hasNext();
+        }
+    }
+
+    @Override
+    protected Repository[] createRepository(RepositoryFixture fixture) throws Exception {
+        if (fixture instanceof OakRepositoryFixture) {
+            return ((OakRepositoryFixture) fixture).setUpCluster(1, new JcrCustomizer() {
+                @Override
+                public Jcr customize(Jcr jcr) {
+                    jcr.with(new LuceneIndexProvider())
+                            .with(new LuceneIndexEditorProvider())
+                            .with(new LuceneInitializerHelper("luceneGlobal", null));
+                    return jcr;
+                }
+            });
+        }
+        return super.createRepository(fixture);
+    }
+
+    private List<String> importWikipedia(Session session) throws Exception {
+        long start = System.currentTimeMillis();
+        int count = 0;
+        Set<String> sampleWords = Sets.newHashSet();
+
+        checkArgument(dump.exists(), "Dump file %s does not exist", dump.getAbsolutePath());
+        if (doReport) {
+            System.out.format("Importing %s...%n", dump);
+        }
+        Node wikipedia = session.getRootNode().addNode(
+                "wikipedia", "nt:unstructured");
+
+        String title = null;
+        String text = null;
+        XMLInputFactory factory = XMLInputFactory.newInstance();
+        XMLStreamReader reader =
+                factory.createXMLStreamReader(new StreamSource(dump));
+        while (reader.hasNext()) {
+            switch (reader.next()) {
+                case XMLStreamConstants.START_ELEMENT:
+                    if ("title".equals(reader.getLocalName())) {
+                        title = reader.getElementText();
+                    } else if ("text".equals(reader.getLocalName())) {
+                        text = reader.getElementText();
+                    }
+                    break;
+                case XMLStreamConstants.END_ELEMENT:
+                    if ("page".equals(reader.getLocalName())) {
+                        String name = Text.escapeIllegalJcrChars(title);
+                        Node page = wikipedia.addNode(name);
+                        page.setProperty("title", title);
+                        page.setProperty("text", Text.escapeIllegalJcrChars(text));
+                        count++;
+
+                        if (count % 1000 == 0
+                                && sampleWords.size() < maxSampleSize
+                                && text != null) {
+                            List<String> words = Splitter.on(CharMatcher.BREAKING_WHITESPACE)
+                                    .trimResults().splitToList(text);
+                            if (!words.isEmpty()) {
+                                sampleWords.add(words.get(words.size() / 2));
+                            }
+                        }
+
+                        if (doReport && count % 1000 == 0) {
+                            long millis = System.currentTimeMillis() - start;
+                            System.out.format(
+                                    "Added %d pages in %d seconds (%.2fms/page)%n",
+                                    count, millis / 1000, (double) millis / count);
+                        }
+                    }
+                    break;
+            }
+        }
+
+        session.save();
+
+        if (doReport) {
+            long millis = System.currentTimeMillis() - start;
+            System.out.format(
+                    "Imported %d pages in %d seconds (%.2fms/page)%n",
+                    count, millis / 1000, (double) millis / count);
+        }
+        return Lists.newArrayList(sampleWords);
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/FullTextSearchTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/JcrCustomizer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/JcrCustomizer.java?rev=1585896&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/JcrCustomizer.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/JcrCustomizer.java Wed Apr  9 06:08:32 2014
@@ -0,0 +1,33 @@
+/*
+ * 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.fixture;
+
+import org.apache.jackrabbit.oak.jcr.Jcr;
+
+public interface JcrCustomizer {
+    JcrCustomizer DEFAULT = new JcrCustomizer() {
+        @Override
+        public Jcr customize(Jcr jcr) {
+            return jcr;
+        }
+    };
+
+    Jcr customize(Jcr jcr);
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/JcrCustomizer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/OakFixture.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/OakFixture.java?rev=1585896&r1=1585895&r2=1585896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/OakFixture.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/OakFixture.java Wed Apr  9 06:08:32 2014
@@ -22,6 +22,8 @@ import java.util.Map;
 import com.google.common.collect.Maps;
 import org.apache.commons.io.FileUtils;
 import org.apache.jackrabbit.core.data.DataStore;
+import org.apache.jackrabbit.core.data.DataStoreException;
+import org.apache.jackrabbit.core.data.FileDataStore;
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.mk.core.MicroKernelImpl;
 import org.apache.jackrabbit.oak.Oak;
@@ -31,6 +33,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore;
 import org.apache.jackrabbit.oak.plugins.document.DocumentMK;
 import org.apache.jackrabbit.oak.plugins.document.util.MongoConnection;
+import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
 import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentStore;
@@ -44,11 +47,13 @@ public abstract class OakFixture {
     public static final String OAK_MEMORY_MK = "Oak-MemoryMK";
 
     public static final String OAK_MONGO = "Oak-Mongo";
+    public static final String OAK_MONGO_FDS = "Oak-Mongo-FDS";
     public static final String OAK_MONGO_NS = "Oak-MongoNS";
     public static final String OAK_MONGO_MK = "Oak-MongoMK";
 
     public static final String OAK_H2 = "Oak-H2";
     public static final String OAK_TAR = "Oak-Tar";
+    public static final String OAK_TAR_FDS = "Oak-Tar-FDS";
 
 
     private final String name;
@@ -120,30 +125,40 @@ public abstract class OakFixture {
     public static OakFixture getMongo(String host, int port, String database,
                                       boolean dropDBAfterTest, long cacheSize) {
         return getMongo(OAK_MONGO, false, host, port, database,
-                dropDBAfterTest, cacheSize);
+                dropDBAfterTest, cacheSize, false, null);
     }
 
     public static OakFixture getMongoMK(String host, int port, String database,
                                         boolean dropDBAfterTest, long cacheSize) {
         return getMongo(OAK_MONGO_MK, true, host, port, database,
-                dropDBAfterTest, cacheSize);
+                dropDBAfterTest, cacheSize, false, null);
     }
 
     public static OakFixture getMongoNS(String host, int port, String database,
                                         boolean dropDBAfterTest, long cacheSize) {
         return getMongo(OAK_MONGO_NS, false, host, port, database,
-                dropDBAfterTest, cacheSize);
+                dropDBAfterTest, cacheSize, false, null);
     }
 
     public static OakFixture getMongo(String name, final boolean useMk, final String host,
                                       final int port, final String database,
-                                      final boolean dropDBAfterTest, final long cacheSize) {
+                                      final boolean dropDBAfterTest, final long cacheSize,
+                                      final boolean useFileDataStore,
+                                      final File base) {
         return new OakFixture(name) {
             private String dbName = database != null ? database : unique;
             private DocumentMK[] kernels;
             private BlobStore blobStore;
+            private File blobStoreDir;
 
             private BlobStore getBlobStore() {
+                if(useFileDataStore){
+                    FileDataStore fds = new FileDataStore();
+                    fds.setMinRecordLength(4092);
+                    blobStoreDir = new File(base, "datastore"+unique);
+                    fds.init(blobStoreDir.getAbsolutePath());
+                    return new DataStoreBlobStore(fds);
+                }
 
                 try {
                     String className = System.getProperty("dataStore");
@@ -243,16 +258,19 @@ public abstract class OakFixture {
                     } catch (Exception e) {
                         throw new RuntimeException(e);
                     }
+                    FileUtils.deleteQuietly(blobStoreDir);
                 }
             }
         };
     }
 
     public static OakFixture getTar(
-            final File base, final int maxFileSizeMB, final int cacheSizeMB,
-            final boolean memoryMapping) {
-        return new OakFixture(OAK_TAR) {
+            final String name, final File base, final int maxFileSizeMB, final int cacheSizeMB,
+            final boolean memoryMapping, final boolean useBlobStore) {
+        return new OakFixture(name) {
             private SegmentStore[] stores;
+            private BlobStore[] blobStores = new BlobStore[0];
+            private String blobStoreDir = "datastore"+unique;
 
             @Override
             public Oak getOak(int clusterId) throws Exception {
@@ -264,9 +282,20 @@ public abstract class OakFixture {
             public Oak[] setUpCluster(int n) throws Exception {
                 Oak[] cluster = new Oak[n];
                 stores = new FileStore[cluster.length];
+                if (useBlobStore) {
+                    blobStores = new BlobStore[cluster.length];
+                }
+
                 for (int i = 0; i < cluster.length; i++) {
-                    stores[i] = new FileStore(
+                    BlobStore blobStore = null;
+                    if (useBlobStore) {
+                        blobStore = createBlobStore();
+                        blobStores[i] = blobStore;
+                    }
+
+                    stores[i] = new FileStore(blobStore,
                             new File(base, unique),
+                            EmptyNodeState.EMPTY_NODE,
                             maxFileSizeMB, cacheSizeMB, memoryMapping);
                     cluster[i] = new Oak(new SegmentNodeStore(stores[i]));
                 }
@@ -277,11 +306,30 @@ public abstract class OakFixture {
                 for (SegmentStore store : stores) {
                     store.close();
                 }
+                for(BlobStore blobStore : blobStores){
+                    if(blobStore instanceof DataStore){
+                        try {
+                            ((DataStore) blobStore).close();
+                        } catch (DataStoreException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                }
                 FileUtils.deleteQuietly(new File(base, unique));
+                FileUtils.deleteQuietly(new File(base, blobStoreDir));
+            }
+
+            private BlobStore createBlobStore(){
+                FileDataStore fds = new FileDataStore();
+                fds.setMinRecordLength(4092);
+                fds.init(new File(base, blobStoreDir).getAbsolutePath());
+                return new DataStoreBlobStore(fds);
             }
         };
     }
 
+
+
     public static OakFixture getH2MK(final File base, final long cacheSize) {
         return new OakFixture(OAK_H2) {
             private MicroKernelImpl[] kernels;

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/OakRepositoryFixture.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/OakRepositoryFixture.java?rev=1585896&r1=1585895&r2=1585896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/OakRepositoryFixture.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/fixture/OakRepositoryFixture.java Wed Apr  9 06:08:32 2014
@@ -47,29 +47,42 @@ public class OakRepositoryFixture implem
 
     public static RepositoryFixture getMongo(String host, int port, String database,
                                              boolean dropDBAfterTest, long cacheSize) {
-        return getMongo(OakFixture.OAK_MONGO, false, host, port, database, dropDBAfterTest, cacheSize);
+        return getMongo(OakFixture.OAK_MONGO, false, host, port, database, dropDBAfterTest, cacheSize, false, null);
+    }
+
+    public static RepositoryFixture getMongoWithFDS(String host, int port, String database,
+                                             boolean dropDBAfterTest, long cacheSize,
+                                             final File base) {
+        return getMongo(OakFixture.OAK_MONGO_FDS, false, host, port, database, dropDBAfterTest, cacheSize, true, base);
     }
 
     public static RepositoryFixture getMongoMK(String host, int port, String database,
                                                boolean dropDBAfterTest, long cacheSize) {
-        return getMongo(OakFixture.OAK_MONGO_MK, true, host, port, database, dropDBAfterTest, cacheSize);
+        return getMongo(OakFixture.OAK_MONGO_MK, true, host, port, database, dropDBAfterTest, cacheSize, false, null);
     }
 
     public static RepositoryFixture getMongoNS(String host, int port, String database,
                                                boolean dropDBAfterTest, long cacheSize) {
-        return getMongo(OakFixture.OAK_MONGO_NS, false, host, port, database, dropDBAfterTest, cacheSize);
+        return getMongo(OakFixture.OAK_MONGO_NS, false, host, port, database, dropDBAfterTest, cacheSize, false, null);
     }
 
     private static RepositoryFixture getMongo(String name, boolean useMK,
                                               String host, int port, String database,
-                                              boolean dropDBAfterTest, long cacheSize) {
-        return new OakRepositoryFixture(OakFixture.getMongo(name, useMK, host, port, database, dropDBAfterTest, cacheSize));
+                                              boolean dropDBAfterTest, long cacheSize,
+                                              final boolean useFileDataStore,
+                                              final File base) {
+        return new OakRepositoryFixture(OakFixture.getMongo(name, useMK, host, port, database, dropDBAfterTest, cacheSize, useFileDataStore, base));
     }
 
     public static RepositoryFixture getTar(File base, int maxFileSizeMB, int cacheSizeMB, boolean memoryMapping) {
-        return new OakRepositoryFixture(OakFixture.getTar(base, maxFileSizeMB, cacheSizeMB, memoryMapping));
+        return new OakRepositoryFixture(OakFixture.getTar(OakFixture.OAK_TAR ,base, maxFileSizeMB, cacheSizeMB, memoryMapping, false));
+    }
+
+    public static RepositoryFixture getTarWithBlobStore(File base, int maxFileSizeMB, int cacheSizeMB, boolean memoryMapping) {
+        return new OakRepositoryFixture(OakFixture.getTar(OakFixture.OAK_TAR_FDS,base, maxFileSizeMB, cacheSizeMB, memoryMapping, true));
     }
 
+
     private final OakFixture oakFixture;
     private Repository[] cluster;
 
@@ -84,10 +97,14 @@ public class OakRepositoryFixture implem
 
     @Override
     public final Repository[] setUpCluster(int n) throws Exception {
+        return setUpCluster(n,JcrCustomizer.DEFAULT);
+    }
+
+    public Repository[] setUpCluster(int n, JcrCustomizer customizer) throws Exception {
         Oak[] oaks = oakFixture.setUpCluster(n);
         cluster = new Repository[oaks.length];
         for (int i = 0; i < oaks.length; i++) {
-            cluster[i] = new Jcr(oaks[i]).createRepository();;
+            cluster[i] = customizer.customize(new Jcr(oaks[i])).createRepository();
         }
         return cluster;
     }

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java?rev=1585896&r1=1585895&r2=1585896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java Wed Apr  9 06:08:32 2014
@@ -379,7 +379,7 @@ public class Main {
             if (baseFile == null) {
                 throw new IllegalArgumentException("Required argument base missing.");
             }
-            oakFixture = OakFixture.getTar(baseFile, 256, cacheSize, mmap.value(options));
+            oakFixture = OakFixture.getTar(OakFixture.OAK_TAR, baseFile, 256, cacheSize, mmap.value(options), false);
         } else if (fix.equals(OakFixture.OAK_H2)) {
             File baseFile = base.value(options);
             if (baseFile == null) {