Author: tomekr
Date: Tue Sep 19 10:02:55 2017
New Revision: 1808851
URL: http://svn.apache.org/viewvc?rev=1808851&view=rev
Log:
OAK-6675: Implement CompositeNodeStoreStatsMBean
Added:
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreMonitor.java
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStats.java
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStatsMBean.java
jackrabbit/oak/trunk/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStatsTest.java
Modified:
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeState.java
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStore.java
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreService.java
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositionContext.java
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/StringCache.java
jackrabbit/oak/trunk/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/CompositionContextTest.java
Modified:
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java?rev=1808851&r1=1808850&r2=1808851&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java
(original)
+++
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java
Tue Sep 19 10:02:55 2017
@@ -47,6 +47,7 @@ class CompositeNodeBuilder implements No
CompositeNodeBuilder(NodeMap<NodeBuilder> nodeBuilders, CompositionContext
ctx) {
this.ctx = ctx;
this.nodeBuilders = nodeBuilders;
+ ctx.getNodeBuilderMonitor().onCreateNodeObject(getPath());
}
NodeBuilder getNodeBuilder(MountedNodeStore mns) {
@@ -208,7 +209,9 @@ class CompositeNodeBuilder implements No
public NodeBuilder getChildNode(final String name) {
String childPath = simpleConcat(getPath(), name);
if (!ctx.shouldBeComposite(childPath)) {
- return
nodeBuilders.get(ctx.getOwningStore(childPath)).getChildNode(name);
+ MountedNodeStore mns = ctx.getOwningStore(childPath);
+ ctx.getNodeBuilderMonitor().onSwitchNodeToNative(mns.getMount());
+ return nodeBuilders.get(mns).getChildNode(name);
}
return new CompositeNodeBuilder(nodeBuilders.lazyApply((mns, b) ->
b.getChildNode(name)), ctx);
}
Modified:
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeState.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeState.java?rev=1808851&r1=1808850&r2=1808851&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeState.java
(original)
+++
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeState.java
Tue Sep 19 10:02:55 2017
@@ -61,6 +61,7 @@ class CompositeNodeState extends Abstrac
this.path = ctx.getPathCache().get(path);
this.ctx = ctx;
this.nodeStates = nodeStates;
+ ctx.getNodeStateMonitor().onCreateNodeObject(path);
}
NodeState getNodeState(MountedNodeStore mns) {
@@ -105,7 +106,9 @@ class CompositeNodeState extends Abstrac
public NodeState getChildNode(final String name) {
String childPath = simpleConcat(getPath(), name);
if (!ctx.shouldBeComposite(childPath)) {
- return
nodeStates.get(ctx.getOwningStore(childPath)).getChildNode(name);
+ MountedNodeStore mns = ctx.getOwningStore(childPath);
+ ctx.getNodeStateMonitor().onSwitchNodeToNative(mns.getMount());
+ return nodeStates.get(mns).getChildNode(name);
}
NodeMap<NodeState> newNodeStates = nodeStates.lazyApply((mns, n) ->
n.getChildNode(name));
return new CompositeNodeState(childPath, newNodeStates, ctx);
Modified:
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStore.java?rev=1808851&r1=1808850&r2=1808851&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStore.java
(original)
+++
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStore.java
Tue Sep 19 10:02:55 2017
@@ -107,11 +107,11 @@ public class CompositeNodeStore implemen
// visible for testing only
CompositeNodeStore(MountInfoProvider mip, NodeStore globalStore,
List<MountedNodeStore> nonDefaultStore) {
- this(mip, globalStore, nonDefaultStore,
Collections.<String>emptyList());
+ this(mip, globalStore, nonDefaultStore,
Collections.<String>emptyList(), CompositeNodeStoreMonitor.EMPTY_INSTANCE,
CompositeNodeStoreMonitor.EMPTY_INSTANCE);
}
- CompositeNodeStore(MountInfoProvider mip, NodeStore globalStore,
List<MountedNodeStore> nonDefaultStore, List<String> ignoreReadOnlyWritePaths) {
- this.ctx = new CompositionContext(mip, globalStore, nonDefaultStore);
+ CompositeNodeStore(MountInfoProvider mip, NodeStore globalStore,
List<MountedNodeStore> nonDefaultStore, List<String> ignoreReadOnlyWritePaths,
CompositeNodeStoreMonitor nodeStateMonitor, CompositeNodeStoreMonitor
nodeBuilderMonitor) {
+ this.ctx = new CompositionContext(mip, globalStore, nonDefaultStore,
nodeStateMonitor, nodeBuilderMonitor);
this.ignoreReadOnlyWritePaths = new
TreeSet<>(ignoreReadOnlyWritePaths);
this.mergeLock = new ReentrantLock();
}
@@ -470,6 +470,10 @@ public class CompositeNodeStore implemen
private final List<String> ignoreReadOnlyWritePaths =
Lists.newArrayList();
+ private CompositeNodeStoreMonitor nodeStateMonitor =
CompositeNodeStoreMonitor.EMPTY_INSTANCE;
+
+ private CompositeNodeStoreMonitor nodeBuilderMonitor =
CompositeNodeStoreMonitor.EMPTY_INSTANCE;
+
private boolean partialReadOnly = true;
private NodeStoreChecks checks;
@@ -484,6 +488,12 @@ public class CompositeNodeStore implemen
return this;
}
+ public Builder with(CompositeNodeStoreMonitor nodeStateMonitor,
CompositeNodeStoreMonitor nodeBuilderMonitor) {
+ this.nodeStateMonitor = nodeStateMonitor;
+ this.nodeBuilderMonitor = nodeBuilderMonitor;
+ return this;
+ }
+
public Builder addMount(String mountName, NodeStore store) {
checkNotNull(store, "store");
checkNotNull(mountName, "mountName");
@@ -511,7 +521,7 @@ public class CompositeNodeStore implemen
if ( checks != null ) {
nonDefaultStores.forEach( s -> checks.check(globalStore, s));
}
- return new CompositeNodeStore(mip, globalStore, nonDefaultStores,
ignoreReadOnlyWritePaths);
+ return new CompositeNodeStore(mip, globalStore, nonDefaultStores,
ignoreReadOnlyWritePaths, nodeStateMonitor, nodeBuilderMonitor);
}
public void assertPartialMountsAreReadOnly() {
Added:
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreMonitor.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreMonitor.java?rev=1808851&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreMonitor.java
(added)
+++
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreMonitor.java
Tue Sep 19 10:02:55 2017
@@ -0,0 +1,44 @@
+/*
+ * 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.composite;
+
+import org.apache.jackrabbit.oak.spi.mount.Mount;
+import org.osgi.annotation.versioning.ProviderType;
+
+@ProviderType
+public interface CompositeNodeStoreMonitor {
+
+ void onCreateNodeObject(String path);
+
+ void onSwitchNodeToNative(Mount mount);
+
+ void onAddStringCacheEntry();
+
+ CompositeNodeStoreMonitor EMPTY_INSTANCE = new CompositeNodeStoreMonitor()
{
+ @Override
+ public void onCreateNodeObject(String path) {
+ }
+
+ @Override
+ public void onSwitchNodeToNative(Mount mount) {
+ }
+
+ @Override
+ public void onAddStringCacheEntry() {
+ }
+ };
+}
Modified:
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreService.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreService.java?rev=1808851&r1=1808850&r2=1808851&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreService.java
(original)
+++
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreService.java
Tue Sep 19 10:02:55 2017
@@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.oak.composite;
+import com.google.common.io.Closer;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
@@ -37,6 +38,8 @@ import org.apache.jackrabbit.oak.spi.sta
import org.apache.jackrabbit.oak.spi.state.NodeStoreProvider;
import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
@@ -54,7 +57,6 @@ import java.util.Map;
import java.util.Set;
import static com.google.common.collect.Sets.newIdentityHashSet;
-import static
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
@Component(policy = ConfigurationPolicy.REQUIRE)
public class CompositeNodeStoreService {
@@ -74,6 +76,9 @@ public class CompositeNodeStoreService {
@Reference
private NodeStoreChecks checks;
+ @Reference
+ private StatisticsProvider statisticsProvider = StatisticsProvider.NOOP;
+
@Property(label = "Ignore read only writes",
unbounded = PropertyUnbounded.ARRAY,
description = "Writes to these read-only paths won't fail the
commit"
@@ -91,13 +96,19 @@ public class CompositeNodeStoreService {
)
private static final String PROP_SEED_MOUNT = "seedMount";
+ @Property(label = "Gather path statistics",
+ description = "Whether the CompositeNodeStoreStatsMBean should
gather information about the most popular paths (may be expensive)",
+ boolValue = false
+ )
+ private static final String PATH_STATS = "pathStats";
+
private ComponentContext context;
private Set<NodeStoreProvider> nodeStoresInUse = newIdentityHashSet();
private ServiceRegistration nsReg;
- private Registration checkpointReg;
+ private Closer mbeanRegistrations;
private ObserverTracker observerTracker;
@@ -107,17 +118,20 @@ public class CompositeNodeStoreService {
private String seedMount;
+ private boolean pathStats;
+
@Activate
protected void activate(ComponentContext context, Map<String, ?> config)
throws IOException, CommitFailedException {
this.context = context;
ignoreReadOnlyWritePaths =
PropertiesUtil.toStringArray(config.get(PROP_IGNORE_READ_ONLY_WRITES), new
String[0]);
partialReadOnly =
PropertiesUtil.toBoolean(config.get(PROP_PARTIAL_READ_ONLY), true);
seedMount = PropertiesUtil.toString(config.get(PROP_SEED_MOUNT), null);
+ pathStats = PropertiesUtil.toBoolean(config.get(PATH_STATS), false);
registerCompositeNodeStore();
}
@Deactivate
- protected void deactivate() {
+ protected void deactivate() throws IOException {
unregisterCompositeNodeStore();
}
@@ -178,6 +192,10 @@ public class CompositeNodeStoreService {
}
}
+ CompositeNodeStoreStats nodeStateStats = new
CompositeNodeStoreStats(statisticsProvider, "NODE_STATE", pathStats);
+ CompositeNodeStoreStats nodeBuilderStats = new
CompositeNodeStoreStats(statisticsProvider, "NODE_BUILDER", pathStats);
+ builder.with(nodeStateStats, nodeBuilderStats);
+
Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put(Constants.SERVICE_PID, CompositeNodeStore.class.getName());
props.put("oak.nodestore.description", new String[] {
"nodeStoreType=compositeStore" } );
@@ -188,11 +206,23 @@ public class CompositeNodeStoreService {
observerTracker.start(context.getBundleContext());
Whiteboard whiteboard = new OsgiWhiteboard(context.getBundleContext());
- checkpointReg = registerMBean(whiteboard,
+
+ mbeanRegistrations = Closer.create();
+ registerMBean(whiteboard,
CheckpointMBean.class,
new CompositeCheckpointMBean(store),
CheckpointMBean.TYPE,
"Composite node store checkpoint management");
+ registerMBean(whiteboard,
+ CompositeNodeStoreStatsMBean.class,
+ nodeStateStats,
+ CompositeNodeStoreStatsMBean.TYPE,
+ "Composite node store statistics (node state)");
+ registerMBean(whiteboard,
+ CompositeNodeStoreStatsMBean.class,
+ nodeBuilderStats,
+ CompositeNodeStoreStatsMBean.TYPE,
+ "Composite node store statistics (node builder)");
LOG.info("Registering the composite node store");
nsReg = context.getBundleContext().registerService(
@@ -203,6 +233,12 @@ public class CompositeNodeStoreService {
props);
}
+ private <T> void registerMBean(Whiteboard whiteboard,
+ Class<T> iface, T bean, String type, String name) {
+ Registration reg = WhiteboardUtils.registerMBean(whiteboard, iface,
bean, type, name);
+ mbeanRegistrations.register(() -> reg.unregister());
+ }
+
private boolean isGlobalNodeStore(NodeStoreWithProps ns) {
return GLOBAL_ROLE.equals(ns.getRole());
}
@@ -218,15 +254,15 @@ public class CompositeNodeStoreService {
return role.substring(MOUNT_ROLE_PREFIX.length());
}
- private void unregisterCompositeNodeStore() {
+ private void unregisterCompositeNodeStore() throws IOException {
if (nsReg != null) {
LOG.info("Unregistering the composite node store");
nsReg.unregister();
nsReg = null;
}
- if (checkpointReg != null) {
- checkpointReg.unregister();
- checkpointReg = null;
+ if (mbeanRegistrations != null) {
+ mbeanRegistrations.close();
+ mbeanRegistrations = null;
}
if (observerTracker != null) {
observerTracker.stop();
@@ -249,7 +285,7 @@ public class CompositeNodeStoreService {
}
}
- protected void unbindNodeStore(NodeStoreProvider ns) {
+ protected void unbindNodeStore(NodeStoreProvider ns) throws IOException {
Iterator<NodeStoreWithProps> it = nodeStores.iterator();
while (it.hasNext()) {
if (it.next().getNodeStoreProvider() == ns) {
Added:
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStats.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStats.java?rev=1808851&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStats.java
(added)
+++
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStats.java
Tue Sep 19 10:02:55 2017
@@ -0,0 +1,223 @@
+/*
+ * 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.composite;
+
+import org.apache.jackrabbit.api.stats.TimeSeries;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.spi.mount.Mount;
+import org.apache.jackrabbit.oak.stats.CounterStats;
+import org.apache.jackrabbit.oak.stats.HistogramStats;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.apache.jackrabbit.oak.stats.StatsOptions;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import static com.google.common.collect.Maps.newHashMap;
+import static org.apache.jackrabbit.stats.TimeSeriesStatsUtil.asCompositeData;
+
+public class CompositeNodeStoreStats implements CompositeNodeStoreStatsMBean,
CompositeNodeStoreMonitor {
+
+ public static final String STRING_CACHE_SIZE = "STRING_CACHE_SIZE";
+
+ public static final String NODE_PATH_DEPTH = "_PATH_DEPTH";
+
+ public static final String NODE_SWITCH_TO_DEFAULT_MOUNT =
"_SWITCH_TO_DEFAULT_MOUNT";
+
+ public static final String NODE_SWITCH_TO_NON_DEFAULT_MOUNT =
"_SWITCH_TO_NON_DEFAULT_MOUNT";
+
+ private final StatisticsProvider statisticsProvider;
+
+ private final CounterStats stringCacheSize;
+
+ private final HistogramStats nodePathDepths;
+
+ private final CounterStats nodeSwitchToDefaultMount;
+
+ private final CounterStats nodeSwitchToNonDefaultMount;
+
+ private final Map<String, Long> nodePathCounts;
+
+ private long maxNodePathCount;
+
+ private final long nodePathCountSizeLimit;
+
+ private final long nodePathCountValueLimit;
+
+ private final boolean countPaths;
+
+ private final String prefix;
+
+ public CompositeNodeStoreStats(StatisticsProvider statisticsProvider,
String prefix, boolean countPaths) {
+ this(statisticsProvider, prefix, countPaths, 100, Long.MAX_VALUE / 2);
+ }
+
+ public CompositeNodeStoreStats(StatisticsProvider statisticsProvider,
String prefix, boolean countPaths, long nodePathCountSizeLimit, long
nodePathCountValueLimit) {
+ this.statisticsProvider = statisticsProvider;
+
+ this.stringCacheSize = statisticsProvider.getCounterStats(prefix +
STRING_CACHE_SIZE, StatsOptions.DEFAULT);
+ this.nodePathDepths = statisticsProvider.getHistogram(prefix +
NODE_PATH_DEPTH, StatsOptions.METRICS_ONLY);
+
+ this.nodeSwitchToDefaultMount =
statisticsProvider.getCounterStats(prefix + NODE_SWITCH_TO_DEFAULT_MOUNT,
StatsOptions.DEFAULT);
+ this.nodeSwitchToNonDefaultMount =
statisticsProvider.getCounterStats(prefix + NODE_SWITCH_TO_NON_DEFAULT_MOUNT,
StatsOptions.DEFAULT);
+
+ this.nodePathCounts = newHashMap();
+ this.maxNodePathCount = 0;
+
+ this.countPaths = countPaths;
+ this.nodePathCountSizeLimit = nodePathCountSizeLimit;
+ this.nodePathCountValueLimit = nodePathCountValueLimit;
+
+ this.prefix = prefix;
+ }
+
+ @Override
+ public void onCreateNodeObject(String path) {
+ nodePathDepths.update(PathUtils.getDepth(path));
+ if (countPaths) {
+ updatePathCount(path);
+ }
+ }
+
+ @Override
+ public void onSwitchNodeToNative(Mount mount) {
+ if (mount.isDefault()) {
+ nodeSwitchToDefaultMount.inc();
+ } else {
+ nodeSwitchToNonDefaultMount.inc();
+ }
+ }
+
+ @Override
+ public void onAddStringCacheEntry() {
+ stringCacheSize.inc();
+ }
+
+ @Override
+ public CompositeData getStringCacheSize() {
+ return getCompositeData(STRING_CACHE_SIZE);
+ }
+
+ @Override
+ public CompositeData getNodeSwitchToDefaultMount() {
+ return getCompositeData(NODE_SWITCH_TO_DEFAULT_MOUNT);
+ }
+
+ @Override
+ public CompositeData getNodeSwitchToNonDefaultMount() {
+ return getCompositeData(NODE_SWITCH_TO_NON_DEFAULT_MOUNT);
+ }
+
+ private CompositeData getCompositeData(String name) {
+ return asCompositeData(getTimeSeries(prefix + name), prefix + name);
+ }
+
+ @Override
+ public TabularData getNodePathCounts() throws OpenDataException {
+ return pathsTable(nodePathCounts, "popularNodeStatePaths", "Popular
node state paths");
+ }
+
+ private TimeSeries getTimeSeries(String name) {
+ return statisticsProvider.getStats().getTimeSeries(name, true);
+ }
+
+ private synchronized void updatePathCount(String path) {
+ long newValue = nodePathCounts.compute(path, (p, v) -> v == null ? 1 :
v + 1);
+ boolean removeZeros = false;
+ if (newValue == 1) {
+ if (nodePathCounts.size() >= nodePathCountSizeLimit) {
+ nodePathCounts.entrySet().stream().forEach(e ->
nodePathCounts.put(e.getKey(), e.getValue() - 1));
+ maxNodePathCount--;
+ removeZeros = true;
+ }
+ }
+ if (maxNodePathCount < newValue) {
+ maxNodePathCount = newValue;
+ if (maxNodePathCount >= nodePathCountValueLimit) {
+ nodePathCounts.entrySet().stream().forEach(e ->
nodePathCounts.put(e.getKey(), e.getValue() / 2));
+ maxNodePathCount /= 2;
+ removeZeros = true;
+ }
+ }
+
+ if (removeZeros) {
+ Iterator<Long> it = nodePathCounts.values().iterator();
+ while (it.hasNext()) {
+ if (it.next() <= 0) {
+ it.remove();
+ }
+ }
+ }
+ }
+
+ private TabularData pathsTable(Map<String, Long> paths, String name,
String description) throws OpenDataException {
+ CompositeType pathRowType = new CompositeType("compositePath", "Path",
+ new String[]{"count", "path"},
+ new String[]{"count", "path"},
+ new OpenType[]{SimpleType.LONG, SimpleType.STRING});
+
+
+ TabularDataSupport tabularData = new TabularDataSupport(
+ new TabularType(name,
+ description,
+ pathRowType,
+ new String[]{"path"}
+ ));
+
+ paths.entrySet()
+ .stream()
+ .sorted(Comparator.<Entry<String,
Long>>comparingLong(Entry::getValue).reversed())
+ .map(e -> {
+ Map<String, Object> m = newHashMap();
+ m.put("count", e.getValue());
+ m.put("path", e.getKey());
+ return m;
+ })
+ .map(d -> mapToCompositeData(pathRowType, d))
+ .forEach(tabularData::put);
+
+ return tabularData;
+ }
+
+ private static CompositeData mapToCompositeData(CompositeType
compositeType, Map<String, Object> data) {
+ try {
+ return new CompositeDataSupport(compositeType, data);
+ } catch (OpenDataException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ Map<String, Long> getNodePathCountsMap() {
+ return nodePathCounts;
+ }
+
+ long getMaxNodePathCount() {
+ return maxNodePathCount;
+ }
+}
Added:
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStatsMBean.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStatsMBean.java?rev=1808851&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStatsMBean.java
(added)
+++
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStatsMBean.java
Tue Sep 19 10:02:55 2017
@@ -0,0 +1,37 @@
+/*
+ * 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.composite;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.TabularData;
+
+@ProviderType
+public interface CompositeNodeStoreStatsMBean {
+
+ String TYPE = "CompositeNodeStoreStats";
+
+ CompositeData getStringCacheSize();
+
+ CompositeData getNodeSwitchToDefaultMount();
+
+ CompositeData getNodeSwitchToNonDefaultMount();
+
+ TabularData getNodePathCounts() throws OpenDataException;
+}
Modified:
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositionContext.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositionContext.java?rev=1808851&r1=1808850&r2=1808851&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositionContext.java
(original)
+++
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositionContext.java
Tue Sep 19 10:02:55 2017
@@ -52,8 +52,12 @@ class CompositionContext {
private final StringCache pathCache;
- CompositionContext(MountInfoProvider mip, NodeStore globalStore,
List<MountedNodeStore> nonDefaultStores) {
- this.pathCache = new StringCache();
+ private final CompositeNodeStoreMonitor nodeStateMonitor;
+
+ private final CompositeNodeStoreMonitor nodeBuilderMonitor;
+
+ CompositionContext(MountInfoProvider mip, NodeStore globalStore,
List<MountedNodeStore> nonDefaultStores, CompositeNodeStoreMonitor
nodeStateMonitor, CompositeNodeStoreMonitor nodeBuilderMonitor) {
+ this.pathCache = new StringCache().withMonitor(nodeStateMonitor);
this.mip = mip;
this.globalStore = new MountedNodeStore(mip.getDefaultMount(),
globalStore);
this.nonDefaultStores = nonDefaultStores;
@@ -64,7 +68,8 @@ class CompositionContext {
allStores = b.build();
this.nodeStoresByMount =
allStores.stream().collect(Collectors.toMap(MountedNodeStore::getMount,
Function.identity()));
-
+ this.nodeStateMonitor = nodeStateMonitor;
+ this.nodeBuilderMonitor = nodeBuilderMonitor;
}
MountedNodeStore getGlobalStore() {
@@ -182,4 +187,12 @@ class CompositionContext {
return pathCache;
}
+ CompositeNodeStoreMonitor getNodeStateMonitor() {
+ return nodeStateMonitor;
+ }
+
+ CompositeNodeStoreMonitor getNodeBuilderMonitor() {
+ return nodeBuilderMonitor;
+ }
+
}
Modified:
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/StringCache.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/StringCache.java?rev=1808851&r1=1808850&r2=1808851&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/StringCache.java
(original)
+++
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/StringCache.java
Tue Sep 19 10:02:55 2017
@@ -36,11 +36,23 @@ public class StringCache {
private final ConcurrentMap<String, String> cache = new
ConcurrentHashMap<>(CACHE_SIZE);
+ private CompositeNodeStoreMonitor monitor;
+
public String get(String path) {
if (cache.size() >= CACHE_SIZE && !cache.containsKey(path)) {
LOG.debug("Cache size too big. Revise your mount setup.");
return path;
}
- return cache.computeIfAbsent(path, (k) -> path);
+ return cache.computeIfAbsent(path, (k) -> {
+ if (monitor != null) {
+ monitor.onAddStringCacheEntry();
+ }
+ return path;
+ });
+ }
+
+ public StringCache withMonitor(CompositeNodeStoreMonitor monitor) {
+ this.monitor = monitor;
+ return this;
}
}
Added:
jackrabbit/oak/trunk/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStatsTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStatsTest.java?rev=1808851&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStatsTest.java
(added)
+++
jackrabbit/oak/trunk/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreStatsTest.java
Tue Sep 19 10:02:55 2017
@@ -0,0 +1,73 @@
+/*
+ * 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.composite;
+
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class CompositeNodeStoreStatsTest {
+
+ @Test
+ public void testNodeCountsMaxSizeLimit() {
+ CompositeNodeStoreStats stats = new
CompositeNodeStoreStats(StatisticsProvider.NOOP, "NODE", true, 6, 20);
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < i + 5; j++) {
+ stats.onCreateNodeObject("/xyz" + i);
+ }
+ }
+
+ assertEquals(9, stats.getMaxNodePathCount());
+ assertEquals(5, stats.getNodePathCountsMap().size());
+
+ stats.onCreateNodeObject("/xyz" + 6);
+
+ assertEquals(8, stats.getMaxNodePathCount());
+ assertEquals(5, stats.getNodePathCountsMap().size());
+ for (int i = 0; i < 5; i++) {
+ assertEquals("Invalid count for /xyz" + i, (long) i + 4, (long)
stats.getNodePathCountsMap().get("/xyz" + i));
+ }
+
+ for (int i = 0; i < 3; i++) {
+ stats.onCreateNodeObject("/xyz" + 6);
+ }
+ assertEquals(5, stats.getMaxNodePathCount());
+ assertEquals(5, stats.getNodePathCountsMap().size());
+
+ stats.onCreateNodeObject("/xyz" + 6); // this should remove the
smallest value
+ assertEquals(4, stats.getNodePathCountsMap().size());
+
+ stats.onCreateNodeObject("/xyz" + 6); // this should add the new value
+ assertEquals(5, stats.getNodePathCountsMap().size());
+ }
+
+ @Test
+ public void testNodeCountsMaxValueLimit() {
+ CompositeNodeStoreStats stats = new
CompositeNodeStoreStats(StatisticsProvider.NOOP, "NODE", true, 5, 20);
+ for (int i = 0; i < 19; i++) {
+ stats.onCreateNodeObject("/xyz");
+ }
+ assertEquals(19, stats.getMaxNodePathCount());
+ assertEquals(19l, (long) stats.getNodePathCountsMap().get("/xyz"));
+
+ stats.onCreateNodeObject("/xyz");
+ assertEquals(10, stats.getMaxNodePathCount());
+ assertEquals(10l, (long) stats.getNodePathCountsMap().get("/xyz"));
+
+ }
+}
Modified:
jackrabbit/oak/trunk/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/CompositionContextTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/CompositionContextTest.java?rev=1808851&r1=1808850&r2=1808851&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/CompositionContextTest.java
(original)
+++
jackrabbit/oak/trunk/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/CompositionContextTest.java
Tue Sep 19 10:02:55 2017
@@ -41,7 +41,7 @@ public class CompositionContextTest {
"/jcr:system/rep:permissionStore/oak:mount-libs-crx.default")
)
.build();
- CompositionContext ctx = new CompositionContext(mip, null,
Collections.emptyList());
+ CompositionContext ctx = new CompositionContext(mip, null,
Collections.emptyList(), CompositeNodeStoreMonitor.EMPTY_INSTANCE,
CompositeNodeStoreMonitor.EMPTY_INSTANCE);
assertTrue(ctx.shouldBeComposite("/"));
assertTrue(ctx.shouldBeComposite("/oak:index"));