Index: jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/ConcurrentCacheTest.java
===================================================================
--- jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/ConcurrentCacheTest.java	(revision 1179987)
+++ jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/ConcurrentCacheTest.java	(working copy)
@@ -37,7 +37,7 @@
         }
 
         ConcurrentCache<NodeId, NodeId> cache =
-            new ConcurrentCache<NodeId, NodeId>();
+            new ConcurrentCache<NodeId, NodeId>("test");
         cache.setMaxMemorySize(ids.length / 2);
 
         for (int i = 0; i < ids.length; i++) {
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/Cache.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/Cache.java	(revision 1179987)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/Cache.java	(working copy)
@@ -45,7 +45,6 @@
      * Get the number of accesses (get or set) until resetAccessCount was called.
      * @return the count
      */
-
     long getAccessCount();
 
     /**
@@ -54,6 +53,30 @@
     void resetAccessCount();
 
     /**
+     * Get the number of cache hits.
+     * @return the number of hits
+     */
+    long getHitCount();
+
+    /**
+     * Get the number of cache misses.
+     * @return the number of misses
+     */
+    long getMissCount();
+
+    /**
+     * Get the number of cache puts.
+     * @return the number of puts
+     */
+    long getPutCount();
+
+    /**
+     * Get the number of elements/objects in the cache.
+     * @return the number of elements
+     */
+    long getElementCount();
+    
+    /**
      * Add a listener to this cache that is informed after a number of accesses.
      */
     void setAccessListener(CacheAccessListener listener);
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java	(revision 1179987)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java	(working copy)
@@ -57,10 +57,12 @@
 
     }
 
+    private final String name;
     private final Map<K, E<V>>[] segments;
 
     @SuppressWarnings({ "unchecked", "serial" })
-    public ConcurrentCache(int numberOfSegments) {
+    public ConcurrentCache(String name, int numberOfSegments) {
+        this.name = name;
         this.segments = new Map[numberOfSegments];
         for (int i = 0; i < segments.length; i++) {
             segments[i] = new LinkedHashMap<K, E<V>>(16, 0.75f, true) {
@@ -77,8 +79,8 @@
         }
     }
 
-    public ConcurrentCache() {
-        this(DEFAULT_NUMBER_OF_SEGMENTS);
+    public ConcurrentCache(String name) {
+        this(name, DEFAULT_NUMBER_OF_SEGMENTS);
     }
 
     /**
@@ -123,8 +125,10 @@
         synchronized (segment) {
             E<V> entry = segment.get(key);
             if (entry != null) {
+                recordCacheHit();
                 return entry.value;
             } else {
+                recordCacheMiss();
                 return null;
             }
         }
@@ -160,6 +164,7 @@
      * @return the previous value, or <code>null</code>
      */
     public V put(K key, V value, long size) {
+        recordCachePut();
         E<V> previous;
 
         Map<K, E<V>> segment = getSegment(key);
@@ -252,4 +257,16 @@
         }
     }
 
+    public long getElementCount() {
+        long count = 0;
+        for (int i = 0; i < segments.length; i++) {
+            count += segments[i].size();
+        }
+        return count;
+    }
+
+    @Override
+    public String toString() {
+        return name + "[" + getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()) + "]";
+    }
 }
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/AbstractCache.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/AbstractCache.java	(revision 1179987)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/AbstractCache.java	(working copy)
@@ -65,6 +65,21 @@
     private final AtomicLong accessCount = new AtomicLong();
 
     /**
+     * Cache put counter.
+     */
+    private final AtomicLong putCount = new AtomicLong();
+
+    /**
+     * Cache hit counter.
+     */
+    private final AtomicLong hitCount = new AtomicLong();
+
+    /**
+     * Cache miss counter.
+     */
+    private final AtomicLong missCount = new AtomicLong();
+
+    /**
      * Cache access listener. Set in the
      * {@link #setAccessListener(CacheAccessListener)} method and accessed
      * by periodically by the {@link #recordCacheAccess()} method.
@@ -107,6 +122,18 @@
         }
     }
 
+    protected void recordCachePut() {
+        putCount.incrementAndGet();
+    }
+
+    protected void recordCacheHit() {
+        hitCount.incrementAndGet();
+    }
+
+    protected void recordCacheMiss() {
+        missCount.incrementAndGet();
+    }
+
     public long getAccessCount() {
         return accessCount.get();
     }
@@ -115,6 +142,18 @@
         accessCount.set(0);
     }
 
+    public long getPutCount() {
+        return putCount.get();
+    }
+
+    public long getHitCount() {
+        return hitCount.get();
+    }
+
+    public long getMissCount() {
+        return missCount.get();
+    }
+
     public long getMemoryUsed() {
         return memoryUsed.get();
     }
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheManager.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheManager.java	(revision 1179987)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/CacheManager.java	(working copy)
@@ -54,6 +54,9 @@
     /** The default minimum resize interval (in ms). */
     private static final int DEFAULT_MIN_RESIZE_INTERVAL = 1000;
 
+    /** The default minimum stats logging interval (in ms). */
+    private static final int DEFAULT_LOG_STATS_INTERVAL = 60 * 1000;
+
     /** The size of a big object, to detect if a cache is full or not. */
     private static final int BIG_OBJECT_SIZE = 16 * 1024;
 
@@ -77,11 +80,21 @@
             "org.apache.jackrabbit.cacheResizeInterval",
             DEFAULT_MIN_RESIZE_INTERVAL);
 
-        /** The last time the caches where resized. */
+    /** The minimum interval time between stats are logged */
+    private long minLogStatsInterval = Long.getLong(
+            "org.apache.jackrabbit.cacheLogStatsInterval",
+            DEFAULT_LOG_STATS_INTERVAL);
+
+    /** The last time the caches where resized. */
     private volatile long nextResize =
         System.currentTimeMillis() + DEFAULT_MIN_RESIZE_INTERVAL;
 
 
+    /** The last time the cache stats were logged. */
+    private volatile long nextLogStats =
+            System.currentTimeMillis() + DEFAULT_LOG_STATS_INTERVAL;
+
+
     public long getMaxMemory() {
         return maxMemory;
     }
@@ -119,6 +132,9 @@
      * Resize the caches if required.
      */
     public void cacheAccessed() {
+
+        logCacheStats();
+        
         long now = System.currentTimeMillis();
         if (now < nextResize) {
             return;
@@ -136,6 +152,24 @@
     }
 
     /**
+     * Log info about the caches.
+     */
+    private void logCacheStats() {
+        if (log.isInfoEnabled()) {
+            long now = System.currentTimeMillis();
+            if (now < nextLogStats) {
+                return;
+            }
+            for (Cache cache : caches.keySet()) {
+                long u = cache.getMemoryUsed() / 1024;
+                long m = cache.getMaxMemorySize() / 1024;
+                log.info("name=" + cache + " num=" + cache.getElementCount() + " mem=" + u + "k max=" + m + "k hits="
+                        + cache.getHitCount() + " miss=" + cache.getMissCount() + " puts=" + cache.getPutCount());
+            }
+            nextLogStats = now + minLogStatsInterval;
+        }
+    }
+    /**
      * Re-calcualte the maximum memory for each cache, and set the new limits.
      */
     private void resizeAll() {
@@ -211,6 +245,7 @@
                 log.debug(cache + " now:" + cache.getMaxMemorySize() + " used:"
                         + info.getMemoryUsed() + " access:" + info.getAccessCount()
                         + " new:" + info.getMemory());
+
             }
             cache.setMaxMemorySize(info.getMemory());
         }
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java	(revision 1179987)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java	(working copy)
@@ -28,6 +28,8 @@
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.core.cache.Cache;
+import org.apache.jackrabbit.core.cache.CacheAccessListener;
 import org.apache.jackrabbit.core.cache.ConcurrentCache;
 import org.apache.jackrabbit.core.fs.FileSystemResource;
 import org.apache.jackrabbit.core.fs.FileSystem;
@@ -82,7 +84,7 @@
  * </ul>
  */
 public abstract class AbstractBundlePersistenceManager implements
-    PersistenceManager, CachingPersistenceManager, IterablePersistenceManager {
+    PersistenceManager, CachingPersistenceManager, IterablePersistenceManager, CacheAccessListener {
 
     /** the default logger */
     private static Logger log = LoggerFactory.getLogger(AbstractBundlePersistenceManager.class);
@@ -112,6 +114,18 @@
     /** the cache of loaded bundles */
     private ConcurrentCache<NodeId, NodePropBundle> bundles;
 
+    /** The default minimum stats logging interval (in ms). */
+    private static final int DEFAULT_LOG_STATS_INTERVAL = 60 * 1000;
+
+    /** The minimum interval time between stats are logged */
+    private long minLogStatsInterval = Long.getLong(
+            "org.apache.jackrabbit.cacheLogStatsInterval",
+            DEFAULT_LOG_STATS_INTERVAL);
+
+    /** The last time the cache stats were logged. */
+    private volatile long nextLogStats =
+            System.currentTimeMillis() + DEFAULT_LOG_STATS_INTERVAL;
+
     /** the persistence manager context */
     protected PMContext context;
 
@@ -377,8 +391,9 @@
     public void init(PMContext context) throws Exception {
         this.context = context;
         // init bundle cache
-        bundles = new ConcurrentCache<NodeId, NodePropBundle>();
+        bundles = new ConcurrentCache<NodeId, NodePropBundle>(context.getHomeDir().getName() + "BundleCache");
         bundles.setMaxMemorySize(bundleCacheSize);
+        bundles.setAccessListener(this);
     }
 
     /**
@@ -709,4 +724,25 @@
         bundles.remove(id);
     }
 
+    public void cacheAccessed() {
+        logCacheStats();
+    }
+
+    private void logCacheStats() {
+        if (log.isInfoEnabled()) {
+            long now = System.currentTimeMillis();
+            if (now < nextLogStats) {
+                return;
+            }
+            long u = bundles.getMemoryUsed() / 1024;
+            long m = bundles.getMaxMemorySize() / 1024;
+            log.info("name=" + bundles + " num=" + bundles.getElementCount() + " mem=" + u + "k max=" + m + "k hits="
+                    + bundles.getHitCount() + " miss=" + bundles.getMissCount() + " puts=" + bundles.getPutCount());
+            nextLogStats = now + minLogStatsInterval;
+        }
+    }
+
+    public void disposeCache(Cache cache) {
+        // NOOP
+    }
 }
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java	(revision 1179987)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java	(working copy)
@@ -34,6 +34,7 @@
 import javax.sql.DataSource;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.core.cache.Cache;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemResource;
 import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
@@ -1432,4 +1433,5 @@
         }
     }
 
+
 }
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java	(revision 1179987)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java	(working copy)
@@ -45,7 +45,7 @@
     private volatile long numWrites = 0;
 
     private final ConcurrentCache<ItemId, ItemState> cache =
-        new ConcurrentCache<ItemId, ItemState>();
+        new ConcurrentCache<ItemId, ItemState>(MLRUItemStateCache.class.getSimpleName());
 
     public MLRUItemStateCache(CacheManager cacheMgr) {
         cache.setMaxMemorySize(DEFAULT_MAX_MEM);
