Commit dc97a815 authored by Tom Evans's avatar Tom Evans

OF-879: Update hazelcast namespace, dependencies

* Repackaged the classes in the Hazelcast plugin to use the project's namespace (org.jivesoftware.* rather than com.jivesoftware.*)
* Updated to latest HZ release (v3.4)
* Updated the name of the default clustering plugin class, used by reflection to initialize the hazelcast plugin (if present).
* Updated docs per community feedback
parent c348e9b9
...@@ -94,7 +94,7 @@ public class CacheFactory { ...@@ -94,7 +94,7 @@ public class CacheFactory {
localCacheFactoryClass = JiveGlobals.getProperty(LOCAL_CACHE_PROPERTY_NAME, localCacheFactoryClass = JiveGlobals.getProperty(LOCAL_CACHE_PROPERTY_NAME,
"org.jivesoftware.util.cache.DefaultLocalCacheStrategy"); "org.jivesoftware.util.cache.DefaultLocalCacheStrategy");
clusteredCacheFactoryClass = JiveGlobals.getProperty(CLUSTERED_CACHE_PROPERTY_NAME, clusteredCacheFactoryClass = JiveGlobals.getProperty(CLUSTERED_CACHE_PROPERTY_NAME,
"com.jivesoftware.util.cache.ClusteredCacheFactory"); "org.jivesoftware.openfire.plugin.util.cache.ClusteredCacheFactory");
cacheNames.put("Favicon Hits", "faviconHits"); cacheNames.put("Favicon Hits", "faviconHits");
cacheNames.put("Favicon Misses", "faviconMisses"); cacheNames.put("Favicon Misses", "faviconMisses");
......
...@@ -44,6 +44,13 @@ ...@@ -44,6 +44,13 @@
Hazelcast Clustering Plugin Changelog Hazelcast Clustering Plugin Changelog
</h1> </h1>
<p><b>2.0.0</b> -- February 6, 2015</p>
<p>Hazelcast update:</p>
<ul>
<li>Updated Hazelcast to latest release (3.4).</li>
<li>Repackaged to use Openfire's org.jivesoftware.openfire namespace prefix (rather than com.jivesoftware.openfire).</li>
</ul>
<p><b>1.3.4</b> -- January 10, 2015</p> <p><b>1.3.4</b> -- January 10, 2015</p>
<p>Bug fixes:</p> <p>Bug fixes:</p>
<ul> <ul>
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
~ limitations under the License. ~ limitations under the License.
--> -->
<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.3.xsd" <hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.4.xsd"
xmlns="http://www.hazelcast.com/schema/config" xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<group> <group>
...@@ -59,7 +59,20 @@ ...@@ -59,7 +59,20 @@
Any integer between 0 and Integer.MAX_VALUE. 0 means Any integer between 0 and Integer.MAX_VALUE. 0 means
Integer.MAX_VALUE. Default is 0. Integer.MAX_VALUE. Default is 0.
--> -->
<max-size-per-jvm>0</max-size-per-jvm> <max-size>0</max-size>
<!--
Number of backups. If 1 is set as the backup-count for example,
then all entries of the map will be copied to another JVM for
fail-safety. 0 means no backup.
-->
<backup-count>1</backup-count>
<!--
Number of async backups. 0 means no backup.
-->
<async-backup-count>0</async-backup-count>
<empty-queue-ttl>-1</empty-queue-ttl>
<!-- <!--
Name of the map configuration that will be used for the backing distributed Name of the map configuration that will be used for the backing distributed
map for this queue. map for this queue.
...@@ -70,6 +83,15 @@ ...@@ -70,6 +83,15 @@
Default Hazelcast cache configuration for Openfire. Default Hazelcast cache configuration for Openfire.
--> -->
<map name="default"> <map name="default">
<!--
Data type that will be used for storing recordMap.
Possible values:
BINARY (default): keys and values will be stored as binary data
OBJECT : values will be stored in their object forms
NATIVE : values will be stored in non-heap region of JVM
-->
<in-memory-format>BINARY</in-memory-format>
<!-- <!--
Number of backups. If 1 is set as the backup-count for example, Number of backups. If 1 is set as the backup-count for example,
then all entries of the map will be copied to another JVM for then all entries of the map will be copied to another JVM for
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<plugin> <plugin>
<class>com.jivesoftware.openfire.HazelcastPlugin</class> <class>org.jivesoftware.openfire.plugin.HazelcastPlugin</class>
<name>${plugin.name}</name> <name>${plugin.name}</name>
<description>${plugin.description}</description> <description>${plugin.description}</description>
<author>Tom Evans</author> <author>Tom Evans</author>
<version>1.3.4</version> <version>2.0.0</version>
<date>01/10/2015</date> <date>02/06/2015</date>
<minServerVersion>3.9.4</minServerVersion> <minServerVersion>3.9.4</minServerVersion>
</plugin> </plugin>
...@@ -65,7 +65,32 @@ open source <a href="http://www.hazelcast.org">Hazelcast</a> data distribution ...@@ -65,7 +65,32 @@ open source <a href="http://www.hazelcast.org">Hazelcast</a> data distribution
framework in lieu of an expensive proprietary third-party product. framework in lieu of an expensive proprietary third-party product.
</p> </p>
<p> <p>
The current Hazelcast release is version 3.3.3. The current Hazelcast release is version 3.4.
</p>
<h3>Clustering vs. Federation</h3>
<p>XMPP is designed to scale in ways that are similar to email. Each Openfire
installation supports a single XMPP domain, and a server-to-server (S2S)
protocol as described in the specification is provided to link multiple XMPP
domains together. This is known as federation. It represents a powerful way to
"scale out" XMPP, as it allows an XMPP user to communicate securely with any
user in any other such federated domain. These federations may be public or
private as appropriate. Federated domains may exchange XMPP stanzas
across the Internet (WAN) and may even discover one another using DNS-based
service lookup and address resolution.
</p>
<p>By contrast, clustering is a technique used to "scale up" a single XMPP domain.
The server members within a cluster all share an identical configuration. Each
member will allow any user within the domain to connect, authenticate, and exchange
stanzas. Clustered servers all share a single database, and are also required to
be resident within the same LAN-based (low latency) network infrastructure. This
type of deployment is suitable to provide runtime redundancy and will support a
larger number of users and connections (within a single domain) than a single
server would be able to provide.
</p>
<p>For very large Openfire deployments, a combination of federation and clustering will
provide the best results. Whereas a single clustered XMPP domain will be able to
support tens or even hundreds of thousands of users, a federated deployment will be
needed to reach true Internet scale of millions of concurrent XMPP connections.
</p> </p>
<h2>Installation</h2> <h2>Installation</h2>
<p> <p>
...@@ -181,10 +206,10 @@ that will be added to the plugin's classpath. This allows a custom Hazelcast ...@@ -181,10 +206,10 @@ that will be added to the plugin's classpath. This allows a custom Hazelcast
configuration file to be located outside the Openfire home directory.</li> configuration file to be located outside the Openfire home directory.</li>
<li><i>hazelcast.config.jmx.enabled</i> (false): Enables JMX support for <li><i>hazelcast.config.jmx.enabled</i> (false): Enables JMX support for
the Hazelcast cluster if JMX has been enabled via the Openfire admin console. the Hazelcast cluster if JMX has been enabled via the Openfire admin console.
Refer to the <a href="http://docs.hazelcast.org/docs/3.3/manual/html/monitoringwithjmx.html"> Refer to the <a href="http://docs.hazelcast.org/docs/3.4/manual/html/monitoringwithjmx.html">
Hazelcast JMX docs</a> for additional information.</li> Hazelcast JMX docs</a> for additional information.</li>
</ol> </ol>
<p>The Hazelcast plugin uses the <a href="http://docs.hazelcast.org/docs/3.3/manual/html/config.html"> <p>The Hazelcast plugin uses the <a href="http://docs.hazelcast.org/docs/3.4/manual/html/configurationoverview.html">
XML configuration builder</a> to initialize the cluster from the XML file described above. XML configuration builder</a> to initialize the cluster from the XML file described above.
By default the cluster members will attempt to discover each other via multicast at the By default the cluster members will attempt to discover each other via multicast at the
following location: following location:
...@@ -210,8 +235,33 @@ following alternative: ...@@ -210,8 +235,33 @@ following alternative:
&lt;/join&gt; &lt;/join&gt;
... ...
</pre> </pre>
<p>Please refer to the <a href="http://docs.hazelcast.org/docs/3.3/manual/html-single/"> <p>Please refer to the <a href="http://docs.hazelcast.org/docs/3.4/manual/html-single/">
Hazelcast reference manual</a> for more information. Hazelcast reference manual</a> for more information.
</p> </p>
<h3>A Word About Garbage Collection</h3>
<p>Hazelcast is quite sensitive to delays that may be caused by long-running GC cycles which are typical
of servers using a default runtime JVM configuration. In most cases it will be preferable to activate the
concurrent garbage collector (CMS) or the new G1 garbage collector to minimize blocking within the JVM.
When using CMS, you may be able to counter the effects of heap fragmentation by using JMX to invoke
System.gc() when the cluster is relatively idle (e.g. overnight). This has the effect of temporarily
interrupting the concurrent GC algortithm in favor of the default GC to collect and compact the heap.
</p>
<p>In addition, the runtime characteristics of your Openfire cluster will vary greatly depending on the
number and type of clients that are connected, and which XMPP services you are using in your deployment.
However, note that because many of the objects allocated on the heap are of the short-lived variety,
increasing the proportion of young generation (eden) space may also have a positive impact on performance.
As an example, the following OPENFIRE_OPTS have been shown to be suitable in a three-node cluster of
servers (four CPUs each), supporting approximately 50k active users:
</p>
<pre>
OPENFIRE_OPTS="-Xmx4G -Xms4G -XX:NewRatio=1 -XX:SurvivorRatio=4
-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=1
-XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSInitiatingOccupancyOnly
-XX:+PrintGCDetails -XX:+PrintPromotionFailure"
</pre>
<p>This GC configuration will also emit helpful GC diagnostic information to the console to aid further
tuning and troubleshooting as appropriate for your deployment.
</p>
</body> </body>
</html> </html>
/** /**
* $RCSfile$ * $RCSfile$
* $Revision: $ * $Revision: $
* $Date: $ * $Date: $
* *
* Copyright (C) 2004-2009 Jive Software. All rights reserved. * Copyright (C) 2004-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire; package org.jivesoftware.openfire.plugin;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.util.TimerTask; import java.util.TimerTask;
import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.cluster.ClusterManager; import org.jivesoftware.openfire.cluster.ClusterManager;
import org.jivesoftware.openfire.container.Plugin; import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager; import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.TaskEngine; import org.jivesoftware.util.TaskEngine;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* Hazelcast clustering plugin. This implementation is based upon * Hazelcast clustering plugin. This implementation is based upon
* (and borrows heavily from) the original Openfire clustering plugin. * (and borrows heavily from) the original Openfire clustering plugin.
* See this plugin's README file for more information. * See this plugin's README file for more information.
* *
* @author Tom Evans * @author Tom Evans
* @author Matt Tucker * @author Matt Tucker
*/ */
public class HazelcastPlugin extends TimerTask implements Plugin { public class HazelcastPlugin extends TimerTask implements Plugin {
private static Logger logger = LoggerFactory.getLogger(HazelcastPlugin.class); private static Logger logger = LoggerFactory.getLogger(HazelcastPlugin.class);
private static final long CLUSTER_STARTUP_DELAY_TIME = private static final long CLUSTER_STARTUP_DELAY_TIME =
JiveGlobals.getLongProperty("hazelcast.startup.delay.seconds", 5); JiveGlobals.getLongProperty("hazelcast.startup.delay.seconds", 5);
public void initializePlugin(PluginManager manager, File pluginDirectory) { public void initializePlugin(PluginManager manager, File pluginDirectory) {
// start cluster using a separate thread after a short delay // start cluster using a separate thread after a short delay
// this will allow other plugins to initialize during startup // this will allow other plugins to initialize during startup
TaskEngine.getInstance().schedule(this, CLUSTER_STARTUP_DELAY_TIME*1000); TaskEngine.getInstance().schedule(this, CLUSTER_STARTUP_DELAY_TIME*1000);
} }
@Override @Override
public void run() { public void run() {
System.out.println("Starting Hazelcast Clustering Plugin"); System.out.println("Starting Hazelcast Clustering Plugin");
// Check if another cluster is installed and stop loading this plugin if found // Check if another cluster is installed and stop loading this plugin if found
File pluginDir = new File(JiveGlobals.getHomeDirectory(), "plugins"); File pluginDir = new File(JiveGlobals.getHomeDirectory(), "plugins");
File[] jars = pluginDir.listFiles(new FileFilter() { File[] jars = pluginDir.listFiles(new FileFilter() {
public boolean accept(File pathname) { public boolean accept(File pathname) {
String fileName = pathname.getName().toLowerCase(); String fileName = pathname.getName().toLowerCase();
return (fileName.equalsIgnoreCase("enterprise.jar") || return (fileName.equalsIgnoreCase("enterprise.jar") ||
fileName.equalsIgnoreCase("coherence.jar")); fileName.equalsIgnoreCase("coherence.jar"));
} }
}); });
if (jars.length > 0) { if (jars.length > 0) {
// Do not load this plugin if a conflicting implementation exists // Do not load this plugin if a conflicting implementation exists
logger.warn("Conflicting clustering plugins found; remove Coherence and/or Enterprise jar files"); logger.warn("Conflicting clustering plugins found; remove Coherence and/or Enterprise jar files");
throw new IllegalStateException("Clustering plugin configuration conflict (Coherence)"); throw new IllegalStateException("Clustering plugin configuration conflict (Coherence)");
} }
ClusterManager.startup(); ClusterManager.startup();
} }
public void destroyPlugin() { public void destroyPlugin() {
// Shutdown is initiated by XMPPServer before unloading plugins // Shutdown is initiated by XMPPServer before unloading plugins
if (!XMPPServer.getInstance().isShuttingDown()) { if (!XMPPServer.getInstance().isShuttingDown()) {
ClusterManager.shutdown(); ClusterManager.shutdown();
} }
} }
} }
/** /**
* $Revision: $ * $Revision: $
* $Date: $ * $Date: $
* *
* Copyright (C) 2007-2009 Jive Software. All rights reserved. * Copyright (C) 2007-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire.session; package org.jivesoftware.openfire.plugin.session;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInput; import java.io.ObjectInput;
import java.io.ObjectOutput; import java.io.ObjectOutput;
import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.cluster.NodeID; import org.jivesoftware.openfire.cluster.NodeID;
import org.jivesoftware.openfire.session.ClientSession; import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.openfire.session.Session; import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.openfire.spi.ClientRoute; import org.jivesoftware.openfire.spi.ClientRoute;
import org.jivesoftware.openfire.spi.RoutingTableImpl; import org.jivesoftware.openfire.spi.RoutingTableImpl;
import org.jivesoftware.util.cache.Cache; import org.jivesoftware.util.cache.Cache;
import org.jivesoftware.util.cache.CacheFactory; import org.jivesoftware.util.cache.CacheFactory;
import org.jivesoftware.util.cache.ExternalizableUtil; import org.jivesoftware.util.cache.ExternalizableUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
/** /**
* Class that defines possible remote operations that could be performed * Class that defines possible remote operations that could be performed
* on remote client sessions. * on remote client sessions.
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class ClientSessionTask extends RemoteSessionTask { public class ClientSessionTask extends RemoteSessionTask {
private static Logger logger = LoggerFactory.getLogger(ClientSessionTask.class); private static Logger logger = LoggerFactory.getLogger(ClientSessionTask.class);
private JID address; private JID address;
private transient Session session; private transient Session session;
public ClientSessionTask() { public ClientSessionTask() {
super(); super();
} }
protected ClientSessionTask(JID address, Operation operation) { protected ClientSessionTask(JID address, Operation operation) {
super(operation); super(operation);
this.address = address; this.address = address;
} }
Session getSession() { Session getSession() {
if (session == null) { if (session == null) {
session = XMPPServer.getInstance().getRoutingTable().getClientRoute(address); session = XMPPServer.getInstance().getRoutingTable().getClientRoute(address);
} }
return session; return session;
} }
public void run() { public void run() {
if (getSession() == null || getSession().isClosed()) { if (getSession() == null || getSession().isClosed()) {
logger.error("Session not found for JID: " + address); logger.error("Session not found for JID: " + address);
return; return;
} }
super.run(); super.run();
ClientSession session = (ClientSession) getSession(); ClientSession session = (ClientSession) getSession();
if (session instanceof RemoteClientSession) { if (session instanceof RemoteClientSession) {
// The session is being hosted by other cluster node so log this unexpected case // The session is being hosted by other cluster node so log this unexpected case
Cache<String, ClientRoute> usersCache = CacheFactory.createCache(RoutingTableImpl.C2S_CACHE_NAME); Cache<String, ClientRoute> usersCache = CacheFactory.createCache(RoutingTableImpl.C2S_CACHE_NAME);
ClientRoute route = usersCache.get(address.toString()); ClientRoute route = usersCache.get(address.toString());
NodeID nodeID = route.getNodeID(); NodeID nodeID = route.getNodeID();
logger.warn("Found remote session instead of local session. JID: " + address + " found in Node: " + logger.warn("Found remote session instead of local session. JID: " + address + " found in Node: " +
nodeID.toByteArray() + " and local node is: " + XMPPServer.getInstance().getNodeID().toByteArray()); nodeID.toByteArray() + " and local node is: " + XMPPServer.getInstance().getNodeID().toByteArray());
} }
if (operation == Operation.isInitialized) { if (operation == Operation.isInitialized) {
if (session instanceof RemoteClientSession) { if (session instanceof RemoteClientSession) {
// Something is wrong since the session shoud be local instead of remote // Something is wrong since the session shoud be local instead of remote
// Assume some default value // Assume some default value
result = true; result = true;
} }
else { else {
result = session.isInitialized(); result = session.isInitialized();
} }
} }
else if (operation == Operation.incrementConflictCount) { else if (operation == Operation.incrementConflictCount) {
if (session instanceof RemoteClientSession) { if (session instanceof RemoteClientSession) {
// Something is wrong since the session shoud be local instead of remote // Something is wrong since the session shoud be local instead of remote
// Assume some default value // Assume some default value
result = 2; result = 2;
} }
else { else {
result = session.incrementConflictCount(); result = session.incrementConflictCount();
} }
} }
} }
public void writeExternal(ObjectOutput out) throws IOException { public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out); super.writeExternal(out);
ExternalizableUtil.getInstance().writeSerializable(out, address); ExternalizableUtil.getInstance().writeSerializable(out, address);
} }
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in); super.readExternal(in);
address = (JID) ExternalizableUtil.getInstance().readSerializable(in); address = (JID) ExternalizableUtil.getInstance().readSerializable(in);
} }
public String toString() { public String toString() {
return super.toString() + " operation: " + operation + " address: " + address; return super.toString() + " operation: " + operation + " address: " + address;
} }
} }
/** /**
* $Revision: $ * $Revision: $
* $Date: $ * $Date: $
* *
* Copyright (C) 2007-2009 Jive Software. All rights reserved. * Copyright (C) 2007-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire.session; package org.jivesoftware.openfire.plugin.session;
import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.session.ComponentSession; import org.jivesoftware.openfire.session.ComponentSession;
import org.jivesoftware.openfire.session.Session; import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.util.cache.ExternalizableUtil; import org.jivesoftware.util.cache.ExternalizableUtil;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInput; import java.io.ObjectInput;
import java.io.ObjectOutput; import java.io.ObjectOutput;
/** /**
* Class that defines possible remote operations that could be performed * Class that defines possible remote operations that could be performed
* on remote component sessions (for external components only). * on remote component sessions (for external components only).
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class ComponentSessionTask extends RemoteSessionTask { public class ComponentSessionTask extends RemoteSessionTask {
private JID address; private JID address;
public ComponentSessionTask() { public ComponentSessionTask() {
} }
protected ComponentSessionTask(JID address, Operation operation) { protected ComponentSessionTask(JID address, Operation operation) {
super(operation); super(operation);
this.address = address; this.address = address;
} }
Session getSession() { Session getSession() {
return SessionManager.getInstance().getComponentSession(address.getDomain()); return SessionManager.getInstance().getComponentSession(address.getDomain());
} }
public void run() { public void run() {
super.run(); super.run();
if (operation == Operation.getType) { if (operation == Operation.getType) {
result = ((ComponentSession) getSession()).getExternalComponent().getType(); result = ((ComponentSession) getSession()).getExternalComponent().getType();
} }
else if (operation == Operation.getCategory) { else if (operation == Operation.getCategory) {
result = ((ComponentSession) getSession()).getExternalComponent().getCategory(); result = ((ComponentSession) getSession()).getExternalComponent().getCategory();
} }
else if (operation == Operation.getInitialSubdomain) { else if (operation == Operation.getInitialSubdomain) {
result = ((ComponentSession) getSession()).getExternalComponent().getInitialSubdomain(); result = ((ComponentSession) getSession()).getExternalComponent().getInitialSubdomain();
} }
else if (operation == Operation.getSubdomains) { else if (operation == Operation.getSubdomains) {
result = ((ComponentSession) getSession()).getExternalComponent().getSubdomains(); result = ((ComponentSession) getSession()).getExternalComponent().getSubdomains();
} }
else if (operation == Operation.getName) { else if (operation == Operation.getName) {
result = ((ComponentSession) getSession()).getExternalComponent().getName(); result = ((ComponentSession) getSession()).getExternalComponent().getName();
} }
else if (operation == Operation.getDescription) { else if (operation == Operation.getDescription) {
result = ((ComponentSession) getSession()).getExternalComponent().getDescription(); result = ((ComponentSession) getSession()).getExternalComponent().getDescription();
} }
else if (operation == Operation.start) { else if (operation == Operation.start) {
((ComponentSession) getSession()).getExternalComponent().start(); ((ComponentSession) getSession()).getExternalComponent().start();
} }
else if (operation == Operation.shutdown) { else if (operation == Operation.shutdown) {
((ComponentSession) getSession()).getExternalComponent().shutdown(); ((ComponentSession) getSession()).getExternalComponent().shutdown();
} }
} }
public void writeExternal(ObjectOutput out) throws IOException { public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out); super.writeExternal(out);
ExternalizableUtil.getInstance().writeSerializable(out, address); ExternalizableUtil.getInstance().writeSerializable(out, address);
} }
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in); super.readExternal(in);
address = (JID) ExternalizableUtil.getInstance().readSerializable(in); address = (JID) ExternalizableUtil.getInstance().readSerializable(in);
} }
public String toString() { public String toString() {
return super.toString() + " operation: " + operation + " address: " + address; return super.toString() + " operation: " + operation + " address: " + address;
} }
} }
/** /**
* $Revision: $ * $Revision: $
* $Date: $ * $Date: $
* *
* Copyright (C) 2007-2009 Jive Software. All rights reserved. * Copyright (C) 2007-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire.session; package org.jivesoftware.openfire.plugin.session;
import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.session.Session; import org.jivesoftware.openfire.session.Session;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
/** /**
* Class that defines possible remote operations that could be performed * Class that defines possible remote operations that could be performed
* on remote connection manager sessions. * on remote connection manager sessions.
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class ConnectionMultiplexerSessionTask extends RemoteSessionTask { public class ConnectionMultiplexerSessionTask extends RemoteSessionTask {
private JID address; private JID address;
public ConnectionMultiplexerSessionTask() { public ConnectionMultiplexerSessionTask() {
} }
protected ConnectionMultiplexerSessionTask(JID address, Operation operation) { protected ConnectionMultiplexerSessionTask(JID address, Operation operation) {
super(operation); super(operation);
this.address = address; this.address = address;
} }
Session getSession() { Session getSession() {
return SessionManager.getInstance().getConnectionMultiplexerSession(address); return SessionManager.getInstance().getConnectionMultiplexerSession(address);
} }
public String toString() { public String toString() {
return super.toString() + " operation: " + operation + " address: " + address; return super.toString() + " operation: " + operation + " address: " + address;
} }
} }
/** /**
* $Revision: $ * $Revision: $
* $Date: $ * $Date: $
* *
* Copyright (C) 2007-2009 Jive Software. All rights reserved. * Copyright (C) 2007-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire.session; package org.jivesoftware.openfire.plugin.session;
import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.session.IncomingServerSession; import org.jivesoftware.openfire.session.IncomingServerSession;
import org.jivesoftware.openfire.session.Session; import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.util.cache.ExternalizableUtil; import org.jivesoftware.util.cache.ExternalizableUtil;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInput; import java.io.ObjectInput;
import java.io.ObjectOutput; import java.io.ObjectOutput;
/** /**
* Class that defines possible remote operations that could be performed * Class that defines possible remote operations that could be performed
* on remote incoming server sessions. * on remote incoming server sessions.
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class IncomingServerSessionTask extends RemoteSessionTask { public class IncomingServerSessionTask extends RemoteSessionTask {
private String streamID; private String streamID;
public IncomingServerSessionTask() { public IncomingServerSessionTask() {
super(); super();
} }
protected IncomingServerSessionTask(Operation operation, String streamID) { protected IncomingServerSessionTask(Operation operation, String streamID) {
super(operation); super(operation);
this.streamID = streamID; this.streamID = streamID;
} }
Session getSession() { Session getSession() {
return SessionManager.getInstance().getIncomingServerSession(streamID); return SessionManager.getInstance().getIncomingServerSession(streamID);
} }
public void run() { public void run() {
super.run(); super.run();
if (operation == Operation.getLocalDomain) { if (operation == Operation.getLocalDomain) {
result = ((IncomingServerSession) getSession()).getLocalDomain(); result = ((IncomingServerSession) getSession()).getLocalDomain();
} }
else if (operation == Operation.getAddress) { else if (operation == Operation.getAddress) {
result = getSession().getAddress(); result = getSession().getAddress();
} }
else if (operation == Operation.isUsingServerDialback) { else if (operation == Operation.isUsingServerDialback) {
result = ((IncomingServerSession) getSession()).isUsingServerDialback(); result = ((IncomingServerSession) getSession()).isUsingServerDialback();
} }
} }
public void writeExternal(ObjectOutput out) throws IOException { public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out); super.writeExternal(out);
ExternalizableUtil.getInstance().writeSafeUTF(out, streamID); ExternalizableUtil.getInstance().writeSafeUTF(out, streamID);
} }
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in); super.readExternal(in);
streamID = ExternalizableUtil.getInstance().readSafeUTF(in); streamID = ExternalizableUtil.getInstance().readSafeUTF(in);
} }
public String toString() { public String toString() {
return super.toString() + " operation: " + operation + " streamID: " + streamID; return super.toString() + " operation: " + operation + " streamID: " + streamID;
} }
} }
/** /**
* $Revision: $ * $Revision: $
* $Date: $ * $Date: $
* *
* Copyright (C) 2007-2009 Jive Software. All rights reserved. * Copyright (C) 2007-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire.session; package org.jivesoftware.openfire.plugin.session;
import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.session.OutgoingServerSession; import org.jivesoftware.openfire.session.OutgoingServerSession;
import org.jivesoftware.openfire.session.Session; import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.util.cache.ExternalizableUtil; import org.jivesoftware.util.cache.ExternalizableUtil;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInput; import java.io.ObjectInput;
import java.io.ObjectOutput; import java.io.ObjectOutput;
/** /**
* Class that defines possible remote operations that could be performed * Class that defines possible remote operations that could be performed
* on remote outgoing server sessions. * on remote outgoing server sessions.
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class OutgoingServerSessionTask extends RemoteSessionTask { public class OutgoingServerSessionTask extends RemoteSessionTask {
private JID address; private JID address;
public OutgoingServerSessionTask() { public OutgoingServerSessionTask() {
} }
protected OutgoingServerSessionTask(JID address, Operation operation) { protected OutgoingServerSessionTask(JID address, Operation operation) {
super(operation); super(operation);
this.address = address; this.address = address;
} }
Session getSession() { Session getSession() {
return SessionManager.getInstance().getOutgoingServerSession(address.getDomain()); return SessionManager.getInstance().getOutgoingServerSession(address.getDomain());
} }
public void run() { public void run() {
super.run(); super.run();
if (operation == Operation.getAuthenticatedDomains) { if (operation == Operation.getAuthenticatedDomains) {
result = ((OutgoingServerSession) getSession()).getAuthenticatedDomains(); result = ((OutgoingServerSession) getSession()).getAuthenticatedDomains();
} }
else if (operation == Operation.getHostnames) { else if (operation == Operation.getHostnames) {
result = ((OutgoingServerSession) getSession()).getHostnames(); result = ((OutgoingServerSession) getSession()).getHostnames();
} }
else if (operation == Operation.isUsingServerDialback) { else if (operation == Operation.isUsingServerDialback) {
result = ((OutgoingServerSession) getSession()).isUsingServerDialback(); result = ((OutgoingServerSession) getSession()).isUsingServerDialback();
} }
} }
public void writeExternal(ObjectOutput out) throws IOException { public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out); super.writeExternal(out);
ExternalizableUtil.getInstance().writeSerializable(out, address); ExternalizableUtil.getInstance().writeSerializable(out, address);
} }
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in); super.readExternal(in);
address = (JID) ExternalizableUtil.getInstance().readSerializable(in); address = (JID) ExternalizableUtil.getInstance().readSerializable(in);
} }
public String toString() { public String toString() {
return super.toString() + " operation: " + operation + " address: " + address; return super.toString() + " operation: " + operation + " address: " + address;
} }
} }
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire.session; package org.jivesoftware.openfire.plugin.session;
import org.dom4j.Element; import org.dom4j.Element;
import org.dom4j.tree.DefaultElement; import org.dom4j.tree.DefaultElement;
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire.session; package org.jivesoftware.openfire.plugin.session;
import org.dom4j.Element; import org.dom4j.Element;
import org.dom4j.tree.DefaultElement; import org.dom4j.tree.DefaultElement;
......
/** /**
* $Revision: $ * $Revision: $
* $Date: $ * $Date: $
* *
* Copyright (C) 2007-2009 Jive Software. All rights reserved. * Copyright (C) 2007-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire.session; package org.jivesoftware.openfire.plugin.session;
import org.jivesoftware.openfire.session.ConnectionMultiplexerSession; import org.jivesoftware.openfire.session.ConnectionMultiplexerSession;
import org.jivesoftware.util.cache.ClusterTask; import org.jivesoftware.util.cache.ClusterTask;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import org.xmpp.packet.Packet; import org.xmpp.packet.Packet;
/** /**
* Surrogate for connection manager sessions hosted in some remote cluster node. * Surrogate for connection manager sessions hosted in some remote cluster node.
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class RemoteConnectionMultiplexerSession extends RemoteSession implements ConnectionMultiplexerSession { public class RemoteConnectionMultiplexerSession extends RemoteSession implements ConnectionMultiplexerSession {
public RemoteConnectionMultiplexerSession(byte[] nodeID, JID address) { public RemoteConnectionMultiplexerSession(byte[] nodeID, JID address) {
super(nodeID, address); super(nodeID, address);
} }
RemoteSessionTask getRemoteSessionTask(RemoteSessionTask.Operation operation) { RemoteSessionTask getRemoteSessionTask(RemoteSessionTask.Operation operation) {
return new ConnectionMultiplexerSessionTask(address, operation); return new ConnectionMultiplexerSessionTask(address, operation);
} }
ClusterTask getDeliverRawTextTask(String text) { ClusterTask getDeliverRawTextTask(String text) {
return new DeliverRawTextTask(this, address, text); return new DeliverRawTextTask(this, address, text);
} }
ClusterTask getProcessPacketTask(Packet packet) { ClusterTask getProcessPacketTask(Packet packet) {
return new ProcessPacketTask(this, address, packet); return new ProcessPacketTask(this, address, packet);
} }
} }
/** /**
* $Revision: $ * $Revision: $
* $Date: $ * $Date: $
* *
* Copyright (C) 2007-2009 Jive Software. All rights reserved. * Copyright (C) 2007-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire.session; package org.jivesoftware.openfire.plugin.session;
import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.session.IncomingServerSession; import org.jivesoftware.openfire.session.IncomingServerSession;
import org.jivesoftware.util.cache.ClusterTask; import org.jivesoftware.util.cache.ClusterTask;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import org.xmpp.packet.Packet; import org.xmpp.packet.Packet;
import java.util.Collection; import java.util.Collection;
/** /**
* Surrogate for incoming server sessions hosted in some remote cluster node. * Surrogate for incoming server sessions hosted in some remote cluster node.
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class RemoteIncomingServerSession extends RemoteSession implements IncomingServerSession { public class RemoteIncomingServerSession extends RemoteSession implements IncomingServerSession {
private String localDomain; private String localDomain;
private long usingServerDialback = -1; private long usingServerDialback = -1;
public RemoteIncomingServerSession(byte[] nodeID, String streamID) { public RemoteIncomingServerSession(byte[] nodeID, String streamID) {
super(nodeID, null); super(nodeID, null);
this.streamID = new BasicStreamID(streamID); this.streamID = new BasicStreamID(streamID);
} }
public boolean isUsingServerDialback() { public boolean isUsingServerDialback() {
if (usingServerDialback == -1) { if (usingServerDialback == -1) {
ClusterTask task = getRemoteSessionTask(RemoteSessionTask.Operation.isUsingServerDialback); ClusterTask task = getRemoteSessionTask(RemoteSessionTask.Operation.isUsingServerDialback);
usingServerDialback = (Boolean) doSynchronousClusterTask(task) ? 1 : 0; usingServerDialback = (Boolean) doSynchronousClusterTask(task) ? 1 : 0;
} }
return usingServerDialback == 1; return usingServerDialback == 1;
} }
public JID getAddress() { public JID getAddress() {
if (address == null) { if (address == null) {
RemoteSessionTask task = getRemoteSessionTask(RemoteSessionTask.Operation.getAddress); RemoteSessionTask task = getRemoteSessionTask(RemoteSessionTask.Operation.getAddress);
address = (JID) doSynchronousClusterTask(task); address = (JID) doSynchronousClusterTask(task);
} }
return address; return address;
} }
public Collection<String> getValidatedDomains() { public Collection<String> getValidatedDomains() {
// Content is stored in a clustered cache so that even in the case of the node hosting // Content is stored in a clustered cache so that even in the case of the node hosting
// the sessions is lost we can still have access to this info to be able to perform // the sessions is lost we can still have access to this info to be able to perform
// proper clean up logic {@link ClusterListener#cleanupNode(NodeCacheKey) // proper clean up logic {@link ClusterListener#cleanupNode(NodeCacheKey)
return SessionManager.getInstance().getValidatedDomains(streamID.getID()); return SessionManager.getInstance().getValidatedDomains(streamID.getID());
} }
public String getLocalDomain() { public String getLocalDomain() {
if (localDomain == null) { if (localDomain == null) {
RemoteSessionTask task = getRemoteSessionTask(RemoteSessionTask.Operation.getLocalDomain); RemoteSessionTask task = getRemoteSessionTask(RemoteSessionTask.Operation.getLocalDomain);
localDomain = (String) doSynchronousClusterTask(task); localDomain = (String) doSynchronousClusterTask(task);
} }
return localDomain; return localDomain;
} }
RemoteSessionTask getRemoteSessionTask(RemoteSessionTask.Operation operation) { RemoteSessionTask getRemoteSessionTask(RemoteSessionTask.Operation operation) {
return new IncomingServerSessionTask(operation, streamID.getID()); return new IncomingServerSessionTask(operation, streamID.getID());
} }
ClusterTask getDeliverRawTextTask(String text) { ClusterTask getDeliverRawTextTask(String text) {
return new DeliverRawTextTask(streamID.getID(), text); return new DeliverRawTextTask(streamID.getID(), text);
} }
ClusterTask getProcessPacketTask(Packet packet) { ClusterTask getProcessPacketTask(Packet packet) {
return new ProcessPacketTask(streamID.getID(), packet); return new ProcessPacketTask(streamID.getID(), packet);
} }
} }
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire.session; package org.jivesoftware.openfire.plugin.session;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Date; import java.util.Date;
......
/** /**
* $Revision: $ * $Revision: $
* $Date: $ * $Date: $
* *
* Copyright (C) 2007-2009 Jive Software. All rights reserved. * Copyright (C) 2007-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.openfire.session; package org.jivesoftware.openfire.plugin.session;
import org.jivesoftware.openfire.session.*; import org.jivesoftware.openfire.session.*;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
/** /**
* Locator of sessions that know how to talk to Hazelcast cluster nodes. * Locator of sessions that know how to talk to Hazelcast cluster nodes.
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class RemoteSessionLocator implements org.jivesoftware.openfire.session.RemoteSessionLocator { public class RemoteSessionLocator implements org.jivesoftware.openfire.session.RemoteSessionLocator {
// TODO Keep a cache for a brief moment so we can reuse same instances (that use their own cache) // TODO Keep a cache for a brief moment so we can reuse same instances (that use their own cache)
public ClientSession getClientSession(byte[] nodeID, JID address) { public ClientSession getClientSession(byte[] nodeID, JID address) {
return new RemoteClientSession(nodeID, address); return new RemoteClientSession(nodeID, address);
} }
public ComponentSession getComponentSession(byte[] nodeID, JID address) { public ComponentSession getComponentSession(byte[] nodeID, JID address) {
return new RemoteComponentSession(nodeID, address); return new RemoteComponentSession(nodeID, address);
} }
public ConnectionMultiplexerSession getConnectionMultiplexerSession(byte[] nodeID, JID address) { public ConnectionMultiplexerSession getConnectionMultiplexerSession(byte[] nodeID, JID address) {
return new RemoteConnectionMultiplexerSession(nodeID, address); return new RemoteConnectionMultiplexerSession(nodeID, address);
} }
public IncomingServerSession getIncomingServerSession(byte[] nodeID, String streamID) { public IncomingServerSession getIncomingServerSession(byte[] nodeID, String streamID) {
return new RemoteIncomingServerSession(nodeID, streamID); return new RemoteIncomingServerSession(nodeID, streamID);
} }
public OutgoingServerSession getOutgoingServerSession(byte[] nodeID, JID address) { public OutgoingServerSession getOutgoingServerSession(byte[] nodeID, JID address) {
return new RemoteOutgoingServerSession(nodeID, address); return new RemoteOutgoingServerSession(nodeID, address);
} }
} }
/** /**
* $Revision: $ * $Revision: $
* $Date: $ * $Date: $
* *
* Copyright (C) 2007-2009 Jive Software. All rights reserved. * Copyright (C) 2007-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.util.cache; package org.jivesoftware.openfire.plugin.util.cache;
import java.util.Set; import java.util.Set;
import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.cluster.NodeID; import org.jivesoftware.openfire.cluster.NodeID;
import org.jivesoftware.util.StringUtils; import org.jivesoftware.util.StringUtils;
import com.hazelcast.core.EntryEvent; import com.hazelcast.core.EntryEvent;
import com.hazelcast.core.EntryListener; import com.hazelcast.core.EntryListener;
import com.hazelcast.core.MapEvent; import com.hazelcast.core.MapEvent;
/** /**
* Base listener for cache events in the cluster. This class helps keep track * Base listener for cache events in the cluster. This class helps keep track
* of nodes and their elements. The actual tracking information is kept in * of nodes and their elements. The actual tracking information is kept in
* {@link ClusterListener}. This information is then used when a node goes * {@link ClusterListener}. This information is then used when a node goes
* down to proper clean up can be done. * down to proper clean up can be done.
* *
* @author Tom Evans * @author Tom Evans
* @author Pete Matern * @author Pete Matern
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
class CacheListener implements EntryListener { class CacheListener implements EntryListener {
protected final String cacheName; protected final String cacheName;
private ClusterListener clusterListener; private ClusterListener clusterListener;
public CacheListener(ClusterListener clusterListener, String cacheName) { public CacheListener(ClusterListener clusterListener, String cacheName) {
this.clusterListener = clusterListener; this.clusterListener = clusterListener;
this.cacheName = cacheName; this.cacheName = cacheName;
} }
public void entryAdded(EntryEvent event) { public void entryAdded(EntryEvent event) {
handleEntryEvent(event, false); handleEntryEvent(event, false);
} }
public void entryUpdated(EntryEvent event) { public void entryUpdated(EntryEvent event) {
handleEntryEvent(event, false); handleEntryEvent(event, false);
} }
public void entryRemoved(EntryEvent event) { public void entryRemoved(EntryEvent event) {
handleEntryEvent(event, true); handleEntryEvent(event, true);
} }
public void entryEvicted(EntryEvent event) { public void entryEvicted(EntryEvent event) {
handleEntryEvent(event, true); handleEntryEvent(event, true);
} }
private void handleEntryEvent(EntryEvent event, boolean removal) { private void handleEntryEvent(EntryEvent event, boolean removal) {
NodeID nodeID = NodeID.getInstance(StringUtils.getBytes(event.getMember().getUuid())); NodeID nodeID = NodeID.getInstance(StringUtils.getBytes(event.getMember().getUuid()));
// ignore events which were triggered by this node // ignore events which were triggered by this node
if (!XMPPServer.getInstance().getNodeID().equals(nodeID)) { if (!XMPPServer.getInstance().getNodeID().equals(nodeID)) {
Set<String> sessionJIDS = clusterListener.lookupJIDList(nodeID, cacheName); Set<String> sessionJIDS = clusterListener.lookupJIDList(nodeID, cacheName);
if (removal) { if (removal) {
sessionJIDS.remove(event.getKey().toString()); sessionJIDS.remove(event.getKey().toString());
} }
else { else {
sessionJIDS.add(event.getKey().toString()); sessionJIDS.add(event.getKey().toString());
} }
} }
} }
private void handleMapEvent(MapEvent event) { private void handleMapEvent(MapEvent event) {
NodeID nodeID = NodeID.getInstance(StringUtils.getBytes(event.getMember().getUuid())); NodeID nodeID = NodeID.getInstance(StringUtils.getBytes(event.getMember().getUuid()));
// ignore events which were triggered by this node // ignore events which were triggered by this node
if (!XMPPServer.getInstance().getNodeID().equals(nodeID)) { if (!XMPPServer.getInstance().getNodeID().equals(nodeID)) {
Set<String> sessionJIDs = clusterListener.lookupJIDList(nodeID, cacheName); Set<String> sessionJIDs = clusterListener.lookupJIDList(nodeID, cacheName);
sessionJIDs.clear(); sessionJIDs.clear();
} }
} }
@Override @Override
public void mapCleared(MapEvent event) { public void mapCleared(MapEvent event) {
handleMapEvent(event); handleMapEvent(event);
} }
@Override @Override
public void mapEvicted(MapEvent event) { public void mapEvicted(MapEvent event) {
handleMapEvent(event); handleMapEvent(event);
} }
} }
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.util.cache; package org.jivesoftware.openfire.plugin.util.cache;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
...@@ -38,6 +38,7 @@ import org.jivesoftware.openfire.cluster.ClusterNodeInfo; ...@@ -38,6 +38,7 @@ import org.jivesoftware.openfire.cluster.ClusterNodeInfo;
import org.jivesoftware.openfire.cluster.NodeID; import org.jivesoftware.openfire.cluster.NodeID;
import org.jivesoftware.openfire.handler.DirectedPresence; import org.jivesoftware.openfire.handler.DirectedPresence;
import org.jivesoftware.openfire.handler.PresenceUpdateHandler; import org.jivesoftware.openfire.handler.PresenceUpdateHandler;
import org.jivesoftware.openfire.plugin.util.cluster.HazelcastClusterNodeInfo;
import org.jivesoftware.openfire.session.ClientSessionInfo; import org.jivesoftware.openfire.session.ClientSessionInfo;
import org.jivesoftware.openfire.session.IncomingServerSession; import org.jivesoftware.openfire.session.IncomingServerSession;
import org.jivesoftware.openfire.session.RemoteSessionLocator; import org.jivesoftware.openfire.session.RemoteSessionLocator;
...@@ -64,7 +65,6 @@ import com.hazelcast.core.Member; ...@@ -64,7 +65,6 @@ import com.hazelcast.core.Member;
import com.hazelcast.core.MemberAttributeEvent; import com.hazelcast.core.MemberAttributeEvent;
import com.hazelcast.core.MembershipEvent; import com.hazelcast.core.MembershipEvent;
import com.hazelcast.core.MembershipListener; import com.hazelcast.core.MembershipListener;
import com.jivesoftware.util.cluster.HazelcastClusterNodeInfo;
/** /**
* ClusterListener reacts to membership changes in the cluster. It takes care of cleaning up the state * ClusterListener reacts to membership changes in the cluster. It takes care of cleaning up the state
...@@ -473,8 +473,10 @@ public class ClusterListener implements MembershipListener, LifecycleListener { ...@@ -473,8 +473,10 @@ public class ClusterListener implements MembershipListener, LifecycleListener {
Collection<JID> getHandlers(EntryEvent event) { Collection<JID> getHandlers(EntryEvent event) {
Object value = event.getValue(); Object value = event.getValue();
Collection<JID> answer = new ArrayList<JID>(); Collection<JID> answer = new ArrayList<JID>();
for (DirectedPresence directedPresence : (Collection<DirectedPresence>)value) { if (value != null) {
answer.add(directedPresence.getHandler()); for (DirectedPresence directedPresence : (Collection<DirectedPresence>)value) {
answer.add(directedPresence.getHandler());
}
} }
return answer; return answer;
} }
......
/** /**
* $Revision$ * $Revision$
* $Date$ * $Date$
* *
* Copyright (C) 1999-2009 Jive Software. All rights reserved. * Copyright (C) 1999-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.util.cluster; package org.jivesoftware.openfire.plugin.util.cluster;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInput; import java.io.ObjectInput;
import java.io.ObjectOutput; import java.io.ObjectOutput;
import org.dom4j.Element; import org.dom4j.Element;
import org.dom4j.tree.DefaultElement; import org.dom4j.tree.DefaultElement;
import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.util.cache.ClusterTask; import org.jivesoftware.util.cache.ClusterTask;
import org.jivesoftware.util.cache.ExternalizableUtil; import org.jivesoftware.util.cache.ExternalizableUtil;
import org.xmpp.packet.Message; import org.xmpp.packet.Message;
/** /**
* Task that will broadcast a message to local connected client sessions. * Task that will broadcast a message to local connected client sessions.
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class BroadcastMessage implements ClusterTask { public class BroadcastMessage implements ClusterTask {
private Message packet; private Message packet;
public BroadcastMessage() { public BroadcastMessage() {
} }
public BroadcastMessage(Message packet) { public BroadcastMessage(Message packet) {
this.packet = packet; this.packet = packet;
} }
public Object getResult() { public Object getResult() {
// Not used since we are using #execute and not #query when using InvocationService // Not used since we are using #execute and not #query when using InvocationService
return null; return null;
} }
public void run() { public void run() {
// Broadcast message to client sessions connected to this node // Broadcast message to client sessions connected to this node
XMPPServer.getInstance().getRoutingTable().broadcastPacket(packet, true); XMPPServer.getInstance().getRoutingTable().broadcastPacket(packet, true);
} }
public void writeExternal(ObjectOutput out) throws IOException { public void writeExternal(ObjectOutput out) throws IOException {
ExternalizableUtil.getInstance().writeSerializable(out, (DefaultElement) packet.getElement()); ExternalizableUtil.getInstance().writeSerializable(out, (DefaultElement) packet.getElement());
} }
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
Element packetElement = (Element) ExternalizableUtil.getInstance().readSerializable(in); Element packetElement = (Element) ExternalizableUtil.getInstance().readSerializable(in);
packet = new Message(packetElement, true); packet = new Message(packetElement, true);
} }
} }
/** /**
* $Revision$ * $Revision$
* $Date$ * $Date$
* *
* Copyright (C) 1999-2009 Jive Software. All rights reserved. * Copyright (C) 1999-2009 Jive Software. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.jivesoftware.util.cluster; package org.jivesoftware.openfire.plugin.util.cluster;
import org.jivesoftware.openfire.RemotePacketRouter; import org.jivesoftware.openfire.RemotePacketRouter;
import org.jivesoftware.util.cache.CacheFactory; import org.jivesoftware.util.cache.CacheFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import org.xmpp.packet.Message; import org.xmpp.packet.Message;
import org.xmpp.packet.Packet; import org.xmpp.packet.Packet;
/** /**
* Route packets to other nodes of the cluster. If the remote node was not found or failed * Route packets to other nodes of the cluster. If the remote node was not found or failed
* to be reached then depending on the type of packet an error packet will be returned. In case * to be reached then depending on the type of packet an error packet will be returned. In case
* the remote node is reached but the remote node fails to route the packet to the recipient (e.g. * the remote node is reached but the remote node fails to route the packet to the recipient (e.g.
* the recipient just left) then an error packet may be created from the remote node and send it * the recipient just left) then an error packet may be created from the remote node and send it
* back to this node.<p> * back to this node.<p>
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class ClusterPacketRouter implements RemotePacketRouter { public class ClusterPacketRouter implements RemotePacketRouter {
private static Logger logger = LoggerFactory.getLogger(ClusterPacketRouter.class); private static Logger logger = LoggerFactory.getLogger(ClusterPacketRouter.class);
public boolean routePacket(byte[] nodeID, JID receipient, Packet packet) { public boolean routePacket(byte[] nodeID, JID receipient, Packet packet) {
// Send the packet to the specified node and let the remote node deliver the packet to the recipient // Send the packet to the specified node and let the remote node deliver the packet to the recipient
try { try {
CacheFactory.doClusterTask(new RemotePacketExecution(receipient, packet), nodeID); CacheFactory.doClusterTask(new RemotePacketExecution(receipient, packet), nodeID);
return true; return true;
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
logger.warn("Error while routing packet to remote node: " + e); logger.warn("Error while routing packet to remote node: " + e);
return false; return false;
} }
} }
public void broadcastPacket(Message packet) { public void broadcastPacket(Message packet) {
// Execute the broadcast task across the cluster // Execute the broadcast task across the cluster
CacheFactory.doClusterTask(new BroadcastMessage(packet)); CacheFactory.doClusterTask(new BroadcastMessage(packet));
} }
} }
<%@ page import="com.jivesoftware.util.cluster.NodeRuntimeStats, <%@ page import="org.jivesoftware.openfire.plugin.util.cluster.NodeRuntimeStats,
org.jivesoftware.util.cache.CacheFactory, org.jivesoftware.util.cache.CacheFactory,
com.hazelcast.core.Hazelcast, com.hazelcast.core.Hazelcast,
com.hazelcast.core.Cluster, com.hazelcast.core.Cluster,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment