From c9b07dd417ad8d2983b91f2de985c108250a4493 Mon Sep 17 00:00:00 2001
From: Jukka Zitting <jukka@apache.org>
Date: Thu, 20 Oct 2011 11:21:12 +0200
Subject: [PATCH] JCR-3117: Stats for the PersistenceManager

Use AtomicLong counters and the TimeSeries mechanism for PM stats
---
 .../api/stats/PersistenceManagerStat.java          |   53 -----------
 .../jackrabbit/api/stats/RepositoryStatistics.java |    9 ++-
 .../org/apache/jackrabbit/core/RepositoryImpl.java |    6 +-
 .../jackrabbit/core/persistence/PMContext.java     |   42 ++++-----
 .../bundle/AbstractBundlePersistenceManager.java   |   63 ++++++++-----
 .../core/stats/PersistenceManagerStatCore.java     |   48 ----------
 .../core/stats/PersistenceManagerStatImpl.java     |   94 --------------------
 .../core/stats/RepositoryStatisticsImpl.java       |    4 +
 .../apache/jackrabbit/core/stats/StatManager.java  |   11 +--
 9 files changed, 71 insertions(+), 259 deletions(-)
 delete mode 100644 jackrabbit-api/src/main/java/org/apache/jackrabbit/api/stats/PersistenceManagerStat.java
 delete mode 100644 jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/PersistenceManagerStatCore.java
 delete mode 100644 jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/PersistenceManagerStatImpl.java

diff --git a/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/stats/PersistenceManagerStat.java b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/stats/PersistenceManagerStat.java
deleted file mode 100644
index b45c779..0000000
--- a/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/stats/PersistenceManagerStat.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.api.stats;
-
-/**
- * Statistics for the PersistenceManager
- */
-public interface PersistenceManagerStat {
-
-    long getCacheAccessCount();
-
-    long getCacheMissCount();
-
-    double getCacheMissAvgDuration();
-
-    double getBundleWritesPerSecond();
-
-    /** -- GENERAL OPS -- **/
-
-    /**
-     * If this service is currently registering stats
-     * 
-     * @return <code>true</code> if the service is enabled
-     */
-    boolean isEnabled();
-
-    /**
-     * Enables/Disables the service
-     * 
-     * @param enabled
-     */
-    void setEnabled(boolean enabled);
-
-    /**
-     * clears all data
-     */
-    void reset();
-
-}
diff --git a/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/stats/RepositoryStatistics.java b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/stats/RepositoryStatistics.java
index 15be8ae..4f6fed0 100644
--- a/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/stats/RepositoryStatistics.java
+++ b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/stats/RepositoryStatistics.java
@@ -24,8 +24,13 @@ package org.apache.jackrabbit.api.stats;
 public interface RepositoryStatistics {
 
     enum Type {
-        SESSION_READ_COUNTER(true), 
-        SESSION_READ_DURATION(true), 
+        BUNDLE_READ_COUNTER(true),
+        BUNDLE_READ_DURATION(true),
+        BUNDLE_WRITE_COUNTER(true),
+        BUNDLE_WRITE_DURATION(true),
+        BUNDLE_CACHE_COUNTER(true),
+        SESSION_READ_COUNTER(true),
+        SESSION_READ_DURATION(true),
         SESSION_WRITE_COUNTER(true),
         SESSION_WRITE_DURATION(true),
         SESSION_LOGIN_COUNTER(true),
diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
index c1d9b94..224977d 100644
--- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
+++ b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
@@ -1332,11 +1332,7 @@ public class RepositoryImpl extends AbstractRepository
         try {
             PersistenceManager pm = pmConfig
                     .newInstance(PersistenceManager.class);
-            PMContext pmContext = new PMContext(homeDir, fs,
-                    context.getRootNodeId(), context.getNamespaceRegistry(),
-                    context.getNodeTypeRegistry(), context.getDataStore());
-            pmContext.setPersistenceManagerStatCore(context.getStatManager()
-                    .getPersistenceManagerStatCore());
+            PMContext pmContext = new PMContext(homeDir, fs, context);
             pm.init(pmContext);
             return pm;
         } catch (Exception e) {
diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PMContext.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PMContext.java
index 884d029..73417bc 100644
--- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PMContext.java
+++ b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PMContext.java
@@ -20,11 +20,12 @@ import java.io.File;
 
 import javax.jcr.NamespaceRegistry;
 
+import org.apache.jackrabbit.core.RepositoryContext;
 import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.stats.PersistenceManagerStatCore;
+import org.apache.jackrabbit.core.stats.RepositoryStatisticsImpl;
 
 /**
  * A <code>PMContext</code> is used to provide context information for a
@@ -64,32 +65,26 @@ public class PMContext {
      */
     private final DataStore dataStore;
 
-    /**
-     * PersistenceManagerStatCore stats object for the PM.
-     */
-    private PersistenceManagerStatCore persistenceManagerStatCore;
+    /** Repository statistics collector. */
+    private final RepositoryStatisticsImpl stats;
 
     /**
      * Creates a new <code>PMContext</code>.
      *
      * @param homeDir the physical home directory
      * @param fs the virtual jackrabbit filesystem
-     * @param rootNodeId id of the root node
-     * @param nsReg        namespace registry
-     * @param ntReg        node type registry
+     * @param context repository component context
      */
     public PMContext(File homeDir,
                      FileSystem fs,
-                     NodeId rootNodeId,
-                     NamespaceRegistry nsReg,
-                     NodeTypeRegistry ntReg,
-                     DataStore dataStore) {
+                     RepositoryContext context) {
         this.physicalHomeDir = homeDir;
         this.fs = fs;
-        this.rootNodeId = rootNodeId;
-        this.nsReg = nsReg;
-        this.ntReg = ntReg;
-        this.dataStore = dataStore;
+        this.rootNodeId = context.getRootNodeId();
+        this.nsReg = context.getNamespaceRegistry();
+        this.ntReg = context.getNodeTypeRegistry();
+        this.dataStore = context.getDataStore();
+        this.stats = context.getRepositoryStatistics();
     }
 
 
@@ -144,17 +139,14 @@ public class PMContext {
         return dataStore;
     }
 
+
     /**
-     * Returns the PersistenceManagerStatCore stats object for the PM.
-     * 
-     * @return the PersistenceManagerStatCore stats object for the PM.
+     * Returns the repository statistics collector.
+     *
+     * @return repository statistics
      */
-    public PersistenceManagerStatCore getPersistenceManagerStatCore() {
-        return persistenceManagerStatCore;
+    public RepositoryStatisticsImpl getRepositoryStatistics() {
+        return stats;
     }
 
-    public void setPersistenceManagerStatCore(
-            PersistenceManagerStatCore persistenceManagerStatCore) {
-        this.persistenceManagerStatCore = persistenceManagerStatCore;
-    }
 }
diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
index 638b0cb..16ee850 100644
--- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
+++ b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
@@ -23,9 +23,11 @@ import static org.apache.jackrabbit.spi.commons.name.NameConstants.JCR_UUID;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
 
 import javax.jcr.PropertyType;
 
+import org.apache.jackrabbit.api.stats.RepositoryStatistics;
 import org.apache.jackrabbit.core.cache.Cache;
 import org.apache.jackrabbit.core.cache.CacheAccessListener;
 import org.apache.jackrabbit.core.cache.ConcurrentCache;
@@ -49,7 +51,7 @@ import org.apache.jackrabbit.core.state.NoSuchItemStateException;
 import org.apache.jackrabbit.core.state.NodeReferences;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.stats.PersistenceManagerStatCore;
+import org.apache.jackrabbit.core.stats.RepositoryStatisticsImpl;
 import org.apache.jackrabbit.core.util.StringIndex;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.spi.Name;
@@ -133,8 +135,20 @@ public abstract class AbstractBundlePersistenceManager implements
     /** default size of the bundle cache */
     private long bundleCacheSize = 8 * 1024 * 1024;
 
-    /** statistics object */
-    private PersistenceManagerStatCore pmStatCore;
+    /** Counter of read operations. */
+    private AtomicLong readCounter;
+
+    /** Counter of write operations. */
+    private AtomicLong writeCounter;
+
+    /** Duration of read operations. */
+    private AtomicLong readDuration;
+
+    /** Duration of write operations. */
+    private AtomicLong writeDuration;
+
+    /** Counter of bundle cache accesses. */
+    private AtomicLong cacheCounter;
 
     /**
      * Returns the size of the bundle cache in megabytes.
@@ -398,7 +412,19 @@ public abstract class AbstractBundlePersistenceManager implements
         bundles = new ConcurrentCache<NodeId, NodePropBundle>(context.getHomeDir().getName() + "BundleCache");
         bundles.setMaxMemorySize(bundleCacheSize);
         bundles.setAccessListener(this);
-        pmStatCore = context.getPersistenceManagerStatCore();
+
+        // statistics
+        RepositoryStatisticsImpl stats = context.getRepositoryStatistics();
+        cacheCounter = stats.getCounter(
+                RepositoryStatistics.Type.BUNDLE_CACHE_COUNTER);
+        readCounter = stats.getCounter(
+                RepositoryStatistics.Type.BUNDLE_READ_COUNTER);
+        readDuration = stats.getCounter(
+                RepositoryStatistics.Type.BUNDLE_READ_DURATION);
+        writeCounter = stats.getCounter(
+                RepositoryStatistics.Type.BUNDLE_WRITE_COUNTER);
+        writeDuration = stats.getCounter(
+                RepositoryStatistics.Type.BUNDLE_WRITE_DURATION);
     }
 
     /**
@@ -675,17 +701,7 @@ public abstract class AbstractBundlePersistenceManager implements
             return bundle;
         }
         // cache miss
-        if (pmStatCore != null && pmStatCore.isEnabled()) {
-            long t = System.currentTimeMillis();
-            try {
-                return getBundleCacheMiss(id);
-            } finally {
-                t = System.currentTimeMillis() - t;
-                pmStatCore.onReadCacheMiss(t);
-            }
-        } else {
-            return getBundleCacheMiss(id);
-        }
+        return getBundleCacheMiss(id);
     }
 
     /**
@@ -700,7 +716,11 @@ public abstract class AbstractBundlePersistenceManager implements
      */
     private NodePropBundle getBundleCacheMiss(NodeId id)
             throws ItemStateException {
+        long time = System.nanoTime();
         NodePropBundle bundle = loadBundle(id);
+        readDuration.addAndGet(System.nanoTime() - time);
+        readCounter.incrementAndGet();
+
         if (bundle != null) {
             bundle.markOld();
             bundles.put(id, bundle, bundle.getSize());
@@ -729,15 +749,12 @@ public abstract class AbstractBundlePersistenceManager implements
      * @throws ItemStateException if an error occurs
      */
     private void putBundle(NodePropBundle bundle) throws ItemStateException {
-
-        long time = System.currentTimeMillis();
+        long time = System.nanoTime();
         storeBundle(bundle);
+        writeDuration.addAndGet(System.nanoTime() - time);
+        writeCounter.incrementAndGet();
+
         bundle.markOld();
-        log.debug("stored bundle {} in {} ms", new Object[] { bundle.getId(),
-                System.currentTimeMillis() - time });
-        if (pmStatCore != null && pmStatCore.isEnabled()) {
-            pmStatCore.onBundleWrite(System.currentTimeMillis() - time);
-        }
 
         // only put to cache if already exists. this is to ensure proper
         // overwrite and not creating big contention during bulk loads
@@ -765,7 +782,7 @@ public abstract class AbstractBundlePersistenceManager implements
 
     public void cacheAccessed(long accessCount) {
         logCacheStats();
-        pmStatCore.cacheAccessed(accessCount);
+        cacheCounter.addAndGet(accessCount);
     }
 
     private void logCacheStats() {
diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/PersistenceManagerStatCore.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/PersistenceManagerStatCore.java
deleted file mode 100644
index 968c355..0000000
--- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/PersistenceManagerStatCore.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.core.stats;
-
-import org.apache.jackrabbit.api.stats.PersistenceManagerStat;
-
-/**
- * Extends external facing {@link PersistenceManagerStat} with some internal
- * operations
- * 
- */
-public interface PersistenceManagerStatCore extends PersistenceManagerStat {
-
-    /**
-     * @param durationMs
-     *            in milliseconds
-     */
-    void onReadCacheMiss(long durationMs);
-
-    /**
-     * @param durationMs
-     *            in milliseconds
-     */
-    void onBundleWrite(long durationMs);
-
-    /**
-     * Called whenever the cache access count reaches a certain threshold.
-     * 
-     * @param accessCount
-     *            number of access times since last call
-     */
-    void cacheAccessed(long accessCount);
-
-}
diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/PersistenceManagerStatImpl.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/PersistenceManagerStatImpl.java
deleted file mode 100644
index 0c0e086..0000000
--- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/PersistenceManagerStatImpl.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.core.stats;
-
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.jackrabbit.core.stats.util.CachingOpsPerSecondDto;
-
-/**
- * Default {@link PersistenceManagerStatCore} impl
- * 
- */
-public class PersistenceManagerStatImpl implements PersistenceManagerStatCore {
-
-    private boolean enabled = false;
-
-    private final CachingOpsPerSecondDto bundleWriteOps = new CachingOpsPerSecondDto();
-
-    private final AtomicLong cacheAccessCount = new AtomicLong();
-
-    private final CachingOpsPerSecondDto cacheReadMissLatency = new CachingOpsPerSecondDto();
-
-    public void onReadCacheMiss(long durationMs) {
-        if (!enabled) {
-            return;
-        }
-        cacheReadMissLatency.onOp(durationMs);
-    }
-
-    public void onBundleWrite(long durationMs) {
-        if (!enabled) {
-            return;
-        }
-        bundleWriteOps.onOp(durationMs);
-    }
-
-    public void cacheAccessed(long accessCount) {
-        if (!enabled) {
-            return;
-        }
-        cacheAccessCount.addAndGet(accessCount);
-    }
-
-    /** -- PersistenceManagerStat -- **/
-
-    public long getCacheMissCount() {
-        return cacheReadMissLatency.getOperations();
-    }
-
-    public double getCacheMissAvgDuration() {
-        return cacheReadMissLatency.getOpAvgTime();
-    }
-
-    public long getCacheAccessCount() {
-        return cacheAccessCount.get();
-    }
-
-    public double getBundleWritesPerSecond() {
-        return bundleWriteOps.getOpsPerSecond();
-    }
-
-    /** -- GENERAL OPS -- **/
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-        if (this.enabled) {
-            reset();
-        }
-    }
-
-    public void reset() {
-        bundleWriteOps.reset();
-        cacheReadMissLatency.reset();
-        cacheAccessCount.set(0);
-    }
-}
diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/RepositoryStatisticsImpl.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/RepositoryStatisticsImpl.java
index 405e773..7148219 100644
--- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/RepositoryStatisticsImpl.java
+++ b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/RepositoryStatisticsImpl.java
@@ -48,6 +48,10 @@ public class RepositoryStatisticsImpl implements
         getOrCreateRecorder(Type.SESSION_READ_DURATION);
         getOrCreateRecorder(Type.SESSION_WRITE_COUNTER);
         getOrCreateRecorder(Type.SESSION_WRITE_DURATION);
+        getOrCreateRecorder(Type.BUNDLE_READ_COUNTER);
+        getOrCreateRecorder(Type.BUNDLE_READ_DURATION);
+        getOrCreateRecorder(Type.BUNDLE_WRITE_COUNTER);
+        getOrCreateRecorder(Type.BUNDLE_WRITE_DURATION);
     }
 
     public synchronized Iterator<Entry<Type, TimeSeries>> iterator() {
diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/StatManager.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/StatManager.java
index b1c6a6e..8b888cc 100644
--- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/StatManager.java
+++ b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/stats/StatManager.java
@@ -30,7 +30,6 @@ public class StatManager {
 
     public static String ALL_STATS_ENABLED_PROPERTY = "org.apache.jackrabbit.api.stats.ALL";
     public static String QUERY_STATS_ENABLED_PROPERTY = "org.apache.jackrabbit.api.stats.QueryStat";
-    public static String PM_STATS_ENABLED_PROPERTY = "org.apache.jackrabbit.api.stats.PersistenceManagerStat";
 
     private static final Logger log = LoggerFactory
             .getLogger(StatManager.class);
@@ -38,8 +37,6 @@ public class StatManager {
     /* STAT OBJECTS */
     private final QueryStatCore queryStat = new QueryStatImpl();
 
-    private final PersistenceManagerStatCore pmStat = new PersistenceManagerStatImpl();
-
     public StatManager() {
         init();
     }
@@ -48,17 +45,13 @@ public class StatManager {
         boolean allEnabled = getBoolean(ALL_STATS_ENABLED_PROPERTY);
         queryStat.setEnabled(allEnabled
                 || getBoolean(QUERY_STATS_ENABLED_PROPERTY));
-        pmStat.setEnabled(allEnabled || getBoolean(PM_STATS_ENABLED_PROPERTY));
         log.debug(
-                "Started StatManager. QueryStat is enabled {}, PersistenceManagerStat is enabled {}",
-                new Object[] { queryStat.isEnabled(), pmStat.isEnabled() });
+                "Started StatManager. QueryStat is enabled {}",
+                new Object[] { queryStat.isEnabled() });
     }
 
     public QueryStatCore getQueryStat() {
         return queryStat;
     }
 
-    public PersistenceManagerStatCore getPersistenceManagerStatCore() {
-        return pmStat;
-    }
 }
-- 
1.7.4.4

