Thanks for doing this, Daniel. I like the changes you made. Much cleaner :). With the threading gone I think the lifetime value needs to be higher, otherwise subscription will die after an hour. Is this correct? What's a good value for infinite lifetime?

-James

[EMAIL PROTECTED] wrote:
dflorey     2004/08/09 04:51:53

Modified: src/share/org/apache/slide/cluster
ClusterCacheRefresher.java
Log:
Removed threading as notificationListener now supports connection timeout
Revision Changes Path
1.2 +198 -216 jakarta-slide/src/share/org/apache/slide/cluster/ClusterCacheRefresher.java
Index: ClusterCacheRefresher.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/cluster/ClusterCacheRefresher.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ClusterCacheRefresher.java 9 Aug 2004 05:03:09 -0000 1.1
+++ ClusterCacheRefresher.java 9 Aug 2004 11:51:53 -0000 1.2
@@ -23,13 +23,11 @@
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
-import org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory;
import org.apache.commons.httpclient.protocol.Protocol;
-import org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory;
import org.apache.slide.authenticate.CredentialsToken;
+import org.apache.slide.authenticate.SecurityToken;
import org.apache.slide.common.Domain;
import org.apache.slide.common.NamespaceAccessToken;
-import org.apache.slide.common.SlideToken;
import org.apache.slide.common.SlideTokenImpl;
import org.apache.slide.common.Uri;
import org.apache.slide.store.ExtendedStore;
@@ -40,7 +38,6 @@
import org.apache.slide.util.logger.Logger;
import org.apache.webdav.lib.NotificationListener;
import org.apache.webdav.lib.Subscriber;
-import org.apache.webdav.lib.methods.DepthSupport;
/**
* <h3>Description</h3>
@@ -54,225 +51,210 @@
* <p>
* Add the following to your Domain.xml inside the &lt;events&gt; node.
* </p>
+ * * <pre>
- * &lt;listener classname="org.apache.slide.cluster.ClusterCacheRefresher"&gt;
- * &lt;configuration&gt;
- * &lt;node local-host="local.host.domain"
- * local-port="4444"
- * repository-host="remote.host.domain"
- * repository-port="8080"
- * repository-protocol="http"
- * username="root"
- * password="root"
- * /&gt;
- * &lt;/configuration&gt;
- * &lt;/listener&gt;
- * </pre>
+ * + * + * &lt;listener classname=&quot;org.apache.slide.cluster.ClusterCacheRefresher&quot;&gt;
+ * &lt;configuration&gt;
+ * &lt;node local-host=&quot;local.host.domain&quot;
+ * local-port=&quot;4444&quot;
+ * repository-host=&quot;remote.host.domain&quot;
+ * repository-port=&quot;8080&quot;
+ * repository-protocol=&quot;http&quot;
+ * username=&quot;root&quot;
+ * password=&quot;root&quot;
+ * /&gt;
+ * &lt;/configuration&gt;
+ * &lt;/listener&gt;
+ * + * + * </pre>
+ * * <p>
* There should be one &lt;node&gt; element for each node in the cluster,
- * <b>except</b> for the current node. ClusterCacheRefresher should not be
+ * <b>except </b> for the current node. ClusterCacheRefresher should not be
* configured to listen to itself except for testing purposes.
* </p>
* <h3>&lt;node&gt; attributes</h3>
* <table>
- * <tr>
- * <th>Attribute Name</th>
- * <th>Required?</th>
- * <th>Default Value</th>
- * <th>Description</th>
- * </tr>
- * <tr>
- * <td>local-host</td>
- * <td>yes</td>
- * <td>none</td>
- * <td>A network-accessible name or ip-address where the remote Slide instance can reach <b>this server.</b></td>
- * </tr>
- * <tr>
- * <td>local-port</td>
- * <td>yes</td>
- * <td>none</td>
- * <td>A port number ClusterCacheRefresher can use to listen for notifications. <b>Must be unique.</b></td>
- * </tr>
- * <tr>
- * <td>repository-host</td>
- * <td>yes</td>
- * <td>none</td>
- * <td>A network-accessible name or ip-address of the remote Slide instance to monitor.</td>
- * </tr>
- * <tr>
- * <td>repository-port</td>
- * <td>yes</td>
- * <td>none</td>
- * <td>The port the remote Slide instance is running on.</td>
- * </tr>
- * <tr>
- * <td>repository-protocol</td>
- * <td>no</td>
- * <td>http</td>
- * <td>The protocol the remote Slide instance is using. Must be one of "http" or "https".</td>
- * </tr>
- * <tr>
- * <td>username</td>
- * <td>no</td>
- * <td>none</td>
- * <td>The username to use to connect to the remote Slide instance.</td>
- * </tr>
- * <tr>
- * <td>password</td>
- * <td>no</td>
- * <td>none</td>
- * <td>The password that goes with the username.</td>
- * </tr>
- * <tr>
- * <td>repository-domain</td>
- * <td>no</td>
- * <td>/slide</td>
- * <td>The context path of the remote Slide instance.</td>
- * </tr>
- * <tr>
- * <td>poll-interval</td>
- * <td>no</td>
- * <td>60000</td>
- * <td>The number of milliseconds to wait between polling the remote Slide instance for any changes. Polling for changes is a backup only, so this value can be set fairly high.</td>
- * </tr>
- * <tr>
- * <td>udp</td>
- * <td>no</td>
- * <td>true</td>
- * <td>Must be "true" or "false". Indicates whether to use udp or tcp to listen for notifications.</td>
- * </tr>
- * <tr>
- * <td>base-uri</td>
- * <td>no</td>
- * <td>/</td>
- * <td>The base path to monitor for changes. Will be appended to the repository-domain.</td>
- * </tr>
- * <tr>
- * <td>subscription-lifetime</td>
- * <td>no</td>
- * <td>3600</td>
- * <td>The number of seconds a subscription should last. Subscriptions are automatically refreshed. Do not set this value too high.</td>
- * </tr>
- * <tr>
- * <td>notification-delay</td>
- * <td>no</td>
- * <td>0</td>
- * <td>Number of seconds the remote Slide instance should wait before sending a notification of a change.</td>
- * </tr>
+ * <tr>
+ * <th>Attribute Name</th>
+ * <th>Required?</th>
+ * <th>Default Value</th>
+ * <th>Description</th>
+ * </tr>
+ * <tr>
+ * <td>local-host</td>
+ * <td>yes</td>
+ * <td>none</td>
+ * <td>A network-accessible name or ip-address where the remote Slide instance
+ * can reach <b>this server. </b></td>
+ * </tr>
+ * <tr>
+ * <td>local-port</td>
+ * <td>yes</td>
+ * <td>none</td>
+ * <td>A port number ClusterCacheRefresher can use to listen for notifications.
+ * <b>Must be unique. </b></td>
+ * </tr>
+ * <tr>
+ * <td>repository-host</td>
+ * <td>yes</td>
+ * <td>none</td>
+ * <td>A network-accessible name or ip-address of the remote Slide instance to
+ * monitor.</td>
+ * </tr>
+ * <tr>
+ * <td>repository-port</td>
+ * <td>yes</td>
+ * <td>none</td>
+ * <td>The port the remote Slide instance is running on.</td>
+ * </tr>
+ * <tr>
+ * <td>repository-protocol</td>
+ * <td>no</td>
+ * <td>http</td>
+ * <td>The protocol the remote Slide instance is using. Must be one of "http"
+ * or "https".</td>
+ * </tr>
+ * <tr>
+ * <td>username</td>
+ * <td>no</td>
+ * <td>none</td>
+ * <td>The username to use to connect to the remote Slide instance.</td>
+ * </tr>
+ * <tr>
+ * <td>password</td>
+ * <td>no</td>
+ * <td>none</td>
+ * <td>The password that goes with the username.</td>
+ * </tr>
+ * <tr>
+ * <td>repository-domain</td>
+ * <td>no</td>
+ * <td>/slide</td>
+ * <td>The context path of the remote Slide instance.</td>
+ * </tr>
+ * <tr>
+ * <td>poll-interval</td>
+ * <td>no</td>
+ * <td>60000</td>
+ * <td>The number of milliseconds to wait between polling the remote Slide
+ * instance for any changes. Polling for changes is a backup only, so this value
+ * can be set fairly high.</td>
+ * </tr>
+ * <tr>
+ * <td>udp</td>
+ * <td>no</td>
+ * <td>true</td>
+ * <td>Must be "true" or "false". Indicates whether to use udp or tcp to listen
+ * for notifications.</td>
+ * </tr>
+ * <tr>
+ * <td>base-uri</td>
+ * <td>no</td>
+ * <td>/</td>
+ * <td>The base path to monitor for changes. Will be appended to the
+ * repository-domain.</td>
+ * </tr>
+ * <tr>
+ * <td>subscription-lifetime</td>
+ * <td>no</td>
+ * <td>3600</td>
+ * <td>The number of seconds a subscription should last. Subscriptions are
+ * automatically refreshed. Do not set this value too high.</td>
+ * </tr>
+ * <tr>
+ * <td>notification-delay</td>
+ * <td>no</td>
+ * <td>0</td>
+ * <td>Number of seconds the remote Slide instance should wait before sending a
+ * notification of a change.</td>
+ * </tr>
* </table>
*/
-public class ClusterCacheRefresher implements Subscriber, EventListener, Configurable {
- protected static final String LOG_CHANNEL = ClusterCacheRefresher.class.getName();
-
- protected NotificationListener listener;
-
- public ClusterCacheRefresher() {
- Domain.log("Creating ClusterCacheRefresher", LOG_CHANNEL, Logger.INFO);
- }
-
- public void notify(String uri, Map information) {
- // FIXME: need a better way to get the right namespace
- NamespaceAccessToken nat = Domain.accessNamespace( new org.apache.slide.authenticate.SecurityToken(this), "slide" );
- Iterator keys = information.keySet().iterator();
- while ( keys.hasNext() ) {
- String key = keys.next().toString();
- if ( "uri".equals( key ) ) {
- Uri theUri = nat.getUri( new SlideTokenImpl(new CredentialsToken("")),information.get(key).toString());
- Store store = theUri.getStore();
- if ( store instanceof ExtendedStore ) {
- Domain.log( "Resetting cache for " + theUri, LOG_CHANNEL, Logger.INFO );
- ((ExtendedStore)store).removeObjectFromCache(theUri);
- }
- store = theUri.getParentUri().getStore();
- if ( store instanceof ExtendedStore ) {
- Domain.log( "Resetting cache for " + theUri.getParentUri(), LOG_CHANNEL, Logger.INFO );
- ((ExtendedStore)store).removeObjectFromCache(theUri.getParentUri());
- }
- }
- }
- }
-
- public void configure(Configuration configuration) throws ConfigurationException {
-
- Domain.log("Configuring ClusterCacheRefresher", LOG_CHANNEL, Logger.INFO);
-
- Enumeration nodes = configuration.getConfigurations("node");
- while ( nodes.hasMoreElements() ) {
- Configuration node = (Configuration)nodes.nextElement();
-
- final String host = node.getAttribute("local-host");
- final int port = node.getAttributeAsInt("local-port");
- final String repositoryHost = node.getAttribute("repository-host");
- final int repositoryPort = node.getAttributeAsInt("repository-port");
- String repositoryProtocolString = node.getAttribute("repository-protocol", "http");
- final Protocol protocol;
- if ( "http".equals(repositoryProtocolString) ) {
- protocol = new Protocol( "http", new DefaultProtocolSocketFactory(), 80 );
- } else if ( "https".equals(repositoryProtocolString) ) {
- protocol = new Protocol( "https", new SSLProtocolSocketFactory(), 443 );
- } else {
- throw new ConfigurationException("Unknown repository-protocol: " + repositoryProtocolString + ". Must be \"http\" or \"https\".", configuration);
- }
- String username = node.getAttribute("username", "");
- String password = node.getAttribute("password", "");
- final Credentials credentials = new UsernamePasswordCredentials( username, password );
- final String repositoryDomain = node.getAttribute("repository-domain", "/slide");
- final int pollInterval = node.getAttributeAsInt("poll-interval", 60000);
- final boolean udp = node.getAttributeAsBoolean("udp", true);
- final String uri = node.getAttribute("base-uri", "/");
-// int depth = DepthSupport.DEPTH_INFINITY;
- final int depth = 1;
- final int lifetime = node.getAttributeAsInt("subscription-lifetime", 3600);
- final int notificationDelay = node.getAttributeAsInt("notification-delay", 0);
- final Subscriber subscriber = this;
-
-// System.out.println( "\n## Creating NotificationListener" );
-
- listener = new NotificationListener( host, port, repositoryHost, repositoryPort, protocol, credentials, repositoryDomain, pollInterval, udp);
-
-// System.out.println( "listener created" );
-
- Thread t = new Thread( new Runnable() {
-
- private boolean first = true;
-
- public void run() {
-
- try {
- if ( first ) {
- // Delay on startup to let server finish starting.
- // FIXME: This should not be necessary when NotificationListener stops freezing
- first = false;
- Thread.sleep(3000);
- Domain.log( "Registering cluster subscriptions", LOG_CHANNEL, Logger.INFO );
- } else {
- Thread.sleep(lifetime*1000-60);
- }
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
-// System.out.println( "creating update subscriber");
-
- listener.subscribe("Update",uri,depth,lifetime,notificationDelay,subscriber,credentials);
-
-// System.out.println( "creating update/newmember subscriber" );
-
- listener.subscribe("Update/newmember",uri,depth,lifetime,notificationDelay,subscriber,credentials);
-
-// System.out.println("creating delete subscriber");
-
- listener.subscribe("Delete",uri,depth,lifetime,notificationDelay,subscriber,credentials);
-
-// System.out.println( "creating move subscriber" );
-
- listener.subscribe("Move",uri,depth,lifetime,notificationDelay,subscriber,credentials);
- }
- });
- t.setDaemon(true);
- t.start();
- }
- }
+public class ClusterCacheRefresher implements EventListener, Configurable {
+ protected static final String LOG_CHANNEL = ClusterCacheRefresher.class.getName();
-}
+ protected NotificationListener listener;
+
+ public ClusterCacheRefresher() {
+ Domain.log("Creating ClusterCacheRefresher", LOG_CHANNEL, Logger.INFO);
+ }
+
+ public void configure(Configuration configuration) throws ConfigurationException {
+ Domain.log("Configuring ClusterCacheRefresher", LOG_CHANNEL, Logger.INFO);
+
+ Enumeration nodes = configuration.getConfigurations("node");
+ while (nodes.hasMoreElements()) {
+ Configuration node = (Configuration) nodes.nextElement();
+ final String host = node.getAttribute("local-host");
+ final int port = node.getAttributeAsInt("local-port");
+ final String repositoryHost = node.getAttribute("repository-host");
+ final int repositoryPort = node.getAttributeAsInt("repository-port");
+ String repositoryProtocolString = node.getAttribute("repository-protocol", "http");
+ final Protocol protocol;
+ try {
+ protocol = Protocol.getProtocol(repositoryProtocolString);
+ } catch (IllegalStateException exception) {
+ throw new ConfigurationException("Unknown repository-protocol: " + repositoryProtocolString
+ + ". Must be \"http\" or \"https\".", configuration);
+ }
+ String username = node.getAttribute("username", "");
+ String password = node.getAttribute("password", "");
+ final Credentials credentials = new UsernamePasswordCredentials(username, password);
+ final String repositoryDomain = node.getAttribute("repository-domain", "/slide");
+ final int pollInterval = node.getAttributeAsInt("poll-interval", 60000);
+ final boolean udp = node.getAttributeAsBoolean("udp", true);
+ final String uri = node.getAttribute("base-uri", "/");
+ final int depth = Integer.MAX_VALUE;
+ final int lifetime = node.getAttributeAsInt("subscription-lifetime", 3600);
+ final int notificationDelay = node.getAttributeAsInt("notification-delay", 0);
+
+ final Subscriber contentSubscriber = new Subscriber() {
+ public void notify(String uri, Map information) {
+ NamespaceAccessToken nat = Domain.accessNamespace(new SecurityToken(this), Domain.getDefaultNamespace());
+ Iterator keys = information.keySet().iterator();
+ while (keys.hasNext()) {
+ String key = keys.next().toString();
+ if ("uri".equals(key)) {
+ Uri theUri = nat.getUri(new SlideTokenImpl(new CredentialsToken("")), information.get(key).toString());
+ Store store = theUri.getStore();
+ if (store instanceof ExtendedStore) {
+ Domain.log("Resetting cache for " + theUri, LOG_CHANNEL, Logger.INFO);
+ ((ExtendedStore) store).removeObjectFromCache(theUri);
+ }
+ }
+ }
+ }
+ };
+
+ final Subscriber structureSubscriber = new Subscriber() {
+ public void notify(String uri, Map information) {
+ NamespaceAccessToken nat = Domain.accessNamespace(new SecurityToken(this), Domain.getDefaultNamespace());
+ Iterator keys = information.keySet().iterator();
+ while (keys.hasNext()) {
+ String key = keys.next().toString();
+ if ("uri".equals(key)) {
+ Uri theUri = nat.getUri(new SlideTokenImpl(new CredentialsToken("")), information.get(key).toString());
+ Store store = theUri.getParentUri().getStore();
+ if (store instanceof ExtendedStore) {
+ Domain.log("Resetting cache for " + theUri.getParentUri(), LOG_CHANNEL, Logger.INFO);
+ ((ExtendedStore) store).removeObjectFromCache(theUri.getParentUri());
+ }
+ }
+ }
+ }
+ };
+
+ listener = new NotificationListener(host, port, repositoryHost, repositoryPort, protocol, credentials,
+ repositoryDomain, pollInterval, udp);
+
+ listener.subscribe("Update", uri, depth, lifetime, notificationDelay, contentSubscriber, credentials);
+ listener.subscribe("Update/newmember", uri, depth, lifetime, notificationDelay, structureSubscriber, credentials);
+ listener.subscribe("Delete", uri, depth, lifetime, notificationDelay, structureSubscriber, credentials);
+ listener.subscribe("Move", uri, depth, lifetime, notificationDelay, structureSubscriber, credentials);
+ }
+ }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]





---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to