Author: chetanm
Date: Thu Jun 30 11:08:39 2016
New Revision: 1750769
URL: http://svn.apache.org/viewvc?rev=1750769&view=rev
Log:
OAK-3629 - Index corruption seen with CopyOnRead when index defnition is
recreated
Switch to different directory format for storing local index. The
implementation is compatible with existing format and newer index updates would
start using newer format.
Added:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMeta.java
(with props)
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectory.java
(with props)
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDir.java
(with props)
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMetaTest.java
(with props)
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectoryTest.java
(with props)
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDirTest.java
(with props)
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopier.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopierTest.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinitionTest.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopier.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopier.java?rev=1750769&r1=1750768&r2=1750769&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopier.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopier.java
Thu Jun 30 11:08:39 2016
@@ -52,17 +52,16 @@ import javax.management.openmbean.Tabula
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
-import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
-import com.google.common.hash.Hashing;
-
import org.apache.commons.io.FileUtils;
import org.apache.jackrabbit.oak.commons.IOUtils;
import org.apache.jackrabbit.oak.commons.concurrent.NotifyingFutureTask;
+import
org.apache.jackrabbit.oak.plugins.index.lucene.directory.IndexRootDirectory;
+import org.apache.jackrabbit.oak.plugins.index.lucene.directory.LocalIndexDir;
import org.apache.jackrabbit.oak.util.PerfLogger;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
@@ -91,7 +90,6 @@ public class IndexCopier implements Copy
private final Logger log = LoggerFactory.getLogger(getClass());
private final PerfLogger PERF_LOGGER = new
PerfLogger(LoggerFactory.getLogger(log.getName() + ".perf"));
private final Executor executor;
- private final File indexRootDir;
private final File indexWorkDir;
private final AtomicInteger readerLocalReadCount = new AtomicInteger();
@@ -122,6 +120,7 @@ public class IndexCopier implements Copy
private final Set<LocalIndexFile> copyInProgressFiles =
Collections.newSetFromMap(new ConcurrentHashMap<LocalIndexFile, Boolean>());
private final boolean prefetchEnabled;
private volatile boolean closed;
+ private final IndexRootDirectory indexRootDirectory;
public IndexCopier(Executor executor, File indexRootDir) throws
IOException {
this(executor, indexRootDir, false);
@@ -129,9 +128,9 @@ public class IndexCopier implements Copy
public IndexCopier(Executor executor, File indexRootDir, boolean
prefetchEnabled) throws IOException {
this.executor = executor;
- this.indexRootDir = indexRootDir;
this.prefetchEnabled = prefetchEnabled;
this.indexWorkDir = initializerWorkDir(indexRootDir);
+ this.indexRootDirectory = new IndexRootDirectory(indexRootDir);
}
public Directory wrapForRead(String indexPath, IndexDefinition definition,
@@ -155,15 +154,13 @@ public class IndexCopier implements Copy
return indexWorkDir;
}
- File getIndexRootDir() {
- return indexRootDir;
+ IndexRootDirectory getIndexRootDirectory() {
+ return indexRootDirectory;
}
protected Directory createLocalDirForIndexWriter(IndexDefinition
definition) throws IOException {
String indexPath = definition.getIndexPathFromConfig();
- File indexDir = getIndexDir(indexPath);
- String newVersion = String.valueOf(definition.getReindexCount());
- File indexWriterDir = getVersionedDir(indexPath, indexDir, newVersion);
+ File indexWriterDir = getIndexDir(definition, indexPath);
//By design indexing in Oak is single threaded so Lucene locking
//can be disabled
@@ -174,30 +171,20 @@ public class IndexCopier implements Copy
}
protected Directory createLocalDirForIndexReader(String indexPath,
IndexDefinition definition) throws IOException {
- File indexDir = getIndexDir(indexPath);
- String newVersion = String.valueOf(definition.getReindexCount());
- File versionedIndexDir = getVersionedDir(indexPath, indexDir,
newVersion);
- Directory result = FSDirectory.open(versionedIndexDir);
-
- String oldVersion = indexPathVersionMapping.put(indexPath, newVersion);
- if (!newVersion.equals(oldVersion) && oldVersion != null) {
- result = new DeleteOldDirOnClose(result, new File(indexDir,
oldVersion));
+ File indexDir = getIndexDir(definition, indexPath);
+ Directory result = FSDirectory.open(indexDir);
+
+ String newPath = indexDir.getAbsolutePath();
+ //TODO Account for type of path also
+ String oldPath = indexPathVersionMapping.put(indexPath, newPath);
+ if (!newPath.equals(oldPath) && oldPath != null) {
+ result = new DeleteOldDirOnClose(result, new File(oldPath));
}
return result;
}
- private File getVersionedDir(String indexPath, File indexDir, String
newVersion) {
- File versionedIndexDir = new File(indexDir, newVersion);
- if (!versionedIndexDir.exists()) {
- checkState(versionedIndexDir.mkdirs(), "Cannot create directory
%s", versionedIndexDir);
- }
- indexPathMapping.put(indexPath, indexDir.getAbsolutePath());
- return versionedIndexDir;
- }
-
- public File getIndexDir(String indexPath) {
- String subDir = Hashing.sha256().hashString(indexPath,
Charsets.UTF_8).toString();
- return new File(indexRootDir, subDir);
+ public File getIndexDir(IndexDefinition definition, String indexPath)
throws IOException {
+ return indexRootDirectory.getIndexDir(definition, indexPath);
}
Map<String, LocalIndexFile> getFailedToDeleteFiles() {
@@ -1229,14 +1216,16 @@ public class IndexCopier implements Copy
TabularType tt = new TabularType(IndexMappingData.class.getName(),
"Lucene Index Stats", IndexMappingData.TYPE, new
String[]{"jcrPath"});
tds = new TabularDataSupport(tt);
- for (Map.Entry<String, String> e : indexPathMapping.entrySet()){
- String size =
humanReadableByteCount(FileUtils.sizeOfDirectory(new File(e.getValue())));
+ for (LocalIndexDir indexDir :
indexRootDirectory.getAllLocalIndexes()){
+ String size = humanReadableByteCount(indexDir.size());
tds.put(new CompositeDataSupport(IndexMappingData.TYPE,
IndexMappingData.FIELD_NAMES,
- new String[]{e.getKey(), e.getValue(), size}));
+ new String[]{indexDir.getJcrPath(),
indexDir.getFSPath(), size}));
}
} catch (OpenDataException e){
throw new IllegalStateException(e);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
}
return tds;
}
@@ -1302,7 +1291,7 @@ public class IndexCopier implements Copy
@Override
public String getLocalIndexSize() {
- return humanReadableByteCount(FileUtils.sizeOfDirectory(indexRootDir));
+ return humanReadableByteCount(indexRootDirectory.getSize());
}
@Override
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java?rev=1750769&r1=1750768&r2=1750769&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
Thu Jun 30 11:08:39 2016
@@ -87,7 +87,7 @@ import static org.apache.jackrabbit.oak.
import static
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
import static
org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NODE_TYPES_PATH;
-class IndexDefinition implements Aggregate.AggregateMapper {
+public final class IndexDefinition implements Aggregate.AggregateMapper {
/**
* Name of the internal property that contains the child order defined in
* org.apache.jackrabbit.oak.plugins.tree.impl.TreeConstants
@@ -125,6 +125,16 @@ class IndexDefinition implements Aggrega
*/
static final String INDEX_VERSION = ":version";
+ /**
+ * Hidden node under index definition which is used to store meta info
+ */
+ static final String STATUS_NODE = ":status";
+
+ /**
+ * Meta property which provides the unique id
+ */
+ static final String PROP_UID = "uid";
+
private static String TYPES_ALLOW_ALL_NAME = "all";
static final int TYPES_ALLOW_NONE = PropertyType.UNDEFINED;
@@ -220,6 +230,9 @@ class IndexDefinition implements Aggrega
private final String indexPath;
+ @Nullable
+ private final String uid;
+
public IndexDefinition(NodeState root, NodeBuilder defn) {
this(root, defn.getBaseState(), defn);
}
@@ -231,6 +244,7 @@ class IndexDefinition implements Aggrega
public IndexDefinition(NodeState root, NodeState defn, @Nullable
NodeBuilder defnb) {
this.root = root;
this.version = determineIndexFormatVersion(defn, defnb);
+ this.uid = determineUniqueId(defn, defnb);
this.definition = defn;
this.indexPath = determineIndexPath(defn, defnb);
this.indexName = indexPath;
@@ -417,6 +431,11 @@ class IndexDefinition implements Aggrega
return queryPaths;
}
+ @CheckForNull
+ public String getUniqueId() {
+ return uid;
+ }
+
@Override
public String toString() {
return "Lucene Index : " + indexName;
@@ -1508,6 +1527,24 @@ class IndexDefinition implements Aggrega
return 0;
}
+ @CheckForNull
+ private static String determineUniqueId(NodeState defn, @Nullable
NodeBuilder defnb) {
+ String uid = null;
+
+ //Check in builder first as that would have latest value
+ if (defnb != null){
+ uid = defnb.getChildNode(STATUS_NODE).getString(PROP_UID);
+ }
+
+ //Fallback to NodeState
+ if (uid == null){
+ uid = defn.getChildNode(STATUS_NODE).getString(PROP_UID);
+ }
+
+ //uid can be null if an old format index has not received any update
+ return uid;
+ }
+
public boolean getActiveDeleteEnabled() {
return activeDelete >= 0;
}
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java?rev=1750769&r1=1750768&r2=1750769&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java
Thu Jun 30 11:08:39 2016
@@ -164,6 +164,7 @@ public class LuceneIndexEditorContext {
LuceneIndexEditorContext(NodeState root, NodeBuilder definition,
IndexUpdateCallback updateCallback,
@Nullable IndexCopier indexCopier,
ExtractedTextCache extractedTextCache,
IndexAugmentorFactory augmentorFactory) {
+ configureUniqueId(definition);
this.root = root;
this.definitionBuilder = definition;
this.indexCopier = indexCopier;
@@ -373,6 +374,7 @@ public class LuceneIndexEditorContext {
reindex = true;
IndexFormatVersion version =
IndexDefinition.determineVersionForFreshIndex(definitionBuilder);
definitionBuilder.setProperty(IndexDefinition.INDEX_VERSION,
version.getVersion());
+ configureUniqueId(definitionBuilder);
//Refresh the index definition based on update builder state
definition = new IndexDefinition(root, definitionBuilder);
@@ -428,6 +430,20 @@ public class LuceneIndexEditorContext {
return reindex;
}
+ public static void configureUniqueId(NodeBuilder definition) {
+ NodeBuilder status = definition.child(IndexDefinition.STATUS_NODE);
+ if (!status.hasProperty(IndexDefinition.PROP_UID)) {
+ String uid;
+ try {
+ uid = String.valueOf(Clock.SIMPLE.getTimeIncreasing());
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ uid = String.valueOf(Clock.SIMPLE.getTime());
+ }
+ status.setProperty(IndexDefinition.PROP_UID, uid);
+ }
+ }
+
private static Parser initializeTikaParser(IndexDefinition definition) {
ClassLoader current = Thread.currentThread().getContextClassLoader();
try {
Added:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMeta.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMeta.java?rev=1750769&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMeta.java
(added)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMeta.java
Thu Jun 30 11:08:39 2016
@@ -0,0 +1,84 @@
+/*
+ * 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.plugins.index.lucene.directory;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Properties;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Represents the index metadata file content as present in index-details.txt
+ */
+final class IndexMeta implements Comparable<IndexMeta> {
+ final String indexPath;
+ final long creationTime;
+ final int metaFormatVersion = 1;
+
+ public IndexMeta(String indexPath, long creationTime) {
+ this.indexPath = indexPath;
+ this.creationTime = creationTime;
+ }
+
+ public IndexMeta(File file) throws IOException {
+ Properties p = loadFromFile(file);
+ this.indexPath = checkNotNull(p.getProperty("indexPath"));
+ this.creationTime =
Long.valueOf(checkNotNull(p.getProperty("creationTime")));
+ }
+
+ public void writeTo(File file) throws IOException {
+ Properties p = new Properties();
+ p.setProperty("metaFormatVersion", String.valueOf(metaFormatVersion));
+ p.setProperty("indexPath", indexPath);
+ p.setProperty("creationTime", String.valueOf(creationTime));
+ OutputStream os = null;
+ try {
+ os = new BufferedOutputStream(new FileOutputStream(file));
+ p.store(os, "Index metadata");
+ } finally {
+ org.apache.commons.io.IOUtils.closeQuietly(os);
+ }
+ }
+
+ @Override
+ public int compareTo(IndexMeta o) {
+ return Long.compare(creationTime, o.creationTime);
+ }
+
+ private static Properties loadFromFile(File file) throws IOException {
+ InputStream is = null;
+ try {
+ is = new BufferedInputStream(new FileInputStream(file));
+ Properties p = new Properties();
+ p.load(is);
+ return p;
+ } finally {
+ org.apache.commons.io.IOUtils.closeQuietly(is);
+ }
+ }
+}
+
\ No newline at end of file
Propchange:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMeta.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectory.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectory.java?rev=1750769&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectory.java
(added)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectory.java
Thu Jun 30 11:08:39 2016
@@ -0,0 +1,162 @@
+/*
+ * 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.plugins.index.lucene.directory;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.hash.Hashing;
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition;
+import org.apache.jackrabbit.oak.stats.Clock;
+
+import static com.google.common.base.Preconditions.checkState;
+
+public class IndexRootDirectory {
+ public static final String INDEX_METADATA_FILE_NAME = "index-details.txt";
+
+ private final File indexRootDir;
+
+ public IndexRootDirectory(File indexRootDir) {
+ this.indexRootDir = indexRootDir;
+ }
+
+ public long getSize(){
+ return FileUtils.sizeOfDirectory(indexRootDir);
+ }
+
+ public File getIndexDir(IndexDefinition definition, String indexPath)
throws IOException {
+ String uid = definition.getUniqueId();
+
+ if (uid == null) {
+ //Old format
+ String subDir = getPathHash(indexPath);
+ File baseFolder = new File(indexRootDir, subDir);
+ String version = String.valueOf(definition.getReindexCount());
+ File indexDir = new File(baseFolder, version);
+ if (!indexDir.exists()){
+ checkState(indexDir.mkdirs(), "Not able to create folder
[%s]", indexDir);
+ }
+ return indexDir;
+ } else {
+ String fileSystemSafeName = getIndexFolderBaseName(indexPath);
+ String folderName = fileSystemSafeName + "-" + uid;
+ File baseFolder = new File(indexRootDir, folderName);
+
+ //Create a base folder <index node name>-<uid>
+ //and add a readme file having index info
+ if (!baseFolder.exists()){
+ checkState(baseFolder.mkdir(), "Not able to create folder
[%s]", baseFolder);
+ File readMe = new File(baseFolder, INDEX_METADATA_FILE_NAME);
+ IndexMeta meta = new IndexMeta(indexPath, getTime());
+ meta.writeTo(readMe);
+ }
+
+ //Create index folder under that
+ //TODO Add support for multiple folders depending on type of
content
+ File indexFolder = new File(baseFolder, "default");
+ if (!indexFolder.exists()) {
+ checkState(indexFolder.mkdir(), "Not able to create folder
[%s]", indexFolder);
+ }
+
+ return indexFolder;
+ }
+ }
+
+ /**
+ * Returns the most recent directory for each index. If for an index 2
versions are present
+ * then it would return the most recent version
+ */
+ public List<LocalIndexDir> getAllLocalIndexes() throws IOException {
+ Map<String, List<LocalIndexDir>> mapping = getIndexesPerPath();
+ List<LocalIndexDir> result =
Lists.newArrayListWithCapacity(mapping.size());
+ for (Map.Entry<String, List<LocalIndexDir>> e : mapping.entrySet()){
+ result.add(e.getValue().get(0));
+ }
+ return result;
+ }
+
+ public List<LocalIndexDir> getLocalIndexes(String jcrPath) throws
IOException {
+ List<LocalIndexDir> result = getIndexesPerPath().get(jcrPath);
+ return result == null ? Collections.<LocalIndexDir>emptyList() :
result;
+ }
+
+ static String getIndexFolderBaseName(String indexPath) {
+ String nodeName = PathUtils.getName(indexPath);
+
+ //Strip of any char outside of a-zA-Z0-9-
+ return nodeName.replaceAll("\\W+", "");
+ }
+
+ static String getPathHash(String indexPath) {
+ return Hashing.sha256().hashString(indexPath,
Charsets.UTF_8).toString();
+ }
+
+ /**
+ * The value is a sorted list with most recent version of index at the
start
+ */
+ private Map<String, List<LocalIndexDir>> getIndexesPerPath() throws
IOException {
+ File[] dirs = indexRootDir.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ if (!file.isDirectory()){
+ return false;
+ }
+ File metaFile = new File(file, INDEX_METADATA_FILE_NAME);
+ return metaFile.exists();
+ }
+ });
+
+ ListMultimap<String, LocalIndexDir> pathToDirMap =
ArrayListMultimap.create();
+ for (File indexDir : dirs){
+ LocalIndexDir localIndexDir = new LocalIndexDir(indexDir);
+ pathToDirMap.get(localIndexDir.getJcrPath()).add(localIndexDir);
+ }
+
+ Map<String, List<LocalIndexDir>> result = Maps.newHashMap();
+ for (Map.Entry<String, Collection<LocalIndexDir>> e :
pathToDirMap.asMap().entrySet()){
+ List<LocalIndexDir> sortedDirs = new ArrayList<>(e.getValue());
+ Collections.sort(sortedDirs,
Collections.<LocalIndexDir>reverseOrder());
+ result.put(e.getKey(), sortedDirs);
+ }
+ return result;
+ }
+
+ private static long getTime() {
+ try {
+ return Clock.SIMPLE.getTimeIncreasing();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ return Clock.SIMPLE.getTimeMonotonic();
+ }
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectory.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDir.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDir.java?rev=1750769&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDir.java
(added)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDir.java
Thu Jun 30 11:08:39 2016
@@ -0,0 +1,77 @@
+/*
+ * 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.plugins.index.lucene.directory;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.io.FileUtils;
+
+import static com.google.common.base.Preconditions.checkState;
+import static
org.apache.jackrabbit.oak.plugins.index.lucene.directory.IndexRootDirectory.INDEX_METADATA_FILE_NAME;
+
+public final class LocalIndexDir implements Comparable<LocalIndexDir> {
+ final File dir;
+ final IndexMeta indexMeta;
+
+ public LocalIndexDir(File dir) throws IOException {
+ this.dir = dir;
+ File indexDetails = new File(dir,
IndexRootDirectory.INDEX_METADATA_FILE_NAME);
+ checkState(isIndexDir(dir), "No file [%s] found in dir [%s]",
+ INDEX_METADATA_FILE_NAME, dir.getAbsolutePath());
+ this.indexMeta = new IndexMeta(indexDetails);
+ }
+
+ public long size() {
+ return FileUtils.sizeOfDirectory(dir);
+ }
+
+ public boolean isEmpty() {
+ String[] listing = dir.list();
+
+ //If some IO error occurs listing would be null
+ //In such a case better to return false
+ if (listing == null) {
+ return false;
+ }
+
+ //If the dir only has the meta file then it would be
+ //considered as empty
+ return listing.length == 1;
+ }
+
+ public String getJcrPath() {
+ return indexMeta.indexPath;
+ }
+
+ public String getFSPath() {
+ return dir.getAbsolutePath();
+ }
+
+ @Override
+ public int compareTo(LocalIndexDir o) {
+ return indexMeta.compareTo(o.indexMeta);
+ }
+
+ static boolean isIndexDir(File file){
+ File indexDetails = new File(file,
IndexRootDirectory.INDEX_METADATA_FILE_NAME);
+ return indexDetails.exists();
+ }
+}
\ No newline at end of file
Propchange:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDir.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopierTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopierTest.java?rev=1750769&r1=1750768&r2=1750769&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopierTest.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexCopierTest.java
Thu Jun 30 11:08:39 2016
@@ -69,9 +69,9 @@ import org.junit.rules.TemporaryFolder;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newHashSet;
import static
com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
-import static
org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_COUNT;
import static
org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent.INITIAL_CONTENT;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -92,9 +92,12 @@ public class IndexCopierTest {
private NodeBuilder builder = root.builder();
+ private String indexPath = "/oak:index/test";
+
@Before
public void setUp(){
- builder.setProperty(IndexConstants.INDEX_PATH, "/oak:index/test");
+ builder.setProperty(IndexConstants.INDEX_PATH, indexPath);
+ LuceneIndexEditorContext.configureUniqueId(builder);
}
@Test
@@ -200,8 +203,7 @@ public class IndexCopierTest {
readAndAssert(wrapped, "t1", t1);
//t1 should now be added to testDir
- File indexBaseDir = c1.getIndexDir("/foo");
- File indexDir = new File(indexBaseDir, "0");
+ File indexDir = c1.getIndexDir(defn, "/foo");
assertTrue(new File(indexDir, "t1").exists());
TabularData td = c1.getIndexPathMapping();
@@ -215,7 +217,7 @@ public class IndexCopierTest {
IndexCopier c1 = new IndexCopier(sameThreadExecutor(), getWorkDir());
Directory remote = new CloseSafeDir();
- Directory w1 = c1.wrapForRead("/foo", defn, remote);
+ Directory w1 = c1.wrapForRead(indexPath, defn, remote);
byte[] t1 = writeFile(remote, "t1");
byte[] t2 = writeFile(remote , "t2");
@@ -224,24 +226,24 @@ public class IndexCopierTest {
readAndAssert(w1, "t2", t2);
//t1 should now be added to testDir
- File indexBaseDir = c1.getIndexDir("/foo");
- File indexDir = new File(indexBaseDir, "0");
+ File indexDir = c1.getIndexDir(defn, indexPath);
assertTrue(new File(indexDir, "t1").exists());
- builder.setProperty(REINDEX_COUNT, 1);
+ doReindex(builder);
defn = new IndexDefinition(root, builder.getNodeState());
//Close old version
w1.close();
//Get a new one with updated reindexCount
- Directory w2 = c1.wrapForRead("/foo", defn, remote);
+ Directory w2 = c1.wrapForRead(indexPath, defn, remote);
readAndAssert(w2, "t1", t1);
w2.close();
assertFalse("Old index directory should have been removed",
indexDir.exists());
- File indexDir2 = new File(indexBaseDir, "1");
+ //Assert that new index file do exist and not get removed
+ File indexDir2 = c1.getIndexDir(defn, indexPath);
assertTrue(new File(indexDir2, "t1").exists());
}
@@ -580,9 +582,13 @@ public class IndexCopierTest {
readAndAssert(remote, "t1", t1);
//Work dir must be empty post close
- List<File> files = new
ArrayList<File>(FileUtils.listFiles(copier.getIndexRootDir(), null, true));
- assertEquals(1, files.size());
- assertEquals("t1", files.get(0).getName());
+ File indexDir = copier.getIndexDir(defn, "foo");
+ List<File> files = new ArrayList<File>(FileUtils.listFiles(indexDir,
null, true));
+ Set<String> fileNames = Sets.newHashSet();
+ for (File f : files){
+ fileNames.add(f.getName());
+ }
+ assertThat(fileNames, contains("t1"));
}
@Test
@@ -993,6 +999,11 @@ public class IndexCopierTest {
executorService.shutdown();
}
+ private static void doReindex(NodeBuilder builder) {
+ builder.child(IndexDefinition.STATUS_NODE).remove();
+ LuceneIndexEditorContext.configureUniqueId(builder);
+ }
+
private byte[] writeFile(Directory dir, String name) throws IOException {
byte[] data = randomBytes(rnd.nextInt(maxFileSize) + 1);
IndexOutput o = dir.createOutput(name, IOContext.DEFAULT);
Modified:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinitionTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinitionTest.java?rev=1750769&r1=1750768&r2=1750769&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinitionTest.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinitionTest.java
Thu Jun 30 11:08:39 2016
@@ -846,6 +846,26 @@ public class IndexDefinitionTest {
assertEquals(1.5, defn.getCostPerEntry(), 0.0);
}
+ @Test
+ public void uniqueId() throws Exception{
+ IndexDefinition defn = new IndexDefinition(root,
builder.getNodeState());
+ assertNull(defn.getUniqueId());
+
+ //Check that uniqueId is properly seeded
+ LuceneIndexEditorContext.configureUniqueId(builder);
+ String uid =
builder.child(IndexDefinition.STATUS_NODE).getString(IndexDefinition.PROP_UID);
+ assertNotNull(uid);
+
+ //Assert via NodeState
+ defn = new IndexDefinition(root, builder.getNodeState());
+ assertEquals(uid, defn.getUniqueId());
+
+ //Assert via NodeBuilder
+ defn = new IndexDefinition(root, EMPTY_NODE, builder);
+ assertEquals(uid, defn.getUniqueId());
+
+ }
+
//TODO indexesAllNodesOfMatchingType - with nullCheckEnabled
private static IndexingRule getRule(IndexDefinition defn, String typeName){
Modified:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java?rev=1750769&r1=1750768&r2=1750769&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
Thu Jun 30 11:08:39 2016
@@ -76,6 +76,7 @@ import org.apache.jackrabbit.oak.api.Com
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider;
+import org.apache.jackrabbit.oak.plugins.index.lucene.directory.LocalIndexDir;
import org.apache.jackrabbit.oak.plugins.index.lucene.score.ScorerProvider;
import
org.apache.jackrabbit.oak.plugins.index.lucene.score.ScorerProviderFactory;
import org.apache.jackrabbit.oak.plugins.memory.ArrayBasedBlob;
@@ -118,7 +119,6 @@ import org.apache.lucene.queries.CustomS
import org.apache.lucene.search.Query;
import org.junit.After;
import org.junit.Assert;
-import org.junit.Ignore;
import org.junit.Test;
import com.google.common.base.Function;
@@ -770,7 +770,9 @@ public class LuceneIndexTest {
@Test
public void luceneWithCopyOnReadDirAndReindex() throws Exception{
NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
- newLucenePropertyIndexDefinition(index, "lucene",
ImmutableSet.of("foo", "foo2", "foo3"), null);
+ NodeBuilder defnState =
+ newLucenePropertyIndexDefinition(index, "lucene",
ImmutableSet.of("foo", "foo2", "foo3"), null);
+ IndexDefinition definition = new IndexDefinition(root,
defnState.getNodeState());
//1. Create index in two increments
NodeState before = builder.getNodeState();
@@ -799,10 +801,12 @@ public class LuceneIndexTest {
indexed = HOOK.processCommit(indexed,
builder.getNodeState(),CommitInfo.EMPTY);
tracker.update(indexed);
+ defnState = builder.child(INDEX_DEFINITIONS_NAME).child("lucene");
+ definition = new IndexDefinition(root, defnState.getNodeState());
assertQuery(tracker, indexed, "foo2", "bar2");
//If reindex case handled properly then invalid count should be zero
assertEquals(0, copier.getInvalidFileCount());
- assertEquals(2,
copier.getIndexDir("/oak:index/lucene").listFiles().length);
+ assertEquals(2,
copier.getIndexRootDirectory().getLocalIndexes("/oak:index/lucene").size());
//3. Update again. Now with close of previous reader
//orphaned directory must be removed
@@ -812,7 +816,14 @@ public class LuceneIndexTest {
tracker.update(indexed);
assertQuery(tracker, indexed, "foo3", "bar3");
assertEquals(0, copier.getInvalidFileCount());
- assertEquals(1,
copier.getIndexDir("/oak:index/lucene").listFiles().length);
+ List<LocalIndexDir> idxDirs =
copier.getIndexRootDirectory().getLocalIndexes("/oak:index/lucene");
+ List<LocalIndexDir> nonEmptyDirs = Lists.newArrayList();
+ for (LocalIndexDir dir : idxDirs){
+ if (!dir.isEmpty()){
+ nonEmptyDirs.add(dir);
+ }
+ }
+ assertEquals(1, nonEmptyDirs.size());
}
@Test
Modified:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java?rev=1750769&r1=1750768&r2=1750769&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
Thu Jun 30 11:08:39 2016
@@ -52,6 +52,7 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.plugins.index.lucene.TestUtil.useV2;
import static
org.apache.jackrabbit.oak.plugins.index.property.OrderedIndex.OrderDirection;
import static
org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
+import static
org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent.INITIAL_CONTENT;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
@@ -102,6 +103,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.index.nodetype.NodeTypeIndexProvider;
import
org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.memory.ArrayBasedBlob;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
import org.apache.jackrabbit.oak.plugins.nodetype.write.NodeTypeRegistry;
@@ -109,6 +111,9 @@ import org.apache.jackrabbit.oak.query.A
import org.apache.jackrabbit.oak.spi.commit.Observer;
import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.apache.jackrabbit.util.ISO8601;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
@@ -135,6 +140,8 @@ public class LucenePropertyIndexTest ext
private LuceneIndexEditorProvider editorProvider;
+ private NodeStore nodeStore;
+
@After
public void after() {
new ExecutorCloser(executorService).close();
@@ -150,7 +157,8 @@ public class LucenePropertyIndexTest ext
IndexCopier copier = createIndexCopier();
editorProvider = new LuceneIndexEditorProvider(copier, new
ExtractedTextCache(10* FileUtils.ONE_MB, 100));
LuceneIndexProvider provider = new LuceneIndexProvider(copier);
- return new Oak()
+ nodeStore = new MemoryNodeStore();
+ return new Oak(nodeStore)
.with(new InitialContent())
.with(new OpenSecurityProvider())
.with((QueryIndexProvider) provider)
@@ -2131,6 +2139,40 @@ public class LucenePropertyIndexTest ext
}
@Test
+ public void uniqueIdInitializedInIndexing() throws Exception{
+ Tree idx = createIndex("test1", of("propa", "propb"));
+ Tree props = TestUtil.newRulePropTree(idx, "nt:base");
+ Tree prop1 = props.addChild(TestUtil.unique("prop"));
+ prop1.setProperty(LuceneIndexConstants.PROP_NAME, "jcr:title");
+ prop1.setProperty(LuceneIndexConstants.PROP_PROPERTY_INDEX, true);
+ root.commit();
+
+ //Make some changes such incremental indexing happens
+ root.getTree("/").addChild("a").setProperty("jcr:title", "foo");
+ root.commit();
+
+ NodeState idxState = NodeStateUtils.getNode(nodeStore.getRoot(),
idx.getPath());
+ IndexDefinition defn = new IndexDefinition(INITIAL_CONTENT, idxState);
+
+ //Check that with normal indexing uid gets initialized
+ String uid = defn.getUniqueId();
+ assertNotNull(defn.getUniqueId());
+
+ //Now trigger a reindex
+ idx.setProperty(IndexConstants.REINDEX_PROPERTY_NAME, true);
+ root.commit();
+
+ //Refetch the NodeState
+ idxState = NodeStateUtils.getNode(nodeStore.getRoot(), idx.getPath());
+ defn = new IndexDefinition(INITIAL_CONTENT, idxState);
+
+ //Check that uid is also initialized in reindexing
+ String uid2 = defn.getUniqueId();
+ assertNotNull(defn.getUniqueId());
+ assertNotEquals(uid, uid2);
+ }
+
+ @Test
public void fulltextQueryWithSpecialChars() throws Exception{
Tree idx = createIndex("test1", of("propa", "propb"));
Tree props = TestUtil.newRulePropTree(idx, "nt:base");
Added:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMetaTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMetaTest.java?rev=1750769&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMetaTest.java
(added)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMetaTest.java
Thu Jun 30 11:08:39 2016
@@ -0,0 +1,45 @@
+/*
+ * 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.plugins.index.lucene.directory;
+
+import java.io.File;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static org.junit.Assert.*;
+
+public class IndexMetaTest {
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder(new
File("target"));
+
+ @Test
+ public void writeTo() throws Exception {
+ IndexMeta m = new IndexMeta("/a/b", 100);
+ File f = temporaryFolder.newFile();
+ m.writeTo(f);
+ IndexMeta m2 = new IndexMeta(f);
+
+ assertEquals(m.indexPath, m2.indexPath);
+ assertEquals(m.creationTime, m2.creationTime);
+ }
+
+}
\ No newline at end of file
Propchange:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexMetaTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectoryTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectoryTest.java?rev=1750769&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectoryTest.java
(added)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectoryTest.java
Thu Jun 30 11:08:39 2016
@@ -0,0 +1,129 @@
+/*
+ * 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.plugins.index.lucene.directory;
+
+import java.io.File;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
+import org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition;
+import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexEditorContext;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static
org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent.INITIAL_CONTENT;
+import static org.junit.Assert.*;
+
+public class IndexRootDirectoryTest {
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder(new
File("target"));
+
+ private IndexRootDirectory dir;
+
+ private NodeState root = INITIAL_CONTENT;
+ private NodeBuilder builder = EMPTY_NODE.builder();
+
+ @Before
+ public void setUp(){
+ dir = new IndexRootDirectory(temporaryFolder.getRoot());
+ }
+
+ @Test
+ public void getIndexDirOldFormat() throws Exception{
+ File f1 = dir.getIndexDir(getDefn(), "/a/b");
+ assertFalse(LocalIndexDir.isIndexDir(f1));
+
+ builder.setProperty(IndexConstants.REINDEX_COUNT, 1);
+ File f2 = dir.getIndexDir(getDefn(), "/a/b");
+ File f3 = dir.getIndexDir(getDefn(), "/a/b");
+ //Both should be same dir
+ assertEquals(f2, f3);
+
+ assertEquals(2, f2.getParentFile().list().length);
+ }
+
+ @Test
+ public void newFormat() throws Exception{
+ LuceneIndexEditorContext.configureUniqueId(builder);
+ File f1 = dir.getIndexDir(getDefn(), "/a/b");
+ File f2 = dir.getIndexDir(getDefn(), "/a/b");
+ assertEquals(f1, f2);
+ }
+
+ @Test
+ public void reindexCaseWithSamePath() throws Exception{
+ LuceneIndexEditorContext.configureUniqueId(builder);
+ File f1 = dir.getIndexDir(getDefn(), "/a/b");
+
+ LuceneIndexEditorContext.configureUniqueId(resetBuilder());
+ File f2 = dir.getIndexDir(getDefn(), "/a/b");
+
+ assertNotEquals(f1, f2);
+ List<LocalIndexDir> dirs = dir.getLocalIndexes("/a/b");
+
+ //First one should be F2 as it got created later
+ assertEquals(f2.getParentFile().getAbsolutePath(),
dirs.get(0).getFSPath());
+
+ assertTrue(dir.getLocalIndexes("/a/b/c").isEmpty());
+ }
+
+ @Test
+ public void allLocalIndexes() throws Exception{
+ LuceneIndexEditorContext.configureUniqueId(builder);
+ File fa1 = dir.getIndexDir(getDefn(), "/a");
+ LuceneIndexEditorContext.configureUniqueId(resetBuilder());
+ File fa2 = dir.getIndexDir(getDefn(), "/a");
+
+ LuceneIndexEditorContext.configureUniqueId(builder);
+ File fb1 = dir.getIndexDir(getDefn(), "/b");
+ LuceneIndexEditorContext.configureUniqueId(resetBuilder());
+ File fb2 = dir.getIndexDir(getDefn(), "/b");
+
+ List<LocalIndexDir> dirs = dir.getAllLocalIndexes();
+ assertEquals(2, dirs.size());
+
+ assertEquals(fb2.getParentFile().getAbsolutePath(), getDir("/b",
dirs).getFSPath());
+ assertEquals(fa2.getParentFile().getAbsolutePath(), getDir("/a",
dirs).getFSPath());
+ }
+
+ private NodeBuilder resetBuilder() {
+ builder = EMPTY_NODE.builder();
+ return builder;
+ }
+
+ private IndexDefinition getDefn(){
+ return new IndexDefinition(root, builder.getNodeState());
+ }
+
+ private static LocalIndexDir getDir(String jcrPath, List<LocalIndexDir>
dirs){
+ for (LocalIndexDir dir : dirs){
+ if (dir.getJcrPath().equals(jcrPath)){
+ return dir;
+ }
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
Propchange:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/IndexRootDirectoryTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDirTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDirTest.java?rev=1750769&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDirTest.java
(added)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDirTest.java
Thu Jun 30 11:08:39 2016
@@ -0,0 +1,90 @@
+/*
+ * 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.plugins.index.lucene.directory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class LocalIndexDirTest {
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder(new
File("target"));
+
+ @Test
+ public void basicStuff() throws Exception{
+ IndexMeta m = new IndexMeta("/a/b", 100);
+ File baseDir = createDirWithIndexMetaFile(m);
+
+ LocalIndexDir dir = new LocalIndexDir(baseDir);
+ assertEquals(dir.getJcrPath(), m.indexPath);
+ assertEquals(dir.getFSPath(), baseDir.getAbsolutePath());
+ assertTrue(dir.isEmpty());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void invalidDir() throws Exception{
+ new LocalIndexDir(temporaryFolder.getRoot());
+ }
+
+ @Test
+ public void nonEmptyDir() throws Exception{
+ IndexMeta m = new IndexMeta("/a/b", 100);
+ File baseDir = createDirWithIndexMetaFile(m);
+ new File(baseDir, "foo").mkdir();
+ LocalIndexDir dir = new LocalIndexDir(baseDir);
+ assertFalse(dir.isEmpty());
+ }
+
+ @Test
+ public void comparison() throws Exception{
+ LocalIndexDir dir = new LocalIndexDir(createDirWithIndexMetaFile(new
IndexMeta("/a/b", 100)));
+ LocalIndexDir dir2 = new LocalIndexDir(createDirWithIndexMetaFile(new
IndexMeta("/a/b/c", 200)));
+ LocalIndexDir dir3 = new LocalIndexDir(createDirWithIndexMetaFile(new
IndexMeta("/a", 300)));
+
+ List<LocalIndexDir> dirs = Lists.newArrayList();
+ dirs.add(dir2);
+ dirs.add(dir);
+ dirs.add(dir3);
+
+ Collections.sort(dirs, Collections.<LocalIndexDir>reverseOrder());
+
+ assertEquals("/a", dirs.get(0).getJcrPath());
+ assertEquals("/a/b/c", dirs.get(1).getJcrPath());
+ assertEquals("/a/b", dirs.get(2).getJcrPath());
+ }
+
+ private File createDirWithIndexMetaFile(IndexMeta m) throws IOException {
+ File baseDir = temporaryFolder.getRoot();
+ File indexMeta = new File(baseDir,
IndexRootDirectory.INDEX_METADATA_FILE_NAME);
+ m.writeTo(indexMeta);
+ return baseDir;
+ }
+
+}
\ No newline at end of file
Propchange:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/LocalIndexDirTest.java
------------------------------------------------------------------------------
svn:eol-style = native