Commit f4bbdc61 authored by Tom Evans's avatar Tom Evans

Merge pull request #86 from tevans/master

OF-843: Update Hazelcast plugin
parents c5e57896 7032818e
......@@ -134,11 +134,12 @@
<path id="javadoc.dependencies">
<fileset dir="${lib.build.dir}" includes="*.jar" excludes="junit.jar"/>
<fileset dir="${lib.merge.dir}" includes="*.jar"/>
<fileset dir="${lib.dist.dir}"
includes="servlet-api.jar, mail.jar, jdic.jar, bcpg-jdk15on.jar bcpkix-jdk15on.jar bcprov-jdk15on.jar"/>
<fileset dir="${lib.dist.dir}" includes="servlet-api.jar, servlet-api-schemas.jar, mail.jar, jdic.jar"/>
<fileset dir="${lib.dist.dir}" includes="bcpg-jdk15on.jar, bcpkix-jdk15on.jar, bcprov-jdk15on.jar"/>
</path>
<path id="compile.dependencies">
<path refid="ant.dependencies"/>
<path refid="javadoc.dependencies"/>
</path>
......
......@@ -206,7 +206,11 @@ public class InternalComponentManager extends BasicModule implements ComponentMa
* @param subdomain the subdomain of the component's address.
*/
public void removeComponent(String subdomain) {
List<Component> componentsToRemove = new ArrayList<Component>(routables.get(subdomain).getComponents());
RoutableComponents components = null;
if (routables == null || (components = routables.get(subdomain)) == null) {
return;
}
List<Component> componentsToRemove = new ArrayList<Component>(components.getComponents());
for (Component component : componentsToRemove) {
removeComponent(subdomain, component);
}
......
......@@ -205,6 +205,9 @@ public class Version implements Comparable<Version> {
@Override
public int compareTo(Version that) {
if (that == null) {
return 1;
}
long thisVersion = (this.getMicro()*10) + (this.getMinor()*1000) + (this.getMajor()*100000);
long thatVersion = (that.getMicro()*10) + (that.getMinor()*1000) + (that.getMajor()*100000);
......
......@@ -44,6 +44,13 @@
Hazelcast Clustering Plugin Changelog
</h1>
<p><b>1.3.1</b> -- October 15, 2014</p>
<p>Hazelcast plugin update for Openfire 3.10.x:</p>
<ul>
<li>Updated Hazelcast to release 3.3.1 (<a href="http://docs.hazelcast.org/docs/3.3/manual/html-single/hazelcast-documentation.html#release-notes">what's new</a>).</li>
<li>Enhanced plugin to implement changes in the 3.10.x Openfire Session API (<a href="http://issues.igniterealtime.org/browse/OF-843">OF-843</a>).</li>
</ul>
<p><b>1.2.2</b> -- May 6, 2014</p>
<p>Bug Fix:</p>
<ul>
......@@ -61,7 +68,7 @@ Hazelcast Clustering Plugin Changelog
<p>Miscellaneous enhancements:</p>
<ul>
<li>Fix cluster initialization logic (<a href="http://issues.igniterealtime.org/browse/OF-699">OF-699</a>)</li>
<li>Updated Hazelcast to release 3.1.5.</li>
<li>Updated Hazelcast to release 3.1.5 (<a href="http://www.hazelcast.org/docs/3.1/manual/html-single/#WhatsNew31">what's new</a>).</li>
</ul>
<p><b>1.1.0</b> -- Sep 13, 2013</p>
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2008-2012, Hazel Bilisim Ltd. All Rights Reserved.
~ Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
......@@ -15,7 +15,7 @@
~ limitations under the License.
-->
<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.1.xsd"
<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.3.xsd"
xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<group>
......@@ -24,7 +24,10 @@
</group>
<management-center enabled="false"/>
<network>
<port auto-increment="true">5701</port>
<port auto-increment="true" port-count="100">5701</port>
<outbound-ports>
<ports>0</ports>
</outbound-ports>
<join>
<multicast enabled="true">
<multicast-group>224.2.2.3</multicast-group>
......@@ -33,46 +36,18 @@
<tcp-ip enabled="false"/>
<aws enabled="false"/>
</join>
<interfaces enabled="false"/>
<ssl enabled="false" />
<socket-interceptor enabled="false" />
<symmetric-encryption enabled="false">
<!--
encryption algorithm such as
DES/ECB/PKCS5Padding,
PBEWithMD5AndDES,
AES/CBC/PKCS5Padding,
Blowfish,
DESede
-->
<algorithm>PBEWithMD5AndDES</algorithm>
<!-- salt value to use when generating the secret key -->
<salt>thesalt</salt>
<!-- pass phrase to use when generating the secret key -->
<password>thepass</password>
<!-- iteration count to use when generating the secret key -->
<iteration-count>19</iteration-count>
</symmetric-encryption>
<asymmetric-encryption enabled="false">
<!-- encryption algorithm -->
<algorithm>RSA/NONE/PKCS1PADDING</algorithm>
<!-- private key password -->
<keyPassword>thekeypass</keyPassword>
<!-- private key alias -->
<keyAlias>local</keyAlias>
<!-- key store type -->
<storeType>JKS</storeType>
<!-- key store password -->
<storePassword>thestorepass</storePassword>
<!-- path to the key store -->
<storePath>keystore</storePath>
</asymmetric-encryption>
<interfaces enabled="false">
<interface>10.10.1.*</interface>
</interfaces>
<ssl enabled="false"/>
<socket-interceptor enabled="false"/>
<symmetric-encryption enabled="false"/>
<asymmetric-encryption enabled="false"/>
</network>
<partition-group enabled="false"/>
<executor-service>
<core-pool-size>16</core-pool-size>
<max-pool-size>64</max-pool-size>
<keep-alive-seconds>60</keep-alive-seconds>
<executor-service name="default">
<pool-size>16</pool-size>
<queue-capacity>0</queue-capacity>
</executor-service>
<queue name="default">
<!--
......@@ -145,6 +120,12 @@
get evicted.
-->
<eviction-percentage>25</eviction-percentage>
<!--
Minimum time in milliseconds which should pass before checking
if a partition of this map is evictable or not.
Default value is 100 millis.
-->
<min-eviction-check-millis>100</min-eviction-check-millis>
<!--
While recovering from split-brain (network partitioning),
map entries in the small cluster will merge into the bigger cluster
......@@ -152,16 +133,15 @@
cluster, there might an existing entry with the same key already.
Values of these entries might be different for that same key.
Which value should be set for the key? Conflict is resolved by
the policy set here. Default policy is hz.ADD_NEW_ENTRY
the policy set here. Default policy is PutIfAbsentMapMergePolicy
There are built-in merge policies such as
hz.NO_MERGE ; no entry will merge.
hz.ADD_NEW_ENTRY ; entry will be added if the merging entry's key
doesn't exist in the cluster.
hz.HIGHER_HITS ; entry with the higher hits wins.
hz.LATEST_UPDATE ; entry with the latest update wins.
com.hazelcast.map.merge.PassThroughMergePolicy; entry will be added if there is no existing entry for the key.
com.hazelcast.map.merge.PutIfAbsentMapMergePolicy ; entry will be added if the merging entry doesn't exist in the cluster.
com.hazelcast.map.merge.HigherHitsMapMergePolicy ; entry with the higher hits wins.
com.hazelcast.map.merge.LatestUpdateMapMergePolicy ; entry with the latest update wins.
-->
<merge-policy>hz.ADD_NEW_ENTRY</merge-policy>
<merge-policy>com.hazelcast.map.merge.PassThroughMergePolicy</merge-policy>
<!--
Near cache provides a local view of the clustered map, which is
ideal for high-read caches. Each cluster member retains a local
......@@ -179,6 +159,41 @@
</near-cache>
</map>
<multimap name="default">
<backup-count>1</backup-count>
<value-collection-type>SET</value-collection-type>
</multimap>
<list name="default">
<backup-count>1</backup-count>
</list>
<set name="default">
<backup-count>1</backup-count>
</set>
<jobtracker name="default">
<max-thread-size>0</max-thread-size>
<!-- Queue size 0 means number of partitions * 2 -->
<queue-size>0</queue-size>
<retry-count>0</retry-count>
<chunk-size>1000</chunk-size>
<communicate-stats>true</communicate-stats>
<topology-changed-strategy>CANCEL_RUNNING_OPERATION</topology-changed-strategy>
</jobtracker>
<semaphore name="default">
<initial-permits>0</initial-permits>
<backup-count>1</backup-count>
<async-backup-count>0</async-backup-count>
</semaphore>
<serialization>
<portable-version>0</portable-version>
</serialization>
<services enable-defaults="true"/>
<!-- Partitioned Openfire caches without size/time limits (no eviction). -->
<map name="opt-$cacheStats">
......
src/plugins/hazelcast/logo_large.gif

1.28 KB | W: | H:

src/plugins/hazelcast/logo_large.gif

1.14 KB | W: | H:

src/plugins/hazelcast/logo_large.gif
src/plugins/hazelcast/logo_large.gif
src/plugins/hazelcast/logo_large.gif
src/plugins/hazelcast/logo_large.gif
  • 2-up
  • Swipe
  • Onion skin
src/plugins/hazelcast/logo_small.gif

976 Bytes | W: | H:

src/plugins/hazelcast/logo_small.gif

943 Bytes | W: | H:

src/plugins/hazelcast/logo_small.gif
src/plugins/hazelcast/logo_small.gif
src/plugins/hazelcast/logo_small.gif
src/plugins/hazelcast/logo_small.gif
  • 2-up
  • Swipe
  • Onion skin
......@@ -5,7 +5,7 @@
<name>${plugin.name}</name>
<description>${plugin.description}</description>
<author>Tom Evans</author>
<version>1.2.2</version>
<date>05/06/2014</date>
<minServerVersion>3.9.0</minServerVersion>
<version>1.3.1</version>
<date>10/15/2014</date>
<minServerVersion>3.10.0</minServerVersion>
</plugin>
......@@ -65,7 +65,7 @@ open source <a href="http://www.hazelcast.org">Hazelcast</a> data distribution
framework in lieu of an expensive proprietary third-party product.
</p>
<p>
The current Hazelcast release is version 3.1.7.
The current Hazelcast release is version 3.3.1.
</p>
<h2>Installation</h2>
<p>
......@@ -158,9 +158,9 @@ This will activate clustering for all members of the cluster.</li>
</ol>
<a name="config" />
<h2>Configuration</h2>
<p>
There are several configuration options built into the Hazelcast plugin
<p>There are several configuration options built into the Hazelcast plugin
as Openfire system properties:
</p>
<ol>
<li><i>hazelcast.startup.delay.seconds</i> (5): Number of seconds
to wait before launching the Hazelcast plugin. This allows Openfire to
......@@ -181,15 +181,14 @@ 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>
<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.
Refer to the <a href="http://www.hazelcast.com/docs/3.1/manual/multi_html/ch07.html">
Refer to the <a href="http://docs.hazelcast.org/docs/3.3/manual/html/monitoringwithjmx.html">
Hazelcast JMX docs</a> for additional information.</li>
</ol>
</p>
<p>
The Hazelcast plugin uses the <a href="http://www.hazelcast.org/docs/3.1/manual/single_html/#Config">
<p>The Hazelcast plugin uses the <a href="http://docs.hazelcast.org/docs/3.3/manual/html/config.html">
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
following location:
</p>
<ul>
<li>IP Address: 224.2.2.3</li>
<li>Port: 54327</li>
......@@ -211,7 +210,7 @@ following alternative:
&lt;/join&gt;
...
</pre>
Please refer to the <a href="http://www.hazelcast.org/docs/3.1/manual/single_html/">
<p>Please refer to the <a href="http://docs.hazelcast.org/docs/3.3/manual/html-single/">
Hazelcast reference manual</a> for more information.
</p>
</body>
......
......@@ -59,6 +59,9 @@ public class IncomingServerSessionTask extends RemoteSessionTask {
else if (operation == Operation.getAddress) {
result = getSession().getAddress();
}
else if (operation == Operation.isUsingServerDialback) {
result = ((IncomingServerSession) getSession()).isUsingServerDialback();
}
}
public void writeExternal(ObjectOutput out) throws IOException {
......
......@@ -53,11 +53,6 @@ public class RemoteClientSession extends RemoteSession implements ClientSession
super(nodeID, address);
}
public String getCipherSuiteName() {
return "NONE";
}
public PrivacyList getActiveList() {
Cache<String, ClientSessionInfo> cache = SessionManager.getInstance().getSessionInfoCache();
ClientSessionInfo sessionInfo = cache.get(getAddress().toString());
......
......@@ -49,10 +49,6 @@ public class RemoteComponentSession extends RemoteSession implements ComponentSe
component = new RemoteExternalComponent(address);
}
public String getCipherSuiteName() {
return "NONE";
}
public ExternalComponent getExternalComponent() {
return component;
}
......
......@@ -35,10 +35,6 @@ public class RemoteConnectionMultiplexerSession extends RemoteSession implements
super(nodeID, address);
}
public String getCipherSuiteName() {
return "NONE";
}
RemoteSessionTask getRemoteSessionTask(RemoteSessionTask.Operation operation) {
return new ConnectionMultiplexerSessionTask(address, operation);
}
......
......@@ -42,10 +42,6 @@ public class RemoteIncomingServerSession extends RemoteSession implements Incomi
this.streamID = new BasicStreamID(streamID);
}
public String getCipherSuiteName() {
return "NONE";
}
public boolean isUsingServerDialback() {
if (usingServerDialback == -1) {
ClusterTask task = getRemoteSessionTask(RemoteSessionTask.Operation.isUsingServerDialback);
......
......@@ -43,10 +43,6 @@ public class RemoteOutgoingServerSession extends RemoteSession implements Outgoi
super(nodeID, address);
}
public String getCipherSuiteName() {
return "NONE";
}
public Collection<String> getAuthenticatedDomains() {
ClusterTask task = getRemoteSessionTask(RemoteSessionTask.Operation.getAuthenticatedDomains);
return (Collection<String>) doSynchronousClusterTask(task);
......
......@@ -114,6 +114,11 @@ public abstract class RemoteSession implements Session {
return (Long) doSynchronousClusterTask(task);
}
public String getCipherSuiteName() {
ClusterTask task = getRemoteSessionTask(RemoteSessionTask.Operation.getCipherSuiteName);
return (String) doSynchronousClusterTask(task);
}
public void process(Packet packet) {
doClusterTask(getProcessPacketTask(packet));
}
......
......@@ -73,6 +73,9 @@ public abstract class RemoteSessionTask implements ClusterTask {
else if (operation == Operation.getNumServerPackets) {
result = getSession().getNumServerPackets();
}
else if (operation == Operation.getCipherSuiteName) {
result = getSession().getCipherSuiteName();
}
else if (operation == Operation.close) {
// Run in another thread so we avoid blocking calls (in hazelcast)
final Session session = getSession();
......@@ -139,6 +142,7 @@ public abstract class RemoteSessionTask implements ClusterTask {
getLastActiveDate,
getNumClientPackets,
getNumServerPackets,
getCipherSuiteName,
close,
isClosed,
isSecure,
......
......@@ -27,6 +27,7 @@ import org.jivesoftware.util.StringUtils;
import com.hazelcast.core.EntryEvent;
import com.hazelcast.core.EntryListener;
import com.hazelcast.core.MapEvent;
/**
* Base listener for cache events in the cluster. This class helps keep track
......@@ -48,24 +49,24 @@ class CacheListener implements EntryListener {
}
public void entryAdded(EntryEvent event) {
handleMapEvent(event, false);
handleEntryEvent(event, false);
}
public void entryUpdated(EntryEvent event) {
handleMapEvent(event, false);
handleEntryEvent(event, false);
}
public void entryRemoved(EntryEvent event) {
handleMapEvent(event, true);
handleEntryEvent(event, true);
}
public void entryEvicted(EntryEvent event) {
handleMapEvent(event, true);
handleEntryEvent(event, true);
}
void handleMapEvent(EntryEvent event, boolean removal) {
private void handleEntryEvent(EntryEvent event, boolean removal) {
NodeID nodeID = NodeID.getInstance(StringUtils.getBytes(event.getMember().getUuid()));
//ignore items which this node has added
// ignore events which were triggered by this node
if (!XMPPServer.getInstance().getNodeID().equals(nodeID)) {
Set<String> sessionJIDS = clusterListener.lookupJIDList(nodeID, cacheName);
if (removal) {
......@@ -77,4 +78,23 @@ class CacheListener implements EntryListener {
}
}
private void handleMapEvent(MapEvent event) {
NodeID nodeID = NodeID.getInstance(StringUtils.getBytes(event.getMember().getUuid()));
// ignore events which were triggered by this node
if (!XMPPServer.getInstance().getNodeID().equals(nodeID)) {
Set<String> sessionJIDs = clusterListener.lookupJIDList(nodeID, cacheName);
sessionJIDs.clear();
}
}
@Override
public void mapCleared(MapEvent event) {
handleMapEvent(event);
}
@Override
public void mapEvicted(MapEvent event) {
handleMapEvent(event);
}
}
......@@ -59,7 +59,9 @@ import com.hazelcast.core.EntryListener;
import com.hazelcast.core.LifecycleEvent;
import com.hazelcast.core.LifecycleEvent.LifecycleState;
import com.hazelcast.core.LifecycleListener;
import com.hazelcast.core.MapEvent;
import com.hazelcast.core.Member;
import com.hazelcast.core.MemberAttributeEvent;
import com.hazelcast.core.MembershipEvent;
import com.hazelcast.core.MembershipListener;
import com.jivesoftware.util.cluster.HazelcastClusterNodeInfo;
......@@ -490,6 +492,24 @@ public class ClusterListener implements MembershipListener, LifecycleListener {
public void entryEvicted(EntryEvent event) {
entryRemoved(event);
}
private void mapClearedOrEvicted(MapEvent event) {
NodeID nodeID = NodeID.getInstance(StringUtils.getBytes(event.getMember().getUuid()));
// ignore events which were triggered by this node
if (!XMPPServer.getInstance().getNodeID().equals(nodeID)) {
nodePresences.get(nodeID).clear();
}
}
@Override
public void mapEvicted(MapEvent event) {
mapClearedOrEvicted(event);
}
@Override
public void mapCleared(MapEvent event) {
mapClearedOrEvicted(event);
}
}
/**
......@@ -538,6 +558,25 @@ public class ClusterListener implements MembershipListener, LifecycleListener {
public void entryEvicted(EntryEvent event) {
entryRemoved(event);
}
private void mapClearedOrEvicted(MapEvent event) {
NodeID nodeID = NodeID.getInstance(StringUtils.getBytes(event.getMember().getUuid()));
// ignore events which were triggered by this node
if (!XMPPServer.getInstance().getNodeID().equals(nodeID)) {
Set<String> sessionJIDs = lookupJIDList(nodeID, componentsCache.getName());
sessionJIDs.clear();
}
}
@Override
public void mapEvicted(MapEvent event) {
mapClearedOrEvicted(event);
}
@Override
public void mapCleared(MapEvent event) {
mapClearedOrEvicted(event);
}
}
private synchronized void joinCluster() {
......@@ -662,4 +701,11 @@ public class ClusterListener implements MembershipListener, LifecycleListener {
joinCluster();
}
}
@Override
public void memberAttributeChanged(MemberAttributeEvent event) {
ClusterNodeInfo priorNodeInfo = clusterNodesInfo.get(event.getMember().getUuid());
clusterNodesInfo.put(event.getMember().getUuid(),
new HazelcastClusterNodeInfo(event.getMember(), priorNodeInfo.getJoinedTime()));
}
}
......@@ -44,7 +44,7 @@ public class HazelcastClusterNodeInfo implements ClusterNodeInfo {
}
public HazelcastClusterNodeInfo(Member member, Long joinedTime) {
hostname = member.getInetSocketAddress().getHostName();
hostname = member.getSocketAddress().getHostName();
nodeID = NodeID.getInstance(StringUtils.getBytes(member.getUuid()));
this.joinedTime = joinedTime;
seniorMember = ClusterManager.getSeniorClusterMember().equals(StringUtils.getBytes(member.getUuid()));
......
......@@ -20,7 +20,10 @@
package org.jivesoftware.openfire.plugin;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import java.io.File;
import java.util.Map;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
......@@ -30,9 +33,6 @@ import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.PropertyEventDispatcher;
import org.jivesoftware.util.PropertyEventListener;
import java.io.File;
import java.util.Map;
/**
* Debugger plugin that prints XML traffic to stdout. By default it will only print
* raw XML traffic (by using a MINA filter). To turn on printing of interpreted XML
......
......@@ -20,16 +20,17 @@
package org.jivesoftware.openfire.plugin;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoFilterAdapter;
import org.apache.mina.common.IoSession;
import org.jivesoftware.util.JiveGlobals;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.mina.core.filterchain.IoFilterAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.core.write.WriteRequest;
import org.jivesoftware.util.JiveGlobals;
/**
* MINA filter that prints to the stdout received XML stanzas before they are actually parsed and
* also prints XML stanzas as sent to the XMPP entities. Moreover, it also prints information when
......@@ -50,13 +51,13 @@ public class RawPrintFilter extends IoFilterAdapter {
@Override
public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
// Decode the bytebuffer and print it to the stdout
if (enabled && message instanceof ByteBuffer) {
if (enabled && message instanceof ByteBuffer) {
ByteBuffer byteBuffer = (ByteBuffer) message;
// Keep current position in the buffer
int currentPos = byteBuffer.position();
// Decode buffer
Charset encoder = Charset.forName("UTF-8");
CharBuffer charBuffer = encoder.decode(byteBuffer.buf());
CharBuffer charBuffer = encoder.decode(byteBuffer.asReadOnlyBuffer());
// Print buffer content
System.out.println(prefix + " - RECV (" + session.hashCode() + "): " + charBuffer);
// Reset to old position in the buffer
......@@ -67,10 +68,10 @@ public class RawPrintFilter extends IoFilterAdapter {
}
@Override
public void messageSent(NextFilter nextFilter, IoSession session, Object message) throws Exception {
public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest message) throws Exception {
if (enabled) {
System.out.println(prefix + " - SENT (" + session.hashCode() + "): " +
Charset.forName("UTF-8").decode(((ByteBuffer) message).buf()));
Charset.forName("UTF-8").decode(((ByteBuffer) message).asReadOnlyBuffer()));
}
// Pass the message to the next filter
......
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