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-devIndex:
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>