You are viewing a plain text version of this content. The canonical link for it is here.
Posted to olio-commits@incubator.apache.org by te...@apache.org on 2009/09/30 14:04:16 UTC

svn commit: r820272 - in /incubator/olio/webapp/java/trunk/ws/apps/webapp: ./ src/java/org/apache/olio/webapp/cache/ src/java/org/apache/olio/webapp/controller/ src/java/org/apache/olio/webapp/model/ src/java/org/apache/olio/webapp/util/

Author: tekgrrl
Date: Wed Sep 30 14:04:15 2009
New Revision: 820272

URL: http://svn.apache.org/viewvc?rev=820272&view=rev
Log:
OLIO-95 put memcached layer back in Java app

Modified:
    incubator/olio/webapp/java/trunk/ws/apps/webapp/build.xml
    incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/Cache.java
    incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/CacheFactory.java
    incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/MemCachedFactory.java
    incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/SimpleMapCacheFactory.java
    incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/controller/EventAction.java
    incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/model/ModelFacade.java
    incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/ContentCachingFilter.java
    incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/WebappUtil.java

Modified: incubator/olio/webapp/java/trunk/ws/apps/webapp/build.xml
URL: http://svn.apache.org/viewvc/incubator/olio/webapp/java/trunk/ws/apps/webapp/build.xml?rev=820272&r1=820271&r2=820272&view=diff
==============================================================================
--- incubator/olio/webapp/java/trunk/ws/apps/webapp/build.xml (original)
+++ incubator/olio/webapp/java/trunk/ws/apps/webapp/build.xml Wed Sep 30 14:04:15 2009
@@ -45,7 +45,7 @@
             <fileset file="${webapp.lib}/rome-fetcher-0.9.jar"/>
             <fileset file="${webapp.lib}/commons-fileupload-1.2.jar"/>
             <fileset file="${webapp.lib}/commons-io-1.2.jar"/>
-            <fileset file="${webapp.lib}/java_memcached-release_1.5.1.jar"/>
+            <fileset file="${webapp.lib}/java_memcached-release_2.0.1.jar"/>
             <fileset file="${webapp.lib}/ajax-wrapper-comp-1.8.1.jar"/>
             <fileset file="${webapp.lib}/JSON.jar"/>
             <!-- add jersey files -->

Modified: incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/Cache.java
URL: http://svn.apache.org/viewvc/incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/Cache.java?rev=820272&r1=820271&r2=820272&view=diff
==============================================================================
--- incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/Cache.java (original)
+++ incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/Cache.java Wed Sep 30 14:04:15 2009
@@ -46,8 +46,21 @@
      * @param timeToLive Time to cache this object in seconds
      */
     void put(String key, Object value, long timeToLive);
-    
-    boolean needsRefresh (String key);
+
+    /**
+     * Invalidates a cached item using a key
+     * @param key
+     * @return success
+     */
+    boolean invalidate(String key);
+
+    /*
+     * Check if cache needs refresh based on existence cached object and of Semaphore
+     * @param key The key
+     * @param cacheObjPresent false if the cache object for this key exists
+     * @return true if the cache object needs a refresh
+     */
+    boolean needsRefresh (boolean cacheObjPresent, String key);
     
     void doneRefresh (String key, long timeToNextRefresh) throws CacheException;
     

Modified: incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/CacheFactory.java
URL: http://svn.apache.org/viewvc/incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/CacheFactory.java?rev=820272&r1=820271&r2=820272&view=diff
==============================================================================
--- incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/CacheFactory.java (original)
+++ incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/CacheFactory.java Wed Sep 30 14:04:15 2009
@@ -171,7 +171,11 @@
         public void put(String key, Object value, long timeToLive) {
         }
 
-        public boolean needsRefresh(String key) {
+        public boolean invalidate(String key) {
+            return false;
+        }
+
+        public boolean needsRefresh(boolean cachObjPresent, String cacheKey) {
             return false;
         }
 

Modified: incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/MemCachedFactory.java
URL: http://svn.apache.org/viewvc/incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/MemCachedFactory.java?rev=820272&r1=820271&r2=820272&view=diff
==============================================================================
--- incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/MemCachedFactory.java (original)
+++ incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/MemCachedFactory.java Wed Sep 30 14:04:15 2009
@@ -17,6 +17,7 @@
  */
 package org.apache.olio.webapp.cache;
 
+import com.danga.MemCached.Logger;
 import com.danga.MemCached.MemCachedClient;
 import com.danga.MemCached.SockIOPool;
 import java.util.Date;
@@ -65,6 +66,7 @@
             pool.initialize();
 
             cache = new MemCachedClient();
+            MemCachedClient.getLogger().setLevel(Logger.LEVEL_WARN);
             
             // Set thelog level to WARNING -- The defautl is INFO which causes unecessary logging
             
@@ -138,43 +140,48 @@
                                         key + ", value=" + value + " to cache");
         }
 
-        public boolean needsRefresh(String key) {
-            // Double checked lock. We first set the lock, then check whether we own the lock
-            // If updateSema is not null, then we don't need to updatet he cache. 
-            // updateSema is stroed with a timeout, so it will expire based on 
+        /** Invalidates a cached item using a key
+         *
+         * @param key The key
+         * @return success
+         */
+        public boolean invalidate(String key) {
+            // Only remove the Semaphore
+            return cache.delete(prefix + key + ".UpdateSema");
+        }
+
+        /*
+         * Check if cache needs refresh based on existence cached object and of Semaphore
+         * @param key The key
+         * @param cacheObjPresent false if the cache object for this key exists
+         * @return true if the object needs a refresh and if we have the lock
+         */
+        public boolean needsRefresh(boolean cacheObjPresent, String key) {
+            // Was a double checked lock. First set the lock, then check  we own the lock
+            // Now using memcached's add which is an atomic get/set
+            // If updateSema is not null, then we don't need to update the cache.
+            // updateSema is stored with a timeout, so it will expire based on
             // cache expiry time
             String updateSema = prefix + key + ".UpdateSema";
             String updateLock = prefix + key + ".UpdateLock";
-            if (cache.get(updateSema) == null) {
+            if (!cacheObjPresent || cache.get(updateSema) == null) {
+               // the lockId is based on the threadId
                String lockId = CacheFactory.getInstance().getLockId();
-               if (cache.get(updateLock) == null) {
-                   Date expiryTime = new Date (System.currentTimeMillis() 
+
+               Date expiryTime = new Date (System.currentTimeMillis()
                    + CacheFactory.getInstance().getCacheLockExpireInSeconds()*1000);
-                   
-                   //if (!cache.set(updateLock, lockId, expiryTime)) {
-                   if (!cache.set(updateLock, lockId, expiryTime)) {
-                       throw new CacheException("Error setting updateLock - key = " + 
-                               updateLock +" lockId = " + lockId);
-                   }
-                   else {
-                       System.out.println ("Set updateLock = " + updateLock + 
-                               " with lockID = " + lockId);
-                   }
-               
-                   // Now that we have set the lock. Check whether anyone has overwritten it.
-                   if (cache.get(updateLock) != null) {
-                       if (cache.get(updateLock).equals(lockId))
-                            return true;
-                   }
-                   else {
-                       System.out.println ("Get updateLock = " + updateLock + 
-                               " return null" );
-                       throw new CacheException("Error getting updateLock - key = " + 
-                               updateLock + " lockId = " + lockId);
-                       
-                   } 
+
+               // Memcached's add is an atomic get/set and can be used for locking
+               if (!cache.add(updateLock, lockId, expiryTime)) {
+                   // someone else has the lock, hopefully they are doing
+                   // what we are trying to do
+                   return false;
                }
+               else
+                   // we got the lock
+                   return true;
             }
+            // no refresh required
             return false;
         }
 

Modified: incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/SimpleMapCacheFactory.java
URL: http://svn.apache.org/viewvc/incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/SimpleMapCacheFactory.java?rev=820272&r1=820271&r2=820272&view=diff
==============================================================================
--- incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/SimpleMapCacheFactory.java (original)
+++ incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/cache/SimpleMapCacheFactory.java Wed Sep 30 14:04:15 2009
@@ -28,6 +28,8 @@
  */
 public class SimpleMapCacheFactory extends CacheFactory {
 
+    private int cacheExpireInSeconds = 120; // in seconds
+
     private static final ConcurrentHashMap<String,SoftReference<Object>> CACHE =
                                     new ConcurrentHashMap<String, SoftReference<Object>>();
 
@@ -36,10 +38,16 @@
      * @return The cache instance
      * @param type
      */
+    @Override
     public Cache createCache(String type) {
         return new MapCache(type);
     }
 
+    @Override
+    public int getCacheExpireInSeconds() {
+        return cacheExpireInSeconds;
+    }
+
     static class MapCache implements Cache {
 
         private String prefix;
@@ -87,16 +95,26 @@
             }
         }
 
-        // This is not implemented for now.
-        public boolean needsRefresh(String key) {
+        public boolean needsRefresh(boolean cacheObjPresent, String key) {
+           if (!cacheObjPresent || (expiryTime > 0 && System.currentTimeMillis() > expiryTime))
+                return true;
+
             return false;
         }
 
         public void doneRefresh(String key, long timeToNextRefresh) throws CacheException {
+            // no-op
         }
 
         public boolean isLocal() {
             return true;
         }
+
+        public boolean invalidate(String key) {
+            put(key, null);
+            if (expiryTime == -1)
+                return true; // well we live in hope right?
+            return false;
+        }
     }
 }

Modified: incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/controller/EventAction.java
URL: http://svn.apache.org/viewvc/incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/controller/EventAction.java?rev=820272&r1=820271&r2=820272&view=diff
==============================================================================
--- incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/controller/EventAction.java (original)
+++ incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/controller/EventAction.java Wed Sep 30 14:04:15 2009
@@ -35,6 +35,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import org.apache.olio.webapp.cache.CacheFactory;
 
 /**
  * Handles action for the event - update of comments and ratings.
@@ -69,17 +70,17 @@
         if (path.equals("/detail")) {
             SocialEvent se = mf.getSocialEvent(eid);
             if (se == null)
-               throw new RuntimeException("Could not find event. eventID = " + eid);
-            
+                throw new RuntimeException("Could not find event. eventID = " + eid);
+
             request.setAttribute("socialEvent", se);
             boolean attending = false;
-            Person user=SecurityHandler.getInstance().getLoggedInPerson(request);
-            
-            if (user != null)
+            Person user = SecurityHandler.getInstance().getLoggedInPerson(request);
+
+            if (user != null) 
                 attending = se.isAttending(user);
-            
+
             request.setAttribute("isAttending", attending);
-            
+
             // If the user is looged in get the comment if there is any
             if (user != null) {
                 CommentsRating cr = mf.getCommentRating(user, se);
@@ -91,15 +92,15 @@
         }
         if (path.equals("/delete"))
             return deleteEvent(eid, request, response);
-        
+
         Person person=SecurityHandler.getInstance().getLoggedInPerson(request);
         String comments = request.getParameter("comments");
-        
+
         SocialEvent event = mf.updateSocialEventComment(person, eid, comments, 0);
-        
+            
         return "/site.jsp?page=event.jsp&socialEventID=" + eventID;
-    }
-    
+        }
+
     private String deleteEvent (int eid, HttpServletRequest request, HttpServletResponse response) throws IOException {
         ModelFacade mf= (ModelFacade) context.getAttribute(MF_KEY);
         mf.deleteEvent(eid);
@@ -108,7 +109,7 @@
         response.sendRedirect(request.getContextPath() + "/event/list");
         return null;
     }
-    
+
     private String addEvent (HttpServletRequest request, HttpServletResponse response) throws IOException {
         String eventID = request.getParameter("socialEventID");
         Person person=SecurityHandler.getInstance().getLoggedInPerson(request);
@@ -206,56 +207,84 @@
         if (cache != null) {
             String cacheKey = WebappUtil.getCacheKey("/event/list", queryMap);
             if (cacheKey != null) {
-                if (cache.isLocal()) {
-                    Object cobj = null;
-                    CachedList cl = (CachedList) cache.get(cacheKey);
-                    if (cl == null) {
-                        cl = new CachedList(cacheKey);
-                        cache.put(cacheKey, cl, WebappUtil.getCacheTimeToLiveInSecs());
-                    }
-                    cobj = cl.get(index);
-                    if (cobj== null) {
-                        // Fill the cache
-                        List<SocialEvent> list = mf.getSocialEvents(queryMap);
-                        int numPages = 1;
-                        if (list != null) {
-                            Object o = queryMap.get("listSize");
-                            if (o != null) {
-                                Long l = (Long) o;
-                                numPages = WebappUtil.getNumPages(l);
-                            }
-                        }
-                            
-                        request.setAttribute("itemList", list);
-                        request.setAttribute("numPages", numPages);
-                        cobj = WebappUtil.acquirePageContent("/eventList.jsp", request, response);
-                        cl.put(index, cobj);
-                        //System.out.println ("Put content in cache - key = " + cacheKey +
-                          //      " index = " + index);
-                    }
-                    else {
-                        //System.out.println ("Got content from cache - key = " + cacheKey +
-                          //      " index = " + index);
+
+                Object cobj = null;
+
+                CachedList cl = (CachedList)cache.get(cacheKey);
+
+                if (cl == null) {
+                    // nothing in cache
+                    cl = new CachedList(cacheKey);
+
+                    // get a new cacheable page/partial
+                    cobj = createCachePageObject(queryMap, response, request, mf);
+                    cl.put(index, cobj); 
+
+
+                    if (cache.needsRefresh(false, cacheKey)) {
+                        cache.put(cacheKey, cl, CacheFactory.getInstance().getCacheExpireInSeconds());
+                        cache.doneRefresh(cacheKey, CacheFactory.getInstance().getCacheLockExpireInSeconds());
                     }
-                    if (cobj != null) {
-                        request.setAttribute("content", cobj);
-                        if (pageType != null && pageType.equalsIgnoreCase("partial")) {
-                            response.getWriter().print((String) cobj);
-                            return null;
-                        }
-                        else {
-                            return "/site.jsp?cachedContent=true";
-                        }
+
+                } else {
+                    // something in the cache
+                    cobj = cl.get(index); // we are using this whatever
+
+                    Object newCobj = createCachePageObject(queryMap, response, request, mf);
+                    cl.put(index, newCobj); // replaces existing value
+                     if (cache.needsRefresh(true, cacheKey)) {
+                        cache.put(cacheKey, cl, CacheFactory.getInstance().getCacheExpireInSeconds());
+                        cache.doneRefresh(cacheKey, CacheFactory.getInstance().getCacheLockExpireInSeconds());
                     }
                 }
-                else {
-                    // TO DO -- Needs different logic for distributed caches since we
-                    // don't intent to cache heirarchical objects in that mode.
+
+                if (cobj != null) {
+                    request.setAttribute("content", cobj);
+
+                    // if it's a partial page then we can just write cobj to the response stream
+                    // But we don't cache partials at the moment
+                    if (pageType != null && pageType.equalsIgnoreCase("partial")) {
+                        response.getWriter().print((String) cobj);
+                        return null;
+                    } else {
+                        // if it's not a partial, we'll redirect and tell it that there's cached content to display
+                        return "/site.jsp?cachedContent=true";
+                    }
                 }
             }
         }
 
-        // This is not cacheable or cache is not enabled.
+        return prepNoCacheRequest(queryMap, response, request, mf);
+
+    }
+
+    private Object createCachePageObject(Map<String, Object> queryMap,
+                                         HttpServletResponse response,
+                                         HttpServletRequest request,
+                                         ModelFacade mf) throws java.io.IOException,
+                                                                javax.servlet.ServletException {
+
+        // Fill the cache
+        List<SocialEvent> list = mf.getSocialEvents(queryMap);
+        int numPages = 1;
+        if (list != null) {
+            Object o = queryMap.get("listSize");
+            if (o != null) {
+                Long l = (Long) o;
+                numPages = WebappUtil.getNumPages(l);
+            }
+        }
+
+        request.setAttribute("itemList", list);
+        request.setAttribute("numPages", numPages);
+
+        return WebappUtil.acquirePageContent("/eventList.jsp", request, response);
+    }
+
+    private String prepNoCacheRequest(Map<String, Object> queryMap, HttpServletResponse response, HttpServletRequest request, ModelFacade mf) {
+
+        String pageType = request.getParameter("displayType");
+        int index = WebappUtil.getIntProperty(request.getParameter("index"));
         List<SocialEvent> list = mf.getSocialEvents(queryMap);
 
         int numPages = 1;
@@ -305,19 +334,20 @@
         return "/site.jsp?page=eventList.jsp&index="+index;
     }
 
-    static class CachedList {
+    static class CachedList implements java.io.Serializable {
+
         public String cacheKey;
         public HashMap<Integer, Object> valueMap;
-        
-        public CachedList (String key) {
+
+        public CachedList(String key) {
             this.cacheKey = key;
             valueMap = new HashMap<Integer, Object>();
         }
-        
+
         public void put(int index, Object value) {
             valueMap.put(index, value);
         }
-        
+
         public Object get(int index) {
             return valueMap.get(index);
         }

Modified: incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/model/ModelFacade.java
URL: http://svn.apache.org/viewvc/incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/model/ModelFacade.java?rev=820272&r1=820271&r2=820272&view=diff
==============================================================================
--- incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/model/ModelFacade.java (original)
+++ incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/model/ModelFacade.java Wed Sep 30 14:04:15 2009
@@ -78,10 +78,7 @@
     /** Creates a new instance of ModelFacade */
     public ModelFacade() {
         calendar = GregorianCalendar.getInstance();
-        // Default the jMaki usage to true
-        ServiceLocator sloc = ServiceLocator.getInstance();
-        jmakiUsage = Boolean.parseBoolean(sloc.getString("webapp.jmakiUsage", "true"));
-        useCache = Boolean.parseBoolean(sloc.getString("useLocalCache", "true"));
+
         /*
         try {
             FileSystem fs = ServiceLocator.getInstance().getFileSystem();  
@@ -107,6 +104,10 @@
         context = sce.getServletContext();
         getContext().setAttribute(WebConstants.MF_KEY, this);
         WebappUtil.setContext(getContext().getContextPath());
+
+        ServiceLocator sloc = ServiceLocator.getInstance();
+        jmakiUsage = Boolean.parseBoolean(sloc.getString("webapp.jmakiUsage", "false"));
+        useCache = Boolean.parseBoolean(sloc.getString("useLocalCache", "true"));
     }
 
     //public String addPerson(Person person, UserSignOn userSignOn){

Modified: incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/ContentCachingFilter.java
URL: http://svn.apache.org/viewvc/incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/ContentCachingFilter.java?rev=820272&r1=820271&r2=820272&view=diff
==============================================================================
--- incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/ContentCachingFilter.java (original)
+++ incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/ContentCachingFilter.java Wed Sep 30 14:04:15 2009
@@ -157,7 +157,7 @@
         
         if (obj != null) {
             // The page is cached. But does it need a refresh?
-            if (cache.needsRefresh(key)) {
+            if (cache.needsRefresh(true, key)) {
                 // We own the lock, so we need to refresh it
                 String str = acquirePageContent (path, request, response, chain);
                 if (str != null) {
@@ -189,7 +189,7 @@
             int attemptCount = 1;
             while (true) {
                 System.out.println ("needsRefreshAttempt = " + attemptCount++);
-                if (cache.needsRefresh(key)) {
+                if (cache.needsRefresh(false, key)) {
                     // We have the lock, refresh the content
                     String str = acquirePageContent (path, request, response, chain);
                     if (str != null) {

Modified: incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/WebappUtil.java
URL: http://svn.apache.org/viewvc/incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/WebappUtil.java?rev=820272&r1=820271&r2=820272&view=diff
==============================================================================
--- incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/WebappUtil.java (original)
+++ incubator/olio/webapp/java/trunk/ws/apps/webapp/src/java/org/apache/olio/webapp/util/WebappUtil.java Wed Sep 30 14:04:15 2009
@@ -86,9 +86,7 @@
          monthMap.put("nov", 11);
          monthMap.put("dec", 12);
          
-         String useCache = ServiceLocator.getInstance().getString("useLocalCache", "true");
-         if (Boolean.parseBoolean(useCache))
-             cache = CacheFactory.getCache("Olio");
+         cache = CacheFactory.getCache("Olio");
     }
 
     /** Creates a new instance of WebappUtil */
@@ -539,7 +537,8 @@
             return;
         String key = getCacheKey(path, map);
         if (key != null) {
-            cache.put(key, null);
+            System.out.println("WebappUtil.clearCache(): " + key);
+            cache.invalidate(key);
         }
     }