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 md...@apache.org on 2016/07/26 13:49:20 UTC
svn commit: r1754128 - in /jackrabbit/oak/trunk/oak-segment-tar/src:
main/java/org/apache/jackrabbit/oak/segment/
main/java/org/apache/jackrabbit/oak/segment/file/
test/java/org/apache/jackrabbit/oak/segment/
Author: mduerig
Date: Tue Jul 26 13:49:20 2016
New Revision: 1754128
URL: http://svn.apache.org/viewvc?rev=1754128&view=rev
Log:
OAK-4277: Finalise de-duplication caches
Monitoring for string and template deduplication caches
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCacheStats.java
Modified:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCache.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/WriterCacheManager.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCompactionIT.java
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCache.java?rev=1754128&r1=1754127&r2=1754128&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCache.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCache.java Tue Jul 26 13:49:20 2016
@@ -26,9 +26,10 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import com.google.common.base.Supplier;
+import com.google.common.cache.CacheStats;
// FIXME OAK-4277: Finalise de-duplication caches
-// implement configuration, monitoring and management
+// implement configuration
/**
* Partial mapping of keys of type {@code T} to values of type {@link RecordId}. This is
* typically used for de-duplicating values that have already been persisted and thus
@@ -36,17 +37,33 @@ import com.google.common.base.Supplier;
* @param <T>
*/
public abstract class RecordCache<T> {
+ private long hitCount;
+ private long missCount;
+ private long loadCount;
+ private long evictionCount;
/**
* Add a mapping from {@code key} to {@code value}. Any existing mapping is replaced.
*/
- public abstract void put(T key, RecordId value);
+ public abstract void put(@Nonnull T key, @Nonnull RecordId value);
/**
* @return The mapping for {@code key}, or {@code null} if none.
*/
@CheckForNull
- public abstract RecordId get(T key);
+ public abstract RecordId get(@Nonnull T key);
+
+ /**
+ * @return number of mappings
+ */
+ public abstract long size();
+
+ /**
+ * @return access statistics for this cache
+ */
+ public CacheStats getStats() {
+ return new CacheStats(hitCount, missCount, loadCount, 0, 0, evictionCount);
+ }
/**
* Factory method for creating {@code RecordCache} instances. The returned
@@ -89,10 +106,18 @@ public abstract class RecordCache<T> {
}
@Override
- public synchronized void put(T key, RecordId value) { }
+ public synchronized void put(@Nonnull T key, @Nonnull RecordId value) { }
@Override
- public synchronized RecordId get(T key) { return null; }
+ public synchronized RecordId get(@Nonnull T key) {
+ super.missCount++;
+ return null;
+ }
+
+ @Override
+ public long size() {
+ return 0;
+ }
}
private static class Default<T> extends RecordCache<T> {
@@ -111,19 +136,35 @@ public abstract class RecordCache<T> {
records = new LinkedHashMap<T, RecordId>(size * 4 / 3, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<T, RecordId> eldest) {
- return size() > size;
+ boolean remove = super.size() > size;
+ if (remove) {
+ Default.super.evictionCount++;
+ }
+ return remove;
}
};
}
@Override
- public synchronized void put(T key, RecordId value) {
+ public synchronized void put(@Nonnull T key, @Nonnull RecordId value) {
+ super.loadCount++;
records.put(key, value);
}
@Override
- public synchronized RecordId get(T key) {
- return records.get(key);
+ public synchronized RecordId get(@Nonnull T key) {
+ RecordId value = records.get(key);
+ if (value == null) {
+ super.missCount++;
+ } else {
+ super.hitCount++;
+ }
+ return value;
+ }
+
+ @Override
+ public synchronized long size() {
+ return records.size();
}
}
}
Added: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCacheStats.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCacheStats.java?rev=1754128&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCacheStats.java (added)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/RecordCacheStats.java Tue Jul 26 13:49:20 2016
@@ -0,0 +1,170 @@
+/*
+ * 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.segment;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.String.format;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static org.apache.jackrabbit.oak.commons.IOUtils.humanReadableByteCount;
+
+import javax.annotation.Nonnull;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Supplier;
+import com.google.common.cache.CacheStats;
+import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean;
+import org.apache.jackrabbit.oak.commons.jmx.AnnotatedStandardMBean;
+
+/**
+ * Statistics for {@link RecordCache}.
+ */
+public class RecordCacheStats extends AnnotatedStandardMBean implements CacheStatsMBean {
+
+ @Nonnull
+ private final String name;
+
+ @Nonnull
+ private final Supplier<CacheStats> stats;
+
+ @Nonnull
+ private final Supplier<Long> elementCount;
+
+ private CacheStats lastSnapshot;
+
+ public RecordCacheStats(
+ @Nonnull String name, @Nonnull Supplier<CacheStats> stats, @Nonnull Supplier<Long> elementCount) {
+ super(CacheStatsMBean.class);
+ this.name = checkNotNull(name);
+ this.stats = checkNotNull(stats);
+ this.elementCount = checkNotNull(elementCount);
+ this.lastSnapshot = stats.get();
+ }
+
+ private CacheStats stats() {
+ return stats.get().minus(lastSnapshot);
+ }
+
+ @Override
+ public synchronized void resetStats() {
+ lastSnapshot = stats.get();
+ }
+
+ @Nonnull
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public long getRequestCount() {
+ return stats().requestCount();
+ }
+
+ @Override
+ public long getHitCount() {
+ return stats().hitCount();
+ }
+
+ @Override
+ public double getHitRate() {
+ return stats().hitRate();
+ }
+
+ @Override
+ public long getMissCount() {
+ return stats().missCount();
+ }
+
+ @Override
+ public double getMissRate() {
+ return stats().missRate();
+ }
+
+ @Override
+ public long getLoadCount() {
+ return stats().loadCount();
+ }
+
+ @Override
+ public long getLoadSuccessCount() {
+ return stats().loadSuccessCount();
+ }
+
+ @Override
+ public long getLoadExceptionCount() {
+ return stats().loadExceptionCount();
+ }
+
+ @Override
+ public double getLoadExceptionRate() {
+ return stats().loadExceptionRate();
+ }
+
+ @Override
+ public long getTotalLoadTime() {
+ return stats().totalLoadTime();
+ }
+
+ @Override
+ public double getAverageLoadPenalty() {
+ return stats().averageLoadPenalty();
+ }
+
+ @Override
+ public long getEvictionCount() {
+ return stats().evictionCount();
+ }
+
+ @Override
+ public long getElementCount() {
+ return elementCount.get();
+ }
+
+ @Override
+ public long getMaxTotalWeight() {
+ return -1;
+ }
+
+ @Override
+ public long estimateCurrentWeight() {
+ return -1;
+ }
+
+ @Override
+ public String cacheInfoAsString() {
+ return Objects.toStringHelper("CacheStats(" + name + ")")
+ .add("hitCount", getHitCount())
+ .add("hitRate", format("%1.2f", getHitRate()))
+ .add("missCount", getMissCount())
+ .add("missRate", format("%1.2f", getMissRate()))
+ .add("requestCount", getRequestCount())
+ .add("loadCount", getLoadCount())
+ .add("loadSuccessCount", getLoadSuccessCount())
+ .add("loadExceptionCount", getLoadExceptionCount())
+ .add("totalLoadTime", format("%d s", NANOSECONDS.toSeconds(getTotalLoadTime())))
+ .add("averageLoadPenalty ", format("%1.2f ns", getAverageLoadPenalty()))
+ .add("evictionCount", getEvictionCount())
+ .add("elementCount", getElementCount())
+ .add("totalWeight", humanReadableByteCount(estimateCurrentWeight()))
+ .add("maxWeight", humanReadableByteCount(getMaxTotalWeight()))
+ .toString();
+ }
+
+}
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java?rev=1754128&r1=1754127&r2=1754128&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java Tue Jul 26 13:49:20 2016
@@ -38,9 +38,11 @@ import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Hashtable;
+import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.felix.scr.annotations.Activate;
@@ -240,21 +242,11 @@ public class SegmentNodeStoreService ext
private ServiceRegistration storeRegistration;
private ServiceRegistration providerRegistration;
- private Registration checkpointRegistration;
- private Registration revisionGCRegistration;
- private Registration blobGCRegistration;
- private Registration gcOptionsRegistration;
- private Registration segmentCacheMBean;
- private Registration stringCacheMBean;
- private Registration fsgcMonitorMBean;
- private Registration fileStoreStatsMBean;
+
+ private final List<Registration> registrations = new ArrayList<>();
private WhiteboardExecutor executor;
private boolean customBlobStore;
- private Registration discoveryLiteDescriptorRegistration;
-
- private Registration clusterIdDescriptorRegistration;
-
/**
* Blob modified before this time duration would be considered for Blob GC
*/
@@ -367,42 +359,62 @@ public class SegmentNodeStoreService ext
// Expose an MBean to provide information about the gc options
- gcOptionsRegistration = registerMBean(
+ registrations.add(registerMBean(
whiteboard,
SegmentRevisionGC.class,
new SegmentRevisionGCMBean(gcOptions),
SegmentRevisionGC.TYPE,
"Segment node store gc options"
- );
+ ));
// Expose stats about the segment cache
- CacheStats segmentCacheStats = store.getSegmentCacheStats();
- segmentCacheMBean = registerMBean(
+ CacheStatsMBean segmentCacheStats = store.getSegmentCacheStats();
+ registrations.add(registerMBean(
whiteboard,
CacheStatsMBean.class,
segmentCacheStats,
CacheStats.TYPE,
segmentCacheStats.getName()
- );
+ ));
// Expose stats about the string and template caches
- CacheStats stringCacheStats = store.getStringCacheStats();
- stringCacheMBean = registerMBean(
+ CacheStatsMBean stringCacheStats = store.getStringCacheStats();
+ registrations.add(registerMBean(
whiteboard,
CacheStatsMBean.class,
stringCacheStats,CacheStats.TYPE,
stringCacheStats.getName()
- );
+ ));
- CacheStats templateCacheStats = store.getTemplateCacheStats();
- stringCacheMBean = registerMBean(
+ CacheStatsMBean templateCacheStats = store.getTemplateCacheStats();
+ registrations.add(registerMBean(
whiteboard,
CacheStatsMBean.class,
templateCacheStats,CacheStats.TYPE,
templateCacheStats.getName()
- );
+ ));
+
+ CacheStatsMBean stringDeduplicationCacheStats = store.getStringDeduplicationCacheStats();
+ if (stringDeduplicationCacheStats != null) {
+ registrations.add(registerMBean(
+ whiteboard,
+ CacheStatsMBean.class,
+ stringDeduplicationCacheStats,CacheStats.TYPE,
+ stringDeduplicationCacheStats.getName()
+ ));
+ }
+
+ CacheStatsMBean templateDeduplicationCacheStats = store.getTemplateDeduplicationCacheStats();
+ if (templateDeduplicationCacheStats != null) {
+ registrations.add(registerMBean(
+ whiteboard,
+ CacheStatsMBean.class,
+ templateDeduplicationCacheStats,CacheStats.TYPE,
+ templateDeduplicationCacheStats.getName()
+ ));
+ }
// Listen for Executor services on the whiteboard
@@ -420,29 +432,29 @@ public class SegmentNodeStoreService ext
};
- revisionGCRegistration = registerMBean(
+ registrations.add(registerMBean(
whiteboard,
RevisionGCMBean.class,
new RevisionGC(triggerGarbageCollection, executor),
RevisionGCMBean.TYPE,
"Segment node store revision garbage collection"
- );
+ ));
// Expose statistics about the FileStore
- fileStoreStatsMBean = registerMBean(
+ registrations.add(registerMBean(
whiteboard,
FileStoreStatsMBean.class,
store.getStats(),
FileStoreStatsMBean.TYPE,
"FileStore statistics"
- );
+ ));
// Register a monitor for the garbage collection of the FileStore
FileStoreGCMonitor fsgcm = new FileStoreGCMonitor(Clock.SIMPLE);
- fsgcMonitorMBean = new CompositeRegistration(
+ registrations.add((new CompositeRegistration(
whiteboard.register(GCMonitor.class, fsgcm, emptyMap()),
registerMBean(
whiteboard,
@@ -452,7 +464,7 @@ public class SegmentNodeStoreService ext
"File Store garbage collection monitor"
),
scheduleWithFixedDelay(whiteboard, fsgcm, 1)
- );
+ )));
// Register a factory service to expose the FileStore
@@ -489,8 +501,8 @@ public class SegmentNodeStoreService ext
observerTracker = new ObserverTracker(segmentNodeStore);
observerTracker.start(context.getBundleContext());
- checkpointRegistration = registerMBean(whiteboard, CheckpointMBean.class, new SegmentCheckpointMBean(segmentNodeStore),
- CheckpointMBean.TYPE, "Segment node store checkpoint management");
+ registrations.add(registerMBean(whiteboard, CheckpointMBean.class, new SegmentCheckpointMBean(segmentNodeStore),
+ CheckpointMBean.TYPE, "Segment node store checkpoint management"));
// ensure a clusterId is initialized
// and expose it as 'oak.clusterid' repository descriptor
@@ -498,18 +510,18 @@ public class SegmentNodeStoreService ext
clusterIdDesc.put(ClusterRepositoryInfo.OAK_CLUSTERID_REPOSITORY_DESCRIPTOR_KEY,
new SimpleValueFactory().createValue(
ClusterRepositoryInfo.getOrCreateId(segmentNodeStore)), true, false);
- clusterIdDescriptorRegistration = whiteboard.register(
+ registrations.add(whiteboard.register(
Descriptors.class,
clusterIdDesc,
Collections.emptyMap()
- );
+ ));
// Register "discovery lite" descriptors
- discoveryLiteDescriptorRegistration = whiteboard.register(
+ registrations.add(whiteboard.register(
Descriptors.class,
new SegmentDiscoveryLiteDescriptors(segmentNodeStore),
Collections.emptyMap()
- );
+ ));
// If a shared data store register the repo id in the data store
String repoId = "";
@@ -532,13 +544,13 @@ public class SegmentNodeStoreService ext
repoId
);
- blobGCRegistration = registerMBean(
+ registrations.add(registerMBean(
whiteboard,
BlobGCMBean.class,
new BlobGC(gc, executor),
BlobGCMBean.TYPE,
"Segment node store blob garbage collection"
- );
+ ));
}
log.info("SegmentNodeStore initialized");
@@ -546,22 +558,7 @@ public class SegmentNodeStoreService ext
}
private void unregisterNodeStore() {
- if (discoveryLiteDescriptorRegistration != null) {
- discoveryLiteDescriptorRegistration.unregister();
- discoveryLiteDescriptorRegistration = null;
- }
- if (clusterIdDescriptorRegistration != null) {
- clusterIdDescriptorRegistration.unregister();
- clusterIdDescriptorRegistration = null;
- }
- if (segmentCacheMBean != null) {
- segmentCacheMBean.unregister();
- segmentCacheMBean = null;
- }
- if (stringCacheMBean != null) {
- stringCacheMBean.unregister();
- stringCacheMBean = null;
- }
+ new CompositeRegistration(registrations).unregister();
if (providerRegistration != null) {
providerRegistration.unregister();
providerRegistration = null;
@@ -570,30 +567,6 @@ public class SegmentNodeStoreService ext
storeRegistration.unregister();
storeRegistration = null;
}
- if (checkpointRegistration != null) {
- checkpointRegistration.unregister();
- checkpointRegistration = null;
- }
- if (revisionGCRegistration != null) {
- revisionGCRegistration.unregister();
- revisionGCRegistration = null;
- }
- if (blobGCRegistration != null) {
- blobGCRegistration.unregister();
- blobGCRegistration = null;
- }
- if (gcOptionsRegistration != null) {
- gcOptionsRegistration.unregister();
- gcOptionsRegistration = null;
- }
- if (fsgcMonitorMBean != null) {
- fsgcMonitorMBean.unregister();
- fsgcMonitorMBean = null;
- }
- if (fileStoreStatsMBean != null) {
- fileStoreStatsMBean.unregister();
- fileStoreStatsMBean = null;
- }
if (executor != null) {
executor.stop();
executor = null;
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java?rev=1754128&r1=1754127&r2=1754128&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java Tue Jul 26 13:49:20 2016
@@ -64,6 +64,7 @@ import org.apache.commons.math3.stat.des
import org.apache.jackrabbit.oak.api.Blob;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean;
import org.apache.jackrabbit.oak.plugins.memory.ModifiedNodeState;
import org.apache.jackrabbit.oak.segment.WriteOperationHandler.WriteOperation;
import org.apache.jackrabbit.oak.spi.blob.BlobStore;
@@ -132,6 +133,22 @@ public class SegmentWriter {
}
/**
+ * @return Statistics for the string deduplication cache or {@code null} if not available.
+ */
+ @CheckForNull
+ public CacheStatsMBean getStringCacheStats() {
+ return cacheManager.getStringCacheStats();
+ }
+
+ /**
+ * @return Statistics for the template deduplication cache or {@code null} if not available.
+ */
+ @CheckForNull
+ public CacheStatsMBean getTemplateCacheStats() {
+ return cacheManager.getTemplateCacheStats();
+ }
+
+ /**
* Write a map record.
* @param base base map relative to which the {@code changes} are applied ot
* {@code null} for the empty map.
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/WriterCacheManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/WriterCacheManager.java?rev=1754128&r1=1754127&r2=1754128&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/WriterCacheManager.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/WriterCacheManager.java Tue Jul 26 13:49:20 2016
@@ -21,6 +21,7 @@ package org.apache.jackrabbit.oak.segmen
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Suppliers.memoize;
+import static com.google.common.collect.Iterators.transform;
import static com.google.common.collect.Maps.newConcurrentMap;
import static java.lang.Integer.getInteger;
import static org.apache.jackrabbit.oak.segment.RecordCache.newRecordCache;
@@ -28,15 +29,20 @@ import static org.apache.jackrabbit.oak.
import java.util.Iterator;
import java.util.concurrent.ConcurrentMap;
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
+import com.google.common.cache.CacheStats;
+import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean;
// FIXME OAK-4277: Finalise de-duplication caches
// implement configuration, monitoring and management
// add unit tests
-// document, nullability
+// document
public abstract class WriterCacheManager {
private static final int DEFAULT_STRING_CACHE_SIZE = getInteger(
"oak.tar.stringsCacheSize", 15000);
@@ -53,6 +59,22 @@ public abstract class WriterCacheManager
@Nonnull
public abstract NodeCache getNodeCache(int generation);
+ /**
+ * @return statistics for the string cache or {@code null} if not available.
+ */
+ @CheckForNull
+ public CacheStatsMBean getStringCacheStats() {
+ return null;
+ }
+
+ /**
+ * @return statistics for the template cache or {@code null} if not available.
+ */
+ @CheckForNull
+ public CacheStatsMBean getTemplateCacheStats() {
+ return null;
+ }
+
public static class Empty extends WriterCacheManager {
public static final WriterCacheManager INSTANCE = new Empty();
@@ -83,27 +105,27 @@ public abstract class WriterCacheManager
* Cache of recently stored string records, used to avoid storing duplicates
* of frequently occurring data.
*/
- private final Generation<RecordCache<String>> stringCaches;
+ private final Generations<RecordCache<String>> stringCaches;
/**
* Cache of recently stored template records, used to avoid storing
* duplicates of frequently occurring data.
*/
- private final Generation<RecordCache<Template>> templateCaches;
+ private final Generations<RecordCache<Template>> templateCaches;
/**
* Cache of recently stored nodes to avoid duplicating linked nodes (i.e. checkpoints)
* during compaction.
*/
- private final Generation<NodeCache> nodeCaches;
+ private final Generations<NodeCache> nodeCaches;
public Default(
@Nonnull Supplier<RecordCache<String>> stringCacheFactory,
@Nonnull Supplier<RecordCache<Template>> templateCacheFactory,
@Nonnull Supplier<NodeCache> nodeCacheFactory) {
- this.stringCaches = new Generation<>(stringCacheFactory);
- this.templateCaches = new Generation<>(templateCacheFactory);
- this.nodeCaches = new Generation<>(nodeCacheFactory);
+ this.stringCaches = new Generations<>(stringCacheFactory);
+ this.templateCaches = new Generations<>(templateCacheFactory);
+ this.nodeCaches = new Generations<>(nodeCacheFactory);
}
public Default() {
@@ -112,11 +134,11 @@ public abstract class WriterCacheManager
NodeCache.factory(1000000, 20));
}
- private static class Generation<T> {
+ private static class Generations<T> implements Iterable<T> {
private final ConcurrentMap<Integer, Supplier<T>> generations = newConcurrentMap();
private final Supplier<T> cacheFactory;
- Generation(@Nonnull Supplier<T> cacheFactory) {
+ Generations(@Nonnull Supplier<T> cacheFactory) {
this.cacheFactory = checkNotNull(cacheFactory);
}
@@ -128,6 +150,16 @@ public abstract class WriterCacheManager
return generations.get(generation).get();
}
+ @Override
+ public Iterator<T> iterator() {
+ return transform(generations.values().iterator(), new Function<Supplier<T>, T>() {
+ @Nullable @Override
+ public T apply(Supplier<T> cacheFactory) {
+ return cacheFactory.get();
+ }
+ });
+ }
+
void evictGenerations(@Nonnull Predicate<Integer> evict) {
Iterator<Integer> it = generations.keySet().iterator();
while (it.hasNext()) {
@@ -156,6 +188,48 @@ public abstract class WriterCacheManager
return nodeCaches.getGeneration(generation);
}
+ @CheckForNull
+ @Override
+ public CacheStatsMBean getStringCacheStats() {
+ return new RecordCacheStats("String deduplication cache stats",
+ accumulateStats(stringCaches), accumulateSizes(stringCaches));
+ }
+
+ @CheckForNull
+ @Override
+ public CacheStatsMBean getTemplateCacheStats() {
+ return new RecordCacheStats("Template deduplication cache stats",
+ accumulateStats(templateCaches), accumulateSizes(templateCaches));
+ }
+
+ @Nonnull
+ private static <T> Supplier<CacheStats> accumulateStats(final Iterable<RecordCache<T>> caches) {
+ return new Supplier<CacheStats>() {
+ @Override
+ public CacheStats get() {
+ CacheStats stats = new CacheStats(0, 0, 0, 0, 0, 0);
+ for (RecordCache<?> cache : caches) {
+ stats = stats.plus(cache.getStats());
+ }
+ return stats;
+ }
+ };
+ }
+
+ @Nonnull
+ public static <T> Supplier<Long> accumulateSizes(final Generations<RecordCache<T>> caches) {
+ return new Supplier<Long>() {
+ @Override
+ public Long get() {
+ long size = 0;
+ for (RecordCache<?> cache : caches) {
+ size += cache.size();
+ }
+ return size;
+ }
+ };
+ }
+
protected final void evictCaches(Predicate<Integer> generations) {
stringCaches.evictGenerations(generations);
templateCaches.evictGenerations(generations);
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java?rev=1754128&r1=1754127&r2=1754128&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java Tue Jul 26 13:49:20 2016
@@ -73,7 +73,7 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Stopwatch;
import com.google.common.base.Supplier;
-import org.apache.jackrabbit.oak.cache.CacheStats;
+import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean;
import org.apache.jackrabbit.oak.plugins.blob.ReferenceCollector;
import org.apache.jackrabbit.oak.segment.BinaryReferenceConsumer;
import org.apache.jackrabbit.oak.segment.CachingSegmentReader;
@@ -400,20 +400,30 @@ public class FileStore implements Segmen
}
@Nonnull
- public CacheStats getSegmentCacheStats() {
+ public CacheStatsMBean getSegmentCacheStats() {
return segmentCache.getCacheStats();
}
@Nonnull
- public CacheStats getStringCacheStats() {
+ public CacheStatsMBean getStringCacheStats() {
return segmentReader.getStringCacheStats();
}
@Nonnull
- public CacheStats getTemplateCacheStats() {
+ public CacheStatsMBean getTemplateCacheStats() {
return segmentReader.getTemplateCacheStats();
}
+ @CheckForNull
+ public CacheStatsMBean getStringDeduplicationCacheStats() {
+ return segmentWriter.getStringCacheStats();
+ }
+
+ @CheckForNull
+ public CacheStatsMBean getTemplateDeduplicationCacheStats() {
+ return segmentWriter.getTemplateCacheStats();
+ }
+
public void maybeCompact(boolean cleanup) throws IOException {
gcListener.info("TarMK GC #{}: started", GC_COUNT.incrementAndGet());
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCompactionIT.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCompactionIT.java?rev=1754128&r1=1754127&r2=1754128&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCompactionIT.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCompactionIT.java Tue Jul 26 13:49:20 2016
@@ -34,6 +34,7 @@ import static java.util.concurrent.TimeU
import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.defaultGCOptions;
import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assume.assumeTrue;
import static org.slf4j.helpers.MessageFormatter.arrayFormat;
import static org.slf4j.helpers.MessageFormatter.format;
@@ -71,7 +72,7 @@ import com.google.common.util.concurrent
import org.apache.jackrabbit.oak.api.Blob;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.cache.CacheStats;
+import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean;
import org.apache.jackrabbit.oak.commons.jmx.AnnotatedStandardMBean;
import org.apache.jackrabbit.oak.plugins.commit.ConflictHook;
import org.apache.jackrabbit.oak.plugins.commit.DefaultConflictHandler;
@@ -242,15 +243,23 @@ public class SegmentCompactionIT {
new ObjectName("IT:TYPE=Segment Revision GC")));
registrations.add(registerMBean(fileStoreGCMonitor,
new ObjectName("IT:TYPE=GC Monitor")));
- CacheStats segmentCacheStats = fileStore.getSegmentCacheStats();
+ CacheStatsMBean segmentCacheStats = fileStore.getSegmentCacheStats();
registrations.add(registerMBean(segmentCacheStats,
new ObjectName("IT:TYPE=" + segmentCacheStats.getName())));
- CacheStats stringCacheStats = fileStore.getStringCacheStats();
+ CacheStatsMBean stringCacheStats = fileStore.getStringCacheStats();
registrations.add(registerMBean(stringCacheStats,
new ObjectName("IT:TYPE=" + stringCacheStats.getName())));
- CacheStats templateCacheStats = fileStore.getTemplateCacheStats();
+ CacheStatsMBean templateCacheStats = fileStore.getTemplateCacheStats();
registrations.add(registerMBean(templateCacheStats,
new ObjectName("IT:TYPE=" + templateCacheStats.getName())));
+ CacheStatsMBean stringDeduplicationCacheStats = fileStore.getStringDeduplicationCacheStats();
+ assertNotNull(stringDeduplicationCacheStats);
+ registrations.add(registerMBean(stringDeduplicationCacheStats,
+ new ObjectName("IT:TYPE=" + stringDeduplicationCacheStats.getName())));
+ CacheStatsMBean templateDeduplicationCacheStats = fileStore.getTemplateDeduplicationCacheStats();
+ assertNotNull(templateDeduplicationCacheStats);
+ registrations.add(registerMBean(templateDeduplicationCacheStats,
+ new ObjectName("IT:TYPE=" + templateDeduplicationCacheStats.getName())));
mBeanRegistration = new CompositeRegistration(registrations);
}