masonjm 2004/08/08 22:03:09
Modified: src/conf/webapp Domain.xml
. build.xml
Added: src/share/org/apache/slide/cluster
ClusterCacheRefresher.java
lib jakarta-slide-webdavlib-2.1b1.jar
Log:
(Semi)working cluster notification support.
Revision Changes Path
1.66 +17 -0 jakarta-slide/src/conf/webapp/Domain.xml
Index: Domain.xml
===================================================================
RCS file: /home/cvs/jakarta-slide/src/conf/webapp/Domain.xml,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -r1.65 -r1.66
--- Domain.xml 5 Aug 2004 14:47:24 -0000 1.65
+++ Domain.xml 9 Aug 2004 05:03:09 -0000 1.66
@@ -344,6 +344,23 @@
<indexer classname="org.apache.slide.search.LoggingIndexer"
synchronous="false" uri="/files/articles" />
</configuration>
</listener>
+
+ <!-- Uncomment for cluster support. Be sure to local-host and
repository-host -->
+ <!--
+ <listener classname="org.apache.slide.cluster.ClusterCacheRefresher">
+ <configuration>
+ <node local-host="local.host.domain"
+ local-port="4444"
+ repository-host="remote.host.domain"
+ repository-port="8080"
+ repository-protocol="http"
+ username="root"
+ password="root"
+ base-uri="/files/"
+ />
+ </configuration>
+ </listener>
+ -->
<listener classname="org.apache.slide.macro.MacroPropertyUpdater">
<!-- Listener that updates some properties if resources are
1.1
jakarta-slide/src/share/org/apache/slide/cluster/ClusterCacheRefresher.java
Index: ClusterCacheRefresher.java
===================================================================
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed 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.slide.cluster;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Iterator;
import java.util.Map;
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.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;
import org.apache.slide.store.Store;
import org.apache.slide.util.conf.Configurable;
import org.apache.slide.util.conf.Configuration;
import org.apache.slide.util.conf.ConfigurationException;
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>
* <p>
* When configured properly this class will register with one or more external
* Slide instances and listen for changes. Upon notification of a change this
* class will cause the cache of the local Slide instance to be refreshed for
* the changed object.
* </p>
* <h3>Usage</h3>
* <p>
* Add the following to your Domain.xml inside the <events> node.
* </p>
* <pre>
* <listener classname="org.apache.slide.cluster.ClusterCacheRefresher">
* <configuration>
* <node local-host="local.host.domain"
* local-port="4444"
* repository-host="remote.host.domain"
* repository-port="8080"
* repository-protocol="http"
* username="root"
* password="root"
* />
* </configuration>
* </listener>
* </pre>
* <p>
* There should be one <node> element for each node in the cluster,
* <b>except</b> for the current node. ClusterCacheRefresher should not be
* configured to listen to itself except for testing purposes.
* </p>
* <h3><node> 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>
* </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();
}
}
}
1.1 jakarta-slide/lib/jakarta-slide-webdavlib-2.1b1.jar
<<Binary file>>
1.228 +4 -1 jakarta-slide/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-slide/build.xml,v
retrieving revision 1.227
retrieving revision 1.228
diff -u -r1.227 -r1.228
--- build.xml 5 Aug 2004 14:53:44 -0000 1.227
+++ build.xml 9 Aug 2004 05:03:09 -0000 1.228
@@ -47,7 +47,8 @@
<property name="xml-im-exporter.jar" value="${lib.dir}/xml-im-exporter1.1.jar"/>
<property name="commons-transaction.jar"
value="${lib.dir}/commons-transaction-20040805.jar"/>
<property name="commons-codec.jar" value="${lib.dir}/commons-codec-1.3.jar"/>
- <!-- ===================================================================
-->
+ <property name="jakarta-slide-webdavlib.jar"
value="${lib.dir}/jakarta-slide-webdavlib-2.1b1.jar"/>
+ <!-- =================================================================== -->
<!-- Produced jars Properties -->
<!-- =================================================================== -->
<property name="slide-kernel.jar" value="slide-kernel-${version}.jar"/>
@@ -115,6 +116,8 @@
<pathelement location="${ehcache.jar}"/>
<pathelement location="${commons-transaction.jar}"/>
<pathelement location="${commons-codec.jar}"/>
+ <pathelement location="${commons-httpclient.jar}"/>
+ <pathelement location="${jakarta-slide-webdavlib.jar}"/>
</path>
<path id="stores.classpath">
<pathelement location="${xmlapi.jar}"/>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]