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]