Return-Path: Delivered-To: apmail-geronimo-dev-archive@www.apache.org Received: (qmail 43316 invoked from network); 27 Aug 2008 20:28:21 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 27 Aug 2008 20:28:21 -0000 Received: (qmail 96766 invoked by uid 500); 27 Aug 2008 20:28:17 -0000 Delivered-To: apmail-geronimo-dev-archive@geronimo.apache.org Received: (qmail 96716 invoked by uid 500); 27 Aug 2008 20:28:17 -0000 Mailing-List: contact dev-help@geronimo.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: dev@geronimo.apache.org List-Id: Delivered-To: mailing list dev@geronimo.apache.org Received: (qmail 96705 invoked by uid 99); 27 Aug 2008 20:28:17 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 27 Aug 2008 13:28:17 -0700 X-ASF-Spam-Status: No, hits=1.2 required=10.0 tests=SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (athena.apache.org: local policy) Received: from [76.13.13.42] (HELO smtp103.prem.mail.ac4.yahoo.com) (76.13.13.42) by apache.org (qpsmtpd/0.29) with SMTP; Wed, 27 Aug 2008 20:27:18 +0000 Received: (qmail 13320 invoked from network); 27 Aug 2008 20:26:47 -0000 Received: from unknown (HELO drwoods.rtp.raleigh.ibm.com) (drw_web@129.33.49.251 with plain) by smtp103.prem.mail.ac4.yahoo.com with SMTP; 27 Aug 2008 20:26:46 -0000 X-Yahoo-Newman-Property: ymail-3 Message-ID: <48B5B885.5090000@apache.org> Date: Wed, 27 Aug 2008 16:26:45 -0400 From: Donald Woods User-Agent: Thunderbird 2.0.0.16 (Macintosh/20080707) MIME-Version: 1.0 To: dev@geronimo.apache.org Subject: Re: svn commit: r689244 - in /geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src: main/java/org/apache/geronimo/openejb/cluster/stateful/container/ test/java/org/apache/geronimo/openejb/cluster/stateful/container/ References: <20080826213712.4298323889E9@eris.apache.org> <48B4B64E.5000101@apache.org> In-Reply-To: Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------ms050504020606000205060908" X-Virus-Checked: Checked by ClamAV on apache.org This is a cryptographically signed message in MIME format. --------------ms050504020606000205060908 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Yep, I went in and modified plugins/pom.xml to not build the openejb modules/plugins for now and got a build to complete.... -Donald Lin Sun wrote: > Me too getting this error. I had to revert this change on my local machine. > > Lin > > On Tue, Aug 26, 2008 at 10:05 PM, Donald Woods wrote: >> Guess we need to build OpenEJB trunk locally until a new SNAPSHOT is >> published? I'm getting build errors on trunk r689302 now even after >> removing openejb from my local repo - >> >> [INFO] Compiling 9 source files to >> /Users/drwoods/geronimo/server-trunk/plugins/openejb/geronimo-openejb-clustering-wadi/target/classes >> [INFO] >> ------------------------------------------------------------------------ >> [ERROR] BUILD FAILURE >> [INFO] >> ------------------------------------------------------------------------ >> [INFO] Compilation failure >> >> /Users/drwoods/geronimo/server-trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulContainer.java:[40,40] >> cannot find symbol >> symbol : class Instance >> location: package org.apache.openejb.core.stateful >> >> >> >> -Donald >> >> >> dain@apache.org wrote: >>> Author: dain >>> Date: Tue Aug 26 14:37:11 2008 >>> New Revision: 689244 >>> >>> URL: http://svn.apache.org/viewvc?rev=689244&view=rev >>> Log: >>> Updated to newest StatefulContainer and Cache APIs >>> >>> Added: >>> >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/WadiCache.java >>> - copied, changed from r688604, >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulInstanceManager.java >>> >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/WadiCacheTest.java >>> - copied, changed from r688604, >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulInstanceManagerTest.java >>> Removed: >>> >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredBeanEntry.java >>> >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulInstanceManager.java >>> >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulInstanceManagerTest.java >>> Modified: >>> >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulContainer.java >>> >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulContainerTest.java >>> >>> Modified: >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulContainer.java >>> URL: >>> http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulContainer.java?rev=689244&r1=689243&r2=689244&view=diff >>> >>> ============================================================================== >>> --- >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulContainer.java >>> (original) >>> +++ >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulContainer.java >>> Tue Aug 26 14:37:11 2008 >>> @@ -37,6 +37,9 @@ >>> import org.apache.openejb.OpenEJBException; >>> import org.apache.openejb.core.CoreDeploymentInfo; >>> import org.apache.openejb.core.stateful.StatefulContainer; >>> +import org.apache.openejb.core.stateful.Instance; >>> +import org.apache.openejb.core.stateful.Cache; >>> +import org.apache.openejb.core.stateful.PassivationStrategy; >>> import org.apache.openejb.spi.SecurityService; >>> import org.codehaus.wadi.core.contextualiser.BasicInvocation; >>> import org.codehaus.wadi.core.contextualiser.InvocationContext; >>> @@ -66,22 +69,15 @@ >>> deploymentIdToNetworkConnectorTracker = new HashMap>> NetworkConnectorTracker>(); >>> } >>> - @Override >>> - protected ClusteredStatefulInstanceManager >>> newStatefulInstanceManager(SecurityService securityService, >>> - Class passivator, >>> - int timeOut, >>> - int poolSize, >>> - int bulkPassivate) throws OpenEJBException { >>> - return new ClusteredStatefulInstanceManager(securityService, >>> - entityManagerRegistry, >>> - passivator, >>> - timeOut, >>> - poolSize, >>> - bulkPassivate); >>> + protected Cache createCache(Class>> PassivationStrategy> passivator, >>> + int timeOut, >>> + int poolSize, >>> + int bulkPassivate) throws OpenEJBException { >>> + return new WadiCache(new StatefulCacheListener()); >>> } >>> public void addSessionManager(Object deploymentId, SessionManager >>> sessionManager) { >>> - ((ClusteredStatefulInstanceManager) >>> instanceManager).addSessionManager(deploymentId, sessionManager); >>> + ((WadiCache) cache).addSessionManager(deploymentId, >>> sessionManager); >>> WADISessionManager wadiSessionManager = >>> (WADISessionManager) sessionManager; >>> @@ -104,7 +100,7 @@ >>> } >>> public void removeSessionManager(Object deploymentId, SessionManager >>> sessionManager) { >>> - ((ClusteredStatefulInstanceManager) >>> instanceManager).removeSessionManager(deploymentId, sessionManager); >>> + ((WadiCache) cache).removeSessionManager(deploymentId, >>> sessionManager); >>> synchronized (deploymentIdToManager) { >>> deploymentIdToManager.remove(deploymentId); >>> @@ -181,8 +177,14 @@ >>> return super.removeEJBObject(deploymentInfo, primKey, >>> callInterface, callMethod, args); >>> } >>> - protected Object invoke(CoreDeploymentInfo deploymentInfo, >>> AbstractEJBInvocation invocation) >>> - throws OpenEJBException { >>> + // >>> + // TODO: THIS WILL NOT WORK >>> + // OpenEJB invocations can not be redirected to another JavaVM. >>> OpenEJB relies on several >>> + // thread local variables to opperate, the most important of which is >>> ThreadContext which >>> + // is used to coordiate transaction boundries. At the very least to >>> redirect calls to a >>> + // remote VM you will need a distributed TransactionManager. >>> + // >>> + protected Object invoke(CoreDeploymentInfo deploymentInfo, >>> AbstractEJBInvocation invocation) throws OpenEJBException { >>> Manager manager; >>> synchronized (deploymentIdToManager) { >>> manager = >>> deploymentIdToManager.get(deploymentInfo.getDeploymentID()); >>> >>> Copied: >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/WadiCache.java >>> (from r688604, >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulInstanceManager.java) >>> URL: >>> http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/WadiCache.java?p2=geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/WadiCache.java&p1=geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulInstanceManager.java&r1=688604&r2=689244&rev=689244&view=diff >>> >>> ============================================================================== >>> --- >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulInstanceManager.java >>> (original) >>> +++ >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/main/java/org/apache/geronimo/openejb/cluster/stateful/container/WadiCache.java >>> Tue Aug 26 14:37:11 2008 >>> @@ -19,200 +19,303 @@ >>> package org.apache.geronimo.openejb.cluster.stateful.container; >>> -import java.lang.reflect.Method; >>> import java.rmi.dgc.VMID; >>> -import java.util.HashMap; >>> -import java.util.Map; >>> +import java.util.Iterator; >>> +import java.util.concurrent.ConcurrentHashMap; >>> +import java.util.concurrent.ConcurrentMap; >>> +import java.util.concurrent.locks.ReentrantLock; >>> -import org.slf4j.Logger; >>> -import org.slf4j.LoggerFactory; >>> import org.apache.geronimo.clustering.Session; >>> import org.apache.geronimo.clustering.SessionAlreadyExistException; >>> import org.apache.geronimo.clustering.SessionListener; >>> import org.apache.geronimo.clustering.SessionManager; >>> import org.apache.geronimo.openejb.cluster.infra.SessionManagerTracker; >>> -import org.apache.openejb.OpenEJBException; >>> -import org.apache.openejb.core.CoreDeploymentInfo; >>> -import org.apache.openejb.core.ThreadContext; >>> -import org.apache.openejb.core.stateful.BeanEntry; >>> -import org.apache.openejb.core.stateful.StatefulInstanceManager; >>> -import org.apache.openejb.core.stateful.StatefulContainer.MethodType; >>> -import org.apache.openejb.persistence.JtaEntityManagerRegistry; >>> -import org.apache.openejb.spi.SecurityService; >>> -import org.apache.openejb.util.Index; >>> +import org.apache.openejb.core.stateful.Cache; >>> +import org.apache.openejb.core.stateful.Instance; >>> +import org.slf4j.Logger; >>> +import org.slf4j.LoggerFactory; >>> /** >>> * >>> * @version $Rev:$ $Date:$ >>> */ >>> -public class ClusteredStatefulInstanceManager extends >>> StatefulInstanceManager implements SessionManagerTracker { >>> - private final Map sessionManagersById; >>> - private final Map deploymentsById; >>> - >>> - public ClusteredStatefulInstanceManager(SecurityService >>> securityService, >>> - JtaEntityManagerRegistry jtaEntityManagerRegistry, >>> - Class passivatorClass, >>> - int timeout, >>> - int poolSize, >>> - int bulkPassivate) throws OpenEJBException { >>> - super(securityService, >>> - jtaEntityManagerRegistry, >>> - passivatorClass, >>> - timeout, >>> - poolSize, >>> - bulkPassivate); >>> - - sessionManagersById = new HashMap>> SessionManager>(); >>> - deploymentsById = new HashMap(); >>> +public class WadiCache implements Cache, >>> SessionManagerTracker { >>> + private final ConcurrentMap >>> sessionManagersById = new ConcurrentHashMap(); >>> + >>> + private final ConcurrentMap localInstances = >>> new ConcurrentHashMap(); >>> + >>> + private final CacheListener cacheListener; >>> + >>> + public WadiCache(CacheListener cacheListener) { >>> + this.cacheListener = cacheListener; >>> } >>> - - public void addSessionManager(Object deploymentId, >>> SessionManager sessionManager) { >>> - synchronized (sessionManagersById) { >>> - sessionManagersById.put(deploymentId, sessionManager); >>> + >>> + public SessionManager getSessionManager(Object deploymentId) { >>> + SessionManager sessionManager = >>> sessionManagersById.get(deploymentId); >>> + if (sessionManager == null) { >>> + throw new IllegalStateException("No SessionManager registered >>> for deployment [" + deploymentId + "]"); >>> } >>> + return sessionManager; >>> + } >>> + >>> + public void addSessionManager(Object deploymentId, SessionManager >>> sessionManager) { >>> + sessionManagersById.put(deploymentId, sessionManager); >>> sessionManager.registerListener(new MigrationListener()); >>> } >>> - + >>> public void removeSessionManager(Object deploymentId, SessionManager >>> sessionManager) { >>> - synchronized (sessionManagersById) { >>> - sessionManagersById.remove(deploymentId); >>> - } >>> + sessionManagersById.remove(deploymentId); >>> } >>> - - @Override >>> - public void deploy(CoreDeploymentInfo deploymentInfo, Index>> MethodType> index) throws OpenEJBException { >>> - synchronized (deploymentsById) { >>> - deploymentsById.put(deploymentInfo.getDeploymentID(), >>> deploymentInfo); >>> - } >>> - super.deploy(deploymentInfo, index); >>> - } >>> - - @Override >>> - public void undeploy(CoreDeploymentInfo deploymentInfo) throws >>> OpenEJBException { >>> - synchronized (deploymentsById) { >>> - deploymentsById.remove(deploymentInfo.getDeploymentID()); >>> - } >>> - super.undeploy(deploymentInfo); >>> - } >>> - - @Override >>> - protected BeanEntry newBeanEntry(Object primaryKey, Object bean) { >>> - ThreadContext threadContext = ThreadContext.getThreadContext(); >>> - if (null == threadContext) { >>> - throw new IllegalStateException("No ThreadContext"); >>> - } >>> - Object deploymentId = >>> threadContext.getDeploymentInfo().getDeploymentID(); >>> - SessionManager sessionManager; >>> - synchronized (sessionManagersById) { >>> - sessionManager = sessionManagersById.get(deploymentId); >>> + public void add(Object primaryKey, Instance instance) { >>> + if (!primaryKey.equals(instance.primaryKey)) throw new >>> IllegalArgumentException("primaryKey does not equal instance.primaryKey"); >>> + >>> + // Check if we already have this primary key cached locally >>> + WadiInstance wadiInstance = localInstances.get(primaryKey); >>> + if (wadiInstance != null) { >>> + wadiInstance.lock.lock(); >>> + try { >>> + if (wadiInstance.getState() != WadiInstanceState.REMOVED) >>> { >>> + throw new IllegalStateException("An entry for the key >>> " + primaryKey + " already exists"); >>> + } >>> + // Entry has been removed between get and lock, simply >>> remove the garbage entry >>> + localInstances.remove(primaryKey); >>> + } finally { >>> + wadiInstance.lock.unlock(); >>> + } >>> } >>> - if (null == sessionManager) { >>> - throw new IllegalStateException("No SessionManager registered >>> for deployment [" + deploymentId + "]"); >>> + >>> + if (!(primaryKey instanceof VMID)) { >>> + // primaryKey.toString() must be an unique String >>> representation for an unique identifier. Here, we >>> + // check that primaryKey is a VMID as its Object.toString >>> implementation returns an unique String >>> + // representation. Other types may not implement >>> Object.toString() "correctly". >>> + throw new AssertionError("primaryKey MUST be a " + >>> VMID.class.getName()); >>> } >>> - - Session session; >>> + >>> try { >>> - if (!(primaryKey instanceof VMID)) { >>> - // primaryKey.toString() must be an unique String >>> representation for an unique identifier. Here, we >>> - // check that primaryKey is a VMID as its Object.toString >>> implementation returns an unique String >>> - // representation. Other types may not implement >>> Object.toString() "correctly". >>> - throw new AssertionError("primaryKey MUST be a " + >>> VMID.class.getName()); >>> - } >>> - session = >>> sessionManager.createSession(primaryKey.toString()); >>> + Object deploymentId = >>> instance.deploymentInfo.getDeploymentID(); >>> + Session session = >>> getSessionManager(deploymentId).createSession(primaryKey.toString()); >>> + localInstances.put(primaryKey, new WadiInstance(instance, >>> session)); >>> } catch (SessionAlreadyExistException e) { >>> throw (IllegalStateException) new >>> IllegalStateException().initCause(e); >>> } >>> - - return new ClusteredBeanEntry(session, deploymentId, >>> bean, primaryKey, timeOut); >>> } >>> - @Override >>> - protected void onFreeBeanEntry(ThreadContext callContext, BeanEntry >>> entry) { >>> - SessionOperation operation = >>> callContext.get(SessionOperation.class); >>> - if (null != operation) { >>> - if (SessionOperation.DESTRUCTION != operation && >>> SessionOperation.OUTBOUND_MIGRATION != operation) { >>> - throw new AssertionError(); >>> + public Instance checkOut(Object primaryKey) throws Exception { >>> + // attempt (up to 10 times) to obtain the entry from the cache >>> + for (int i = 0; i < 10; i++) { >>> + // find the entry >>> + WadiInstance wadiInstance = localInstances.get(primaryKey); >>> + if (wadiInstance == null) { >>> + return null; >>> + } >>> + >>> + wadiInstance.lock.lock(); >>> + try { >>> + // verfiy state >>> + switch (wadiInstance.getState()) { >>> + case AVAILABLE: >>> + break; >>> + case CHECKED_OUT: >>> + throw new IllegalStateException("The entry " + >>> primaryKey + " is already checked-out"); >>> + case PASSIVATED: >>> + // Entry was passivated between get and lock, we >>> need to load the Entry again >>> + // If the cache somehow got corrupted by an entry >>> containing in state PASSIVATED, this remove >>> + // call will remove the corruption >>> + localInstances.remove(primaryKey, wadiInstance); >>> + continue; >>> + case REMOVED: >>> + // Entry has been removed between get and lock >>> (most likely by undeploying the EJB), simply drop the instance >>> + return null; >>> + } >>> + >>> + // mark entry as in-use >>> + wadiInstance.setState(WadiInstanceState.CHECKED_OUT); >>> + >>> + return wadiInstance.instance; >>> + } finally { >>> + wadiInstance.lock.unlock(); >>> } >>> + } >>> + >>> + // something is really messed up with this entry, try to cleanup >>> before throwing an exception >>> + localInstances.remove(primaryKey); >>> + throw new RuntimeException("Cache is corrupted: the entry " + >>> primaryKey + " in the Map 'cache' is in state PASSIVATED"); } >>> + >>> + public void checkIn(Object primaryKey) { >>> + // find the entry >>> + WadiInstance wadiInstance = localInstances.get(primaryKey); >>> + if (wadiInstance == null) { >>> return; >>> } >>> - ClusteredBeanEntry clusteredBeanEntry = (ClusteredBeanEntry) >>> entry; >>> - clusteredBeanEntry.release(); >>> - } >>> - - @Override >>> - protected void onPoolInstanceWithoutTransaction(ThreadContext >>> callContext, BeanEntry entry) { >>> - SessionOperation operation = >>> callContext.get(SessionOperation.class); >>> - if (null != operation) { >>> - if (SessionOperation.INBOUND_MIGRATION != operation) { >>> - throw new AssertionError(); >>> + >>> + wadiInstance.lock.lock(); >>> + try { >>> + // verfiy state >>> + switch (wadiInstance.getState()) { >>> + case AVAILABLE: >>> + throw new IllegalStateException("The entry " + >>> primaryKey + " is not checked-out"); >>> + case PASSIVATED: >>> + // An entry in-use should not be passivated so we can >>> only assume >>> + // that the caller never checked out the bean in the >>> first place >>> + throw new IllegalStateException("The entry " + >>> primaryKey + " is not checked-out"); >>> + case REMOVED: >>> + // Entry has been removed between get and lock (most >>> likely by undeploying the EJB), simply drop the instance >>> + return; >>> } >>> - return; >>> + >>> + // mark entry as available >>> + wadiInstance.setState(WadiInstanceState.AVAILABLE); >>> + } finally { >>> + wadiInstance.lock.unlock(); >>> + } >>> + >>> + // todo should this be instide of the lock? >>> + wadiInstance.endAccess(); >>> + } >>> + >>> + public Instance remove(Object primaryKey) { >>> + // find the entry >>> + WadiInstance wadiInstance = localInstances.get(primaryKey); >>> + if (wadiInstance == null) { >>> + return null; >>> + } >>> + >>> + wadiInstance.lock.lock(); >>> + try { >>> + // remove the entry from the cache >>> + localInstances.remove(primaryKey); >>> + >>> + // There is no need to check the state because users of the >>> cache >>> + // are responsible for maintaining references to beans in use >>> + >>> + // mark the entry as removed >>> + wadiInstance.setState(WadiInstanceState.REMOVED); >>> + >>> + } finally { >>> + wadiInstance.lock.unlock(); >>> } >>> - ClusteredBeanEntry clusteredBeanEntry = (ClusteredBeanEntry) >>> entry; >>> - clusteredBeanEntry.endAccess(); >>> + >>> + wadiInstance.release(); >>> + return wadiInstance.instance; >>> } >>> - - protected enum SessionOperation { >>> - INBOUND_MIGRATION, >>> - OUTBOUND_MIGRATION, >>> - DESTRUCTION >>> + >>> + public void removeAll(CacheFilter filter) { >>> + for (Iterator iterator = >>> localInstances.values().iterator(); iterator.hasNext();) { >>> + WadiInstance wadiInstance = iterator.next(); >>> + >>> + wadiInstance.lock.lock(); >>> + try { >>> + if (filter.matches(wadiInstance.instance)) { >>> + // remove the entry from the cache and lru >>> + iterator.remove(); >>> + >>> + // There is no need to check the state because users >>> of the cache >>> + // are responsible for maintaining references to >>> beans in use >>> + >>> + // mark the entry as removed >>> + wadiInstance.setState(WadiInstanceState.REMOVED); >>> + } >>> + } finally { >>> + wadiInstance.lock.unlock(); >>> + } >>> + } >>> } >>> - + >>> protected class MigrationListener implements SessionListener { >>> private final Logger log = >>> LoggerFactory.getLogger(MigrationListener.class); >>> - public void >>> notifyInboundSessionMigration(org.apache.geronimo.clustering.Session >>> session) { >>> - ClusteredBeanEntry beanEntry = new >>> ClusteredBeanEntry(session); >>> - ThreadContext context = newThreadContext(beanEntry); >>> - if (null == context) { >>> + public void notifyInboundSessionMigration(Session session) { >>> + WadiInstance instance = getWadiInstance(session); >>> + if (instance == null) { >>> return; >>> } >>> - context.set(SessionOperation.class, >>> SessionOperation.INBOUND_MIGRATION); >>> try { >>> - activateInstance(context, beanEntry); >>> - poolInstance(context, beanEntry.getBean()); >>> + cacheListener.afterLoad(instance.instance); >>> + localInstances.put(instance.instance.primaryKey, >>> instance); >>> } catch (Exception e) { >>> log.warn("Cannot activate migrated bean entry.", e); >>> } >>> } >>> - public void >>> notifyOutboundSessionMigration(org.apache.geronimo.clustering.Session >>> session) { >>> - ClusteredBeanEntry beanEntry = new >>> ClusteredBeanEntry(session); >>> - ThreadContext context = newThreadContext(beanEntry); >>> - if (null == context) { >>> + public void notifyOutboundSessionMigration(Session session) { >>> + WadiInstance instance = getWadiInstance(session); >>> + if (instance == null) { >>> return; >>> } >>> - context.set(SessionOperation.class, >>> SessionOperation.OUTBOUND_MIGRATION); >>> - passivate(context, beanEntry); >>> - freeInstance(context); >>> + try { >>> + cacheListener.beforeStore(instance.instance); >>> + localInstances.remove(instance.instance.primaryKey); >>> + } catch (Exception e) { >>> + log.warn("Cannot passivate EJB for migration.", e); >>> + } >>> } >>> - public void >>> notifySessionDestruction(org.apache.geronimo.clustering.Session session) { >>> - ClusteredBeanEntry beanEntry = new >>> ClusteredBeanEntry(session); >>> - ThreadContext context = newThreadContext(beanEntry); >>> - if (null == context) { >>> + public void notifySessionDestruction(Session session) { >>> + WadiInstance instance = getWadiInstance(session); >>> + if (instance == null) { >>> return; >>> } >>> - context.set(SessionOperation.class, >>> SessionOperation.DESTRUCTION); >>> - freeInstance(context); >>> + localInstances.remove(instance.instance.primaryKey); >>> } >>> + } >>> - protected ThreadContext newThreadContext(ClusteredBeanEntry >>> beanEntry) { >>> - Object deploymentId = beanEntry.getDeploymentId(); >>> - CoreDeploymentInfo deploymentInfo; >>> - synchronized (deploymentsById) { >>> - deploymentInfo = deploymentsById.get(deploymentId); >>> - } >>> - if (null == deploymentInfo) { >>> - log.warn("Deployment [" + deploymentId + "] is >>> unknown."); >>> - return null; >>> + public static final String SESSION_KEY_ENTRY = "entry"; >>> + >>> + protected WadiInstance getWadiInstance(Session session) { >>> + if (session == null) { >>> + throw new IllegalArgumentException("session is required"); >>> + } >>> + Instance instance = (Instance) >>> session.getState(SESSION_KEY_ENTRY); >>> + if (instance == null) { >>> + return null; >>> + } >>> + return new WadiInstance(instance, session); >>> + } >>> + >>> + private static class WadiInstance { >>> + private final Instance instance; >>> + private final Session session; >>> + private final ReentrantLock lock = new ReentrantLock(); >>> + private WadiInstanceState state; >>> + >>> + private WadiInstance(Instance instance, Session session) { >>> + this.instance = instance; >>> + this.session = session; >>> + session.addState(SESSION_KEY_ENTRY, instance); >>> + } >>> + >>> + public void release() { >>> + session.release(); >>> + } >>> + >>> + public void endAccess() { >>> + session.addState(SESSION_KEY_ENTRY, this); >>> + session.onEndAccess(); >>> + } >>> + >>> + private WadiInstanceState getState() { >>> + assertLockHeld(); >>> + return state; >>> + } >>> + >>> + private void setState(WadiInstanceState state) { >>> + assertLockHeld(); >>> + this.state = state; >>> + } >>> + >>> + private void assertLockHeld() { >>> + if (!lock.isHeldByCurrentThread()) { >>> + throw new IllegalStateException("Entry must be locked"); >>> } >>> - return new ThreadContext(deploymentInfo, >>> beanEntry.getPrimaryKey()); >>> } >>> } >>> - -} >>> + >>> + private enum WadiInstanceState { >>> + AVAILABLE, CHECKED_OUT, PASSIVATED, REMOVED >>> + } >>> + >>> +} >>> \ No newline at end of file >>> >>> Modified: >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulContainerTest.java >>> URL: >>> http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulContainerTest.java?rev=689244&r1=689243&r2=689244&view=diff >>> >>> ============================================================================== >>> --- >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulContainerTest.java >>> (original) >>> +++ >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulContainerTest.java >>> Tue Aug 26 14:37:11 2008 >>> @@ -46,8 +46,6 @@ >>> public class ClusteredStatefulContainerTest extends RMockTestCase { >>> private WADISessionManager sessionManager; >>> - private TransactionManager txManager; >>> - private SecurityService securityService; >>> private ClusteredStatefulContainer container; >>> private CoreDeploymentInfo deploymentInfo; >>> private String deploymentId; >>> @@ -80,12 +78,12 @@ >>> modify().multiplicity(expect.from(0)); >>> tracker = (NetworkConnectorTracker) >>> mock(NetworkConnectorTracker.class); >>> modify().returnValue(tracker); >>> - - txManager = (TransactionManager) >>> mock(TransactionManager.class); >>> - securityService = (SecurityService) mock(SecurityService.class); >>> + >>> + TransactionManager txManager = (TransactionManager) >>> mock(TransactionManager.class); >>> + SecurityService securityService = (SecurityService) >>> mock(SecurityService.class); >>> container = (ClusteredStatefulContainer) >>> intercept(ClusteredStatefulContainer.class, new Object[] {"id", >>> - txManager, >>> - securityService, + txManager, >>> + securityService, >>> null, >>> 1, >>> 1, >>> >>> Copied: >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/WadiCacheTest.java >>> (from r688604, >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulInstanceManagerTest.java) >>> URL: >>> http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/WadiCacheTest.java?p2=geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/WadiCacheTest.java&p1=geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulInstanceManagerTest.java&r1=688604&r2=689244&rev=689244&view=diff >>> >>> ============================================================================== >>> --- >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/ClusteredStatefulInstanceManagerTest.java >>> (original) >>> +++ >>> geronimo/server/trunk/plugins/openejb/geronimo-openejb-clustering-wadi/src/test/java/org/apache/geronimo/openejb/cluster/stateful/container/WadiCacheTest.java >>> Tue Aug 26 14:37:11 2008 >>> @@ -20,12 +20,17 @@ >>> import java.io.IOException; >>> import java.rmi.dgc.VMID; >>> +import java.util.Map; >>> import java.util.concurrent.Callable; >>> import java.util.concurrent.FutureTask; >>> +import javax.persistence.EntityManager; >>> +import javax.persistence.EntityManagerFactory; >>> -import javax.transaction.TransactionManager; >>> -import javax.transaction.TransactionSynchronizationRegistry; >>> - >>> +import com.agical.rmock.core.Action; >>> +import com.agical.rmock.core.MethodHandle; >>> +import com.agical.rmock.core.describe.ExpressionDescriber; >>> +import com.agical.rmock.core.match.operator.AbstractExpression; >>> +import com.agical.rmock.extension.junit.RMockTestCase; >>> import org.apache.geronimo.clustering.Session; >>> import org.apache.geronimo.clustering.SessionListener; >>> import org.apache.geronimo.clustering.wadi.WADISessionManager; >>> @@ -33,22 +38,15 @@ >>> import org.apache.openejb.core.CoreDeploymentInfo; >>> import org.apache.openejb.core.DeploymentContext; >>> import org.apache.openejb.core.ThreadContext; >>> -import org.apache.openejb.core.stateful.BeanEntry; >>> -import org.apache.openejb.persistence.JtaEntityManagerRegistry; >>> -import org.apache.openejb.spi.SecurityService; >>> - >>> -import com.agical.rmock.core.Action; >>> -import com.agical.rmock.core.MethodHandle; >>> -import com.agical.rmock.core.describe.ExpressionDescriber; >>> -import com.agical.rmock.core.match.operator.AbstractExpression; >>> -import com.agical.rmock.extension.junit.RMockTestCase; >>> +import org.apache.openejb.core.stateful.Cache.CacheListener; >>> +import org.apache.openejb.core.stateful.Instance; >>> /** >>> * @version $Rev$ $Date$ >>> */ >>> -public class ClusteredStatefulInstanceManagerTest extends RMockTestCase { >>> +public class WadiCacheTest extends RMockTestCase { >>> - private ClusteredStatefulInstanceManager manager; >>> + private WadiCache manager; >>> private String deploymentId; >>> private CoreDeploymentInfo deploymentInfo; >>> private VMID primKey; >>> @@ -58,14 +56,17 @@ >>> @Override >>> protected void setUp() throws Exception { >>> - TransactionManager txManager = (TransactionManager) >>> mock(TransactionManager.class); >>> - SecurityService securityService = (SecurityService) >>> mock(SecurityService.class); >>> - TransactionSynchronizationRegistry txSynchRegistry = >>> (TransactionSynchronizationRegistry) >>> mock(TransactionSynchronizationRegistry.class); >>> - JtaEntityManagerRegistry jtaEntityManagerRegistry = new >>> JtaEntityManagerRegistry(txSynchRegistry); >>> - - manager = (ClusteredStatefulInstanceManager) >>> intercept(ClusteredStatefulInstanceManager.class, >>> - new Object[] { securityService, jtaEntityManagerRegistry, >>> null, 1, 1, 1 }); >>> - + manager = new WadiCache(new CacheListener() { >>> + public void afterLoad(Instance instance) throws Exception { >>> + } >>> + >>> + public void beforeStore(Instance instance) throws Exception { >>> + } >>> + >>> + public void timedOut(Instance instance) { >>> + } >>> + }); >>> + >>> deploymentId = "deploymentId"; >>> deploymentInfo = new CoreDeploymentInfo(new >>> DeploymentContext(deploymentId, null, null), >>> SFSB.class, >>> @@ -95,125 +96,131 @@ >>> threadContext = new ThreadContext(deploymentInfo, primKey); >>> ThreadContext.enter(threadContext); >>> } >>> - + >>> @Override >>> protected void tearDown() throws Exception { >>> if (threadContext != null) { >>> ThreadContext.exit(threadContext); >>> } >>> } >>> - + >>> public void testNewBeanEntryForUnknownDeploymentThrowsISE() throws >>> Exception { >>> startVerification(); >>> - + >>> try { >>> - manager.newBeanEntry("primaryKey", new Object()); >>> + VMID primaryKey = new VMID(); >>> + Instance instance = new Instance(deploymentInfo, primaryKey, >>> new Object(), null, (Map) null); >>> + manager.add(primaryKey, instance); >>> fail(); >>> } catch (IllegalStateException e) { >>> } >>> } >>> - + >>> public void testNewBeanEntryOK() throws Exception { >>> VMID primaryKey = new VMID(); >>> recordAddSessionManagerAndCreateSession(primaryKey); >>> - + >>> startVerification(); >>> - + >>> manager.addSessionManager(deploymentId, sessionManager); >>> - manager.newBeanEntry(primaryKey, new Object()); >>> + >>> + Instance instance = new Instance(deploymentInfo, primaryKey, new >>> Object(), null, (Map) null); >>> + manager.add(primaryKey, instance); >>> } >>> public void testSessionDestructionFreeInstance() throws Exception { >>> Session session = >>> recordAddSessionManagerAndCreateSession(primKey); >>> - FutureTask newBeanEntryTask = >>> newBeanEntryTask(primKey, session); >>> + FutureTask newBeanEntryTask = newBeanEntryTask(primKey, >>> session); >>> - manager.freeInstance(null); >>> +// manager.freeInstance(null); >>> modify().args(new ThreadContextArgAssertion()); >>> - + >>> startVerification(); >>> - - manager.deploy(deploymentInfo, null); >>> + >>> +// manager.deploy(deploymentInfo, null); >>> manager.addSessionManager(deploymentId, sessionManager); >>> - + >>> newBeanEntryTask.run(); >>> - sessionListener.notifySessionDestruction(session); >>> +// sessionListener.notifySessionDestruction(session); >>> } >>> public void testInboundSessionMigrationActivateAndPoolBeanEntry() >>> throws Exception { >>> Session session = >>> recordAddSessionManagerAndCreateSession(primKey); >>> - FutureTask newBeanEntryTask = >>> newBeanEntryTask(primKey, session); >>> + FutureTask newBeanEntryTask = newBeanEntryTask(primKey, >>> session); >>> + >>> +// manager.activateInstance(null, null); >>> +// modify().args(new ThreadContextArgAssertion(), is.NOT_NULL); >>> +// manager.poolInstance(null, null); >>> +// modify().args(new ThreadContextArgAssertion(), is.NOT_NULL); >>> - manager.activateInstance(null, null); >>> - modify().args(new ThreadContextArgAssertion(), is.NOT_NULL); >>> - manager.poolInstance(null, null); >>> - modify().args(new ThreadContextArgAssertion(), is.NOT_NULL); >>> - startVerification(); >>> - - manager.deploy(deploymentInfo, null); >>> + >>> +// manager.deploy(deploymentInfo, null); >>> manager.addSessionManager(deploymentId, sessionManager); >>> - + >>> newBeanEntryTask.run(); >>> - sessionListener.notifyInboundSessionMigration(session); >>> +// sessionListener.notifyInboundSessionMigration(session); >>> } >>> - + >>> public void testOutboundSessionMigrationPassivateBeanEntry() throws >>> Exception { >>> Session session = >>> recordAddSessionManagerAndCreateSession(primKey); >>> - FutureTask newBeanEntryTask = >>> newBeanEntryTask(primKey, session); >>> - - manager.passivate(null, null); >>> - modify().args(new ThreadContextArgAssertion(), is.NOT_NULL); >>> - - manager.freeInstance(null); >>> - modify().args(new ThreadContextArgAssertion()); >>> - + FutureTask newBeanEntryTask = >>> newBeanEntryTask(primKey, session); >>> + >>> +// manager.passivate(null, null); >>> +// modify().args(new ThreadContextArgAssertion(), is.NOT_NULL); >>> +// >>> +// manager.freeInstance(null); >>> +// modify().args(new ThreadContextArgAssertion()); >>> + >>> startVerification(); >>> - - manager.deploy(deploymentInfo, null); >>> + >>> +// manager.deploy(deploymentInfo, null); >>> manager.addSessionManager(deploymentId, sessionManager); >>> - + >>> newBeanEntryTask.run(); >>> - sessionListener.notifyOutboundSessionMigration(session); >>> +// sessionListener.notifyOutboundSessionMigration(session); >>> } >>> - - public void testOnFreeBeanEntryReleaseSession() throws Exception >>> { >>> - Session session = (Session) mock(Session.class); >>> - session.addState(ClusteredBeanEntry.SESSION_KEY_ENTRY, null); >>> - modify().args(is.AS_RECORDED, is.NOT_NULL); >>> - >>> - session.release(); >>> - - startVerification(); >>> - manager.onFreeBeanEntry(threadContext, new >>> ClusteredBeanEntry(session, deploymentId, new Object(), primKey, 0)); >>> - } >>> - - public void >>> testOnPoolInstanceWithoutTransactionTriggersSessionOnEndAccess() throws >>> Exception { >>> - Session session = (Session) mock(Session.class); >>> - session.addState(ClusteredBeanEntry.SESSION_KEY_ENTRY, null); >>> - modify().args(is.AS_RECORDED, is.NOT_NULL); >>> - - session.addState(ClusteredBeanEntry.SESSION_KEY_ENTRY, >>> null); >>> - modify().args(is.AS_RECORDED, is.NOT_NULL); >>> - session.onEndAccess(); >>> - - startVerification(); >>> - - manager.onPoolInstanceWithoutTransaction(threadContext, >>> new ClusteredBeanEntry(session, >>> - deploymentId, >>> - new Object(), >>> - primKey, >>> - 0)); >>> - } >>> - - private FutureTask newBeanEntryTask(final VMID >>> primaryKey, Session session) { >>> - final FutureTask newBeanEntryTask = new >>> FutureTask(new Callable() { >>> - public BeanEntry call() throws Exception { >>> - return manager.newBeanEntry(primaryKey, new Object()); >>> +// public void testOnFreeBeanEntryReleaseSession() throws Exception { >>> +// Session session = (Session) mock(Session.class); >>> +// session.addState(ClusteredBeanEntry.SESSION_KEY_ENTRY, null); >>> +// modify().args(is.AS_RECORDED, is.NOT_NULL); >>> +// >>> +// session.release(); >>> +// >>> +// startVerification(); >>> +// >>> +// manager.onFreeBeanEntry(threadContext, new >>> ClusteredBeanEntry(session, deploymentId, new Object(), primKey, 0)); >>> +// } >>> +// >>> +// public void >>> testOnPoolInstanceWithoutTransactionTriggersSessionOnEndAccess() throws >>> Exception { >>> +// Session session = (Session) mock(Session.class); >>> +// session.addState(ClusteredBeanEntry.SESSION_KEY_ENTRY, null); >>> +// modify().args(is.AS_RECORDED, is.NOT_NULL); >>> +// >>> +// session.addState(ClusteredBeanEntry.SESSION_KEY_ENTRY, null); >>> +// modify().args(is.AS_RECORDED, is.NOT_NULL); >>> +// session.onEndAccess(); >>> +// >>> +// startVerification(); >>> +// >>> +// manager.onPoolInstanceWithoutTransaction(threadContext, new >>> ClusteredBeanEntry(session, >>> +// deploymentId, >>> +// new Object(), >>> +// primKey, >>> +// 0)); >>> +// } >>> + >>> + private FutureTask newBeanEntryTask(final VMID primaryKey, >>> Session session) { >>> + final FutureTask newBeanEntryTask = new >>> FutureTask(new Callable() { >>> + public Instance call() throws Exception { >>> + Instance instance = new Instance(deploymentInfo, >>> primaryKey, new Object(), null, (Map) >>> null); >>> + manager.add(primaryKey, instance); >>> + return instance; >>> } >>> }); >>> - session.getState(ClusteredBeanEntry.SESSION_KEY_ENTRY); >>> + session.getState(WadiCache.SESSION_KEY_ENTRY); >>> modify().multiplicity(expect.from(0)).perform(new Action() { >>> public Object invocation(Object[] arg0, MethodHandle arg1) >>> throws Throwable { >>> return newBeanEntryTask.get(); >>> @@ -221,7 +228,7 @@ >>> }); >>> return newBeanEntryTask; >>> } >>> - + >>> private Session recordAddSessionManagerAndCreateSession(VMID >>> primaryKey) throws Exception { >>> sessionManager.registerListener(null); >>> modify().args(new AbstractExpression() { >>> @@ -233,25 +240,25 @@ >>> return true; >>> } >>> }); >>> - + >>> Session session = >>> sessionManager.createSession(primaryKey.toString()); >>> - - session.addState(ClusteredBeanEntry.SESSION_KEY_ENTRY, >>> null); >>> + >>> + session.addState(WadiCache.SESSION_KEY_ENTRY, null); >>> modify().args(is.AS_RECORDED, is.NOT_NULL); >>> - + >>> return session; >>> } >>> - + >>> protected final class ThreadContextArgAssertion extends >>> AbstractExpression { >>> public void describeWith(ExpressionDescriber arg0) throws >>> IOException { >>> } >>> public boolean passes(Object arg0) { >>> - ThreadContext context = (ThreadContext) arg0; >>> - assertSame(deploymentInfo, context.getDeploymentInfo()); >>> - assertSame(primKey, context.getPrimaryKey()); >>> +// ThreadContext context = (ThreadContext) arg0; >>> +// assertSame(deploymentInfo, context.getDeploymentInfo()); >>> +// assertSame(primKey, context.getPrimaryKey()); >>> return true; >>> } >>> } >>> -} >>> +} >>> \ No newline at end of file >>> >>> >>> > --------------ms050504020606000205060908 Content-Type: application/x-pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" Content-Description: S/MIME Cryptographic Signature MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIJbTCC AxEwggJ6oAMCAQICEGE7sdOcvnyCHwhd2kbEvQ8wDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UE BhMCWkExJTAjBgNVBAoTHFRoYXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMT I1RoYXd0ZSBQZXJzb25hbCBGcmVlbWFpbCBJc3N1aW5nIENBMB4XDTA4MDQwMjE5MjcwOVoX DTA5MDQwMjE5MjcwOVowZTEfMB0GA1UEAxMWVGhhd3RlIEZyZWVtYWlsIE1lbWJlcjEgMB4G CSqGSIb3DQEJARYRZHJ3X3dlYkB5YWhvby5jb20xIDAeBgkqhkiG9w0BCQEWEWR3b29kc0Bh cGFjaGUub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlylHzveM+GK2U2Ib +9wzj8Ga4z4zK/wmMGbRmJ4IM9W4HBGntekfCQfwkb0K/qD8QZcQY4HfyfxIkIA+TaYy5/nL 1wWvH73Oc1HMT7Fyc7Vfkewpi1KZoxLzAdr358uAi5TEYxOoUvCxLoI+BpM1655EDyRRlD8e dK3zemHv+gRoWkb11QmfFt6putMBi0VZZ3k2rJZRDXQDjMGOu/GPR1XcV+ah43Z/+vnPWMd+ NSqV9IUC7UWkL5kwhGpWOtgZg0tabr2xj79y13bG6fDQjwRKgSlN98wZjMQLx4MZPtn3lT1C zCOxsqjr86MGePVk2QXNvbCkxun6EHezeKtA/wIDAQABo0EwPzAvBgNVHREEKDAmgRFkcndf d2ViQHlhaG9vLmNvbYERZHdvb2RzQGFwYWNoZS5vcmcwDAYDVR0TAQH/BAIwADANBgkqhkiG 9w0BAQUFAAOBgQAitedgxXImBqxgW9UftLIVMaIzfKgnue/Q4GvPS0J6ucqyGB4l5f50aKEB kuLfajXpC/ZrScinLNFi8ZvMw6KCUaiWjAwupl5KiF7cWh93kNFihD2SM+M8+hFf9kVyGMxs 49FAn3yoP9QVCQtq4C1sixTfayi4rFRvRMlPRcYqdjCCAxEwggJ6oAMCAQICEGE7sdOcvnyC Hwhd2kbEvQ8wDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UEBhMCWkExJTAjBgNVBAoTHFRoYXd0 ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMTI1RoYXd0ZSBQZXJzb25hbCBGcmVl bWFpbCBJc3N1aW5nIENBMB4XDTA4MDQwMjE5MjcwOVoXDTA5MDQwMjE5MjcwOVowZTEfMB0G A1UEAxMWVGhhd3RlIEZyZWVtYWlsIE1lbWJlcjEgMB4GCSqGSIb3DQEJARYRZHJ3X3dlYkB5 YWhvby5jb20xIDAeBgkqhkiG9w0BCQEWEWR3b29kc0BhcGFjaGUub3JnMIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlylHzveM+GK2U2Ib+9wzj8Ga4z4zK/wmMGbRmJ4IM9W4 HBGntekfCQfwkb0K/qD8QZcQY4HfyfxIkIA+TaYy5/nL1wWvH73Oc1HMT7Fyc7Vfkewpi1KZ oxLzAdr358uAi5TEYxOoUvCxLoI+BpM1655EDyRRlD8edK3zemHv+gRoWkb11QmfFt6putMB i0VZZ3k2rJZRDXQDjMGOu/GPR1XcV+ah43Z/+vnPWMd+NSqV9IUC7UWkL5kwhGpWOtgZg0ta br2xj79y13bG6fDQjwRKgSlN98wZjMQLx4MZPtn3lT1CzCOxsqjr86MGePVk2QXNvbCkxun6 EHezeKtA/wIDAQABo0EwPzAvBgNVHREEKDAmgRFkcndfd2ViQHlhaG9vLmNvbYERZHdvb2Rz QGFwYWNoZS5vcmcwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOBgQAitedgxXImBqxg W9UftLIVMaIzfKgnue/Q4GvPS0J6ucqyGB4l5f50aKEBkuLfajXpC/ZrScinLNFi8ZvMw6KC UaiWjAwupl5KiF7cWh93kNFihD2SM+M8+hFf9kVyGMxs49FAn3yoP9QVCQtq4C1sixTfayi4 rFRvRMlPRcYqdjCCAz8wggKooAMCAQICAQ0wDQYJKoZIhvcNAQEFBQAwgdExCzAJBgNVBAYT AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMg RGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBGcmVlbWFpbCBDQTErMCkGCSqG SIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhhd3RlLmNvbTAeFw0wMzA3MTcwMDAwMDBa Fw0xMzA3MTYyMzU5NTlaMGIxCzAJBgNVBAYTAlpBMSUwIwYDVQQKExxUaGF3dGUgQ29uc3Vs dGluZyAoUHR5KSBMdGQuMSwwKgYDVQQDEyNUaGF3dGUgUGVyc29uYWwgRnJlZW1haWwgSXNz dWluZyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxKY8VXNV+065yplaHmjAdQRw nd/p/6Me7L3N9VvyGna9fww6YfK/Uc4B1OVQCjDXAmNaLIkVcI7dyfArhVqqP3FWy688Cwfn 8R+RNiQqE88r1fOCdz0Dviv+uxg+B79AgAJk16emu59l0cUqVIUPSAR/p7bRPGEEQB5kGXJg t/sCAwEAAaOBlDCBkTASBgNVHRMBAf8ECDAGAQH/AgEAMEMGA1UdHwQ8MDowOKA2oDSGMmh0 dHA6Ly9jcmwudGhhd3RlLmNvbS9UaGF3dGVQZXJzb25hbEZyZWVtYWlsQ0EuY3JsMAsGA1Ud DwQEAwIBBjApBgNVHREEIjAgpB4wHDEaMBgGA1UEAxMRUHJpdmF0ZUxhYmVsMi0xMzgwDQYJ KoZIhvcNAQEFBQADgYEASIzRUIPqCy7MDaNmrGcPf6+svsIXoUOWlJ1/TCG4+DYfqi2fNi/A 9BxQIJNwPP2t4WFiw9k6GX6EsZkbAMUaC4J0niVQlGLH2ydxVyWN3amcOY6MIE9lX5Xa9/eH 1sYITq726jTlEBpbNU1341YheILcIRk13iSx0x1G/11fZU8xggNkMIIDYAIBATB2MGIxCzAJ BgNVBAYTAlpBMSUwIwYDVQQKExxUaGF3dGUgQ29uc3VsdGluZyAoUHR5KSBMdGQuMSwwKgYD VQQDEyNUaGF3dGUgUGVyc29uYWwgRnJlZW1haWwgSXNzdWluZyBDQQIQYTux05y+fIIfCF3a RsS9DzAJBgUrDgMCGgUAoIIBwzAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3 DQEJBTEPFw0wODA4MjcyMDI2NDVaMCMGCSqGSIb3DQEJBDEWBBSUg6Mc/JLbNk0i5vH7IPLr 8XvA+jBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIAgDANBggq hkiG9w0DAgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDCBhQYJKwYBBAGCNxAEMXgwdjBi MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEs MCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVtYWlsIElzc3VpbmcgQ0ECEGE7sdOcvnyC Hwhd2kbEvQ8wgYcGCyqGSIb3DQEJEAILMXigdjBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMc VGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFs IEZyZWVtYWlsIElzc3VpbmcgQ0ECEGE7sdOcvnyCHwhd2kbEvQ8wDQYJKoZIhvcNAQEBBQAE ggEAeeYmQIeTVp4VfV53mkc0FE7HrbeKKSbZmXZ7X7atsPcrhfPTx+H8Xy9jNKFsf3Pqck1y k80HmmzC7dL4yFQmmBMF7ww3CcD7kzJWc4LnDZdIXlSEHyMdp7+cNWKvNntsGz+se8pkv2Ck 9e8Xzzi8jgSwa6gHIXgiFruFJq8Qgv92yOIdDmIenoy4+7PzfP8uTIJiiecaUFrJalw/3+lK 2XU3eLcOvmabJPM9wFdllTs/xHZTkGS7p9a8DzXf4e8fzQOZQrKjJoY3Fd7HkGaWKhA4RQQu Naa7MEb3nXPgkQCodn4/J13V4V1KCo6RGEUHCtfjeZa+mx/v2pd+p7XvwAAAAAAAAA== --------------ms050504020606000205060908--