I've created a JIRA: 
http://www.ja-sig.org/issues/secure/ManageAttachments.jspa?id=16023

And I've attached an updated patch.

Eric Dalquist wrote:
> 
> I think a user can actually have multiple layouts loaded. In the 
> database I believe layouts are keyed via userId (numeric) and profileId 
> (numeric). You might want to look at using a composite of those two 
> values for the cache key to ensure we don't add unneeded restriction to 
> the object model.

You're right about the database, but I don't think that's supported in 
the code...  at least I think a user would need two concurrent sessions, 
as well as two profiles each having a different layout.

But I've made the adjustment:  the layoutCache key is now 
{username}-{layoutId}.

> The changing when logged in issue is ok I think, we'll just ship with a 
> default idle expire time of 30 minutes which would match session 
> timeouts. 

Default changed to timeToIdleSeconds="1800" (30 min).

> This all sounds good. Lets take another look at the cache key and then 
> get this in for 3.1

Not 3.0.2?

I'm ok either way on this point.

drew wills


-- 
You are currently subscribed to [email protected] as: [EMAIL 
PROTECTED]
To unsubscribe, change settings or access archives, see 
http://www.ja-sig.org/wiki/display/JSG/uportal-dev
Index: 
uportal-impl/src/main/java/org/jasig/portal/layout/dlm/DistributedLayoutManager.java
===================================================================
--- 
uportal-impl/src/main/java/org/jasig/portal/layout/dlm/DistributedLayoutManager.java
        (revision 43854)
+++ 
uportal-impl/src/main/java/org/jasig/portal/layout/dlm/DistributedLayoutManager.java
        (working copy)
@@ -90,7 +90,7 @@
      */
     static final String FOLDER_LABEL_POLICY = "FolderLabelPolicy";
     
-    protected Document userLayoutDocument=null;
+    private final Map<String,Document> layoutCache = 
LayoutCachingService.getInstance().getLayoutCache();
     
     protected static Random rnd=new Random();
     protected String cacheKey="initialKey";
@@ -226,7 +226,8 @@
     }
 
     private void setUserLayoutDOM(Document doc) {
-        this.userLayoutDocument = doc;
+
+       layoutCache.put(getLayoutCacheKey(), doc);
         this.updateCacheKey();
 
         // determine if this is a layout fragment by looking at the root node
@@ -243,6 +244,7 @@
         if (labelPolicy != null) {
             labelPolicy.coordinateFolderLabels(owner.getID(), isFragmentOwner, 
doc);
         }
+        
     }
     private int domRequests = 0;
 
@@ -261,7 +263,7 @@
             {
                 LOG.debug("domRequest: " + (domRequests++));
             }
-            Document userLayoutDocument = this.userLayoutDocument;
+            Document userLayoutDocument = layoutCache.get(getLayoutCacheKey());
             if ( null == userLayoutDocument )
             {
                 IUserLayoutStore layoutStore = getLayoutStore();
@@ -407,7 +409,7 @@
         try {
             //Clear the loaded document first if this is a forced reload
             if (reload) {
-                this.userLayoutDocument = null;
+               layoutCache.remove(getLayoutCacheKey());
             }
             
             uli=getUserLayoutDOM();
@@ -1507,7 +1509,7 @@
         }
         //this.markedUserLayout=null;
         this.updateCacheKey();
-        this.userLayoutDocument=doc;
+        layoutCache.put(getLayoutCacheKey(), doc);
     }
 
     /* Returns the ID attribute of the root folder of the layout. This folder 
@@ -1689,7 +1691,7 @@
             // so we need to refresh our local copy of their layout
             if (person == owner)
             {
-                this.userLayoutDocument = null;
+               layoutCache.remove(getLayoutCacheKey());
                 updateCacheKey();
                 getUserLayoutDOM();
             }
@@ -1820,4 +1822,8 @@
         }
         return label;
     }
+    
+    private String getLayoutCacheKey() {
+       return owner.getUserName() + "-" + profile.getLayoutId();
+    }
 }
Index: 
uportal-impl/src/main/java/org/jasig/portal/layout/dlm/LayoutCachingService.java
===================================================================
--- 
uportal-impl/src/main/java/org/jasig/portal/layout/dlm/LayoutCachingService.java
    (revision 0)
+++ 
uportal-impl/src/main/java/org/jasig/portal/layout/dlm/LayoutCachingService.java
    (revision 0)
@@ -0,0 +1,120 @@
+/**
+ * Copyright 2008 The JA-SIG Collaborative.  All rights reserved.
+ * See license distributed with this file and
+ * available online at http://www.uportal.org/license.html
+ */
+
+package org.jasig.portal.layout.dlm;
+
+import java.util.Map;
+import org.w3c.dom.Document;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jasig.portal.utils.cache.CacheFactory;
+
+/**
+ * Provides caching services for layouts contained in 
+ * <code>DistributedLayoutManager</code> instances.  This class is an 
old-school 
+ * singleton whose backing-map is "injected" by a spring context at startup. 
+ */
+public final class LayoutCachingService {
+
+       /**
+        * The name of the cache used by <code>LayoutCachingService</code>.  A 
cache 
+        * of this name must be defined within uPortal's 
<code>'cacheFactory'</code> 
+        * bean.
+        */
+       private static final String CACHE_NAME = 
"org.jasig.portal.layout.dlm.LAYOUT_CACHE";
+       
+       /**
+        * Single(ton) instance of this class.
+        */
+       private static LayoutCachingService instance = null;
+       
+       /**
+        * "Injected" at startup by the bean container.  This object is 
typically 
+        * defined as the bean with id='cacheFactory' in cacheContext.xml.
+        */
+       private CacheFactory cacheFactory = null;
+       
+    private final Log log = LogFactory.getLog(LayoutCachingService.class);
+       
+       /*
+        * Public API.
+        */
+           
+    /**
+     * Accessor method or the single(ton) instance of this class.
+     */
+    public static LayoutCachingService getInstance() {
+               
+               if (instance == null) {
+                       init();
+               }
+
+               return instance;
+               
+       }
+       
+    /**
+     * Called by the spring IoC container at startup.
+     * 
+     * @param cf Ordinarily 'cacheFactory' bean defined in cacheContext.xml 
+     */
+       @Required
+       public void setCacheFactory(CacheFactory cf) {
+               
+               // Assertions.
+               if (cf == null) {
+                       String msg = "Argument 'cpf [CacheFactory]' cannot be 
null.";
+                       throw new IllegalArgumentException(msg);
+               }
+               
+               log.debug("INITIALIZING:  Setting cacheFactory.");
+
+               this.cacheFactory = cf;
+               
+       }
+       
+       /**
+        * Provides clients of <code>LayoutCachingService</code> with access to 
the 
+        * layout cache.
+        * 
+        * @return A <code>Map</code> of cached layouts.
+        */
+       public Map<String,Document> getLayoutCache() {
+               return cacheFactory.getCache(CACHE_NAME);
+       }
+       
+       /*
+        * Implementation.
+        */
+
+       /**
+        * Private as per classic Singleton pattern. 
+        */
+       private LayoutCachingService() {
+               log.debug("INITIALIZING:  Constructing.");
+       }
+       
+       /**
+        * Method that creates the single(ton) instance of 
+        * <code>LayoutCachingService</code>, synchronized to be sure it only 
+        * happens once.
+        */
+       private static synchronized void init() {
+
+               // Make sure we only create one instance...
+               if (instance != null) {
+                       // Must have invoked getInstance() w/ 2 threads.
+                       return;
+               }
+
+               instance = new LayoutCachingService();
+               
+       }
+       
+}
Index: uportal-impl/src/main/resources/properties/ehcache.xml
===================================================================
--- uportal-impl/src/main/resources/properties/ehcache.xml      (revision 43854)
+++ uportal-impl/src/main/resources/properties/ehcache.xml      (working copy)
@@ -32,6 +32,9 @@
         eternal="false" maxElementsInMemory="250" overflowToDisk="false" 
diskPersistent="false" 
         timeToIdleSeconds="0" timeToLiveSeconds="900" 
memoryStoreEvictionPolicy="LRU" />
         
+    <cache name="org.jasig.portal.layout.dlm.LAYOUT_CACHE"
+        eternal="false" maxElementsInMemory="250" overflowToDisk="false" 
diskPersistent="false" 
+        timeToIdleSeconds="0" timeToLiveSeconds="0" 
memoryStoreEvictionPolicy="LRU" />
         
     <!-- uPortal IBasicEntity Caches -->
 
Index: uportal-impl/src/main/resources/properties/contexts/cacheContext.xml
===================================================================
--- uportal-impl/src/main/resources/properties/contexts/cacheContext.xml        
(revision 43854)
+++ uportal-impl/src/main/resources/properties/contexts/cacheContext.xml        
(working copy)
@@ -43,4 +43,22 @@
         <property name="cacheManagerName" value="uPortal.cacheManager" />
         <property name="configLocation" 
value="classpath:/properties/ehcache.xml" />
     </bean>
-</beans>
\ No newline at end of file
+
+    <!--
+     | Service used by DLM to cache Layouts.
+     +-->
+    <bean id="layoutCachingService" 
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
+        <property name="targetClass" 
value="org.jasig.portal.layout.dlm.LayoutCachingService" />
+        <property name="targetMethod" value="getInstance" />
+    </bean>
+    <bean 
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
+        <property name="targetObject" ref="layoutCachingService" />
+        <property name="targetMethod" value="setCacheFactory" />
+        <property name="arguments">
+            <list>
+                <ref bean="cacheFactory"/>
+            </list>
+        </property>
+    </bean>
+
+</beans>

Reply via email to