This sounds really useful. Definitely a +1
On Tue, Jul 8, 2008 at 11:32 AM, Drew Wills <[EMAIL PROTECTED]> wrote: > Hey folks, > > I'm working at JHU, and we've put together an enhancement to DLM: the > ability to store users' layouts in a standard, portal managed cache. > Currently users' layouts are stored (at least in DLM) as a member > variable on each user's LayoutManager instance. > > This situation means that: > - User layouts never change until (1) the user makes a manual change, > or (2) the user logs in again > - There's no way to manage in-memory layout data administratively > > With this enhancement, you'd be able to: > - specify that user layouts should expire and be rebuilt, say, 15 min > after creation or after 10 min of "idle" time (i.e. not used for 10 min) > - specify that no more than, say, 500 layouts should be held in > memory at one time > - use JMX to "clear" (drop) all the layouts in a running instance of > uPortal > - write Java tools that intelligently invalidate individual layouts > (or all layouts) when certain portal events happen > > The changes are relatively small & encapsulated, so they're unlikely to > "break" existing features or even custom Java tech that integrates with > DLM. > > I'm attaching a .patch that shows the delta. > > Please share thoughts on whether this enhancement is desirable or even > acceptable. If there's interest, I'll create the JIRA etc. > > 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 6156) > +++ > 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(owner.getUserName(), 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(owner.getUserName()); > 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(owner.getUserName()); > } > > uli=getUserLayoutDOM(); > @@ -1507,7 +1509,7 @@ > } > //this.markedUserLayout=null; > this.updateCacheKey(); > - this.userLayoutDocument=doc; > + layoutCache.put(owner.getUserName(), 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(owner.getUserName()); > updateCacheKey(); > getUserLayoutDOM(); > } > 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/contexts/cacheContext.xml > =================================================================== > --- uportal-impl/src/main/resources/properties/contexts/cacheContext.xml > (revision 6156) > +++ 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> > Index: uportal-impl/src/main/resources/properties/ehcache.xml > =================================================================== > --- uportal-impl/src/main/resources/properties/ehcache.xml (revision > 6156) > +++ uportal-impl/src/main/resources/properties/ehcache.xml (working > copy) > @@ -81,6 +81,10 @@ > replicateRemovals=true "/> > </cache> > > + <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 --> > > <cache name="org.jasig.portal.ChannelDefinition" > > -- 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
