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 2016/01/04 07:36:02 UTC

svn commit: r1722790 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ ...

Author: chetanm
Date: Mon Jan  4 06:36:02 2016
New Revision: 1722790

URL: http://svn.apache.org/viewvc?rev=1722790&view=rev
Log:
OAK-3829 - Expose BlobStore cache statistics

Added:
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreServiceTest.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/CachingBlobStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/AbstractDataStoreService.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreBlobStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
    jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/DocumentNodeStoreConfigTest.groovy

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/CachingBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/CachingBlobStore.java?rev=1722790&r1=1722789&r2=1722790&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/CachingBlobStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/CachingBlobStore.java Mon Jan  4 06:36:02 2016
@@ -16,7 +16,10 @@
  */
 package org.apache.jackrabbit.oak.plugins.blob;
 
+import com.sun.javafx.beans.annotations.NonNull;
 import org.apache.jackrabbit.oak.cache.CacheLIRS;
+import org.apache.jackrabbit.oak.cache.CacheStats;
+import org.apache.jackrabbit.oak.commons.StringUtils;
 import org.apache.jackrabbit.oak.spi.blob.AbstractBlobStore;
 
 import com.google.common.cache.Weigher;
@@ -32,19 +35,28 @@ public abstract class CachingBlobStore e
 
     protected final long blobCacheSize;
 
+    private final Weigher<String, byte[]> weigher = new Weigher<String, byte[]>() {
+        @Override
+        public int weigh(@NonNull String key, @NonNull byte[] value) {
+            return StringUtils.estimateMemoryUsage(key) + value.length;
+        }
+    };
+
+    private final CacheStats cacheStats;
+
+    public static final String MEM_CACHE_NAME = "BlobStore-MemCache";
+
     public CachingBlobStore(long cacheSize) {
         this.blobCacheSize = cacheSize;
         cache = CacheLIRS.<String, byte[]>newBuilder().
-                module("CachingBlobStore").
+                recordStats().
+                module(MEM_CACHE_NAME).
                 maximumWeight(cacheSize).
                 averageWeight(getBlockSize() / 2).
-                weigher(new Weigher<String, byte[]>() {
-                    @Override
-                    public int weigh(String key, byte[] value) {
-                        return value.length;
-                    }
-                }).build();
+                weigher(weigher).
+                build();
 
+        cacheStats = new CacheStats(cache, MEM_CACHE_NAME, weigher, cacheSize);
     }
 
     public CachingBlobStore() {
@@ -60,4 +72,8 @@ public abstract class CachingBlobStore e
         //Required for testcase to validate the configured cache size
         return blobCacheSize;
     }
+
+    public CacheStats getCacheStats() {
+        return cacheStats;
+    }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/AbstractDataStoreService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/AbstractDataStoreService.java?rev=1722790&r1=1722789&r2=1722790&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/AbstractDataStoreService.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/AbstractDataStoreService.java Mon Jan  4 06:36:02 2016
@@ -29,14 +29,18 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.data.DataStoreException;
+import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean;
 import org.apache.jackrabbit.oak.commons.PropertiesUtil;
 import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
 import org.apache.jackrabbit.oak.spi.blob.stats.BlobStoreStatsMBean;
 import org.apache.jackrabbit.oak.plugins.blob.BlobStoreStats;
 import org.apache.jackrabbit.oak.spi.blob.BlobStore;
 import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore;
+import org.apache.jackrabbit.oak.spi.whiteboard.CompositeRegistration;
 import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
 import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.component.ComponentContext;
@@ -92,11 +96,7 @@ public abstract class AbstractDataStoreS
                 GarbageCollectableBlobStore.class.getName()
         }, dataStore , props);
 
-        mbeanReg = registerMBean(new OsgiWhiteboard(context.getBundleContext()),
-                BlobStoreStatsMBean.class,
-                stats,
-                BlobStoreStatsMBean.TYPE,
-                ds.getClass().getSimpleName());
+        mbeanReg = registerMBeans(context.getBundleContext(), dataStore, stats);
     }
 
     protected void deactivate() throws DataStoreException {
@@ -121,6 +121,10 @@ public abstract class AbstractDataStoreS
         return new String[] {"type=unknown"};
     }
 
+    void setStatisticsProvider(StatisticsProvider statisticsProvider) {
+        this.statisticsProvider = statisticsProvider;
+    }
+
     protected static String lookup(ComponentContext context, String property) {
         //Prefer property from BundleContext first
         if (context.getBundleContext().getProperty(property) != null) {
@@ -132,4 +136,20 @@ public abstract class AbstractDataStoreS
         }
         return null;
     }
+
+    private static Registration registerMBeans(BundleContext context, DataStoreBlobStore ds, BlobStoreStats stats){
+        Whiteboard wb = new OsgiWhiteboard(context);
+        return new CompositeRegistration(
+                registerMBean(wb,
+                        BlobStoreStatsMBean.class,
+                        stats,
+                        BlobStoreStatsMBean.TYPE,
+                        ds.getClass().getSimpleName()),
+                registerMBean(wb,
+                        CacheStatsMBean.class,
+                        ds.getCacheStats(),
+                        CacheStatsMBean.TYPE,
+                        ds.getCacheStats().getName())
+        );
+    }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreBlobStore.java?rev=1722790&r1=1722789&r2=1722790&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreBlobStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreBlobStore.java Mon Jan  4 06:36:02 2016
@@ -55,6 +55,7 @@ import org.apache.jackrabbit.core.data.D
 import org.apache.jackrabbit.core.data.DataStoreException;
 import org.apache.jackrabbit.core.data.MultiDataStoreAware;
 import org.apache.jackrabbit.oak.cache.CacheLIRS;
+import org.apache.jackrabbit.oak.cache.CacheStats;
 import org.apache.jackrabbit.oak.commons.StringUtils;
 import org.apache.jackrabbit.oak.plugins.blob.SharedDataStore;
 import org.apache.jackrabbit.oak.spi.blob.BlobStore;
@@ -99,6 +100,16 @@ public class DataStoreBlobStore implemen
      */
     private int maxCachedBinarySize = 1024 * 1024;
 
+    private final Weigher<String, byte[]> weigher = new Weigher<String, byte[]>() {
+        @Override
+        public int weigh(@Nonnull String key, @Nonnull byte[] value) {
+            return StringUtils.estimateMemoryUsage(key) + value.length;
+        }
+    };
+
+    private final CacheStats cacheStats;
+
+    public static final String MEM_CACHE_NAME = "BlobStore-MemCache";
 
     public DataStoreBlobStore(DataStore delegate) {
         this(delegate, true, DEFAULT_CACHE_SIZE);
@@ -112,16 +123,14 @@ public class DataStoreBlobStore implemen
         this.delegate = delegate;
         this.encodeLengthInId = encodeLengthInId;
 
+        long cacheSize = (long) cacheSizeInMB * FileUtils.ONE_MB;
         this.cache = CacheLIRS.<String, byte[]>newBuilder()
-                .module("DataStoreBlobStore")
-                .maximumWeight((long) cacheSizeInMB * FileUtils.ONE_MB)
-                .weigher(new Weigher<String, byte[]>() {
-                    @Override
-                    public int weigh(@Nonnull String key, @Nonnull byte[] value) {
-                        return StringUtils.estimateMemoryUsage(key) + value.length;
-                    }
-                })
+                .module(MEM_CACHE_NAME)
+                .recordStats()
+                .maximumWeight(cacheSize)
+                .weigher(weigher)
                 .build();
+        this.cacheStats = new CacheStats(cache, MEM_CACHE_NAME, weigher, cacheSize);
     }
 
     //~----------------------------------< DataStore >
@@ -473,6 +482,10 @@ public class DataStoreBlobStore implemen
         return delegate;
     }
 
+    public CacheStats getCacheStats() {
+        return cacheStats;
+    }
+
     public void setMaxCachedBinarySize(int maxCachedBinarySize) {
         this.maxCachedBinarySize = maxCachedBinarySize;
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java?rev=1722790&r1=1722789&r2=1722790&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java Mon Jan  4 06:36:02 2016
@@ -47,6 +47,7 @@ import org.apache.jackrabbit.oak.commons
 import org.apache.jackrabbit.oak.commons.json.JsopTokenizer;
 import org.apache.jackrabbit.oak.json.JsopDiff;
 import org.apache.jackrabbit.oak.plugins.blob.BlobStoreStats;
+import org.apache.jackrabbit.oak.plugins.blob.CachingBlobStore;
 import org.apache.jackrabbit.oak.plugins.blob.ReferencedBlob;
 import org.apache.jackrabbit.oak.plugins.document.DocumentNodeState.Children;
 import org.apache.jackrabbit.oak.plugins.document.cache.NodeDocumentCache;
@@ -518,6 +519,7 @@ public class DocumentMK {
         private LeaseFailureHandler leaseFailureHandler;
         private StatisticsProvider statisticsProvider = StatisticsProvider.NOOP;
         private BlobStoreStats blobStoreStats;
+        private CacheStats blobStoreCacheStats;
 
         public Builder() {
         }
@@ -568,7 +570,7 @@ public class DocumentMK {
 
             if (this.blobStore == null) {
                 GarbageCollectableBlobStore s = new MongoBlobStore(db, blobCacheSizeMB * 1024 * 1024L);
-                configureStatsCollector(s);
+                configureBlobStore(s);
                 PersistentCache p = getPersistentCache();
                 if (p != null) {
                     s = p.wrapBlobStore(s);
@@ -598,7 +600,7 @@ public class DocumentMK {
             this.documentStore = new RDBDocumentStore(ds, this);
             if(this.blobStore == null) {
                 this.blobStore = new RDBBlobStore(ds);
-                configureStatsCollector(blobStore);
+                configureBlobStore(blobStore);
             }
             return this;
         }
@@ -613,7 +615,7 @@ public class DocumentMK {
             this.documentStore = new RDBDocumentStore(ds, this, options);
             if(this.blobStore == null) {
                 this.blobStore = new RDBBlobStore(ds, options);
-                configureStatsCollector(blobStore);
+                configureBlobStore(blobStore);
             }
             return this;
         }
@@ -637,7 +639,7 @@ public class DocumentMK {
         public Builder setRDBConnection(DataSource documentStoreDataSource, DataSource blobStoreDataSource) {
             this.documentStore = new RDBDocumentStore(documentStoreDataSource, this);
             this.blobStore = new RDBBlobStore(blobStoreDataSource);
-            configureStatsCollector(blobStore);
+            configureBlobStore(blobStore);
             return this;
         }
 
@@ -734,7 +736,7 @@ public class DocumentMK {
         public BlobStore getBlobStore() {
             if (blobStore == null) {
                 blobStore = new MemoryBlobStore();
-                configureStatsCollector(blobStore);
+                configureBlobStore(blobStore);
             }
             return blobStore;
         }
@@ -877,6 +879,11 @@ public class DocumentMK {
             return blobStoreStats;
         }
 
+        @CheckForNull
+        public CacheStats getBlobStoreCacheStats() {
+            return blobStoreCacheStats;
+        }
+
         public Clock getClock() {
             return clock;
         }
@@ -1037,11 +1044,22 @@ public class DocumentMK {
                     build();
         }
 
-        private void configureStatsCollector(BlobStore blobStore) {
+        /**
+         * BlobStore which are created by builder might get wrapped.
+         * So here we perform any configuration and also access any
+         * service exposed by the store
+         *
+         * @param blobStore store to config
+         */
+        private void configureBlobStore(BlobStore blobStore) {
             if (blobStore instanceof AbstractBlobStore){
                 this.blobStoreStats = new BlobStoreStats(statisticsProvider);
                 ((AbstractBlobStore) blobStore).setStatsCollector(blobStoreStats);
             }
+
+            if (blobStore instanceof CachingBlobStore){
+                blobStoreCacheStats = ((CachingBlobStore) blobStore).getCacheStats();
+            }
         }
 
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java?rev=1722790&r1=1722789&r2=1722790&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java Mon Jan  4 06:36:02 2016
@@ -631,6 +631,16 @@ public class DocumentNodeStoreService {
                         "Document node store management")
         );
 
+        if (mkBuilder.getBlobStoreCacheStats() != null) {
+            registrations.add(
+                    registerMBean(whiteboard,
+                            CacheStatsMBean.class,
+                            mkBuilder.getBlobStoreCacheStats(),
+                            CacheStatsMBean.TYPE,
+                            mkBuilder.getBlobStoreCacheStats().getName())
+            );
+        }
+
         final long versionGcMaxAgeInSecs = toLong(prop(PROP_VER_GC_MAX_AGE), DEFAULT_VER_GC_MAX_AGE);
         final long blobGcMaxAgeInSecs = toLong(prop(PROP_BLOB_GC_MAX_AGE), DEFAULT_BLOB_GC_MAX_AGE);
 
@@ -662,7 +672,6 @@ public class DocumentNodeStoreService {
                     BlobStoreStatsMBean.TYPE,
                     ds.getClass().getSimpleName()));
         }
-        //TODO Register JMX bean for Off Heap Cache stats
     }
 
     private void registerLastRevRecoveryJob(final DocumentNodeStore nodeStore) {

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreServiceTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreServiceTest.java?rev=1722790&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreServiceTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreServiceTest.java Mon Jan  4 06:36:02 2016
@@ -0,0 +1,57 @@
+/*
+ * 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.blob.datastore;
+
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean;
+import org.apache.jackrabbit.oak.spi.blob.stats.BlobStoreStatsMBean;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.apache.sling.testing.mock.osgi.MockOsgi;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static org.junit.Assert.assertNotNull;
+
+public class DataStoreServiceTest {
+    @Rule
+    public final TemporaryFolder folder = new TemporaryFolder();
+
+    @Rule
+    public final OsgiContext context = new OsgiContext();
+
+    @Test
+    public void mbeanRegs() throws Exception{
+        Map<String, Object> config = ImmutableMap.<String, Object>of(
+                "repository.home", folder.getRoot().getAbsolutePath()
+        );
+
+        FileDataStoreService fds = new FileDataStoreService();
+        fds.setStatisticsProvider(StatisticsProvider.NOOP);
+        MockOsgi.activate(fds, context.bundleContext(), config);
+
+        assertNotNull(context.getService(BlobStoreStatsMBean.class));
+        assertNotNull(context.getService(CacheStatsMBean.class));
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/DataStoreServiceTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/DocumentNodeStoreConfigTest.groovy
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/DocumentNodeStoreConfigTest.groovy?rev=1722790&r1=1722789&r2=1722790&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/DocumentNodeStoreConfigTest.groovy (original)
+++ jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/DocumentNodeStoreConfigTest.groovy Mon Jan  4 06:36:02 2016
@@ -21,6 +21,8 @@ package org.apache.jackrabbit.oak.run.os
 
 import org.apache.felix.connect.launch.PojoServiceRegistry
 import org.apache.jackrabbit.oak.api.Blob
+import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean
+import org.apache.jackrabbit.oak.plugins.blob.CachingBlobStore
 import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore
 import org.apache.jackrabbit.oak.plugins.document.mongo.MongoBlobStore
 import org.apache.jackrabbit.oak.plugins.document.util.MongoConnection
@@ -32,6 +34,7 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.h2.jdbcx.JdbcDataSource
 import org.junit.After
 import org.junit.Test
+import org.osgi.framework.ServiceReference
 import org.osgi.framework.ServiceRegistration
 
 import javax.sql.DataSource
@@ -270,6 +273,9 @@ class DocumentNodeStoreConfigTest extend
 
         assert stats.downloadCount > 0
         assert stats.downloadTotalSize > 0
+
+        assertCacheStatsMBean(CachingBlobStore.MEM_CACHE_NAME)
+
     }
 
     @Override
@@ -334,4 +340,16 @@ class DocumentNodeStoreConfigTest extend
         new Random().nextBytes(data);
         return new ByteArrayInputStream(data);
     }
+
+    private void assertCacheStatsMBean(String name){
+        ServiceReference[] refs = registry.getServiceReferences(CacheStatsMBean.class.name,null);
+        def names = []
+        def cacheStatsRef = refs.find { ServiceReference ref ->
+            CacheStatsMBean mbean = registry.getService(ref);
+            names << mbean.name
+            return mbean.name == name
+        }
+
+        assert  cacheStatsRef : "No CacheStat found for [$name]. Registered cache stats $names"
+    }
 }