You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by am...@apache.org on 2014/10/17 09:30:20 UTC

svn commit: r1632481 - /jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/LocalCache.java

Author: amitj
Date: Fri Oct 17 07:30:19 2014
New Revision: 1632481

URL: http://svn.apache.org/r1632481
Log:
JCR-3815: Local Cache Purge Cause Performance Issues
Applying patch from Shashank Gupta.

Modified:
    jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/LocalCache.java

Modified: jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/LocalCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/LocalCache.java?rev=1632481&r1=1632480&r2=1632481&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/LocalCache.java (original)
+++ jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/LocalCache.java Fri Oct 17 07:30:19 2014
@@ -165,17 +165,24 @@ public class LocalCache {
                         transFile.getAbsolutePath());
                 }
                 transFile = null;
-                LOG.debug("file [{}] added to local cache.", fileName);
+                LOG.debug(
+                    "file [{}] doesn't exists. adding to local cache using inputstream.",
+                    fileName);
                 cache.put(fileName, f.length());
             } else {
+                LOG.debug(
+                    "file [{}] doesn't exists. returning transient file [{}].",
+                    fileName, transFile.getAbsolutePath());
                 f = transFile;
             }
         } else {
-            // f.exists and not in purge mode
             f.setLastModified(System.currentTimeMillis());
+            LOG.debug(
+                "file [{}]  exists. adding to local cache using inputstream.",
+                fileName);
             cache.put(fileName, f.length());
         }
-        cache.tryPurge();
+        tryPurge();
         return new LazyFileInputStream(f);
     }
 
@@ -214,7 +221,8 @@ public class LocalCache {
      *         file, if it is added to {@link LocalCache} or original file.
      * @throws IOException
      */
-    public AsyncUploadCacheResult store(String fileName, File src, boolean tryForAsyncUpload) throws IOException {
+    public AsyncUploadCacheResult store(String fileName, File src,
+            boolean tryForAsyncUpload) throws IOException {
         fileName = fileName.replace("\\", "/");
         File dest = getFile(fileName);
         File parent = dest.getParentFile();
@@ -223,19 +231,24 @@ public class LocalCache {
         result.setAsyncUpload(false);
         boolean destExists = false;
         if ((destExists = dest.exists())
-            || (src.exists() && !dest.exists() && !src.equals(dest) && canAdmitFile(src.length())
+            || (src.exists() && !dest.exists() && !src.equals(dest)
+                && canAdmitFile(src.length())
                 && (parent.exists() || parent.mkdirs()) && (src.renameTo(dest)))) {
             if (destExists) {
                 dest.setLastModified(System.currentTimeMillis());
             }
+            LOG.debug("file [{}]  exists= [{}] and adding to local cache.",
+                fileName, destExists);
             cache.put(fileName, dest.length());
-            LOG.debug("file [{}] added to local cache.", fileName);
             result.setFile(dest);
             if (tryForAsyncUpload) {
                 result.setAsyncUpload(asyncUploadCache.add(fileName).canAsyncUpload());
             }
+        } else {
+            LOG.info("file [{}] exists= [{}] not added to local cache.",
+                fileName, destExists);
         }
-        cache.tryPurge();
+        tryPurge();
         return result;
     }
     /**
@@ -261,8 +274,8 @@ public class LocalCache {
             return null;
         } else {
             // touch entry in LRU caches
-            cache.put(fileName, f.length());
             f.setLastModified(System.currentTimeMillis());
+            cache.get(fileName);
             return f;
         }
     }
@@ -351,8 +364,9 @@ public class LocalCache {
     private void deleteOldFiles() {
         int initialSize = toBeDeleted.size();
         int count = 0;
-        for (String n : new ArrayList<String>(toBeDeleted)) {
-            if (tryDelete(n)) {
+        for (String fileName : new ArrayList<String>(toBeDeleted)) {
+            fileName = fileName.replace("\\", "/");
+            if( cache.remove(fileName) != null) {
                 count++;
             }
         }
@@ -397,6 +411,28 @@ public class LocalCache {
         count = Math.min(64 * 1024, count);
         return count;
     }
+    
+    /**
+     * This method tries purging of local cache. It checks if local cache
+     * has exceeded the defined limit then it triggers purge cache job in a
+     * seperate thread.
+     */
+    synchronized void tryPurge() {
+        if (!isInPurgeMode()
+            && cache.currentSizeInBytes > cache.cachePurgeTrigSize) {
+            setPurgeMode(true);
+            LOG.info(
+                "cache.entries = [{}], currentSizeInBytes=[{}]  exceeds cachePurgeTrigSize=[{}]",
+                new Object[] { cache.size(), cache.currentSizeInBytes,
+                    cache.cachePurgeTrigSize });
+            new Thread(new PurgeJob()).start();
+        } else {
+            LOG.debug(
+                "currentSizeInBytes=[{}],cachePurgeTrigSize=[{}], isInPurgeMode =[{}]",
+                new Object[] { cache.currentSizeInBytes,
+                    cache.cachePurgeTrigSize, isInPurgeMode() });
+        }
+    }
 
     /**
      * A LRU based extension {@link LinkedHashMap}. The key is file name and
@@ -462,41 +498,42 @@ public class LocalCache {
                         fileName, flength);
                     currentSizeInBytes -= flength.longValue();
                 }
+            } else {
+                LOG.info("not able to remove cache entry [{}], size [{}]", key,
+                    super.get(key));
             }
             return flength;
         }
 
         @Override
-        public synchronized Long put(final String fileName, final Long value) {
-            Long oldValue = cache.get(fileName);
-            if (oldValue == null) {
-                long flength = value.longValue();
-                currentSizeInBytes += flength;
-                return super.put(fileName.replace("\\", "/"), value);
+        public Long put(final String fileName, final Long value) {
+            if( isInPurgeMode()) {
+                LOG.debug("cache is purge mode: put is no-op");
+                return null;
+            }
+            synchronized (this) {
+                Long oldValue = cache.get(fileName);
+                if (oldValue == null) {
+                    long flength = value.longValue();
+                    currentSizeInBytes += flength;
+                    return super.put(fileName.replace("\\", "/"), value);
+                }
+                toBeDeleted.remove(fileName);
+                return oldValue;
             }
-           toBeDeleted.remove(fileName);
-           return oldValue;
         }
-
-        /**
-         * This method tries purging of local cache. It checks if local cache
-         * has exceeded the defined limit then it triggers purge cache job in a
-         * seperate thread.
-         */
-        synchronized void tryPurge() {
-            if (currentSizeInBytes > cachePurgeTrigSize && !isInPurgeMode()) {
-                setPurgeMode(true);
-                LOG.info(
-                    "currentSizeInBytes=[{}]  exceeds cachePurgeTrigSize=[{}]",
-                    cache.currentSizeInBytes, cache.cachePurgeTrigSize);
-                new Thread(new PurgeJob()).start();
-            } else {
-                LOG.debug(
-                    "currentSizeInBytes=[{}],cachePurgeTrigSize=[{}], isInPurgeMode =[{}]",
-                    new Object[] { cache.currentSizeInBytes,
-                        cache.cachePurgeTrigSize, isInPurgeMode() });
+        
+        @Override
+        public Long get(Object key) {
+            if( isInPurgeMode()) {
+                LOG.debug("cache is purge mode: get is no-op");
+                return null;
+            }
+            synchronized (this) {
+                return super.get(key);
             }
         }
+        
         /**
          * This method check if cache can admit file of given length. 
          * @param length length of file.
@@ -524,9 +561,9 @@ public class LocalCache {
         public void run() {
             try {
                 synchronized (cache) {
-                    LOG.info(" cache purge job started");
                     // first try to delete toBeDeleted files
                     int initialSize = cache.size();
+                    LOG.info(" cache purge job started. initial cache entries = [{}]", initialSize);
                     for (String fileName : new ArrayList<String>(toBeDeleted)) {
                         cache.remove(fileName);
                     }
@@ -536,12 +573,10 @@ public class LocalCache {
                         if (entry.getKey() != null) {
                             if (cache.currentSizeInBytes > cache.cachePurgeResize) {
                                 itr.remove();
-
                             } else {
                                 break;
                             }
                         }
-
                     }
                     LOG.info(
                         " cache purge job completed: cleaned [{}] files and currentSizeInBytes = [{}]",