Author: julien_viet
Date: 2009-11-13 08:35:01 -0500 (Fri, 13 Nov 2009)
New Revision: 593
Added:
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestCache.java
Modified:
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/config/DataStorageImpl.java
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/config/NewPortalConfigListener.java
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMDataStorage.java
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSession.java
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSessionManager.java
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/cache/DataCache.java
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/tasks/PortalConfigTask.java
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestDataStorage.java
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestUserPortalConfigService.java
Log:
better cache eviction based on mop session life cycle
Modified:
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/config/DataStorageImpl.java
===================================================================
---
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/config/DataStorageImpl.java 2009-11-13
10:49:53 UTC (rev 592)
+++
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/config/DataStorageImpl.java 2009-11-13
13:35:01 UTC (rev 593)
@@ -148,7 +148,7 @@
public void create(PageNavigation navigation) throws Exception
{
- delegate.save(navigation.build());
+ delegate.create(navigation.build());
}
private abstract class Bilto<O extends ModelObject, D extends ModelData>
Modified:
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/config/NewPortalConfigListener.java
===================================================================
---
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/config/NewPortalConfigListener.java 2009-11-13
10:49:53 UTC (rev 592)
+++
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/config/NewPortalConfigListener.java 2009-11-13
13:35:01 UTC (rev 593)
@@ -320,6 +320,11 @@
}
PortalConfig pconfig = fromXML(config.getOwnerType(), owner, xml,
PortalConfig.class);
+
+ // We use that owner value because it may have been fixed for group names
+ owner = pconfig.getName();
+
+ //
PortalConfig currentPortalConfig = pdcService_.getPortalConfig(type, owner);
if (currentPortalConfig == null)
{
Modified:
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMDataStorage.java
===================================================================
---
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMDataStorage.java 2009-11-13
10:49:53 UTC (rev 592)
+++
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMDataStorage.java 2009-11-13
13:35:01 UTC (rev 593)
@@ -48,7 +48,6 @@
import org.exoplatform.portal.pom.data.PageKey;
import org.exoplatform.portal.pom.data.PortalData;
import org.exoplatform.portal.pom.data.PortalKey;
-import org.exoplatform.services.cache.CacheService;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.jibx.runtime.BindingDirectory;
@@ -79,11 +78,11 @@
/** . */
private final TaskExecutionDecorator executor;
- public POMDataStorage(CacheService cacheService, POMSessionManager pomMgr,
ConfigurationManager confManager)
+ public POMDataStorage(POMSessionManager pomMgr, ConfigurationManager confManager)
{
this.pomMgr = pomMgr;
this.confManager_ = confManager;
- this.executor = new DataCache(cacheService, new ExecutorDispatcher());
+ this.executor = new DataCache(new ExecutorDispatcher());
}
public POMSessionManager getPOMSessionManager()
@@ -134,7 +133,7 @@
public void create(PortalData config) throws Exception
{
- execute(new PortalConfigTask.Save(config, true));
+ execute(new PortalConfigTask.Save(config, false));
}
public void save(PortalData config) throws Exception
Modified:
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSession.java
===================================================================
---
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSession.java 2009-11-13
10:49:53 UTC (rev 592)
+++
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSession.java 2009-11-13
13:35:01 UTC (rev 593)
@@ -36,10 +36,13 @@
import org.gatein.mop.core.api.workspace.PageImpl;
import javax.jcr.RepositoryException;
+import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -65,13 +68,51 @@
/** . */
private boolean markedForRollback;
+ /** . */
+ private List<Serializable> staleKeys;
+
+ /** . */
+ private boolean modified;
+
public POMSession(POMSessionManager mgr)
{
this.mgr = mgr;
this.isInTask = false;
this.markedForRollback = false;
+ this.staleKeys = null;
}
+ public Object getFromCache(Serializable key)
+ {
+ if (isModified())
+ {
+ throw new IllegalStateException("Cannot read object in shared cache from a
modified session");
+ }
+ return mgr.cache.get(key);
+ }
+
+ public void putInCache(Serializable key, Object value)
+ {
+ if (isModified())
+ {
+ throw new IllegalStateException("Cannot put object in shared cache from a
modified session");
+ }
+ mgr.cache.put(key, value);
+ }
+
+ public void scheduleForEviction(Serializable key)
+ {
+ if (key == null)
+ {
+ throw new NullPointerException();
+ }
+ if (staleKeys == null)
+ {
+ staleKeys = new LinkedList<Serializable>();
+ }
+ staleKeys.add(key);
+ }
+
private Model getModel()
{
if (model == null)
@@ -81,17 +122,21 @@
return model;
}
- // julien todo : investigate how expensive is the call to hasPendingChanges method
public boolean isModified()
{
+ if (modified)
+ {
+ return true;
+ }
try
{
- return getSession().getJCRSession().hasPendingChanges();
+ modified = getSession().getJCRSession().hasPendingChanges();
}
catch (RepositoryException e)
{
throw new UndeclaredRepositoryException(e);
}
+ return modified;
}
protected ChromatticSession getSession()
@@ -356,5 +401,14 @@
{
model.close();
}
+
+ //
+ if (staleKeys != null)
+ {
+ for (Serializable key : staleKeys)
+ {
+ mgr.cache.remove(key);
+ }
+ }
}
}
Modified:
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSessionManager.java
===================================================================
---
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSessionManager.java 2009-11-13
10:49:53 UTC (rev 592)
+++
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSessionManager.java 2009-11-13
13:35:01 UTC (rev 593)
@@ -35,6 +35,8 @@
import org.exoplatform.portal.pom.spi.wsrp.WSRP;
import org.exoplatform.portal.pom.spi.wsrp.WSRPContentProvider;
import org.exoplatform.portal.pom.spi.wsrp.WSRPState;
+import org.exoplatform.services.cache.CacheService;
+import org.exoplatform.services.cache.ExoCache;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.ext.registry.RegistryService;
@@ -68,6 +70,7 @@
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Set;
@@ -94,14 +97,26 @@
/** . */
final String workspaceName = "portal-system";
- public POMSessionManager(RegistryService service) throws Exception
+ /** . */
+ final ExoCache<Serializable, Object> cache;
+
+ public POMSessionManager(CacheService cacheService, RegistryService service) throws
Exception
{
RepositoryService repositoryService = service.getRepositoryService();
//
+ this.cache =
cacheService.getCacheInstance(POMSessionManager.class.getSimpleName());
this.repositoryService = repositoryService;
this.pomService = null;
+
+ //
+ this.cache.setLiveTime(100000000);
}
+
+ public void clearCache()
+ {
+ cache.clearCache();
+ }
public Session login() throws RepositoryException
{
Modified:
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/cache/DataCache.java
===================================================================
---
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/cache/DataCache.java 2009-11-13
10:49:53 UTC (rev 592)
+++
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/cache/DataCache.java 2009-11-13
13:35:01 UTC (rev 593)
@@ -22,8 +22,6 @@
import org.exoplatform.portal.pom.config.POMTask;
import org.exoplatform.portal.pom.config.TaskExecutor;
import org.exoplatform.portal.pom.config.TaskExecutionDecorator;
-import org.exoplatform.services.cache.CacheService;
-import org.exoplatform.services.cache.ExoCache;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicLong;
@@ -36,48 +34,35 @@
{
/** . */
- private final ExoCache<Serializable, Object> cache;
-
- /** . */
private final AtomicLong readCount = new AtomicLong();
- public DataCache(CacheService cacheService, TaskExecutor next)
+ public DataCache(TaskExecutor next)
{
super(next);
-
- //
- this.cache = cacheService.getCacheInstance(DataCache.class.getSimpleName());
}
public void execute(POMSession session, POMTask task) throws Exception
{
if (task instanceof CacheableDataTask)
{
- if (!session.isModified())
+ CacheableDataTask<?, ?> loadTask = (CacheableDataTask<?,?>)task;
+ switch (loadTask.getAccessMode())
{
- CacheableDataTask<?, ?> loadTask = (CacheableDataTask<?,?>)task;
- switch (loadTask.getAccessMode())
- {
- case READ:
- read(session, loadTask);
- break;
- case CREATE:
- create(session, loadTask);
- break;
- case WRITE:
- write(session, loadTask);
- break;
- case DESTROY:
- remove(session, loadTask);
- break;
- default:
- throw new UnsupportedOperationException();
- }
+ case READ:
+ read(session, loadTask);
+ break;
+ case CREATE:
+ create(session, loadTask);
+ break;
+ case WRITE:
+ write(session, loadTask);
+ break;
+ case DESTROY:
+ remove(session, loadTask);
+ break;
+ default:
+ throw new UnsupportedOperationException();
}
- else
- {
- super.execute(session, task);
- }
}
else
{
@@ -85,22 +70,17 @@
}
}
- public void clear()
- {
- cache.clearCache();
- }
-
private <K extends Serializable, V> void remove(POMSession session,
CacheableDataTask<K, V> task) throws Exception
{
K key = task.getKey();
- cache.remove(key);
+ session.scheduleForEviction(key);
super.execute(session, task);
}
private <K extends Serializable, V> void write(POMSession session,
CacheableDataTask<K, V> task) throws Exception
{
K key = task.getKey();
- cache.remove(key);
+ session.scheduleForEviction(key);
super.execute(session, task);
}
@@ -112,37 +92,44 @@
private <K extends Serializable, V> void read(POMSession session,
CacheableDataTask<K, V> task) throws Exception
{
- K key = task.getKey();
- Object o = cache.get(key);
- V v = null;
- if (o != null)
+ if (!session.isModified())
{
- Class<V> type = task.getValueType();
- if (type.isInstance(o))
+ K key = task.getKey();
+ Object o = session.getFromCache(key);
+ V v = null;
+ if (o != null)
{
- v = type.cast(o);
+ Class<V> type = task.getValueType();
+ if (type.isInstance(o))
+ {
+ v = type.cast(o);
+ }
}
- }
- //
- if (v != null)
- {
- task.setValue(v);
- }
- else
- {
- readCount.incrementAndGet();
-
//
- super.execute(session, task);
-
- //
- v = task.getValue();
if (v != null)
{
- cache.put(key, v);
+ task.setValue(v);
}
+ else
+ {
+ readCount.incrementAndGet();
+
+ //
+ super.execute(session, task);
+
+ //
+ v = task.getValue();
+ if (v != null)
+ {
+ session.putInCache(key, v);
+ }
+ }
}
+ else
+ {
+ super.execute(session, task);
+ }
}
public long getReadCount()
Modified:
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/tasks/PortalConfigTask.java
===================================================================
---
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/tasks/PortalConfigTask.java 2009-11-13
10:49:53 UTC (rev 592)
+++
portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/tasks/PortalConfigTask.java 2009-11-13
13:35:01 UTC (rev 593)
@@ -125,7 +125,7 @@
public DataAccessMode getAccessMode()
{
- return config.getStorageId() != null ? DataAccessMode.WRITE :
DataAccessMode.CREATE;
+ return overwrite ? DataAccessMode.WRITE : DataAccessMode.CREATE;
}
public void setValue(PortalData value)
@@ -161,6 +161,12 @@
}
else
{
+ if (overwrite)
+ {
+ throw new IllegalArgumentException("Cannot update portal " +
config.getName() + " that does not exist");
+ }
+
+ //
site = workspace.addSite(type, config.getName());
Page root = site.getRootPage();
root.addChild("pages");
Added:
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestCache.java
===================================================================
---
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestCache.java
(rev 0)
+++
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestCache.java 2009-11-13
13:35:01 UTC (rev 593)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2003-2007 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.portal.config;
+
+import org.exoplatform.container.PortalContainer;
+import org.exoplatform.portal.config.model.Page;
+import org.exoplatform.portal.pom.config.POMSessionManager;
+import org.exoplatform.test.BasicTestCase;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien
Viet</a>
+ * @version $Revision$
+ */
+public class TestCache extends BasicTestCase
+{
+
+ /** . */
+ DataStorage storage_;
+
+ /** . */
+ private POMSessionManager mgr;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ if (storage_ != null)
+ return;
+ PortalContainer container = PortalContainer.getInstance();
+ storage_ = (DataStorage)container.getComponentInstanceOfType(DataStorage.class);
+ mgr =
(POMSessionManager)container.getComponentInstanceOfType(POMSessionManager.class);
+ mgr.openSession();
+ }
+
+ protected void tearDown() throws Exception
+ {
+ mgr.closeSession(false);
+ }
+
+ public void testDirtyWrite() throws Exception
+ {
+ // Read
+ Page page = storage_.getPage("portal::test::test4");
+ assertEquals(null, page.getTitle());
+
+ // Update
+ page.setTitle("foo");
+ storage_.save(page);
+
+ //
+ final AtomicBoolean go = new AtomicBoolean(false);
+
+ // Force a cache update
+ new Thread()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ mgr.openSession();
+ storage_.getPage("portal::test::test4");
+ mgr.closeSession(false);
+ }
+ catch (Exception e)
+ {
+ throw new Error(e);
+ }
+ finally
+ {
+ go.set(true);
+ }
+ }
+ }.start();
+
+ //
+ while (!go.get())
+ {
+ Thread.sleep(1);
+ }
+
+ // Reopen session with no modifications that use the cache
+ mgr.closeSession(true);
+ mgr.openSession();
+
+ //
+ page = storage_.getPage("portal::test::test4");
+ assertEquals("foo", page.getTitle());
+ }
+}
Modified:
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestDataStorage.java
===================================================================
---
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestDataStorage.java 2009-11-13
10:49:53 UTC (rev 592)
+++
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestDataStorage.java 2009-11-13
13:35:01 UTC (rev 593)
@@ -236,7 +236,7 @@
portal.setName("foo");
portal.setLocale("en");
portal.setAccessPermissions(new String[]{UserACL.EVERYONE});
- storage_.save(portal);
+ storage_.create(portal);
//
PageNavigation navigation = new PageNavigation();
Modified:
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestUserPortalConfigService.java
===================================================================
---
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestUserPortalConfigService.java 2009-11-13
10:49:53 UTC (rev 592)
+++
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestUserPortalConfigService.java 2009-11-13
13:35:01 UTC (rev 593)
@@ -722,16 +722,22 @@
{
public void execute() throws Exception
{
+// mgr.clearCache();
+
PortalConfig cfg = storage_.getPortalConfig(PortalConfig.USER_TYPE,
"overwritelayout");
assertNotNull(cfg);
+
+
Container container = cfg.getPortalLayout();
assertNotNull(container);
assertEquals(2, container.getChildren().size());
assertTrue(container.getChildren().get(0) instanceof PageBody);
assertTrue(((Application)container.getChildren().get(1)).getType() ==
ApplicationType.PORTLET);
Application<Portlet> pa =
(Application<Portlet>)container.getChildren().get(1);
- ApplicationState state = pa.getState();
- assertEquals("overwrite_application_ref/overwrite_portlet_ref",
storage_.getId(pa.getState()));
+ ApplicationState<Portlet> state = pa.getState();
+
+
+ assertEquals("overwrite_application_ref/overwrite_portlet_ref",
storage_.getId(state));
}
}.execute(null);
}
@@ -775,6 +781,7 @@
{
public void execute() throws Exception
{
+ mgr.clearCache();
DataCache cache = mopStorage.getDecorator(DataCache.class);
long readCount0 = cache.getReadCount();
userPortalConfigSer_.getUserPortalConfig("classic", null);
@@ -793,6 +800,7 @@
{
public void execute() throws Exception
{
+ mgr.clearCache();
DataCache cache = mopStorage.getDecorator(DataCache.class);
long readCount0 = cache.getReadCount();
userPortalConfigSer_.getPage("portal::test::test1");
@@ -811,6 +819,7 @@
{
public void execute() throws Exception
{
+ mgr.clearCache();
DataCache cache = mopStorage.getDecorator(DataCache.class);
long readCount0 = cache.getReadCount();
userPortalConfigSer_.getPageNavigation("portal",
"test");
@@ -862,8 +871,7 @@
}
// Clear cache
- DataCache cache = mopStorage.getDecorator(DataCache.class);
- cache.clear();
+// mgr.clearCache();
//
mopSession = mgr.openSession();