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 2017/05/09 11:42:44 UTC
svn commit: r1794543 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/index/
test/java/org/apache/jackrabbit/oak/plugins/index/
Author: chetanm
Date: Tue May 9 11:42:43 2017
New Revision: 1794543
URL: http://svn.apache.org/viewvc?rev=1794543&view=rev
Log:
OAK-6080 - Index report service
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfo.java (with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoProvider.java (with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoService.java (with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImpl.java (with props)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImplTest.java (with props)
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfo.java?rev=1794543&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfo.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfo.java Tue May 9 11:42:43 2017
@@ -0,0 +1,85 @@
+/*
+ * 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;
+
+import javax.annotation.CheckForNull;
+
+import aQute.bnd.annotation.ProviderType;
+
+/**
+ * Captures information related to index
+ */
+@ProviderType
+public interface IndexInfo {
+ /**
+ * Returns paths of index definition in the repository
+ */
+ String getIndexPath();
+
+ /**
+ * Returns type of index definition like 'property' or 'lucene'
+ */
+ String getType();
+
+ /**
+ * Returns name of the async index lane to which this index is bound to
+ * or null if its not an async index
+ */
+ @CheckForNull
+ String getAsyncLaneName();
+
+ /**
+ * Time in millis at which index was last updated
+ *
+ * @return time in millis or -1 if unknown, -2 if synchronous
+ */
+ long getLastUpdatedTime();
+
+ /**
+ * Returns time in millis of the repository state up to which index is up-to-date.
+ * This may or may not be same as {@code #getLastUpdatedTime}. For e.g.
+ * consider an index at /oak:index/fooIndex bound to async lane "async".
+ * The index might have got updated 2 cycle ago when async indexer traversed content
+ * node which were indexed by this index and it was not updated in last index cycle.
+ * Then {@code indexedUptoTime} is the time of last complete cycle while
+ * {@code lastUpdatedTime} is the time of 2nd last cycle
+ *
+ * @return time in millis or -1 if unknown
+ */
+ long getIndexedUpToTime();
+
+ /**
+ * An estimate of entry count in the index
+ */
+ long getEstimatedEntryCount();
+
+ /**
+ * Index data storage size
+
+ * @return storage size or -1 if unknown
+ */
+ long getSizeInBytes();
+
+ /**
+ * Determines if index definition has changed but no reindexing
+ * was done for that change.
+ */
+ boolean hasIndexDefinitionChangedWithoutReindexing();
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfo.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoProvider.java?rev=1794543&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoProvider.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoProvider.java Tue May 9 11:42:43 2017
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import java.io.IOException;
+
+import javax.annotation.CheckForNull;
+
+import aQute.bnd.annotation.ConsumerType;
+
+/**
+ * Service to be provided by various index implementations.
+ * This would then be used by {@code IndexInfoService}
+ * for collecting information related to index.
+ */
+@ConsumerType
+public interface IndexInfoProvider {
+
+ /**
+ * Index type for this implementation can provide information
+ */
+ String getType();
+
+ @CheckForNull
+ IndexInfo getInfo(String indexPath) throws IOException;
+
+ /**
+ * Determined if the index is valid and usable. If the index is corrupt
+ * then it returns false
+ */
+ boolean isValid(String indexPath) throws IOException;
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoService.java?rev=1794543&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoService.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoService.java Tue May 9 11:42:43 2017
@@ -0,0 +1,53 @@
+/*
+ * 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;
+
+import java.io.IOException;
+
+import javax.annotation.CheckForNull;
+
+import aQute.bnd.annotation.ProviderType;
+
+@ProviderType
+public interface IndexInfoService {
+
+ /**
+ * Returns {@code IndexInfo} for all the indexes present in
+ * the repository
+ */
+ Iterable<IndexInfo> getAllIndexInfo();
+
+ /**
+ * Returns {@code IndexInfo} for index at given path
+ *
+ * @param indexPath path repository
+ *
+ * @return indexInfo for the index or null if there is no index node
+ * found at given path
+ */
+ @CheckForNull
+ IndexInfo getInfo(String indexPath) throws IOException;
+
+ /**
+ * Determined if the index is valid and usable. If the index is corrupt
+ * then it returns false
+ */
+ boolean isValid(String indexPath) throws IOException;
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoService.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImpl.java?rev=1794543&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImpl.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImpl.java Tue May 9 11:42:43 2017
@@ -0,0 +1,169 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.ReferencePolicyOption;
+import org.apache.felix.scr.annotations.Service;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.notNull;
+
+@Component
+@Service
+public class IndexInfoServiceImpl implements IndexInfoService{
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Reference
+ private IndexPathService indexPathService;
+
+ @Reference(policy = ReferencePolicy.DYNAMIC,
+ cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policyOption = ReferencePolicyOption.GREEDY,
+ referenceInterface = IndexInfoProvider.class
+ )
+ private final Map<String, IndexInfoProvider> infoProviders = new ConcurrentHashMap<>();
+
+ @Reference
+ private NodeStore nodeStore;
+
+ @Override
+ public Iterable<IndexInfo> getAllIndexInfo() {
+ return Iterables.filter(Iterables.transform(indexPathService.getIndexPaths(), new Function<String, IndexInfo>() {
+ @Override
+ public IndexInfo apply(String indexPath) {
+ try {
+ return getInfo(indexPath);
+ } catch (Exception e) {
+ log.warn("Error occurred while capturing IndexInfo for path {}", indexPath, e);
+ return null;
+ }
+ }
+ }), notNull());
+ }
+
+ @Override
+ public IndexInfo getInfo(String indexPath) throws IOException {
+ String type = getIndexType(indexPath);
+ if (type == null) return null;
+ IndexInfoProvider infoProvider = infoProviders.get(type);
+
+ if (infoProvider == null) {
+ return new SimpleIndexInfo(indexPath, type);
+ }
+
+ return infoProvider.getInfo(indexPath);
+ }
+
+ @Override
+ public boolean isValid(String indexPath) throws IOException {
+ String type = getIndexType(indexPath);
+ if (type == null){
+ log.warn("No type property defined for index definition at path {}", indexPath);
+ return false;
+ }
+ IndexInfoProvider infoProvider = infoProviders.get(type);
+ if (infoProvider == null){
+ log.warn("No IndexInfoProvider for for index definition at path {} of type {}", indexPath, type);
+ return true; //TODO Reconsider this scenario
+ }
+ return infoProvider.isValid(indexPath);
+ }
+
+ protected void bindInfoProviders(IndexInfoProvider infoProvider){
+ infoProviders.put(checkNotNull(infoProvider.getType()), infoProvider);
+ }
+
+ protected void unbindInfoProviders(IndexInfoProvider infoProvider){
+ infoProviders.remove(infoProvider.getType());
+ }
+
+ private String getIndexType(String indexPath) {
+ NodeState idxState = NodeStateUtils.getNode(nodeStore.getRoot(), indexPath);
+ String type = idxState.getString(IndexConstants.TYPE_PROPERTY_NAME);
+ if (type == null || "disabled".equals(type)){
+ return null;
+ }
+ return type;
+ }
+
+ private static class SimpleIndexInfo implements IndexInfo {
+ private final String indexPath;
+ private final String type;
+
+ private SimpleIndexInfo(String indexPath, String type) {
+ this.indexPath = indexPath;
+ this.type = type;
+ }
+
+ @Override
+ public String getIndexPath() {
+ return indexPath;
+ }
+
+ @Override
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public String getAsyncLaneName() {
+ return null;
+ }
+
+ @Override
+ public long getLastUpdatedTime() {
+ return -1; }
+
+ @Override
+ public long getIndexedUpToTime() {
+ return -1;
+ }
+
+ @Override
+ public long getEstimatedEntryCount() {
+ return -1;
+ }
+
+ @Override
+ public long getSizeInBytes() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasIndexDefinitionChangedWithoutReindexing() {
+ return false;
+ }
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImplTest.java?rev=1794543&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImplTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImplTest.java Tue May 9 11:42:43 2017
@@ -0,0 +1,138 @@
+/*
+ * 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;
+
+import java.util.Collections;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.sling.testing.mock.osgi.MockOsgi;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class IndexInfoServiceImplTest {
+
+ @Rule
+ public final OsgiContext context = new OsgiContext();
+
+ private IndexInfoServiceImpl service = new IndexInfoServiceImpl();
+
+ private NodeStore store = new MemoryNodeStore();
+ private SimpleIndexPathService pathService = new SimpleIndexPathService();
+
+ @Before
+ public void setUp(){
+ context.registerService(NodeStore.class, store);
+ context.registerService(IndexPathService.class, pathService);
+ MockOsgi.injectServices(service, context.bundleContext());
+ }
+
+ @Test
+ public void indexInfo() throws Exception{
+ //1. Test Empty
+ assertNull(service.getInfo("/nonExistingPath"));
+
+ //2. Test when no backing InfoProvider
+ NodeBuilder builder = store.getRoot().builder();
+ builder.child("oak:index").child("fooIndex").setProperty("type", "foo");
+ store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ IndexInfo info = service.getInfo("/oak:index/fooIndex");
+ assertNotNull(info);
+
+ assertEquals("/oak:index/fooIndex", info.getIndexPath());
+ assertEquals("foo", info.getType());
+
+ //3. Test when backing InfoProvider
+ IndexInfo testInfo = mock(IndexInfo.class);
+ when(testInfo.getIndexPath()).thenReturn("/some/other/path");
+
+ IndexInfoProvider infoProvider = mock(IndexInfoProvider.class);
+ when(infoProvider.getType()).thenReturn("foo");
+ when(infoProvider.getInfo(anyString())).thenReturn(testInfo);
+
+ service.bindInfoProviders(infoProvider);
+
+ IndexInfo info2 = service.getInfo("/oak:index/fooIndex");
+ assertNotNull(info2);
+ assertEquals("/some/other/path", info2.getIndexPath());
+ }
+
+ @Test
+ public void allIndexInfo() throws Exception{
+ pathService.paths = Lists.newArrayList("/oak:index/a", "/oak:index/b", "/oak:index/c", "/oak:index/d");
+
+ NodeBuilder builder = store.getRoot().builder();
+ builder.child("oak:index").child("a"); //Index with no type
+ builder.child("oak:index").child("b").setProperty("type", "type-b"); //No backing info provider
+ builder.child("oak:index").child("c").setProperty("type", "type-c"); //Info provider throws exception
+ builder.child("oak:index").child("d").setProperty("type", "type-d"); //Info provider returns result
+ store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ IndexInfoProvider type_c = mock(IndexInfoProvider.class);
+ when(type_c.getInfo(anyString())).thenThrow(new RuntimeException());
+ when(type_c.getType()).thenReturn("type-c");
+
+ IndexInfo infod = mock(IndexInfo.class);
+ when(infod.getType()).thenReturn("type-d");
+ when(infod.getAsyncLaneName()).thenReturn("async-d");
+
+ IndexInfoProvider type_d = mock(IndexInfoProvider.class);
+ when(type_d.getInfo(anyString())).thenReturn(infod);
+ when(type_d.getType()).thenReturn("type-d");
+
+ service.bindInfoProviders(type_c);
+ service.bindInfoProviders(type_d);
+
+ List<IndexInfo> infos = Lists.newArrayList(service.getAllIndexInfo());
+
+ //Result would only have 2 entries. One throwing exception would be ignored
+ assertEquals(2, infos.size());
+
+ for (IndexInfo info : infos) {
+ if (info.getType().equals("type-d")){
+ assertEquals("async-d", info.getAsyncLaneName());
+ }
+ }
+
+ }
+
+ private static class SimpleIndexPathService implements IndexPathService {
+ List<String> paths = Collections.emptyList();
+
+ @Override
+ public Iterable<String> getIndexPaths() {
+ return paths;
+ }
+ }
+
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexInfoServiceImplTest.java
------------------------------------------------------------------------------
svn:eol-style = native