Have a look at using ehcache in an endpoint registry impl. In sandbaox for now to avoid yet another impl that doesnt work properly in trunk.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@894790 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cc231b19a1
commit
cb17099e7f
9 changed files with 1862 additions and 0 deletions
28
sandbox/endpoint-ehcache/META-INF/MANIFEST.MF
Normal file
28
sandbox/endpoint-ehcache/META-INF/MANIFEST.MF
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
Manifest-Version: 1.0
|
||||||
|
Private-Package: org.apache.tuscany.sca.xsd.impl;version="2.0.0"
|
||||||
|
SCA-Version: 1.1
|
||||||
|
Bundle-Name: Apache Tuscany SCA Tomcat Tribes Based EndPoint Registry
|
||||||
|
Bundle-Vendor: The Apache Software Foundation
|
||||||
|
Bundle-Version: 2.0.0
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||||
|
Bundle-Description: Apache Tuscany SCA XSD Model
|
||||||
|
Bundle-SymbolicName: org.apache.tuscany.sca.endpoint.tribes
|
||||||
|
Bundle-DocURL: http://www.apache.org/
|
||||||
|
Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6
|
||||||
|
Import-Package: org.apache.catalina.tribes,
|
||||||
|
org.apache.catalina.tribes.group,
|
||||||
|
org.apache.catalina.tribes.group.interceptors,
|
||||||
|
org.apache.catalina.tribes.io,
|
||||||
|
org.apache.catalina.tribes.membership,
|
||||||
|
org.apache.catalina.tribes.tipis,
|
||||||
|
org.apache.catalina.tribes.transport,
|
||||||
|
org.apache.catalina.tribes.util,
|
||||||
|
org.apache.juli.logging;resolution:=optional,
|
||||||
|
org.apache.tuscany.sca.assembly;version="2.0.0",
|
||||||
|
org.apache.tuscany.sca.core;version="2.0.0",
|
||||||
|
org.apache.tuscany.sca.core.assembly.impl;scope=internal;version="2.0.0";resolution:=optional,
|
||||||
|
org.apache.tuscany.sca.management;version="2.0.0",
|
||||||
|
org.apache.tuscany.sca.policy;version="2.0.0",
|
||||||
|
org.apache.tuscany.sca.runtime;version="2.0.0"
|
||||||
|
Export-Package: org.apache.tuscany.sca.endpoint.tribes;version="2.0.0"
|
||||||
74
sandbox/endpoint-ehcache/pom.xml
Normal file
74
sandbox/endpoint-ehcache/pom.xml
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
-->
|
||||||
|
<project>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.tuscany.sca</groupId>
|
||||||
|
<artifactId>tuscany-modules</artifactId>
|
||||||
|
<version>2.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<artifactId>tuscany-endpoint-echache</artifactId>
|
||||||
|
<name>Apache Tuscany SCA EndPoint Registry using Ehcache</name>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>sourceforge</id>
|
||||||
|
<url>http://oss.sonatype.org/content/groups/sourceforge/</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.sf.ehcache</groupId>
|
||||||
|
<artifactId>ehcache-core</artifactId>
|
||||||
|
<version>1.7.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tuscany.sca</groupId>
|
||||||
|
<artifactId>tuscany-core-spi</artifactId>
|
||||||
|
<version>2.0-SNAPSHOT</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tuscany.sca</groupId>
|
||||||
|
<artifactId>tuscany-core</artifactId>
|
||||||
|
<version>2.0-SNAPSHOT</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tuscany.sca</groupId>
|
||||||
|
<artifactId>tuscany-deployment</artifactId>
|
||||||
|
<version>2.0-SNAPSHOT</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tuscany.sca</groupId>
|
||||||
|
<artifactId>tuscany-implementation-java-runtime</artifactId>
|
||||||
|
<version>2.0-SNAPSHOT</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,602 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.tuscany.sca.endpoint.ehcache;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.rmi.Naming;
|
||||||
|
import java.rmi.NotBoundException;
|
||||||
|
import java.rmi.Remote;
|
||||||
|
import java.rmi.RemoteException;
|
||||||
|
import java.rmi.registry.LocateRegistry;
|
||||||
|
import java.rmi.registry.Registry;
|
||||||
|
import java.rmi.server.ExportException;
|
||||||
|
import java.rmi.server.UnicastRemoteObject;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import net.sf.ehcache.CacheException;
|
||||||
|
import net.sf.ehcache.CacheManager;
|
||||||
|
import net.sf.ehcache.Ehcache;
|
||||||
|
import net.sf.ehcache.Status;
|
||||||
|
import net.sf.ehcache.distribution.CacheManagerPeerListener;
|
||||||
|
import net.sf.ehcache.distribution.CacheReplicator;
|
||||||
|
import net.sf.ehcache.distribution.RMICacheManagerPeerListener;
|
||||||
|
import net.sf.ehcache.distribution.RMICachePeer;
|
||||||
|
import net.sf.ehcache.event.CacheEventListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cache server which exposes available cache operations remotely through RMI.
|
||||||
|
* <p/>
|
||||||
|
* It acts as a Decorator to a Cache. It holds an instance of cache, which is a local cache it talks to.
|
||||||
|
* <p/>
|
||||||
|
* This class could specify a security manager with code like:
|
||||||
|
* <pre>
|
||||||
|
* if (System.getSecurityManager() == null) {
|
||||||
|
* System.setSecurityManager(new RMISecurityManager());
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* Doing so would require the addition of <code>grant</code> statements in the <code>java.policy</code> file.
|
||||||
|
* <p/>
|
||||||
|
* Per the JDK documentation: "If no security manager is specified no class loading, by RMI clients or servers, is allowed,
|
||||||
|
* aside from what can be found in the local CLASSPATH." The classpath of each instance of this class should have
|
||||||
|
* all required classes to enable distribution, so no remote classloading is required or desirable. Accordingly,
|
||||||
|
* no security manager is set and there are no special JVM configuration requirements.
|
||||||
|
* <p/>
|
||||||
|
* This class opens a ServerSocket. The dispose method should be called for orderly closure of that socket. This class
|
||||||
|
* has a shutdown hook which calls dispose() as a convenience feature for developers.
|
||||||
|
*
|
||||||
|
* @author Greg Luck
|
||||||
|
* @version $Id: RMICacheManagerPeerListener.java 1012 2009-08-20 04:23:00Z gregluck $
|
||||||
|
*/
|
||||||
|
public class TuscanyRMICacheManagerPeerListener implements CacheManagerPeerListener {
|
||||||
|
|
||||||
|
private static final Logger LOG = Logger.getLogger(TuscanyRMICacheManagerPeerListener.class.getName());
|
||||||
|
private static final int MINIMUM_SENSIBLE_TIMEOUT = 200;
|
||||||
|
private static final int NAMING_UNBIND_RETRY_INTERVAL = 400;
|
||||||
|
private static final int NAMING_UNBIND_MAX_RETRIES = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cache peers. The value is an RMICachePeer.
|
||||||
|
*/
|
||||||
|
protected final Map cachePeers = new HashMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* status.
|
||||||
|
*/
|
||||||
|
protected Status status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The RMI listener port
|
||||||
|
*/
|
||||||
|
protected Integer port;
|
||||||
|
|
||||||
|
private Registry registry;
|
||||||
|
private boolean registryCreated;
|
||||||
|
private final String hostName;
|
||||||
|
|
||||||
|
private CacheManager cacheManager;
|
||||||
|
private Integer socketTimeoutMillis;
|
||||||
|
private Integer remoteObjectPort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor with full arguments.
|
||||||
|
*
|
||||||
|
* @param hostName may be null, in which case the hostName will be looked up. Machines with multiple
|
||||||
|
* interfaces should specify this if they do not want it to be the default NIC.
|
||||||
|
* @param port a port in the range 1025 - 65536
|
||||||
|
* @param remoteObjectPort the port number on which the remote objects bound in the registry receive calls.
|
||||||
|
This defaults to a free port if not specified.
|
||||||
|
* @param cacheManager the CacheManager this listener belongs to
|
||||||
|
* @param socketTimeoutMillis TCP/IP Socket timeout when waiting on response
|
||||||
|
*/
|
||||||
|
public TuscanyRMICacheManagerPeerListener(String hostName, Integer port, Integer remoteObjectPort, CacheManager cacheManager,
|
||||||
|
Integer socketTimeoutMillis) throws UnknownHostException {
|
||||||
|
|
||||||
|
status = Status.STATUS_UNINITIALISED;
|
||||||
|
|
||||||
|
if (hostName != null && hostName.length() != 0) {
|
||||||
|
this.hostName = hostName;
|
||||||
|
if (hostName.equals("localhost")) {
|
||||||
|
LOG.log(Level.WARNING, "Explicitly setting the listener hostname to 'localhost' is not recommended. "
|
||||||
|
+ "It will only work if all CacheManager peers are on the same machine.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.hostName = calculateHostAddress();
|
||||||
|
}
|
||||||
|
if (port == null || port.intValue() == 0) {
|
||||||
|
assignFreePort(false);
|
||||||
|
} else {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
//by default is 0, which is ok.
|
||||||
|
this.remoteObjectPort = remoteObjectPort;
|
||||||
|
|
||||||
|
this.cacheManager = cacheManager;
|
||||||
|
if (socketTimeoutMillis == null || socketTimeoutMillis.intValue() < MINIMUM_SENSIBLE_TIMEOUT) {
|
||||||
|
throw new IllegalArgumentException("socketTimoutMillis must be a reasonable value greater than 200ms");
|
||||||
|
}
|
||||||
|
this.socketTimeoutMillis = socketTimeoutMillis;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a free port to be the listener port.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if the statis of the listener is not {@link net.sf.ehcache.Status#STATUS_UNINITIALISED}
|
||||||
|
*/
|
||||||
|
protected void assignFreePort(boolean forced) throws IllegalStateException {
|
||||||
|
if (status != Status.STATUS_UNINITIALISED) {
|
||||||
|
throw new IllegalStateException("Cannot change the port of an already started listener.");
|
||||||
|
}
|
||||||
|
this.port = new Integer(this.getFreePort());
|
||||||
|
if (forced) {
|
||||||
|
LOG.log(Level.WARNING, "Resolving RMI port conflict by automatically using a free TCP/IP port to listen on: " + this.port);
|
||||||
|
} else {
|
||||||
|
LOG.log(Level.FINE, "Automatically finding a free TCP/IP port to listen on: " + this.port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the host address as the default NICs IP address
|
||||||
|
*
|
||||||
|
* @throws UnknownHostException
|
||||||
|
*/
|
||||||
|
protected String calculateHostAddress() throws UnknownHostException {
|
||||||
|
return InetAddress.getLocalHost().getHostAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a free server socket port.
|
||||||
|
*
|
||||||
|
* @return a number in the range 1025 - 65536 that was free at the time this method was executed
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
*/
|
||||||
|
protected int getFreePort() throws IllegalArgumentException {
|
||||||
|
ServerSocket serverSocket = null;
|
||||||
|
try {
|
||||||
|
serverSocket = new ServerSocket(0);
|
||||||
|
return serverSocket.getLocalPort();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalArgumentException("Could not acquire a free port number.");
|
||||||
|
} finally {
|
||||||
|
if (serverSocket != null && !serverSocket.isClosed()) {
|
||||||
|
try {
|
||||||
|
serverSocket.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.log(Level.FINE, "Error closing ServerSocket: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void init() throws CacheException {
|
||||||
|
if (!status.equals(Status.STATUS_UNINITIALISED)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RMICachePeer rmiCachePeer = null;
|
||||||
|
try {
|
||||||
|
startRegistry();
|
||||||
|
int counter = 0;
|
||||||
|
populateListOfRemoteCachePeers();
|
||||||
|
synchronized (cachePeers) {
|
||||||
|
for (Iterator iterator = cachePeers.values().iterator(); iterator.hasNext();) {
|
||||||
|
rmiCachePeer = (RMICachePeer) iterator.next();
|
||||||
|
bind(rmiCachePeer.getUrl(), rmiCachePeer);
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.log(Level.FINE, counter + " RMICachePeers bound in registry for RMI listener");
|
||||||
|
status = Status.STATUS_ALIVE;
|
||||||
|
} catch (Exception e) {
|
||||||
|
String url = null;
|
||||||
|
if (rmiCachePeer != null) {
|
||||||
|
url = rmiCachePeer.getUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new CacheException("Problem starting listener for RMICachePeer "
|
||||||
|
+ url + ". Initial cause was " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind a cache peer
|
||||||
|
*
|
||||||
|
* @param rmiCachePeer
|
||||||
|
*/
|
||||||
|
protected void bind(String peerName, RMICachePeer rmiCachePeer) throws Exception {
|
||||||
|
Naming.rebind(peerName, rmiCachePeer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of bound objects.
|
||||||
|
* <p/>
|
||||||
|
* This should match the list of cachePeers i.e. they should always be bound
|
||||||
|
*
|
||||||
|
* @return a list of String representations of <code>RMICachePeer</code> objects
|
||||||
|
*/
|
||||||
|
protected String[] listBoundRMICachePeers() throws CacheException {
|
||||||
|
try {
|
||||||
|
return registry.list();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw new CacheException("Unable to list cache peers " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reference to the remote object.
|
||||||
|
*
|
||||||
|
* @param name the name of the cache e.g. <code>sampleCache1</code>
|
||||||
|
*/
|
||||||
|
protected Remote lookupPeer(String name) throws CacheException {
|
||||||
|
try {
|
||||||
|
return registry.lookup(name);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CacheException("Unable to lookup peer for replicated cache " + name + " "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should be called on init because this is one of the last things that should happen on CacheManager startup.
|
||||||
|
*/
|
||||||
|
protected void populateListOfRemoteCachePeers() throws RemoteException {
|
||||||
|
String[] names = cacheManager.getCacheNames();
|
||||||
|
for (int i = 0; i < names.length; i++) {
|
||||||
|
String name = names[i];
|
||||||
|
Ehcache cache = cacheManager.getEhcache(name);
|
||||||
|
synchronized (cachePeers) {
|
||||||
|
if (cachePeers.get(name) == null) {
|
||||||
|
if (isDistributed(cache)) {
|
||||||
|
RMICachePeer peer = new RMICachePeer(cache, hostName, port, remoteObjectPort, socketTimeoutMillis);
|
||||||
|
cachePeers.put(name, peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the given cache is distributed.
|
||||||
|
*
|
||||||
|
* @param cache the cache to check
|
||||||
|
* @return true if a <code>CacheReplicator</code> is found in the listeners
|
||||||
|
*/
|
||||||
|
protected boolean isDistributed(Ehcache cache) {
|
||||||
|
Set listeners = cache.getCacheEventNotificationService().getCacheEventListeners();
|
||||||
|
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
|
||||||
|
CacheEventListener cacheEventListener = (CacheEventListener) iterator.next();
|
||||||
|
if (cacheEventListener instanceof CacheReplicator) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the rmiregistry.
|
||||||
|
* <p/>
|
||||||
|
* The alternative is to use the <code>rmiregistry</code> binary, in which case:
|
||||||
|
* <ol/>
|
||||||
|
* <li>rmiregistry running
|
||||||
|
* <li>-Djava.rmi.server.codebase="file:///Users/gluck/work/ehcache/build/classes/ file:///Users/gluck/work/ehcache/lib/commons-logging-1.0.4.jar"
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* @throws RemoteException
|
||||||
|
*/
|
||||||
|
protected void startRegistry() throws RemoteException {
|
||||||
|
try {
|
||||||
|
registry = LocateRegistry.getRegistry(port.intValue());
|
||||||
|
try {
|
||||||
|
//may not be created. Let's create it.
|
||||||
|
registry = LocateRegistry.createRegistry(port.intValue());
|
||||||
|
registryCreated = true;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
registry.list();
|
||||||
|
}
|
||||||
|
} catch (ExportException exception) {
|
||||||
|
LOG.log(Level.SEVERE, "Exception starting RMI registry. Error was " + exception.getMessage(), exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the rmiregistry if it was started by this class.
|
||||||
|
*
|
||||||
|
* @throws RemoteException
|
||||||
|
*/
|
||||||
|
protected void stopRegistry() throws RemoteException {
|
||||||
|
if (registryCreated) {
|
||||||
|
// the unexportObject call must be done on the Registry object returned
|
||||||
|
// by createRegistry not by getRegistry, a NoSuchObjectException is
|
||||||
|
// thrown otherwise
|
||||||
|
boolean success = UnicastRemoteObject.unexportObject(registry, true);
|
||||||
|
if (success) {
|
||||||
|
LOG.log(Level.FINE, "rmiregistry unexported.");
|
||||||
|
} else {
|
||||||
|
LOG.log(Level.WARNING, "Could not unexport rmiregistry.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the listener. It
|
||||||
|
* <ul>
|
||||||
|
* <li>unbinds the objects from the registry
|
||||||
|
* <li>unexports Remote objects
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public void dispose() throws CacheException {
|
||||||
|
if (!status.equals(Status.STATUS_ALIVE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
int counter = 0;
|
||||||
|
synchronized (cachePeers) {
|
||||||
|
for (Iterator iterator = cachePeers.values().iterator(); iterator.hasNext();) {
|
||||||
|
RMICachePeer rmiCachePeer = (RMICachePeer) iterator.next();
|
||||||
|
disposeRMICachePeer(rmiCachePeer);
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
stopRegistry();
|
||||||
|
}
|
||||||
|
LOG.log(Level.FINE, counter + " RMICachePeers unbound from registry in RMI listener");
|
||||||
|
status = Status.STATUS_SHUTDOWN;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CacheException("Problem unbinding remote cache peers. Initial cause was " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A template method to dispose an individual RMICachePeer. This consists of:
|
||||||
|
* <ol>
|
||||||
|
* <li>Unbinding the peer from the naming service
|
||||||
|
* <li>Unexporting the peer
|
||||||
|
* </ol>
|
||||||
|
* Override to specialise behaviour
|
||||||
|
*
|
||||||
|
* @param rmiCachePeer the cache peer to dispose of
|
||||||
|
* @throws Exception thrown if something goes wrong
|
||||||
|
*/
|
||||||
|
protected void disposeRMICachePeer(RMICachePeer rmiCachePeer) throws Exception {
|
||||||
|
unbind(rmiCachePeer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbinds an RMICachePeer and unexports it.
|
||||||
|
* <p/>
|
||||||
|
* We unbind from the registry first before unexporting.
|
||||||
|
* Unbinding first removes the very small possibility of a client
|
||||||
|
* getting the object from the registry while we are trying to unexport it.
|
||||||
|
* <p/>
|
||||||
|
* This method may take up to 4 seconds to complete, if we are having trouble
|
||||||
|
* unexporting the peer.
|
||||||
|
*
|
||||||
|
* @param rmiCachePeer the bound and exported cache peer
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected void unbind(RMICachePeer rmiCachePeer) throws Exception {
|
||||||
|
String url = rmiCachePeer.getUrl();
|
||||||
|
try {
|
||||||
|
Naming.unbind(url);
|
||||||
|
} catch (NotBoundException e) {
|
||||||
|
LOG.log(Level.WARNING, url + " not bound therefore not unbinding.");
|
||||||
|
}
|
||||||
|
// Try to gracefully unexport before forcing it.
|
||||||
|
boolean unexported = UnicastRemoteObject.unexportObject(rmiCachePeer, false);
|
||||||
|
for (int count = 1; (count < NAMING_UNBIND_MAX_RETRIES) && !unexported; count++) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(NAMING_UNBIND_RETRY_INTERVAL);
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
// break out of the unexportObject loop
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
unexported = UnicastRemoteObject.unexportObject(rmiCachePeer, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we still haven't been able to unexport, force the unexport
|
||||||
|
// as a last resort.
|
||||||
|
if (!unexported) {
|
||||||
|
if (!UnicastRemoteObject.unexportObject(rmiCachePeer, true)) {
|
||||||
|
LOG.log(Level.WARNING, "Unable to unexport rmiCachePeer: " + rmiCachePeer.getUrl() + ". Skipping.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All of the caches which are listening for remote changes.
|
||||||
|
*
|
||||||
|
* @return a list of <code>RMICachePeer</code> objects. The list if not live
|
||||||
|
*/
|
||||||
|
public List getBoundCachePeers() {
|
||||||
|
List cachePeerList = new ArrayList();
|
||||||
|
synchronized (cachePeers) {
|
||||||
|
for (Iterator iterator = cachePeers.values().iterator(); iterator.hasNext();) {
|
||||||
|
RMICachePeer rmiCachePeer = (RMICachePeer) iterator.next();
|
||||||
|
cachePeerList.add(rmiCachePeer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cachePeerList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the listener status.
|
||||||
|
*/
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A listener will normally have a resource that only one instance can use at the same time,
|
||||||
|
* such as a port. This identifier is used to tell if it is unique and will not conflict with an
|
||||||
|
* existing instance using the resource.
|
||||||
|
*
|
||||||
|
* @return a String identifier for the resource
|
||||||
|
*/
|
||||||
|
public String getUniqueResourceIdentifier() {
|
||||||
|
return "RMI listener port: " + port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a conflict is detected in unique resource use, this method signals the listener to attempt
|
||||||
|
* automatic resolution of the resource conflict.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if the statis of the listener is not {@link net.sf.ehcache.Status#STATUS_UNINITIALISED}
|
||||||
|
*/
|
||||||
|
public void attemptResolutionOfUniqueResourceConflict() throws IllegalStateException, CacheException {
|
||||||
|
assignFreePort(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The replication scheme this listener interacts with.
|
||||||
|
* Each peer provider has a scheme name, which can be used by caches to specify for replication and bootstrap purposes.
|
||||||
|
*
|
||||||
|
* @return the well-known scheme name, which is determined by the replication provider author.
|
||||||
|
*/
|
||||||
|
public String getScheme() {
|
||||||
|
return "RMI";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called immediately after a cache has been added and activated.
|
||||||
|
* <p/>
|
||||||
|
* Note that the CacheManager calls this method from a synchronized method. Any attempt to call a synchronized
|
||||||
|
* method on CacheManager from this method will cause a deadlock.
|
||||||
|
* <p/>
|
||||||
|
* Note that activation will also cause a CacheEventListener status change notification from
|
||||||
|
* {@link net.sf.ehcache.Status#STATUS_UNINITIALISED} to {@link net.sf.ehcache.Status#STATUS_ALIVE}. Care should be
|
||||||
|
* taken on processing that notification because:
|
||||||
|
* <ul>
|
||||||
|
* <li>the cache will not yet be accessible from the CacheManager.
|
||||||
|
* <li>the addCaches methods whih cause this notification are synchronized on the CacheManager. An attempt to call
|
||||||
|
* {@link net.sf.ehcache.CacheManager#getCache(String)} will cause a deadlock.
|
||||||
|
* </ul>
|
||||||
|
* The calling method will block until this method returns.
|
||||||
|
* <p/>
|
||||||
|
* Repopulates the list of cache peers and rebinds the list.
|
||||||
|
* This method should be called if a cache is dynamically added
|
||||||
|
*
|
||||||
|
* @param cacheName the name of the <code>Cache</code> the operation relates to
|
||||||
|
* @see net.sf.ehcache.event.CacheEventListener
|
||||||
|
*/
|
||||||
|
public void notifyCacheAdded(String cacheName) throws CacheException {
|
||||||
|
|
||||||
|
if (LOG.isLoggable(Level.FINE)) {
|
||||||
|
LOG.log(Level.FINE, "Adding " + cacheName + " to RMI listener");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Don't add if exists.
|
||||||
|
synchronized (cachePeers) {
|
||||||
|
if (cachePeers.get(cacheName) != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ehcache cache = cacheManager.getEhcache(cacheName);
|
||||||
|
if (isDistributed(cache)) {
|
||||||
|
RMICachePeer rmiCachePeer = null;
|
||||||
|
String url = null;
|
||||||
|
try {
|
||||||
|
rmiCachePeer = new RMICachePeer(cache, hostName, port, remoteObjectPort, socketTimeoutMillis);
|
||||||
|
url = rmiCachePeer.getUrl();
|
||||||
|
bind(url, rmiCachePeer);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CacheException("Problem starting listener for RMICachePeer "
|
||||||
|
+ url + ". Initial cause was " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (cachePeers) {
|
||||||
|
cachePeers.put(cacheName, rmiCachePeer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (LOG.isLoggable(Level.FINE)) {
|
||||||
|
LOG.log(Level.FINE, cachePeers.size() + " RMICachePeers bound in registry for RMI listener");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called immediately after a cache has been disposed and removed. The calling method will block until
|
||||||
|
* this method returns.
|
||||||
|
* <p/>
|
||||||
|
* Note that the CacheManager calls this method from a synchronized method. Any attempt to call a synchronized
|
||||||
|
* method on CacheManager from this method will cause a deadlock.
|
||||||
|
* <p/>
|
||||||
|
* Note that a {@link net.sf.ehcache.event.CacheEventListener} status changed will also be triggered. Any attempt from that notification
|
||||||
|
* to access CacheManager will also result in a deadlock.
|
||||||
|
*
|
||||||
|
* @param cacheName the name of the <code>Cache</code> the operation relates to
|
||||||
|
*/
|
||||||
|
public void notifyCacheRemoved(String cacheName) {
|
||||||
|
|
||||||
|
if (LOG.isLoggable(Level.FINE)) {
|
||||||
|
LOG.log(Level.FINE, "Removing " + cacheName + " from RMI listener");
|
||||||
|
}
|
||||||
|
|
||||||
|
//don't remove if already removed.
|
||||||
|
synchronized (cachePeers) {
|
||||||
|
if (cachePeers.get(cacheName) == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RMICachePeer rmiCachePeer;
|
||||||
|
synchronized (cachePeers) {
|
||||||
|
rmiCachePeer = (RMICachePeer) cachePeers.remove(cacheName);
|
||||||
|
}
|
||||||
|
String url = null;
|
||||||
|
try {
|
||||||
|
unbind(rmiCachePeer);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CacheException("Error removing Cache Peer "
|
||||||
|
+ url + " from listener. Message was: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LOG.isLoggable(Level.FINE)) {
|
||||||
|
LOG.log(Level.FINE, cachePeers.size() + " RMICachePeers bound in registry for RMI listener");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Package local method for testing
|
||||||
|
*/
|
||||||
|
void addCachePeer(String name, RMICachePeer peer) {
|
||||||
|
synchronized (cachePeers) {
|
||||||
|
cachePeers.put(name, peer);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.tuscany.sca.endpoint.ehcache;
|
||||||
|
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import net.sf.ehcache.CacheException;
|
||||||
|
import net.sf.ehcache.CacheManager;
|
||||||
|
import net.sf.ehcache.distribution.CacheManagerPeerListener;
|
||||||
|
import net.sf.ehcache.distribution.CacheManagerPeerListenerFactory;
|
||||||
|
import net.sf.ehcache.distribution.RMICacheManagerPeerListener;
|
||||||
|
import net.sf.ehcache.util.PropertyUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a listener based on RMI.
|
||||||
|
* <p/>
|
||||||
|
* Expected configuration line:
|
||||||
|
* <p/>
|
||||||
|
* <code>
|
||||||
|
* <cachePeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
|
||||||
|
* properties="hostName=localhost, port=5000" />
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @author Greg Luck
|
||||||
|
* @version $Id: RMICacheManagerPeerListenerFactory.java 1012 2009-08-20 04:23:00Z gregluck $
|
||||||
|
*/
|
||||||
|
public class TuscanyRMICacheManagerPeerListenerFactory extends CacheManagerPeerListenerFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default timeout for cache replication for a single replication action.
|
||||||
|
* This may need to be increased for large data transfers.
|
||||||
|
*/
|
||||||
|
public static final Integer DEFAULT_SOCKET_TIMEOUT_MILLIS = new Integer(120000);
|
||||||
|
|
||||||
|
private static final String HOSTNAME = "hostName";
|
||||||
|
private static final String PORT = "port";
|
||||||
|
private static final String REMOTE_OBJECT_PORT = "remoteObjectPort";
|
||||||
|
private static final String SOCKET_TIMEOUT_MILLIS = "socketTimeoutMillis";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param properties implementation specific properties. These are configured as comma
|
||||||
|
* separated name value pairs in ehcache.xml
|
||||||
|
*/
|
||||||
|
public final CacheManagerPeerListener createCachePeerListener(CacheManager cacheManager, Properties properties)
|
||||||
|
throws CacheException {
|
||||||
|
String hostName = PropertyUtil.extractAndLogProperty(HOSTNAME, properties);
|
||||||
|
|
||||||
|
String portString = PropertyUtil.extractAndLogProperty(PORT, properties);
|
||||||
|
Integer port = null;
|
||||||
|
if (portString != null && portString.length() != 0) {
|
||||||
|
port = new Integer(portString);
|
||||||
|
} else {
|
||||||
|
port = new Integer(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//0 means any port in UnicastRemoteObject, so it is ok if not specified to make it 0
|
||||||
|
String remoteObjectPortString = PropertyUtil.extractAndLogProperty(REMOTE_OBJECT_PORT, properties);
|
||||||
|
Integer remoteObjectPort = null;
|
||||||
|
if (remoteObjectPortString != null && remoteObjectPortString.length() != 0) {
|
||||||
|
remoteObjectPort = new Integer(remoteObjectPortString);
|
||||||
|
} else {
|
||||||
|
remoteObjectPort = new Integer(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
String socketTimeoutMillisString = PropertyUtil.extractAndLogProperty(SOCKET_TIMEOUT_MILLIS, properties);
|
||||||
|
Integer socketTimeoutMillis;
|
||||||
|
if (socketTimeoutMillisString == null || socketTimeoutMillisString.length() == 0) {
|
||||||
|
socketTimeoutMillis = DEFAULT_SOCKET_TIMEOUT_MILLIS;
|
||||||
|
} else {
|
||||||
|
socketTimeoutMillis = new Integer(socketTimeoutMillisString);
|
||||||
|
}
|
||||||
|
return doCreateCachePeerListener(hostName, port, remoteObjectPort, cacheManager, socketTimeoutMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A template method to actually create the factory
|
||||||
|
*
|
||||||
|
* @param hostName
|
||||||
|
* @param port
|
||||||
|
* @param remoteObjectPort
|
||||||
|
* @param cacheManager
|
||||||
|
* @param socketTimeoutMillis @return a crate CacheManagerPeerListener
|
||||||
|
*/
|
||||||
|
protected CacheManagerPeerListener doCreateCachePeerListener(String hostName,
|
||||||
|
Integer port,
|
||||||
|
Integer remoteObjectPort,
|
||||||
|
CacheManager cacheManager,
|
||||||
|
Integer socketTimeoutMillis) {
|
||||||
|
try {
|
||||||
|
return new TuscanyRMICacheManagerPeerListener(hostName, port, remoteObjectPort, cacheManager, socketTimeoutMillis);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new CacheException("Unable to create CacheManagerPeerListener. Initial cause was " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
org.apache.tuscany.sca.endpoint.tribes.ReplicatedEndpointRegistry;ranking=150,address=228.0.0.100,port=50000,timeout=50,scheme=tribes
|
||||||
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.tuscany.sca.endpoint.tribes;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
import net.sf.ehcache.Cache;
|
||||||
|
import net.sf.ehcache.CacheManager;
|
||||||
|
import net.sf.ehcache.Ehcache;
|
||||||
|
import net.sf.ehcache.Element;
|
||||||
|
import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
|
||||||
|
import net.sf.ehcache.config.CacheConfiguration;
|
||||||
|
import net.sf.ehcache.config.Configuration;
|
||||||
|
import net.sf.ehcache.config.ConfigurationHelper;
|
||||||
|
import net.sf.ehcache.config.FactoryConfiguration;
|
||||||
|
import net.sf.ehcache.config.TerracottaConfiguration;
|
||||||
|
import net.sf.ehcache.distribution.CacheManagerPeerProvider;
|
||||||
|
import net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory;
|
||||||
|
import net.sf.ehcache.distribution.RMICacheManagerPeerListener;
|
||||||
|
import net.sf.ehcache.distribution.RMICacheReplicatorFactory;
|
||||||
|
import net.sf.ehcache.event.CacheEventListener;
|
||||||
|
import net.sf.ehcache.event.RegisteredEventListeners;
|
||||||
|
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class RegistryTestCase {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void foo() throws InterruptedException {
|
||||||
|
Cache cache2 = createCache2("ehcache2.xml");
|
||||||
|
// Thread.sleep(4000);
|
||||||
|
Cache cache1 = createCache2("ehcache1.xml");
|
||||||
|
cache1.put(new Element("key1", "bla1"));
|
||||||
|
Thread.sleep(400);
|
||||||
|
|
||||||
|
Assert.assertEquals("bla1", cache2.get("key1").getObjectValue());
|
||||||
|
cache2.put(new Element("k2", "foo2"));
|
||||||
|
Thread.sleep(400);
|
||||||
|
Assert.assertEquals("foo2", cache1.get("k2").getObjectValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cache createCache2(String file) {
|
||||||
|
CacheManager manager = new CacheManager("target/test-classes/" + file);
|
||||||
|
Cache test = manager.getCache("sampleDistributedCache1");
|
||||||
|
|
||||||
|
manager.addCache("foo");
|
||||||
|
Cache test2 = manager.getCache("foo");
|
||||||
|
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
|
// final Ehcache createCache(CacheConfiguration cacheConfiguration) {
|
||||||
|
// boolean terracottaClustered = false;
|
||||||
|
// String terracottaValueMode = null;
|
||||||
|
// boolean terracottaCoherentReads = true;
|
||||||
|
// TerracottaConfiguration tcConfiguration = cacheConfiguration.getTerracottaConfiguration();
|
||||||
|
// if (tcConfiguration != null) {
|
||||||
|
// terracottaClustered = tcConfiguration.isClustered();
|
||||||
|
// terracottaValueMode = tcConfiguration.getValueMode().name();
|
||||||
|
// terracottaCoherentReads = tcConfiguration.getCoherentReads();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Ehcache cache = new Cache(cacheConfiguration.name,
|
||||||
|
// cacheConfiguration.maxElementsInMemory,
|
||||||
|
// cacheConfiguration.memoryStoreEvictionPolicy,
|
||||||
|
// cacheConfiguration.overflowToDisk,
|
||||||
|
// getDiskStorePath(),
|
||||||
|
// cacheConfiguration.eternal,
|
||||||
|
// cacheConfiguration.timeToLiveSeconds,
|
||||||
|
// cacheConfiguration.timeToIdleSeconds,
|
||||||
|
// cacheConfiguration.diskPersistent,
|
||||||
|
// cacheConfiguration.diskExpiryThreadIntervalSeconds,
|
||||||
|
// null,
|
||||||
|
// null,
|
||||||
|
// cacheConfiguration.maxElementsOnDisk,
|
||||||
|
// cacheConfiguration.diskSpoolBufferSizeMB,
|
||||||
|
// cacheConfiguration.clearOnFlush,
|
||||||
|
// terracottaClustered,
|
||||||
|
// terracottaValueMode,
|
||||||
|
// terracottaCoherentReads);
|
||||||
|
// RegisteredEventListeners listeners = cache.getCacheEventNotificationService();
|
||||||
|
// registerCacheListeners(cacheConfiguration, listeners);
|
||||||
|
// registerCacheExtensions(cacheConfiguration, cache);
|
||||||
|
// BootstrapCacheLoader bootstrapCacheLoader = createBootstrapCacheLoader(
|
||||||
|
// cacheConfiguration.getBootstrapCacheLoaderFactoryConfiguration());
|
||||||
|
// cache.setBootstrapCacheLoader(bootstrapCacheLoader);
|
||||||
|
// registerCacheLoaders(cacheConfiguration, cache);
|
||||||
|
// cache = applyCacheExceptionHandler(cacheConfiguration, cache);
|
||||||
|
// return cache;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private Ehcache create(CacheManager manager, String name) {
|
||||||
|
// ConfigurationHelper ch = new ConfigurationHelper(manager, null);
|
||||||
|
// CacheConfiguration cc = new CacheConfiguration();
|
||||||
|
// cc.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Ehcache cache = new Cache(name,
|
||||||
|
// 10000,
|
||||||
|
// MemoryStoreEvictionPolicy.LRU,
|
||||||
|
// false,
|
||||||
|
// "",
|
||||||
|
// true,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// false,
|
||||||
|
// 0,
|
||||||
|
// null,
|
||||||
|
// null,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// false,
|
||||||
|
// false,
|
||||||
|
// null,
|
||||||
|
// false);
|
||||||
|
// RegisteredEventListeners listeners = cache.getCacheEventNotificationService();
|
||||||
|
// Properties properties = new Properties();
|
||||||
|
// properties.put("asynchronousReplicationIntervalMillis", "100");
|
||||||
|
// listeners.registerListener(new RMICacheReplicatorFactory().createCacheEventListener(properties));
|
||||||
|
//// registerCacheListeners(cacheConfiguration, listeners);
|
||||||
|
//// registerCacheExtensions(cacheConfiguration, cache);
|
||||||
|
// cache.setBootstrapCacheLoader(new RMIBootstrapCacheLoaderFactory().createBootstrapCacheLoader(null));
|
||||||
|
//// registerCacheLoaders(cacheConfiguration, cache);
|
||||||
|
// // cache = applyCacheExceptionHandler(cacheConfiguration, cache);
|
||||||
|
// return cache;
|
||||||
|
// }
|
||||||
|
|
||||||
|
private Cache createCache(int port, boolean multicast, String remotes) {
|
||||||
|
Configuration config = new Configuration();
|
||||||
|
|
||||||
|
if (remotes != null && remotes.length() > 0) {
|
||||||
|
FactoryConfiguration factory = new FactoryConfiguration();
|
||||||
|
factory.setClass("net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory");
|
||||||
|
factory.setPropertySeparator(",");
|
||||||
|
factory.setProperties("peerDiscovery=manual,rmiUrls=//" + remotes);
|
||||||
|
config.addCacheManagerPeerProviderFactory(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <cacheManagerPeerProviderFactory
|
||||||
|
// class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
|
||||||
|
// properties="peerDiscovery=automatic,
|
||||||
|
// multicastGroupAddress=230.0.0.1,
|
||||||
|
// multicastGroupPort=4446, timeToLive=1"/>
|
||||||
|
//-->
|
||||||
|
|
||||||
|
if (multicast) {
|
||||||
|
FactoryConfiguration factory = new FactoryConfiguration();
|
||||||
|
factory.setClass("net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory");
|
||||||
|
factory.setPropertySeparator(",");
|
||||||
|
factory.setProperties("peerDiscovery=automatic,multicastGroupAddress=230.0.0.1,multicastGroupPort=4446,timeToLive=1");
|
||||||
|
config.addCacheManagerPeerProviderFactory(factory);
|
||||||
|
}
|
||||||
|
RMICacheManagerPeerListener xxx;
|
||||||
|
FactoryConfiguration factoryx = new FactoryConfiguration();
|
||||||
|
factoryx.setClass("net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory");
|
||||||
|
factoryx.setPropertySeparator(",");
|
||||||
|
factoryx.setProperties("hostname=192.168.0.101,port=" + port);
|
||||||
|
config.addCacheManagerPeerListenerFactory(factoryx);
|
||||||
|
|
||||||
|
CacheConfiguration defaultCacheConfiguration = new CacheConfiguration();
|
||||||
|
defaultCacheConfiguration.setDiskPersistent(false);
|
||||||
|
config.setDefaultCacheConfiguration(defaultCacheConfiguration);
|
||||||
|
CacheManager singletonManager = new CacheManager(config);
|
||||||
|
CacheManagerPeerProvider pp = singletonManager.getCacheManagerPeerProvider("RMI");
|
||||||
|
Cache memoryOnlyCache = new Cache("testCache", 5000, false, false, 5, 2);
|
||||||
|
// CacheEventListener cacheEventListener = new CacheEventListener();
|
||||||
|
// memoryOnlyCache.getCacheEventNotificationService().registerListener(cacheEventListener);
|
||||||
|
singletonManager.addCache(memoryOnlyCache);
|
||||||
|
Cache test = singletonManager.getCache("testCache");
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
741
sandbox/endpoint-ehcache/src/test/resources/ehcache.xml
Normal file
741
sandbox/endpoint-ehcache/src/test/resources/ehcache.xml
Normal file
|
|
@ -0,0 +1,741 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
CacheManager Configuration
|
||||||
|
==========================
|
||||||
|
An ehcache.xml corresponds to a single CacheManager.
|
||||||
|
|
||||||
|
See instructions below or the ehcache schema (ehcache.xsd) on how to configure.
|
||||||
|
|
||||||
|
System property tokens can be specified in this file which are replaced when the configuration
|
||||||
|
is loaded. For example multicastGroupPort=${multicastGroupPort} can be replaced with the
|
||||||
|
System property either from an environment variable or a system property specified with a
|
||||||
|
command line switch such as -DmulticastGroupPort=4446.
|
||||||
|
|
||||||
|
The attributes of <ehcache> are:
|
||||||
|
* name - an optional name for the CacheManager. The name is optional and primarily used
|
||||||
|
for documentation or to distinguish Terracotta clustered cache state. With Terracotta
|
||||||
|
clustered caches, a combination of CacheManager name and cache name uniquely identify a
|
||||||
|
particular cache store in the Terracotta clustered memory.
|
||||||
|
* updateCheck - an optional boolean flag specifying whether this CacheManager should check
|
||||||
|
for new versions of Ehcache over the Internet. If not specified, updateCheck="true".
|
||||||
|
* monitoring - an optional setting that determines whether the CacheManager should
|
||||||
|
automatically register the SampledCacheMBean with the system MBean server.
|
||||||
|
|
||||||
|
Currently, this monitoring is only useful when using Terracotta clustering and using the
|
||||||
|
Terracotta Developer Console. With the "autodetect" value, the presence of Terracotta clustering
|
||||||
|
will be detected and monitoring, via the Developer Console, will be enabled. Other allowed values
|
||||||
|
are "on" and "off". The default is "autodetect". This setting does not perform any function when
|
||||||
|
used with JMX monitors.
|
||||||
|
-->
|
||||||
|
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="ehcache.xsd"
|
||||||
|
updateCheck="true" monitoring="autodetect">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
DiskStore configuration
|
||||||
|
=======================
|
||||||
|
|
||||||
|
The diskStore element is optional. To turn off disk store path creation, comment out the diskStore
|
||||||
|
element below.
|
||||||
|
|
||||||
|
Configure it if you have overflowToDisk or diskPersistent enabled for any cache.
|
||||||
|
|
||||||
|
If it is not configured, and a cache is created which requires a disk store, a warning will be
|
||||||
|
issued and java.io.tmpdir will automatically be used.
|
||||||
|
|
||||||
|
diskStore has only one attribute - "path". It is the path to the directory where
|
||||||
|
.data and .index files will be created.
|
||||||
|
|
||||||
|
If the path is one of the following Java System Property it is replaced by its value in the
|
||||||
|
running VM. For backward compatibility these are not specified without being enclosed in the ${token}
|
||||||
|
replacement syntax.
|
||||||
|
|
||||||
|
The following properties are translated:
|
||||||
|
* user.home - User's home directory
|
||||||
|
* user.dir - User's current working directory
|
||||||
|
* java.io.tmpdir - Default temp file path
|
||||||
|
* ehcache.disk.store.dir - A system property you would normally specify on the command line
|
||||||
|
e.g. java -Dehcache.disk.store.dir=/u01/myapp/diskdir ...
|
||||||
|
|
||||||
|
Subdirectories can be specified below the property e.g. java.io.tmpdir/one
|
||||||
|
|
||||||
|
-->
|
||||||
|
<diskStore path="java.io.tmpdir"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
CacheManagerEventListener
|
||||||
|
=========================
|
||||||
|
Specifies a CacheManagerEventListenerFactory which is notified when Caches are added
|
||||||
|
or removed from the CacheManager.
|
||||||
|
|
||||||
|
The attributes of CacheManagerEventListenerFactory are:
|
||||||
|
* class - a fully qualified factory class name
|
||||||
|
* properties - comma separated properties having meaning only to the factory.
|
||||||
|
|
||||||
|
Sets the fully qualified class name to be registered as the CacheManager event listener.
|
||||||
|
|
||||||
|
The events include:
|
||||||
|
* adding a Cache
|
||||||
|
* removing a Cache
|
||||||
|
|
||||||
|
Callbacks to listener methods are synchronous and unsynchronized. It is the responsibility
|
||||||
|
of the implementer to safely handle the potential performance and thread safety issues
|
||||||
|
depending on what their listener is doing.
|
||||||
|
|
||||||
|
If no class is specified, no listener is created. There is no default.
|
||||||
|
-->
|
||||||
|
<cacheManagerEventListenerFactory class="" properties=""/>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
CacheManagerPeerProvider
|
||||||
|
========================
|
||||||
|
(For distributed operation)
|
||||||
|
|
||||||
|
Specifies a CacheManagerPeerProviderFactory which will be used to create a
|
||||||
|
CacheManagerPeerProvider, which discovers other CacheManagers in the cluster.
|
||||||
|
|
||||||
|
One or more providers can be configured. The first one in the ehcache.xml is the default, which is used
|
||||||
|
for replication and bootstrapping.
|
||||||
|
|
||||||
|
The attributes of cacheManagerPeerProviderFactory are:
|
||||||
|
* class - a fully qualified factory class name
|
||||||
|
* properties - comma separated properties having meaning only to the factory.
|
||||||
|
|
||||||
|
Providers are available for RMI, JGroups and JMS as shown following.
|
||||||
|
|
||||||
|
RMICacheManagerPeerProvider
|
||||||
|
+++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
Ehcache comes with a built-in RMI-based distribution system with two means of discovery of
|
||||||
|
CacheManager peers participating in the cluster:
|
||||||
|
* automatic, using a multicast group. This one automatically discovers peers and detects
|
||||||
|
changes such as peers entering and leaving the group
|
||||||
|
* manual, using manual rmiURL configuration. A hardcoded list of peers is provided at
|
||||||
|
configuration time.
|
||||||
|
|
||||||
|
Configuring Automatic Discovery:
|
||||||
|
Automatic discovery is configured as per the following example:
|
||||||
|
<cacheManagerPeerProviderFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
|
||||||
|
properties="hostName=fully_qualified_hostname_or_ip,
|
||||||
|
peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
|
||||||
|
multicastGroupPort=4446, timeToLive=32"/>
|
||||||
|
|
||||||
|
Valid properties are:
|
||||||
|
* peerDiscovery (mandatory) - specify "automatic"
|
||||||
|
* multicastGroupAddress (mandatory) - specify a valid multicast group address
|
||||||
|
* multicastGroupPort (mandatory) - specify a dedicated port for the multicast heartbeat
|
||||||
|
traffic
|
||||||
|
* timeToLive - specify a value between 0 and 255 which determines how far the packets will
|
||||||
|
propagate.
|
||||||
|
|
||||||
|
By convention, the restrictions are:
|
||||||
|
0 - the same host
|
||||||
|
1 - the same subnet
|
||||||
|
32 - the same site
|
||||||
|
64 - the same region
|
||||||
|
128 - the same continent
|
||||||
|
255 - unrestricted
|
||||||
|
|
||||||
|
* hostName - the hostname or IP of the interface to be used for sending and receiving multicast packets
|
||||||
|
(relevant to mulithomed hosts only)
|
||||||
|
|
||||||
|
Configuring Manual Discovery:
|
||||||
|
Manual discovery requires a unique configuration per host. It is contains a list of rmiURLs for the peers, other
|
||||||
|
than itself. So, if we have server1, server2 and server3 the configuration will be:
|
||||||
|
|
||||||
|
In server1's configuration:
|
||||||
|
<cacheManagerPeerProviderFactory class=
|
||||||
|
"net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
|
||||||
|
properties="peerDiscovery=manual,
|
||||||
|
rmiUrls=//server2:40000/sampleCache1|//server3:40000/sampleCache1
|
||||||
|
| //server2:40000/sampleCache2|//server3:40000/sampleCache2"
|
||||||
|
propertySeparator="," />
|
||||||
|
|
||||||
|
In server2's configuration:
|
||||||
|
<cacheManagerPeerProviderFactory class=
|
||||||
|
"net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
|
||||||
|
properties="peerDiscovery=manual,
|
||||||
|
rmiUrls=//server1:40000/sampleCache1|//server3:40000/sampleCache1
|
||||||
|
| //server1:40000/sampleCache2|//server3:40000/sampleCache2"
|
||||||
|
propertySeparator="," />
|
||||||
|
|
||||||
|
In server3's configuration:
|
||||||
|
<cacheManagerPeerProviderFactory class=
|
||||||
|
"net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
|
||||||
|
properties="peerDiscovery=manual,
|
||||||
|
rmiUrls=//server1:40000/sampleCache1|//server2:40000/sampleCache1
|
||||||
|
| //server1:40000/sampleCache2|//server2:40000/sampleCache2"
|
||||||
|
propertySeparator="," />
|
||||||
|
|
||||||
|
|
||||||
|
Valid properties are:
|
||||||
|
* peerDiscovery (mandatory) - specify "manual"
|
||||||
|
* rmiUrls (mandatory) - specify a pipe separated list of rmiUrls, in the form
|
||||||
|
//hostname:port
|
||||||
|
* hostname (optional) - the hostname is the hostname of the remote CacheManager peer. The port is the listening
|
||||||
|
port of the RMICacheManagerPeerListener of the remote CacheManager peer.
|
||||||
|
|
||||||
|
JGroupsCacheManagerPeerProvider
|
||||||
|
+++++++++++++++++++++++++++++++
|
||||||
|
<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
|
||||||
|
properties="connect=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;
|
||||||
|
mcast_send_buf_size=150000;mcast_recv_buf_size=80000):
|
||||||
|
PING(timeout=2000;num_initial_members=6):
|
||||||
|
MERGE2(min_interval=5000;max_interval=10000):
|
||||||
|
FD_SOCK:VERIFY_SUSPECT(timeout=1500):
|
||||||
|
pbcast.NAKACK(gc_lag=10;retransmit_timeout=3000):
|
||||||
|
UNICAST(timeout=5000):
|
||||||
|
pbcast.STABLE(desired_avg_gossip=20000):
|
||||||
|
FRAG:
|
||||||
|
pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=false)"
|
||||||
|
propertySeparator="::"
|
||||||
|
/>
|
||||||
|
The only property necessary is the connect String used by jgroups to configure itself. Refer to the Jgroups documentation for explanation
|
||||||
|
of all the protocols. The example above uses UDP multicast. If the connect property is not specified the default JGroups connection will be
|
||||||
|
used.
|
||||||
|
|
||||||
|
|
||||||
|
JMSCacheManagerPeerProviderFactory
|
||||||
|
++++++++++++++++++++++++++++++++++
|
||||||
|
<cacheManagerPeerProviderFactory
|
||||||
|
class="net.sf.ehcache.distribution.jms.JMSCacheManagerPeerProviderFactory"
|
||||||
|
properties="..."
|
||||||
|
propertySeparator=","
|
||||||
|
/>
|
||||||
|
|
||||||
|
The JMS PeerProviderFactory uses JNDI to maintain message queue independence. Refer to the manual for full configuration
|
||||||
|
examples using ActiveMQ and Open Message Queue.
|
||||||
|
|
||||||
|
Valid properties are:
|
||||||
|
* initialContextFactoryName (mandatory) - the name of the factory used to create the message queue initial context.
|
||||||
|
* providerURL (mandatory) - the JNDI configuration information for the service provider to use.
|
||||||
|
* topicConnectionFactoryBindingName (mandatory) - the JNDI binding name for the TopicConnectionFactory
|
||||||
|
* topicBindingName (mandatory) - the JNDI binding name for the topic name
|
||||||
|
* getQueueBindingName (mandatory only if using jmsCacheLoader) - the JNDI binding name for the queue name
|
||||||
|
* securityPrincipalName - the JNDI java.naming.security.principal
|
||||||
|
* securityCredentials - the JNDI java.naming.security.credentials
|
||||||
|
* urlPkgPrefixes - the JNDI java.naming.factory.url.pkgs
|
||||||
|
* userName - the user name to use when creating the TopicConnection to the Message Queue
|
||||||
|
* password - the password to use when creating the TopicConnection to the Message Queue
|
||||||
|
* acknowledgementMode - the JMS Acknowledgement mode for both publisher and subscriber. The available choices are
|
||||||
|
AUTO_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE and SESSION_TRANSACTED. The default is AUTO_ACKNOWLEDGE.
|
||||||
|
-->
|
||||||
|
<cacheManagerPeerProviderFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
|
||||||
|
properties="peerDiscovery=automatic,
|
||||||
|
multicastGroupAddress=230.0.0.1,
|
||||||
|
multicastGroupPort=4446, timeToLive=1"
|
||||||
|
propertySeparator=","
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
CacheManagerPeerListener
|
||||||
|
========================
|
||||||
|
(Enable for distributed operation)
|
||||||
|
|
||||||
|
Specifies a CacheManagerPeerListenerFactory which will be used to create a
|
||||||
|
CacheManagerPeerListener, which listens for messages from cache replicators participating in the cluster.
|
||||||
|
|
||||||
|
The attributes of cacheManagerPeerListenerFactory are:
|
||||||
|
class - a fully qualified factory class name
|
||||||
|
properties - comma separated properties having meaning only to the factory.
|
||||||
|
|
||||||
|
Ehcache comes with a built-in RMI-based distribution system. The listener component is
|
||||||
|
RMICacheManagerPeerListener which is configured using
|
||||||
|
RMICacheManagerPeerListenerFactory. It is configured as per the following example:
|
||||||
|
|
||||||
|
<cacheManagerPeerListenerFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
|
||||||
|
properties="hostName=fully_qualified_hostname_or_ip,
|
||||||
|
port=40001,
|
||||||
|
remoteObjectPort=40002,
|
||||||
|
socketTimeoutMillis=120000"
|
||||||
|
propertySeparator="," />
|
||||||
|
|
||||||
|
All properties are optional. They are:
|
||||||
|
* hostName - the hostName of the host the listener is running on. Specify
|
||||||
|
where the host is multihomed and you want to control the interface over which cluster
|
||||||
|
messages are received. Defaults to the host name of the default interface if not
|
||||||
|
specified.
|
||||||
|
* port - the port the RMI Registry listener listens on. This defaults to a free port if not specified.
|
||||||
|
* remoteObjectPort - the port number on which the remote objects bound in the registry receive calls.
|
||||||
|
This defaults to a free port if not specified.
|
||||||
|
* socketTimeoutMillis - the number of ms client sockets will stay open when sending
|
||||||
|
messages to the listener. This should be long enough for the slowest message.
|
||||||
|
If not specified it defaults to 120000ms.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<cacheManagerPeerListenerFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
TerracottaConfig
|
||||||
|
========================
|
||||||
|
(Enable for Terracotta clustered operation)
|
||||||
|
|
||||||
|
Note: You need to install and run one or more Terracotta servers to use Terracotta clustering.
|
||||||
|
See http://www.terracotta.org/web/display/orgsite/Download.
|
||||||
|
|
||||||
|
Specifies a TerracottaConfig which will be used to configure the Terracotta
|
||||||
|
runtime for this CacheManager.
|
||||||
|
|
||||||
|
Configuration can be specified in two main ways: by reference to a source of
|
||||||
|
configuration or by use of an embedded Terracotta configuration file.
|
||||||
|
|
||||||
|
To specify a reference to a source (or sources) of configuration, use the url
|
||||||
|
attribute. The url attribute must contain a comma-separated list of:
|
||||||
|
* path to Terracotta configuration file (usually named tc-config.xml)
|
||||||
|
* URL to Terracotta configuration file
|
||||||
|
* <server host>:<port> of running Terracotta Server instance
|
||||||
|
|
||||||
|
Simplest example for pointing to a Terracotta server on this machine:
|
||||||
|
<terracottaConfig url="localhost:9510"/>
|
||||||
|
|
||||||
|
Example using a path to Terracotta configuration file:
|
||||||
|
<terracottaConfig url="/app/config/tc-config.xml"/>
|
||||||
|
|
||||||
|
Example using a URL to a Terracotta configuration file:
|
||||||
|
<terracottaConfig url="http://internal/ehcache/app/tc-config.xml"/>
|
||||||
|
|
||||||
|
Example using multiple Terracotta server instance URLs (for fault tolerance):
|
||||||
|
<terracottaConfig url="host1:9510,host2:9510,host3:9510"/>
|
||||||
|
|
||||||
|
To embed a Terracotta configuration file within the ehcache configuration, simply
|
||||||
|
place a normal Terracotta XML config within the <terracottaConfig> element.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
<terracottaConfig>
|
||||||
|
<tc-config>
|
||||||
|
<servers>
|
||||||
|
<server host="server1" name="s1"/>
|
||||||
|
<server host="server2" name="s2"/>
|
||||||
|
</servers>
|
||||||
|
<clients>
|
||||||
|
<logs>app/logs-%i</logs>
|
||||||
|
</clients>
|
||||||
|
</tc-config>
|
||||||
|
</terracottaConfig>
|
||||||
|
|
||||||
|
For more information on the Terracotta configuration, see the Terracotta documentation.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Cache configuration
|
||||||
|
===================
|
||||||
|
|
||||||
|
The following attributes are required.
|
||||||
|
|
||||||
|
name:
|
||||||
|
Sets the name of the cache. This is used to identify the cache. It must be unique.
|
||||||
|
|
||||||
|
maxElementsInMemory:
|
||||||
|
Sets the maximum number of objects that will be created in memory
|
||||||
|
|
||||||
|
maxElementsOnDisk:
|
||||||
|
Sets the maximum number of objects that will be maintained in the DiskStore
|
||||||
|
The default value is zero, meaning unlimited.
|
||||||
|
|
||||||
|
eternal:
|
||||||
|
Sets whether elements are eternal. If eternal, timeouts are ignored and the
|
||||||
|
element is never expired.
|
||||||
|
|
||||||
|
overflowToDisk:
|
||||||
|
Sets whether elements can overflow to disk when the memory store
|
||||||
|
has reached the maxInMemory limit.
|
||||||
|
|
||||||
|
The following attributes and elements are optional.
|
||||||
|
|
||||||
|
timeToIdleSeconds:
|
||||||
|
Sets the time to idle for an element before it expires.
|
||||||
|
i.e. The maximum amount of time between accesses before an element expires
|
||||||
|
Is only used if the element is not eternal.
|
||||||
|
Optional attribute. A value of 0 means that an Element can idle for infinity.
|
||||||
|
The default value is 0.
|
||||||
|
|
||||||
|
timeToLiveSeconds:
|
||||||
|
Sets the time to live for an element before it expires.
|
||||||
|
i.e. The maximum time between creation time and when an element expires.
|
||||||
|
Is only used if the element is not eternal.
|
||||||
|
Optional attribute. A value of 0 means that and Element can live for infinity.
|
||||||
|
The default value is 0.
|
||||||
|
|
||||||
|
diskPersistent:
|
||||||
|
Whether the disk store persists between restarts of the Virtual Machine.
|
||||||
|
The default value is false.
|
||||||
|
|
||||||
|
diskExpiryThreadIntervalSeconds:
|
||||||
|
The number of seconds between runs of the disk expiry thread. The default value
|
||||||
|
is 120 seconds.
|
||||||
|
|
||||||
|
diskSpoolBufferSizeMB:
|
||||||
|
This is the size to allocate the DiskStore for a spool buffer. Writes are made
|
||||||
|
to this area and then asynchronously written to disk. The default size is 30MB.
|
||||||
|
Each spool buffer is used only by its cache. If you get OutOfMemory errors consider
|
||||||
|
lowering this value. To improve DiskStore performance consider increasing it. Trace level
|
||||||
|
logging in the DiskStore will show if put back ups are occurring.
|
||||||
|
|
||||||
|
clearOnFlush:
|
||||||
|
whether the MemoryStore should be cleared when flush() is called on the cache.
|
||||||
|
By default, this is true i.e. the MemoryStore is cleared.
|
||||||
|
|
||||||
|
memoryStoreEvictionPolicy:
|
||||||
|
Policy would be enforced upon reaching the maxElementsInMemory limit. Default
|
||||||
|
policy is Least Recently Used (specified as LRU). Other policies available -
|
||||||
|
First In First Out (specified as FIFO) and Less Frequently Used
|
||||||
|
(specified as LFU)
|
||||||
|
|
||||||
|
Cache elements can also contain sub elements which take the same format of a factory class
|
||||||
|
and properties. Defined sub-elements are:
|
||||||
|
|
||||||
|
* cacheEventListenerFactory - Enables registration of listeners for cache events, such as
|
||||||
|
put, remove, update, and expire.
|
||||||
|
|
||||||
|
* bootstrapCacheLoaderFactory - Specifies a BootstrapCacheLoader, which is called by a
|
||||||
|
cache on initialisation to prepopulate itself.
|
||||||
|
|
||||||
|
* cacheExtensionFactory - Specifies a CacheExtension, a generic mechansim to tie a class
|
||||||
|
which holds a reference to a cache to the cache lifecycle.
|
||||||
|
|
||||||
|
* cacheExceptionHandlerFactory - Specifies a CacheExceptionHandler, which is called when
|
||||||
|
cache exceptions occur.
|
||||||
|
|
||||||
|
* cacheLoaderFactory - Specifies a CacheLoader, which can be used both asynchronously and
|
||||||
|
synchronously to load objects into a cache. More than one cacheLoaderFactory element
|
||||||
|
can be added, in which case the loaders form a chain which are executed in order. If a
|
||||||
|
loader returns null, the next in chain is called.
|
||||||
|
|
||||||
|
|
||||||
|
RMI Cache Replication
|
||||||
|
+++++++++++++++++++++
|
||||||
|
|
||||||
|
Each cache that will be distributed needs to set a cache event listener which replicates
|
||||||
|
messages to the other CacheManager peers. For the built-in RMI implementation this is done
|
||||||
|
by adding a cacheEventListenerFactory element of type RMICacheReplicatorFactory to each
|
||||||
|
distributed cache's configuration as per the following example:
|
||||||
|
|
||||||
|
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
|
||||||
|
properties="replicateAsynchronously=true,
|
||||||
|
replicatePuts=true,
|
||||||
|
replicatePutsViaCopy=false,
|
||||||
|
replicateUpdates=true,
|
||||||
|
replicateUpdatesViaCopy=true,
|
||||||
|
replicateRemovals=true
|
||||||
|
asynchronousReplicationIntervalMillis=<number of milliseconds"
|
||||||
|
propertySeparator="," />
|
||||||
|
|
||||||
|
The RMICacheReplicatorFactory recognises the following properties:
|
||||||
|
|
||||||
|
* replicatePuts=true|false - whether new elements placed in a cache are
|
||||||
|
replicated to others. Defaults to true.
|
||||||
|
|
||||||
|
* replicatePutsViaCopy=true|false - whether the new elements are
|
||||||
|
copied to other caches (true), or whether a remove message is sent. Defaults to true.
|
||||||
|
|
||||||
|
* replicateUpdates=true|false - whether new elements which override an
|
||||||
|
element already existing with the same key are replicated. Defaults to true.
|
||||||
|
|
||||||
|
* replicateRemovals=true - whether element removals are replicated. Defaults to true.
|
||||||
|
|
||||||
|
* replicateAsynchronously=true | false - whether replications are
|
||||||
|
asynchronous (true) or synchronous (false). Defaults to true.
|
||||||
|
|
||||||
|
* replicateUpdatesViaCopy=true | false - whether the new elements are
|
||||||
|
copied to other caches (true), or whether a remove message is sent. Defaults to true.
|
||||||
|
|
||||||
|
* asynchronousReplicationIntervalMillis=<number of milliseconds> - The asynchronous
|
||||||
|
replicator runs at a set interval of milliseconds. The default is 1000. The minimum
|
||||||
|
is 10. This property is only applicable if replicateAsynchronously=true
|
||||||
|
|
||||||
|
|
||||||
|
JGroups Replication
|
||||||
|
+++++++++++++++++++
|
||||||
|
|
||||||
|
For the Jgroups replication this is done with:
|
||||||
|
<cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
|
||||||
|
properties="replicateAsynchronously=true, replicatePuts=true,
|
||||||
|
replicateUpdates=true, replicateUpdatesViaCopy=false,
|
||||||
|
replicateRemovals=true,asynchronousReplicationIntervalMillis=1000"/>
|
||||||
|
This listener supports the same properties as the RMICacheReplicationFactory.
|
||||||
|
|
||||||
|
|
||||||
|
JMS Replication
|
||||||
|
+++++++++++++++
|
||||||
|
|
||||||
|
For JMS-based replication this is done with:
|
||||||
|
<cacheEventListenerFactory
|
||||||
|
class="net.sf.ehcache.distribution.jms.JMSCacheReplicatorFactory"
|
||||||
|
properties="replicateAsynchronously=true,
|
||||||
|
replicatePuts=true,
|
||||||
|
replicateUpdates=true,
|
||||||
|
replicateUpdatesViaCopy=true,
|
||||||
|
replicateRemovals=true,
|
||||||
|
asynchronousReplicationIntervalMillis=1000"
|
||||||
|
propertySeparator=","/>
|
||||||
|
|
||||||
|
This listener supports the same properties as the RMICacheReplicationFactory.
|
||||||
|
|
||||||
|
Cluster Bootstrapping
|
||||||
|
+++++++++++++++++++++
|
||||||
|
|
||||||
|
Bootstrapping a cluster may use a different mechanism to replication. e.g you can mix
|
||||||
|
JMS replication with bootstrap via RMI - just make sure you have the cacheManagerPeerProviderFactory
|
||||||
|
and cacheManagerPeerListenerFactory configured.
|
||||||
|
|
||||||
|
There are two bootstrapping mechanisms: RMI and JGroups.
|
||||||
|
|
||||||
|
RMI Bootstrap
|
||||||
|
|
||||||
|
The RMIBootstrapCacheLoader bootstraps caches in clusters where RMICacheReplicators are
|
||||||
|
used. It is configured as per the following example:
|
||||||
|
|
||||||
|
<bootstrapCacheLoaderFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
|
||||||
|
properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"
|
||||||
|
propertySeparator="," />
|
||||||
|
|
||||||
|
The RMIBootstrapCacheLoaderFactory recognises the following optional properties:
|
||||||
|
|
||||||
|
* bootstrapAsynchronously=true|false - whether the bootstrap happens in the background
|
||||||
|
after the cache has started. If false, bootstrapping must complete before the cache is
|
||||||
|
made available. The default value is true.
|
||||||
|
|
||||||
|
* maximumChunkSizeBytes=<integer> - Caches can potentially be very large, larger than the
|
||||||
|
memory limits of the VM. This property allows the bootstraper to fetched elements in
|
||||||
|
chunks. The default chunk size is 5000000 (5MB).
|
||||||
|
|
||||||
|
JGroups Bootstrap
|
||||||
|
|
||||||
|
Here is an example of bootstrap configuration using JGroups boostrap:
|
||||||
|
|
||||||
|
<bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsBootstrapCacheLoaderFactory"
|
||||||
|
properties="bootstrapAsynchronously=true"/>
|
||||||
|
|
||||||
|
The configuration properties are the same as for RMI above. Note that JGroups bootstrap only supports
|
||||||
|
asynchronous bootstrap mode.
|
||||||
|
|
||||||
|
|
||||||
|
Cache Exception Handling
|
||||||
|
|
||||||
|
By default, most cache operations will propagate a runtime CacheException on failure. An
|
||||||
|
interceptor, using a dynamic proxy, may be configured so that a CacheExceptionHandler can
|
||||||
|
be configured to intercept Exceptions. Errors are not intercepted.
|
||||||
|
|
||||||
|
It is configured as per the following example:
|
||||||
|
|
||||||
|
<cacheExceptionHandlerFactory class="com.example.ExampleExceptionHandlerFactory"
|
||||||
|
properties="logLevel=FINE"/>
|
||||||
|
|
||||||
|
Caches with ExceptionHandling configured are not of type Cache, but are of type Ehcache only,
|
||||||
|
and are not available using CacheManager.getCache(), but using CacheManager.getEhcache().
|
||||||
|
|
||||||
|
|
||||||
|
Cache Loader
|
||||||
|
|
||||||
|
A default CacheLoader may be set which loads objects into the cache through asynchronous and
|
||||||
|
synchronous methods on Cache. This is different to the bootstrap cache loader, which is used
|
||||||
|
only in distributed caching.
|
||||||
|
|
||||||
|
It is configured as per the following example:
|
||||||
|
|
||||||
|
<cacheLoaderFactory class="com.example.ExampleCacheLoaderFactory"
|
||||||
|
properties="type=int,startCounter=10"/>
|
||||||
|
|
||||||
|
Cache Extension
|
||||||
|
|
||||||
|
CacheExtensions are a general purpose mechanism to allow generic extensions to a Cache.
|
||||||
|
CacheExtensions are tied into the Cache lifecycle.
|
||||||
|
|
||||||
|
CacheExtensions are created using the CacheExtensionFactory which has a
|
||||||
|
<code>createCacheCacheExtension()</code> method which takes as a parameter a
|
||||||
|
Cache and properties. It can thus call back into any public method on Cache, including, of
|
||||||
|
course, the load methods.
|
||||||
|
|
||||||
|
Extensions are added as per the following example:
|
||||||
|
|
||||||
|
<cacheExtensionFactory class="com.example.FileWatchingCacheRefresherExtensionFactory"
|
||||||
|
properties="refreshIntervalMillis=18000, loaderTimeout=3000,
|
||||||
|
flushPeriod=whatever, someOtherProperty=someValue ..."/>
|
||||||
|
|
||||||
|
Terracotta Clustering
|
||||||
|
|
||||||
|
Cache elements can also contain information about whether the cache can be clustered with Terracotta.
|
||||||
|
The <terracotta> sub-element has the following attributes:
|
||||||
|
|
||||||
|
* clustered=true|false - indicates whether this cache should be clustered with Terracotta. By
|
||||||
|
default, if the <terracotta> element is included, clustered=true.
|
||||||
|
* valueMode=serialization|identity - indicates whether this cache should be clustered with
|
||||||
|
serialized copies of the values or using Terracotta identity mode. By default, values will
|
||||||
|
be cached in serialization mode which is similar to other replicated Ehcache modes. The identity
|
||||||
|
mode is only available in certain Terracotta deployment scenarios and will maintain actual object
|
||||||
|
identity of the keys and values across the cluster. In this case, all users of a value retrieved from
|
||||||
|
the cache are using the same clustered value and must provide appropriate locking for any changes
|
||||||
|
made to the value (or objects referred to by the value).
|
||||||
|
* coherentReads=true|false - indicates whether this cache should have coherent reads with guaranteed
|
||||||
|
consistency across the cluster. By default, this setting is true. If you set this property to
|
||||||
|
false, reads are allowed to check the local value without locking, possibly seeing stale values.
|
||||||
|
This is a performance optimization with weaker concurrency guarantees and should generally be used
|
||||||
|
with caches that contain read-only data or where the application can tolerate reading stale
|
||||||
|
data.
|
||||||
|
|
||||||
|
Simplest example to indicate clustering:
|
||||||
|
<terracotta/>
|
||||||
|
|
||||||
|
To indicate the cache should not be clustered (or remove the <terracotta> element altogether):
|
||||||
|
<terracotta clustered="false"/>
|
||||||
|
|
||||||
|
To indicate the cache should be clustered using identity mode:
|
||||||
|
<terracotta clustered="true" valueMode="identity"/>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Mandatory Default Cache configuration. These settings will be applied to caches
|
||||||
|
created programmtically using CacheManager.add(String cacheName).
|
||||||
|
|
||||||
|
The defaultCache has an implicit name "default" which is a reserved cache name.
|
||||||
|
-->
|
||||||
|
<defaultCache
|
||||||
|
maxElementsInMemory="10000"
|
||||||
|
eternal="false"
|
||||||
|
timeToIdleSeconds="120"
|
||||||
|
timeToLiveSeconds="120"
|
||||||
|
overflowToDisk="true"
|
||||||
|
diskSpoolBufferSizeMB="30"
|
||||||
|
maxElementsOnDisk="10000000"
|
||||||
|
diskPersistent="false"
|
||||||
|
diskExpiryThreadIntervalSeconds="120"
|
||||||
|
memoryStoreEvictionPolicy="LRU"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Sample caches. Following are some example caches. Remove these before use.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Sample cache named sampleCache1
|
||||||
|
This cache contains a maximum in memory of 10000 elements, and will expire
|
||||||
|
an element if it is idle for more than 5 minutes and lives for more than
|
||||||
|
10 minutes.
|
||||||
|
|
||||||
|
If there are more than 10000 elements it will overflow to the
|
||||||
|
disk cache, which in this configuration will go to wherever java.io.tmp is
|
||||||
|
defined on your system. On a standard Linux system this will be /tmp"
|
||||||
|
-->
|
||||||
|
<cache name="sampleCache1"
|
||||||
|
maxElementsInMemory="10000"
|
||||||
|
maxElementsOnDisk="1000"
|
||||||
|
eternal="false"
|
||||||
|
overflowToDisk="true"
|
||||||
|
diskSpoolBufferSizeMB="20"
|
||||||
|
timeToIdleSeconds="300"
|
||||||
|
timeToLiveSeconds="600"
|
||||||
|
memoryStoreEvictionPolicy="LFU"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Sample cache named sampleCache2
|
||||||
|
This cache has a maximum of 1000 elements in memory. There is no overflow to disk, so 1000
|
||||||
|
is also the maximum cache size. Note that when a cache is eternal, timeToLive and
|
||||||
|
timeToIdle are not used and do not need to be specified.
|
||||||
|
-->
|
||||||
|
<cache name="sampleCache2"
|
||||||
|
maxElementsInMemory="1000"
|
||||||
|
eternal="true"
|
||||||
|
overflowToDisk="false"
|
||||||
|
memoryStoreEvictionPolicy="FIFO"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Sample cache named sampleCache3. This cache overflows to disk. The disk store is
|
||||||
|
persistent between cache and VM restarts. The disk expiry thread interval is set to 10
|
||||||
|
minutes, overriding the default of 2 minutes.
|
||||||
|
-->
|
||||||
|
<cache name="sampleCache3"
|
||||||
|
maxElementsInMemory="500"
|
||||||
|
eternal="false"
|
||||||
|
overflowToDisk="true"
|
||||||
|
timeToIdleSeconds="300"
|
||||||
|
timeToLiveSeconds="600"
|
||||||
|
diskPersistent="true"
|
||||||
|
diskExpiryThreadIntervalSeconds="1"
|
||||||
|
memoryStoreEvictionPolicy="LFU"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Sample distributed cache named sampleDistributedCache1.
|
||||||
|
This cache replicates using defaults.
|
||||||
|
It also bootstraps from the cluster, using default properties.
|
||||||
|
-->
|
||||||
|
<cache name="sampleDistributedCache1"
|
||||||
|
maxElementsInMemory="10"
|
||||||
|
eternal="false"
|
||||||
|
timeToIdleSeconds="100"
|
||||||
|
timeToLiveSeconds="100"
|
||||||
|
overflowToDisk="false">
|
||||||
|
|
||||||
|
<cacheEventListenerFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
|
||||||
|
<bootstrapCacheLoaderFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/>
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Sample distributed cache named sampleDistributedCache2.
|
||||||
|
This cache replicates using specific properties.
|
||||||
|
It only replicates updates and does so synchronously via copy
|
||||||
|
-->
|
||||||
|
<cache name="sampleDistributedCache2"
|
||||||
|
maxElementsInMemory="10"
|
||||||
|
eternal="false"
|
||||||
|
timeToIdleSeconds="100"
|
||||||
|
timeToLiveSeconds="100"
|
||||||
|
overflowToDisk="false">
|
||||||
|
<cacheEventListenerFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
|
||||||
|
properties="replicateAsynchronously=false, replicatePuts=false,
|
||||||
|
replicatePutsViaCopy=false, replicateUpdates=true,
|
||||||
|
replicateUpdatesViaCopy=true, replicateRemovals=false"/>
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Sample distributed cache named sampleDistributedCache3.
|
||||||
|
This cache replicates using defaults except that the asynchronous replication
|
||||||
|
interval is set to 200ms.
|
||||||
|
This one includes / and # which were illegal in ehcache 1.5.
|
||||||
|
-->
|
||||||
|
<cache name="sample/DistributedCache3"
|
||||||
|
maxElementsInMemory="10"
|
||||||
|
eternal="false"
|
||||||
|
timeToIdleSeconds="100"
|
||||||
|
timeToLiveSeconds="100"
|
||||||
|
overflowToDisk="true">
|
||||||
|
<cacheEventListenerFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
|
||||||
|
properties="asynchronousReplicationIntervalMillis=200"/>
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Sample Terracotta clustered cache named sampleTerracottaCache.
|
||||||
|
This cache uses Terracotta to cluster the contents of the cache.
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
<cache name="sampleTerracottaCache"
|
||||||
|
maxElementsInMemory="1000"
|
||||||
|
eternal="false"
|
||||||
|
timeToIdleSeconds="3600"
|
||||||
|
timeToLiveSeconds="1800"
|
||||||
|
overflowToDisk="false">
|
||||||
|
<terracotta/>
|
||||||
|
</cache>
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ehcache>
|
||||||
46
sandbox/endpoint-ehcache/src/test/resources/ehcache1.xml
Normal file
46
sandbox/endpoint-ehcache/src/test/resources/ehcache1.xml
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="ehcache.xsd"
|
||||||
|
updateCheck="false" monitoring="autodetect">
|
||||||
|
|
||||||
|
<cacheManagerEventListenerFactory class="" properties=""/>
|
||||||
|
|
||||||
|
<cacheManagerPeerProviderFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
|
||||||
|
properties="peerDiscovery=manual,
|
||||||
|
rmiUrls=//localhost:40009/sampleDistributedCache1"
|
||||||
|
propertySeparator="," />
|
||||||
|
|
||||||
|
<cacheManagerPeerListenerFactory
|
||||||
|
class="org.apache.tuscany.sca.endpoint.ehcache.TuscanyRMICacheManagerPeerListenerFactory"
|
||||||
|
properties="localhost,
|
||||||
|
port=40001,
|
||||||
|
remoteObjectPort=40002,
|
||||||
|
socketTimeoutMillis=120000"
|
||||||
|
propertySeparator="," />
|
||||||
|
|
||||||
|
<defaultCache
|
||||||
|
maxElementsInMemory="10000"
|
||||||
|
eternal="true"
|
||||||
|
overflowToDisk="false">
|
||||||
|
<cacheEventListenerFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
|
||||||
|
properties="asynchronousReplicationIntervalMillis=100"/>
|
||||||
|
<bootstrapCacheLoaderFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
|
||||||
|
properties="bootstrapAsynchronously=false "/>
|
||||||
|
</defaultCache>
|
||||||
|
|
||||||
|
<cache name="sampleDistributedCache1"
|
||||||
|
maxElementsInMemory="10000"
|
||||||
|
eternal="true"
|
||||||
|
overflowToDisk="false">
|
||||||
|
<cacheEventListenerFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
|
||||||
|
properties="asynchronousReplicationIntervalMillis=100"/>
|
||||||
|
<bootstrapCacheLoaderFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
|
||||||
|
properties="bootstrapAsynchronously=false "/>
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
</ehcache>
|
||||||
48
sandbox/endpoint-ehcache/src/test/resources/ehcache2.xml
Normal file
48
sandbox/endpoint-ehcache/src/test/resources/ehcache2.xml
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="ehcache.xsd"
|
||||||
|
updateCheck="true" monitoring="autodetect">
|
||||||
|
|
||||||
|
<cacheManagerEventListenerFactory class="" properties=""/>
|
||||||
|
|
||||||
|
<cacheManagerPeerProviderFactory class=
|
||||||
|
"net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
|
||||||
|
properties="peerDiscovery=manual,
|
||||||
|
rmiUrls=//localhost:40001/sampleDistributedCache1"
|
||||||
|
propertySeparator="," />
|
||||||
|
|
||||||
|
<cacheManagerPeerListenerFactory
|
||||||
|
class="org.apache.tuscany.sca.endpoint.ehcache.TuscanyRMICacheManagerPeerListenerFactory"
|
||||||
|
properties="localhost,
|
||||||
|
port=40009,
|
||||||
|
remoteObjectPort=40008,
|
||||||
|
socketTimeoutMillis=120000"
|
||||||
|
propertySeparator="," />
|
||||||
|
|
||||||
|
|
||||||
|
<defaultCache
|
||||||
|
maxElementsInMemory="10000"
|
||||||
|
eternal="true"
|
||||||
|
overflowToDisk="false">
|
||||||
|
<cacheEventListenerFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
|
||||||
|
properties="asynchronousReplicationIntervalMillis=100"/>
|
||||||
|
<bootstrapCacheLoaderFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
|
||||||
|
properties="bootstrapAsynchronously=false "/>
|
||||||
|
</defaultCache>
|
||||||
|
|
||||||
|
<cache name="sampleDistributedCache1"
|
||||||
|
maxElementsInMemory="10000"
|
||||||
|
eternal="true"
|
||||||
|
overflowToDisk="false">
|
||||||
|
<cacheEventListenerFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
|
||||||
|
properties="asynchronousReplicationIntervalMillis=100"/>
|
||||||
|
<bootstrapCacheLoaderFactory
|
||||||
|
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
|
||||||
|
properties="bootstrapAsynchronously=false "/>
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
</ehcache>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue