IDEMPIERE-728 Hazelcast Instance is not active exception on webui. Improve handling of shutdown/crash of hazelcast instance .

This commit is contained in:
Heng Sin Low 2013-03-13 16:04:20 +08:00
parent 34f7824b5f
commit fa61820db5
4 changed files with 96 additions and 49 deletions

View File

@ -142,19 +142,23 @@ public class CacheMgt
if (service != null) { if (service != null) {
ResetCacheCallable callable = new ResetCacheCallable(tableName, recordId); ResetCacheCallable callable = new ResetCacheCallable(tableName, recordId);
Future<Collection<Integer>> future = service.execute(callable, service.getMembers()); Future<Collection<Integer>> future = service.execute(callable, service.getMembers());
int total = 0; if (future != null) {
try { int total = 0;
Collection<Integer> results = future.get(); try {
for(Integer i : results) Collection<Integer> results = future.get();
{ for(Integer i : results)
total += i.intValue(); {
total += i.intValue();
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} }
} catch (InterruptedException e) { return total;
e.printStackTrace(); } else {
} catch (ExecutionException e) { return resetLocalCache(tableName, recordId);
e.printStackTrace();
} }
return total;
} else { } else {
return resetLocalCache(tableName, recordId); return resetLocalCache(tableName, recordId);
} }
@ -172,7 +176,9 @@ public class CacheMgt
IClusterService service = holder.getService(); IClusterService service = holder.getService();
if (service != null) { if (service != null) {
CacheNewRecordCallable callable = new CacheNewRecordCallable(tableName, recordId); CacheNewRecordCallable callable = new CacheNewRecordCallable(tableName, recordId);
service.execute(callable, service.getMembers()); if (service.execute(callable, service.getMembers()) == null) {
localNewRecord(tableName, recordId);
}
} else { } else {
localNewRecord(tableName, recordId); localNewRecord(tableName, recordId);
} }

View File

@ -17,10 +17,11 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.text.DateFormat;
import java.util.Date;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicReference;
import org.compiere.Adempiere; import org.compiere.Adempiere;
import org.compiere.model.ServerStateChangeEvent; import org.compiere.model.ServerStateChangeEvent;
@ -46,7 +47,7 @@ public class Activator implements BundleActivator {
} }
private volatile static HazelcastInstance hazelcastInstance; private volatile static HazelcastInstance hazelcastInstance;
private static AtomicReference<Future<?>> futureRef = new AtomicReference<Future<?>>(); private static Future<?> future;
/* /*
* (non-Javadoc) * (non-Javadoc)
@ -68,10 +69,10 @@ public class Activator implements BundleActivator {
} }
} }
private void createHazelCastInstance() { private static synchronized void createHazelCastInstance() {
ScheduledThreadPoolExecutor executor = Adempiere.getThreadPoolExecutor(); ScheduledThreadPoolExecutor executor = Adempiere.getThreadPoolExecutor();
Future<?> future = executor.submit(new Runnable() { future = executor.submit(new Runnable() {
@Override @Override
public void run() { public void run() {
String dataArea = System.getProperty("osgi.install.area"); String dataArea = System.getProperty("osgi.install.area");
@ -92,11 +93,9 @@ public class Activator implements BundleActivator {
hazelcastInstance = Hazelcast.newHazelcastInstance(null); hazelcastInstance = Hazelcast.newHazelcastInstance(null);
} }
}); });
futureRef.set(future);
} }
public static HazelcastInstance getHazelcastInstance() { public static synchronized HazelcastInstance getHazelcastInstance() {
Future<?> future = futureRef.get();
if (future != null && !future.isDone()) { if (future != null && !future.isDone()) {
try { try {
future.get(); future.get();
@ -105,6 +104,26 @@ public class Activator implements BundleActivator {
} }
} }
if (hazelcastInstance != null) {
if (!hazelcastInstance.getLifecycleService().isRunning()) {
System.err.println(DateFormat.getDateTimeInstance().format(new Date()) + " Hazelcast instance is down!");
//recreate
try {
hazelcastInstance = Hazelcast.newHazelcastInstance(null);
if (!hazelcastInstance.getLifecycleService().isRunning()) {
hazelcastInstance = null;
System.err.println(DateFormat.getDateTimeInstance().format(new Date()) + " Failed to re-create Hazelcast instance!");
} else {
System.err.println(DateFormat.getDateTimeInstance().format(new Date()) + " Hazelcast instance re-created!");
}
} catch (Throwable t) {
t.printStackTrace();
hazelcastInstance = null;
System.err.println(DateFormat.getDateTimeInstance().format(new Date()) + " Failed to re-create Hazelcast instance!");
}
}
}
return hazelcastInstance; return hazelcastInstance;
} }
@ -114,13 +133,13 @@ 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;
Future<?> future = futureRef.get(); synchronized (Activator.class) {
if (future != null && !future.isDone()) { if (future != null && !future.isDone()) {
future.cancel(true); future.cancel(true);
} else if (hazelcastInstance != null) { } else if (hazelcastInstance != null) {
hazelcastInstance.getLifecycleService().shutdown(); hazelcastInstance.getLifecycleService().shutdown();
hazelcastInstance = null; hazelcastInstance = null;
}
} }
futureRef.set(null);
} }
} }

View File

@ -23,6 +23,7 @@ import org.idempiere.distributed.IClusterMember;
import org.idempiere.distributed.IClusterService; import org.idempiere.distributed.IClusterService;
import com.hazelcast.core.DistributedTask; import com.hazelcast.core.DistributedTask;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.Member; import com.hazelcast.core.Member;
import com.hazelcast.core.MultiTask; import com.hazelcast.core.MultiTask;
@ -37,10 +38,13 @@ public class ClusterServiceImpl implements IClusterService {
*/ */
@Override @Override
public Collection<IClusterMember> getMembers() { public Collection<IClusterMember> getMembers() {
Set<Member> members = Activator.getHazelcastInstance().getCluster().getMembers(); HazelcastInstance instance = Activator.getHazelcastInstance();
Set<IClusterMember> clusterMembers = new HashSet<IClusterMember>(); Set<IClusterMember> clusterMembers = new HashSet<IClusterMember>();
for(Member member : members) { if (instance != null) {
clusterMembers.add(new ClusterMember(member.getUuid(), member.getInetSocketAddress().getAddress(), member.getInetSocketAddress().getPort())); Set<Member> members = instance.getCluster().getMembers();
for(Member member : members) {
clusterMembers.add(new ClusterMember(member.getUuid(), member.getInetSocketAddress().getAddress(), member.getInetSocketAddress().getPort()));
}
} }
return clusterMembers; return clusterMembers;
} }
@ -50,8 +54,13 @@ public class ClusterServiceImpl implements IClusterService {
*/ */
@Override @Override
public IClusterMember getLocalMember() { public IClusterMember getLocalMember() {
Member member = Activator.getHazelcastInstance().getCluster().getLocalMember(); HazelcastInstance instance = Activator.getHazelcastInstance();
return new ClusterMember(member.getUuid(), member.getInetSocketAddress().getAddress(), member.getInetSocketAddress().getPort()); if (instance != null) {
Member member = instance.getCluster().getLocalMember();
return new ClusterMember(member.getUuid(), member.getInetSocketAddress().getAddress(), member.getInetSocketAddress().getPort());
} else {
return null;
}
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -59,12 +68,15 @@ public class ClusterServiceImpl implements IClusterService {
*/ */
@Override @Override
public <V> Future<V> execute(Callable<V> task, IClusterMember clusterMember) { public <V> Future<V> execute(Callable<V> task, IClusterMember clusterMember) {
Set<Member> members = Activator.getHazelcastInstance().getCluster().getMembers(); HazelcastInstance instance = Activator.getHazelcastInstance();
for(Member member : members) { if (instance != null) {
if (member.getUuid().equals(clusterMember.getId())) { Set<Member> members = instance.getCluster().getMembers();
DistributedTask<V> distributedTask = new DistributedTask<V>(task, member); for(Member member : members) {
Activator.getHazelcastInstance().getExecutorService().execute(distributedTask); if (member.getUuid().equals(clusterMember.getId())) {
return distributedTask; DistributedTask<V> distributedTask = new DistributedTask<V>(task, member);
Activator.getHazelcastInstance().getExecutorService().execute(distributedTask);
return distributedTask;
}
} }
} }
return null; return null;
@ -81,17 +93,20 @@ public class ClusterServiceImpl implements IClusterService {
for(IClusterMember clusterMember : clusterMembers) { for(IClusterMember clusterMember : clusterMembers) {
selectedIds.add(clusterMember.getId()); selectedIds.add(clusterMember.getId());
} }
Set<Member> members = Activator.getHazelcastInstance().getCluster().getMembers(); HazelcastInstance instance = Activator.getHazelcastInstance();
Set<Member> selectedMembers = new HashSet<Member>(); if (instance != null) {
for(Member member : members) { Set<Member> members = instance.getCluster().getMembers();
if (selectedIds.contains(member.getUuid())) { Set<Member> selectedMembers = new HashSet<Member>();
selectedMembers.add(member); for(Member member : members) {
if (selectedIds.contains(member.getUuid())) {
selectedMembers.add(member);
}
}
if (selectedMembers.size() > 0) {
MultiTask<V> multiTask = new MultiTask<V>(task, selectedMembers);
Activator.getHazelcastInstance().getExecutorService().execute(multiTask);
return multiTask;
} }
}
if (selectedMembers.size() > 0) {
MultiTask<V> multiTask = new MultiTask<V>(task, selectedMembers);
Activator.getHazelcastInstance().getExecutorService().execute(multiTask);
return multiTask;
} }
return null; return null;
} }

View File

@ -16,6 +16,8 @@ package org.idempiere.hazelcast.service;
import org.idempiere.distributed.IMessageService; import org.idempiere.distributed.IMessageService;
import org.idempiere.distributed.ITopic; import org.idempiere.distributed.ITopic;
import com.hazelcast.core.HazelcastInstance;
/** /**
* @author hengsin * @author hengsin
* *
@ -30,7 +32,12 @@ public class MessageServiceImpl implements IMessageService {
@Override @Override
public <T> ITopic<T> getTopic(String name) { public <T> ITopic<T> getTopic(String name) {
com.hazelcast.core.ITopic<T> topic = Activator.getHazelcastInstance().getTopic(name); HazelcastInstance instance = Activator.getHazelcastInstance();
return new TopicImpl<T>(topic); if (instance != null) {
com.hazelcast.core.ITopic<T> topic = instance.getTopic(name);
return new TopicImpl<T>(topic);
} else {
return null;
}
} }
} }