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