IDEMPIERE-3653 1008833 Upgrade hazelcast to version 3.9.3 / integrate patch from hengsin

This commit is contained in:
Carlos Ruiz 2018-01-23 17:19:21 +08:00
parent 3bc0e45599
commit 4069878bf9
13 changed files with 258 additions and 184 deletions

View File

@ -2352,7 +2352,7 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
return; // avoid NPE below return; // avoid NPE below
} }
DataStatusListener[] listeners = m_listenerList.getListeners(DataStatusListener.class); DataStatusListener[] listeners = m_listenerList.getListeners(DataStatusListener.class);
if (listeners.length == 0) if (listeners.length == 0 || e == null)
return; return;
if (log.isLoggable(Level.FINE)) log.fine(e.toString()); if (log.isLoggable(Level.FINE)) log.fine(e.toString());
// WHO Info // WHO Info

View File

@ -166,9 +166,9 @@ public class CacheMgt
int total = 0; int total = 0;
try { try {
Collection<Future<Integer>> results = futureMap.values(); Collection<Future<Integer>> results = futureMap.values();
for(Future<Integer> future : results) { for(Future<Integer> i : results)
Integer i = future.get(); {
total += i.intValue(); total += i.get();
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -191,7 +191,11 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
m_desktop.addListener(this); m_desktop.addListener(this);
//subscribing to broadcast event //subscribing to broadcast event
bindEventManager(); bindEventManager();
try {
ZKBroadCastManager.getBroadCastMgr(); ZKBroadCastManager.getBroadCastMgr();
} catch (Throwable e) {
e.printStackTrace();
}
EventQueue<Event> queue = EventQueues.lookup(ACTIVITIES_EVENT_QUEUE, true); EventQueue<Event> queue = EventQueues.lookup(ACTIVITIES_EVENT_QUEUE, true);
queue.subscribe(this); queue.subscribe(this);

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
~ Copyright (c) 2008-2012, Hazel Bilisim Ltd. All Rights Reserved. ~ Copyright (c) 2008-2017, Hazelcast, Inc. 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.
@ -15,7 +15,13 @@
~ limitations under the License. ~ limitations under the License.
--> -->
<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-2.4.xsd" <!--
The default Hazelcast configuration. This is used when no hazelcast.xml is present.
Please see the schema for how to configure Hazelcast at https://hazelcast.com/schema/config/hazelcast-config-3.9.xsd
or the documentation at https://hazelcast.org/documentation/
-->
<!--suppress XmlDefaultAttributeValue -->
<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.9.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>
@ -24,7 +30,7 @@
</group> </group>
<management-center enabled="false">http://localhost:8080/mancenter</management-center> <management-center enabled="false">http://localhost:8080/mancenter</management-center>
<network> <network>
<port auto-increment="true">5701</port> <port auto-increment="true" port-count="100">5701</port>
<outbound-ports> <outbound-ports>
<!-- <!--
Allowed port range when connecting to other nodes. Allowed port range when connecting to other nodes.
@ -39,6 +45,9 @@
</multicast> </multicast>
<tcp-ip enabled="false"> <tcp-ip enabled="false">
<interface>127.0.0.1</interface> <interface>127.0.0.1</interface>
<member-list>
<member>127.0.0.1</member>
</member-list>
</tcp-ip> </tcp-ip>
<aws enabled="false"> <aws enabled="false">
<access-key>my-access-key</access-key> <access-key>my-access-key</access-key>
@ -46,18 +55,20 @@
<!--optional, default is us-east-1 --> <!--optional, default is us-east-1 -->
<region>us-west-1</region> <region>us-west-1</region>
<!--optional, default is ec2.amazonaws.com. If set, region shouldn't be set as it will override this property --> <!--optional, default is ec2.amazonaws.com. If set, region shouldn't be set as it will override this property -->
<hostHeader>ec2.amazonaws.com</hostHeader> <host-header>ec2.amazonaws.com</host-header>
<!-- optional, only instances belonging to this group will be discovered, default will try all running instances --> <!-- optional, only instances belonging to this group will be discovered, default will try all running instances -->
<security-group-name>hazelcast-sg</security-group-name> <security-group-name>hazelcast-sg</security-group-name>
<tag-key>type</tag-key> <tag-key>type</tag-key>
<tag-value>hz-nodes</tag-value> <tag-value>hz-nodes</tag-value>
</aws> </aws>
<discovery-strategies>
</discovery-strategies>
</join> </join>
<interfaces enabled="false"> <interfaces enabled="false">
<interface>10.10.1.*</interface> <interface>10.10.1.*</interface>
</interfaces> </interfaces>
<ssl enabled="false" /> <ssl enabled="false"/>
<socket-interceptor enabled="false" /> <socket-interceptor enabled="false"/>
<symmetric-encryption enabled="false"> <symmetric-encryption enabled="false">
<!-- <!--
encryption algorithm such as encryption algorithm such as
@ -75,26 +86,12 @@
<!-- iteration count to use when generating the secret key --> <!-- iteration count to use when generating the secret key -->
<iteration-count>19</iteration-count> <iteration-count>19</iteration-count>
</symmetric-encryption> </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>
</network> </network>
<partition-group enabled="false"/> <partition-group enabled="false"/>
<executor-service> <executor-service name="default">
<core-pool-size>16</core-pool-size> <pool-size>16</pool-size>
<max-pool-size>64</max-pool-size> <!--Queue capacity. 0 means Integer.MAX_VALUE.-->
<keep-alive-seconds>60</keep-alive-seconds> <queue-capacity>0</queue-capacity>
</executor-service> </executor-service>
<queue name="default"> <queue name="default">
<!-- <!--
@ -104,14 +101,31 @@
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>
<!-- <!--
Name of the map configuration that will be used for the backing distributed Number of backups. If 1 is set as the backup-count for example,
map for this queue. then all entries of the map will be copied to another JVM for
fail-safety. 0 means no backup.
--> -->
<backing-map-ref>default</backing-map-ref> <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>
</queue> </queue>
<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
@ -150,14 +164,21 @@
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 policy="cluster_wide_map_size">1000</max-size> <max-size policy="PER_NODE">1000</max-size>
<!-- <!--
When max. size is reached, specified percentage of `eviction-percentage` property is deprecated and will be ignored when it is set.
the map will be evicted. Any integer between 0 and 100.
If 25 is set for example, 25% of the entries will As of version 3.7, eviction mechanism changed.
get evicted. It uses a probabilistic algorithm based on sampling. Please see documentation for further details
--> -->
<eviction-percentage>25</eviction-percentage> <eviction-percentage>25</eviction-percentage>
<!--
`min-eviction-check-millis` property is deprecated and will be ignored when it is set.
As of version 3.7, eviction mechanism changed.
It uses a probabilistic algorithm based on sampling. Please see documentation for further details
-->
<min-eviction-check-millis>100</min-eviction-check-millis>
<!-- <!--
While recovering from split-brain (network partitioning), While recovering from split-brain (network partitioning),
map entries in the small cluster will merge into the bigger cluster map entries in the small cluster will merge into the bigger cluster
@ -165,32 +186,93 @@
cluster, there might an existing entry with the same key already. cluster, there might an existing entry with the same key already.
Values of these entries might be different for that same key. Values of these entries might be different for that same key.
Which value should be set for the key? Conflict is resolved by 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 There are built-in merge policies such as
hz.NO_MERGE ; no entry will merge. com.hazelcast.map.merge.PassThroughMergePolicy; entry will be overwritten if merging entry exists for the key.
hz.ADD_NEW_ENTRY ; entry will be added if the merging entry's key com.hazelcast.map.merge.PutIfAbsentMapMergePolicy ; entry will be added if the merging entry doesn't exist in the cluster.
doesn't exist in the cluster. com.hazelcast.map.merge.HigherHitsMapMergePolicy ; entry with the higher hits wins.
hz.HIGHER_HITS ; entry with the higher hits wins. com.hazelcast.map.merge.LatestUpdateMapMergePolicy ; entry with the latest update wins.
hz.LATEST_UPDATE ; entry with the latest update wins.
-->
<merge-policy>hz.ADD_NEW_ENTRY</merge-policy>
</map>
<!-- Add your own semaphore configurations here:
<semaphore name="default">
<initial-permits>10</initial-permits>
<semaphore-factory enabled="true">
<class-name>com.acme.MySemaphoreFactory</class-name>
</semaphore-factory>
</semaphore>
--> -->
<merge-policy>com.hazelcast.map.merge.PutIfAbsentMapMergePolicy</merge-policy>
<!-- Add your own map merge policy implementations here: <!--
<merge-policies> Control caching of de-serialized values. Caching makes query evaluation faster, but it cost memory.
<map-merge-policy name="MY_MERGE_POLICY"> Possible Values:
<class-name>com.acme.MyOwnMergePolicy</class-name> NEVER: Never cache deserialized object
</map-merge-policy> INDEX-ONLY: Caches values only when they are inserted into an index.
</merge-policies> ALWAYS: Always cache deserialized values.
--> -->
<cache-deserialized-values>INDEX-ONLY</cache-deserialized-values>
</map>
<!--
Configuration for an event journal. The event journal keeps events related
to a specific partition and data structure. For instance, it could keep
map add, update, remove, merge events along with the key, old value, new value and so on.
-->
<event-journal enabled="false">
<mapName>mapName</mapName>
<capacity>10000</capacity>
<time-to-live-seconds>0</time-to-live-seconds>
</event-journal>
<event-journal enabled="false">
<cacheName>cacheName</cacheName>
<capacity>10000</capacity>
<time-to-live-seconds>0</time-to-live-seconds>
</event-journal>
<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>
<reliable-topic name="default">
<read-batch-size>10</read-batch-size>
<topic-overload-policy>BLOCK</topic-overload-policy>
<statistics-enabled>true</statistics-enabled>
</reliable-topic>
<ringbuffer name="default">
<capacity>10000</capacity>
<backup-count>1</backup-count>
<async-backup-count>0</async-backup-count>
<time-to-live-seconds>0</time-to-live-seconds>
<in-memory-format>BINARY</in-memory-format>
</ringbuffer>
<serialization>
<portable-version>0</portable-version>
</serialization>
<services enable-defaults="true"/>
<lite-member enabled="false"/>
</hazelcast> </hazelcast>

View File

@ -3,7 +3,7 @@
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="hazelcast-3.5.3.jar"/> <classpathentry kind="lib" path="hazelcast-3.9.3.jar"/>
<classpathentry kind="lib" path="hazelcast-cloud-3.5.3.jar"/> <classpathentry kind="lib" path="hazelcast-aws-2.1.0.jar"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@ -26,7 +26,7 @@ Import-Package: javax.crypto,
org.w3c.dom org.w3c.dom
DynamicImport-Package: * DynamicImport-Package: *
Bundle-ClassPath: ., Bundle-ClassPath: .,
hazelcast-3.5.3.jar, hazelcast-3.9.3.jar,
hazelcast-cloud-3.5.3.jar hazelcast-aws-2.1.0.jar
Service-Component: OSGI-INF/clusterservice.xml, OSGI-INF/cacheservice.xml, OSGI-INF/messageservice.xml Service-Component: OSGI-INF/clusterservice.xml, OSGI-INF/cacheservice.xml, OSGI-INF/messageservice.xml
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-RequiredExecutionEnvironment: JavaSE-1.8

View File

@ -5,6 +5,6 @@ bin.includes = META-INF/,\
OSGI-INF/cacheservice.xml,\ OSGI-INF/cacheservice.xml,\
OSGI-INF/messageservice.xml,\ OSGI-INF/messageservice.xml,\
OSGI-INF/,\ OSGI-INF/,\
hazelcast-3.5.3.jar,\ hazelcast-3.9.3.jar,\
hazelcast-cloud-3.5.3.jar hazelcast-aws-2.1.0.jar
source.. = src/ source.. = src/

View File

@ -1,6 +1,6 @@
<project name="zklibrary" basedir="." default="copy"> <project name="zklibrary" basedir="." default="copy">
<target name="copy"> <target name="copy">
<get src="${url.maven2.lib}/maven2/com/hazelcast/hazelcast/3.5.3/hazelcast-3.5.3.jar" dest="hazelcast-3.5.3.jar" usetimestamp="true" verbose="true" retries="5" /> <get src="${url.maven2.lib}/maven2/com/hazelcast/hazelcast/3.9.3/hazelcast-3.9.3.jar" dest="hazelcast-3.9.3.jar" usetimestamp="true" verbose="true" retries="5" />
<get src="${url.maven2.lib}/maven2/com/hazelcast/hazelcast-cloud/3.5.3/hazelcast-cloud-3.5.3.jar" dest="hazelcast-cloud-3.5.3.jar" usetimestamp="true" verbose="true" retries="5" /> <get src="${url.maven2.lib}/maven2/com/hazelcast/hazelcast-aws/2.1.0/hazelcast-aws-2.1.0.jar" dest="hazelcast-aws-2.1.0.jar" usetimestamp="true" verbose="true" retries="5" />
</target> </target>
</project> </project>

View File

@ -20,9 +20,6 @@ import java.net.URL;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.Date; import java.util.Date;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import org.compiere.Adempiere; import org.compiere.Adempiere;
import org.compiere.model.ServerStateChangeEvent; import org.compiere.model.ServerStateChangeEvent;
@ -34,7 +31,8 @@ import com.hazelcast.config.Config;
import com.hazelcast.config.FileSystemXmlConfig; import com.hazelcast.config.FileSystemXmlConfig;
import com.hazelcast.config.MapConfig; import com.hazelcast.config.MapConfig;
import com.hazelcast.config.UrlXmlConfig; import com.hazelcast.config.UrlXmlConfig;
import com.hazelcast.core.*; import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
/** /**
* *
@ -50,7 +48,6 @@ public class Activator implements BundleActivator {
} }
private volatile static HazelcastInstance hazelcastInstance; private volatile static HazelcastInstance hazelcastInstance;
private static Future<?> future;
/* /*
* (non-Javadoc) * (non-Javadoc)
@ -73,11 +70,6 @@ public class Activator implements BundleActivator {
} }
private static synchronized void createHazelCastInstance() { private static synchronized void createHazelCastInstance() {
ScheduledThreadPoolExecutor executor = Adempiere.getThreadPoolExecutor();
future = executor.submit(new Runnable() {
@Override
public void run() {
File file = null; File file = null;
//try idempiere home //try idempiere home
String dataArea = System.getProperty("IDEMPIERE_HOME"); String dataArea = System.getProperty("IDEMPIERE_HOME");
@ -125,7 +117,7 @@ public class Activator implements BundleActivator {
if (file != null && file.exists()) { if (file != null && file.exists()) {
try { try {
Config config = new FileSystemXmlConfig(file); Config config = new FileSystemXmlConfig(file);
config.setClassLoader(getClass().getClassLoader()); config.setClassLoader(Activator.class.getClassLoader());
hazelcastInstance = Hazelcast.newHazelcastInstance(config); hazelcastInstance = Hazelcast.newHazelcastInstance(config);
MapConfig mc = config.getMapConfig("default"); MapConfig mc = config.getMapConfig("default");
if (mc != null) { if (mc != null) {
@ -140,7 +132,7 @@ public class Activator implements BundleActivator {
if (url != null) { if (url != null) {
try { try {
Config config = new UrlXmlConfig(url); Config config = new UrlXmlConfig(url);
config.setClassLoader(getClass().getClassLoader()); config.setClassLoader(Activator.class.getClassLoader());
hazelcastInstance = Hazelcast.newHazelcastInstance(config); hazelcastInstance = Hazelcast.newHazelcastInstance(config);
MapConfig mc = config.getMapConfig("default"); MapConfig mc = config.getMapConfig("default");
if (mc != null) { if (mc != null) {
@ -151,25 +143,15 @@ public class Activator implements BundleActivator {
} }
Config config = new Config(); Config config = new Config();
config.setClassLoader(getClass().getClassLoader()); config.setClassLoader(Activator.class.getClassLoader());
hazelcastInstance = Hazelcast.newHazelcastInstance(config); hazelcastInstance = Hazelcast.newHazelcastInstance(config);
MapConfig mc = config.getMapConfig("default"); MapConfig mc = config.getMapConfig("default");
if (mc != null) { if (mc != null) {
System.out.println("Hazelcast Max Size Config: "+mc.getMaxSizeConfig().getMaxSizePolicy() + " " + mc.getMaxSizeConfig().getSize()); System.out.println("Hazelcast Max Size Config: "+mc.getMaxSizeConfig().getMaxSizePolicy() + " " + mc.getMaxSizeConfig().getSize());
} }
} }
});
}
public static synchronized HazelcastInstance getHazelcastInstance() { public static synchronized HazelcastInstance getHazelcastInstance() {
if (future != null && !future.isDone()) {
try {
future.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
}
if (hazelcastInstance != null) { if (hazelcastInstance != null) {
if (!hazelcastInstance.getLifecycleService().isRunning()) { if (!hazelcastInstance.getLifecycleService().isRunning()) {
System.err.println(DateFormat.getDateTimeInstance().format(new Date()) + " Hazelcast instance is down!"); System.err.println(DateFormat.getDateTimeInstance().format(new Date()) + " Hazelcast instance is down!");
@ -200,9 +182,7 @@ public class Activator implements BundleActivator {
public void stop(BundleContext bundleContext) throws Exception { public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null; Activator.context = null;
synchronized (Activator.class) { synchronized (Activator.class) {
if (future != null && !future.isDone()) { if (hazelcastInstance != null) {
future.cancel(true);
} else if (hazelcastInstance != null) {
hazelcastInstance.getLifecycleService().shutdown(); hazelcastInstance.getLifecycleService().shutdown();
hazelcastInstance = null; hazelcastInstance = null;
} }

View File

@ -17,6 +17,8 @@ import java.net.InetAddress;
import org.idempiere.distributed.IClusterMember; import org.idempiere.distributed.IClusterMember;
import com.hazelcast.core.Member;
/** /**
* @author hengsin * @author hengsin
* *
@ -37,6 +39,12 @@ public class ClusterMember implements IClusterMember {
this.port = port; this.port = port;
} }
public ClusterMember(Member member) {
this.id = member.getUuid();
this.address = member.getSocketAddress().getAddress();
this.port = member.getSocketAddress().getPort();
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.idempiere.distributed.IClusterMember#getId() * @see org.idempiere.distributed.IClusterMember#getId()
*/ */

View File

@ -14,8 +14,8 @@
package org.idempiere.hazelcast.service; package org.idempiere.hazelcast.service;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
@ -25,6 +25,7 @@ import org.idempiere.distributed.IClusterMember;
import org.idempiere.distributed.IClusterService; import org.idempiere.distributed.IClusterService;
import com.hazelcast.core.HazelcastInstance; import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IExecutorService;
import com.hazelcast.core.Member; import com.hazelcast.core.Member;
/** /**
@ -43,7 +44,7 @@ public class ClusterServiceImpl implements IClusterService {
if (instance != null) { if (instance != null) {
Set<Member> members = instance.getCluster().getMembers(); Set<Member> members = instance.getCluster().getMembers();
for(Member member : members) { for(Member member : members) {
clusterMembers.add(new ClusterMember(member.getUuid(), member.getSocketAddress().getAddress(), member.getSocketAddress().getPort())); clusterMembers.add(new ClusterMember(member));
} }
} }
return clusterMembers; return clusterMembers;
@ -57,7 +58,7 @@ public class ClusterServiceImpl implements IClusterService {
HazelcastInstance instance = Activator.getHazelcastInstance(); HazelcastInstance instance = Activator.getHazelcastInstance();
if (instance != null) { if (instance != null) {
Member member = instance.getCluster().getLocalMember(); Member member = instance.getCluster().getLocalMember();
return new ClusterMember(member.getUuid(), member.getSocketAddress().getAddress(), member.getSocketAddress().getPort()); return new ClusterMember(member);
} else { } else {
return null; return null;
} }
@ -73,7 +74,8 @@ public class ClusterServiceImpl implements IClusterService {
Set<Member> members = instance.getCluster().getMembers(); Set<Member> members = instance.getCluster().getMembers();
for(Member member : members) { for(Member member : members) {
if (member.getUuid().equals(clusterMember.getId())) { if (member.getUuid().equals(clusterMember.getId())) {
return Activator.getHazelcastInstance().getExecutorService("default").submitToMember(task, member); IExecutorService service = Activator.getHazelcastInstance().getExecutorService("default");
return service.submitToMember(task, member);
} }
} }
} }
@ -100,13 +102,13 @@ public class ClusterServiceImpl implements IClusterService {
} }
} }
if (selectedMembers.size() > 0) { if (selectedMembers.size() > 0) {
Map<Member, Future<V>> maps = Activator.getHazelcastInstance().getExecutorService("default").submitToMembers(task, selectedMembers); IExecutorService service = Activator.getHazelcastInstance().getExecutorService("default");
Map<IClusterMember, Future<V>> result = new HashMap<IClusterMember, Future<V>>(); Map<Member, Future<V>> map = service.submitToMembers(task, selectedMembers);
for(Member m : maps.keySet()) { Map<IClusterMember, Future<V>> futureMap = new LinkedHashMap<>();
ClusterMember cm = new ClusterMember(m.getUuid(), m.getSocketAddress().getAddress(), m.getSocketAddress().getPort()); for(Member member : map.keySet()) {
result.put(cm, maps.get(m)); futureMap.put(new ClusterMember(member), map.get(member));
} }
return result; return futureMap;
} }
} }
return null; return null;

View File

@ -14,7 +14,9 @@
package org.idempiere.hazelcast.service; package org.idempiere.hazelcast.service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import org.idempiere.distributed.ITopic; import org.idempiere.distributed.ITopic;
import org.idempiere.distributed.ITopicSubscriber; import org.idempiere.distributed.ITopicSubscriber;
@ -31,6 +33,7 @@ public class TopicImpl<E> implements ITopic<E> {
private com.hazelcast.core.ITopic<E> topic; private com.hazelcast.core.ITopic<E> topic;
private List<TopicSubscriberAdapter<E>> adapters; private List<TopicSubscriberAdapter<E>> adapters;
private Map<TopicSubscriberAdapter<E>, String> registrationMap;
/** /**
* *
@ -38,6 +41,7 @@ public class TopicImpl<E> implements ITopic<E> {
public TopicImpl(com.hazelcast.core.ITopic<E> topic) { public TopicImpl(com.hazelcast.core.ITopic<E> topic) {
this.topic = topic; this.topic = topic;
adapters = new ArrayList<TopicSubscriberAdapter<E>>(); adapters = new ArrayList<TopicSubscriberAdapter<E>>();
registrationMap = new HashMap<>();
} }
@Override @Override
@ -48,8 +52,9 @@ public class TopicImpl<E> implements ITopic<E> {
@Override @Override
public void subscribe(final ITopicSubscriber<E> subscriber) { public void subscribe(final ITopicSubscriber<E> subscriber) {
TopicSubscriberAdapter<E> adapter = new TopicSubscriberAdapter<E>(subscriber); TopicSubscriberAdapter<E> adapter = new TopicSubscriberAdapter<E>(subscriber);
adapter.setListenerId(topic.addMessageListener(adapter)); String registrationId = topic.addMessageListener(adapter);
adapters.add(adapter); adapters.add(adapter);
registrationMap.put(adapter, registrationId);
} }
@Override @Override
@ -58,7 +63,9 @@ public class TopicImpl<E> implements ITopic<E> {
for(TopicSubscriberAdapter<E> adapter : adapters) { for(TopicSubscriberAdapter<E> adapter : adapters) {
if (adapter.subscriber == subscriber) { if (adapter.subscriber == subscriber) {
found = adapter; found = adapter;
topic.removeMessageListener(adapter.getListenerId()); String registrationId = registrationMap.get(adapter);
if (topic.removeMessageListener(registrationId))
registrationMap.remove(adapter);
break; break;
} }
} }
@ -73,20 +80,11 @@ public class TopicImpl<E> implements ITopic<E> {
class TopicSubscriberAdapter<T> implements MessageListener<T> { class TopicSubscriberAdapter<T> implements MessageListener<T> {
protected ITopicSubscriber<T> subscriber; protected ITopicSubscriber<T> subscriber;
private String listenerId;
protected TopicSubscriberAdapter(ITopicSubscriber<T> subscriber) { protected TopicSubscriberAdapter(ITopicSubscriber<T> subscriber) {
this.subscriber = subscriber; this.subscriber = subscriber;
} }
public void setListenerId(String listenerId) {
this.listenerId = listenerId;
}
public String getListenerId() {
return listenerId;
}
@Override @Override
public void onMessage(Message<T> message) { public void onMessage(Message<T> message) {
subscriber.onMessage(message.getMessageObject()); subscriber.onMessage(message.getMessageObject());