ContentMirrorStoreStrategy implements IndexStoreStrategy { @Override public long count(NodeState root, NodeState indexMeta, Set<String> values, int max) { return count(null, root, indexMeta, this.indexName, values, max); } ContentMirrorStoreStrategy();  ContentMirrorStoreStrategy(String indexName);  ContentMirrorStoreStrategy(String indexName, String pathPrefix, boolean prependPathPrefix); @Override void update(
            Supplier<NodeBuilder> index, String path,
            @Nullable final String indexName,
            @Nullable final NodeBuilder indexMeta,
            Set<String> beforeKeys, Set<String> afterKeys); Iterable<String> query(final Filter filter, final String indexName,
            final NodeState indexMeta, final String indexStorageNodeName,
            final Iterable<String> values); @Override Iterable<String> query(final Filter filter, final String name,
            final NodeState indexMeta, final Iterable<String> values); @Override long count(NodeState root, NodeState indexMeta, Set<String> values, int max); @Override long count(final Filter filter, NodeState root, NodeState indexMeta, Set<String> values, int max); @Override boolean exists(Supplier<NodeBuilder> index, String key); @Override String getIndexNodeName(); static final int TRAVERSING_WARN; }
@Test public void testIndexCountersUsageWithoutPathRestriction() { final long approxNodeCount = 50; final long approxKeyCount = 25; final long entryCount = 30 * DEFAULT_RESOLUTION; final long keyCount = 75; final int maxTraversal = 200; final String keyValue = KEY.iterator().next(); final String approxPropName = COUNT_PROPERTY_PREFIX + "gen_uuid"; IndexStoreStrategy store = new ContentMirrorStoreStrategy(); NodeState root = EMPTY_NODE; NodeBuilder indexMeta = root.builder(); NodeBuilder index = indexMeta.child(INDEX_CONTENT_NODE_NAME); NodeBuilder key = index.child(keyValue); index.setProperty(approxPropName, approxNodeCount, Type.LONG); Assert.assertEquals("Approximate count not used for is-not-null query", approxNodeCount, store.count(root, indexMeta.getNodeState(), null, maxTraversal)); key.setProperty(approxPropName, approxKeyCount, Type.LONG); Assert.assertEquals("Approximate count not used for key=value query", approxKeyCount, store.count(root, indexMeta.getNodeState(), KEY, maxTraversal)); indexMeta .setProperty(ENTRY_COUNT_PROPERTY_NAME, entryCount, Type.LONG); Assert.assertEquals( "Entry count not used even when present for is-not-null query", entryCount, store.count(root, indexMeta.getNodeState(), null, maxTraversal)); Assert.assertTrue("Rough key count not considered for key=value query", entryCount > store.count(root, indexMeta.getNodeState(), KEY, maxTraversal)); indexMeta.setProperty(KEY_COUNT_PROPERTY_NAME, keyCount, Type.LONG); Assert.assertTrue("Key count not considered for key=value query", entryCount > store.count(root, indexMeta.getNodeState(), KEY, maxTraversal)); indexMeta.setProperty(ENTRY_COUNT_PROPERTY_NAME, (long) -1, Type.LONG); Assert.assertEquals( "Entry count not used even when present for is-not-null query", 0, store.count(root, indexMeta.getNodeState(), null, maxTraversal)); }
@Test public void testIndexCountersUsageWithPathRestriction() { final String subPathName = "sub-path"; final int filteredNodeFactor = 2; final long repoTreeApproxNodeCount = 50000; final long repoSubPathApproxNodeCount = repoTreeApproxNodeCount / filteredNodeFactor; final FilterImpl filter = FilterImpl.newTestInstance(); filter.restrictPath("/" + subPathName, Filter.PathRestriction.ALL_CHILDREN); final long approxNodeCount = 100; final long approxKeyCount = 50; final long entryCount = 60 * DEFAULT_RESOLUTION; final long keyCount = 150; final int maxTraversal = 200; final String keyValue = KEY.iterator().next(); final String approxPropName = COUNT_PROPERTY_PREFIX + "gen_uuid"; IndexStoreStrategy store = new ContentMirrorStoreStrategy(); NodeBuilder rootBuilder = EMPTY_NODE.builder(); rootBuilder.setProperty(COUNT_PROPERTY_NAME, repoTreeApproxNodeCount, Type.LONG); NodeBuilder subPath = rootBuilder.child(subPathName); subPath.setProperty(COUNT_PROPERTY_NAME, repoSubPathApproxNodeCount, Type.LONG); NodeState root = rootBuilder.getNodeState(); NodeBuilder indexMeta = rootBuilder.child("propIndex"); NodeBuilder index = indexMeta.child(INDEX_CONTENT_NODE_NAME); NodeBuilder key = index.child(keyValue); index.setProperty(approxPropName, approxNodeCount, Type.LONG); assertInRange( "Approximate count not used for is-not-null query", approxNodeCount, store.count(filter, root, indexMeta.getNodeState(), null, maxTraversal)); key.setProperty(approxPropName, approxKeyCount, Type.LONG); assertInRange( "Approximate count not used for key=value query", approxKeyCount, store.count(filter, root, indexMeta.getNodeState(), KEY, maxTraversal)); indexMeta .setProperty(ENTRY_COUNT_PROPERTY_NAME, entryCount, Type.LONG); assertInRange( "Entry count not used even when present for is-not-null query", entryCount, filteredNodeFactor * store.count(filter, root, indexMeta.getNodeState(), null, maxTraversal)); Assert.assertTrue( "Rough key count not considered for key=value query", entryCount > filteredNodeFactor * store.count(filter, root, indexMeta.getNodeState(), KEY, maxTraversal)); indexMeta.setProperty(KEY_COUNT_PROPERTY_NAME, keyCount, Type.LONG); Assert.assertTrue( "Key count not considered for key=value query", entryCount > filteredNodeFactor * store.count(filter, root, indexMeta.getNodeState(), KEY, maxTraversal)); }