IDEMPIERE-4056 Implement cluster support for idempiere Monitor and Server Manager

This commit is contained in:
Heng Sin Low 2019-10-02 12:58:48 +08:00
parent f579549cba
commit 2cecee1a0c
19 changed files with 1729 additions and 180 deletions

View File

@ -38,6 +38,8 @@ Import-Package: javax.jms;version="1.1.0",
Export-Package: org.adempiere.server,
org.compiere.ldap,
org.compiere.server,
org.idempiere.server.cluster,
org.idempiere.server.cluster.callable,
org.idempiere.server.factory
Bundle-ActivationPolicy: lazy
Service-Component: OSGI-INF/*.xml

View File

@ -35,6 +35,7 @@ import org.compiere.model.MScheduler;
import org.compiere.model.MSession;
import org.compiere.util.CLogger;
import org.compiere.util.Env;
import org.idempiere.server.cluster.ClusterServerMgr;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.ServiceReference;
@ -47,19 +48,15 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
* @author Jorg Janke
* @version $Id: AdempiereServerMgr.java,v 1.4 2006/10/09 00:23:26 jjanke Exp $
*/
public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFactory<AdempiereServer, AdempiereProcessor>, IServerFactory<AdempiereServer, AdempiereProcessor>>, BundleListener
public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFactory<AdempiereServer, AdempiereProcessor>, IServerFactory<AdempiereServer, AdempiereProcessor>>, BundleListener, IServerManager
{
private static ServiceTracker<IServerFactory<AdempiereServer, AdempiereProcessor>, IServerFactory<AdempiereServer, AdempiereProcessor>> serviceTracker;
public static int SERVER_STATE_NOT_SCHEDULE = 0;
public static int SERVER_STATE_STARTED = 1;
public static int SERVER_STATE_STOPPED = 2;
/**
* Get Adempiere Server Manager
* @return mgr
*/
public synchronized static AdempiereServerMgr get()
public synchronized static IServerManager get()
{
return get(true);
}
@ -68,7 +65,7 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
* Get Adempiere Server Manager
* @return mgr
*/
public synchronized static AdempiereServerMgr get(boolean createNew)
public synchronized static IServerManager get(boolean createNew)
{
if (m_serverMgr == null && createNew)
{
@ -93,12 +90,12 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
{
super();
startEnvironment();
m_servers=new ArrayList<ServerWrapper>();
m_servers=new ArrayList<LocalServerController>();
processorClass = new HashSet<String>();
} // AdempiereServerMgr
/** The Servers */
private ArrayList<ServerWrapper> m_servers = new ArrayList<ServerWrapper>();
private ArrayList<LocalServerController> m_servers = new ArrayList<LocalServerController>();
/** Context */
private Properties m_ctx = Env.getCtx();
/** Start */
@ -129,14 +126,15 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
* @return true if started
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public synchronized boolean reload()
@Override
public synchronized String reload()
{
log.info("");
if (!stopAll())
return false;
if (stopAll() != null)
return "Failed to stop all servers";
int noServers = 0;
m_servers=new ArrayList<ServerWrapper>();
m_servers=new ArrayList<LocalServerController>();
processorClass = new HashSet<String>();
//osgi server
@ -150,7 +148,7 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
}
if (log.isLoggable(Level.FINE)) log.fine("#" + noServers);
return startAll();
return startAll() == null ? null : "Failed to restart all servers";
} // startEnvironment
private void createServers(IServerFactory<AdempiereServer, AdempiereProcessor> factory) {
@ -164,13 +162,18 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
for (AdempiereServer server : servers)
{
AdempiereProcessor model = server.getModel();
if (AdempiereServer.isOKtoRunOnIP(model)) {
m_servers.add(new ServerWrapper(server));
if (canRunHere(server, model)) {
m_servers.add(new LocalServerController(server));
}
}
}
}
}
private boolean canRunHere(AdempiereServer server, AdempiereProcessor model) {
return AdempiereServer.isOKtoRunOnIP(model)
&& ClusterServerMgr.getInstance().getServerInstanceAtOtherMembers(server.getServerID())==null;
}
/**
* @param scheduler
@ -179,7 +182,7 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
@SuppressWarnings({ "rawtypes", "unchecked" })
public boolean addScheduler(MScheduler scheduler) {
String serverId = scheduler.getServerID();
if (getServer(serverId) != null)
if (getServerInstance(serverId) != null)
return false;
//osgi server
@ -190,9 +193,9 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
{
if (factory.getProcessorClass().getName().equals(scheduler.getClass().getName())) {
AdempiereServer server = factory.create(m_ctx, scheduler);
if (server != null && AdempiereServer.isOKtoRunOnIP(scheduler)) {
m_servers.add(new ServerWrapper(server));
return start(serverId);
if (server != null && canRunHere(server, scheduler)) {
m_servers.add(new LocalServerController(server));
return start(serverId)==null;
}
}
}
@ -214,13 +217,14 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
* Start all servers
* @return true if started
*/
public synchronized boolean startAll()
@Override
public synchronized String startAll()
{
log.info ("");
ServerWrapper[] servers = getInActive();
LocalServerController[] servers = getInActive();
for (int i = 0; i < servers.length; i++)
{
ServerWrapper server = servers[i];
LocalServerController server = servers[i];
try
{
if (server.scheduleFuture != null && !server.scheduleFuture.isDone())
@ -243,7 +247,7 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
int noStopped = 0;
for (int i = 0; i < servers.length; i++)
{
ServerWrapper server = servers[i];
LocalServerController server = servers[i];
try
{
if (server.scheduleFuture != null && !server.scheduleFuture.isDone())
@ -264,7 +268,7 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
}
}
if (log.isLoggable(Level.FINE)) log.fine("Running=" + noRunning + ", Stopped=" + noStopped);
return noStopped == 0;
return noStopped == 0 ? null : "Failed to start all servers";
} // startAll
/**
@ -272,13 +276,14 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
* @param serverID server ID
* @return true if started
*/
public synchronized boolean start (String serverID)
@Override
public synchronized String start (String serverID)
{
ServerWrapper server = getServer(serverID);
LocalServerController server = getLocalServerController(serverID);
if (server == null)
return false;
return "Server not found";
if (server.scheduleFuture != null && !server.scheduleFuture.isDone())
return true;
return "Server is already running";
try
{
@ -290,28 +295,29 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
catch (Exception e)
{
log.log(Level.SEVERE, "Server=" + serverID, e);
return false;
return e.getMessage();
}
finally
{
Env.setContext(Env.getCtx(), Env.AD_CLIENT_ID, 0);
}
if (log.isLoggable(Level.INFO)) log.info(server.toString());
return (server.scheduleFuture != null && !server.scheduleFuture.isDone());
return (server.scheduleFuture != null && !server.scheduleFuture.isDone()) ? null : "Failed to start server";
} // startIt
/**
* Stop all Servers
* @return true if stopped
*/
public synchronized boolean stopAll()
@Override
public synchronized String stopAll()
{
log.info ("");
ServerWrapper[] servers = getActive();
LocalServerController[] servers = getActive();
// Interrupt
for (int i = 0; i < servers.length; i++)
{
ServerWrapper server = servers[i];
LocalServerController server = servers[i];
try
{
if (server.scheduleFuture != null && !server.scheduleFuture.isDone())
@ -329,7 +335,7 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
// Wait for death
for (int i = 0; i < servers.length; i++)
{
ServerWrapper server = servers[i];
LocalServerController server = servers[i];
try
{
int maxWait = 10; // 10 iterations = 1 sec
@ -354,7 +360,7 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
int noStopped = 0;
for (int i = 0; i < servers.length; i++)
{
ServerWrapper server = servers[i];
LocalServerController server = servers[i];
try
{
if (server.scheduleFuture != null && !server.scheduleFuture.isDone())
@ -376,7 +382,7 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
}
if (log.isLoggable(Level.FINE)) log.fine("Running=" + noRunning + ", Stopped=" + noStopped);
AdempiereServerGroup.get().dump();
return noRunning == 0;
return noRunning == 0 ? null : "Failed to stop all servers";
} // stopAll
/**
@ -384,13 +390,14 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
* @param serverID server ID
* @return true if interrupted
*/
public synchronized boolean stop (String serverID)
@Override
public synchronized String stop (String serverID)
{
ServerWrapper server = getServer(serverID);
LocalServerController server = getLocalServerController(serverID);
if (server == null)
return false;
return "Server not found";
if (server.scheduleFuture == null || server.scheduleFuture.isDone())
return true;
return "Server is already stop";
try
{
@ -400,10 +407,10 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
catch (Exception e)
{
log.log(Level.SEVERE, "stop", e);
return false;
return e.getMessage();
}
if (log.isLoggable(Level.INFO)) log.info(server.toString());
return (server.scheduleFuture == null || server.scheduleFuture.isDone());
return (server.scheduleFuture == null || server.scheduleFuture.isDone()) ? null : "Failed to stop server";
} // stop
@ -421,16 +428,16 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
* Get Active Servers
* @return array of active servers
*/
protected synchronized ServerWrapper[] getActive()
protected synchronized LocalServerController[] getActive()
{
ArrayList<ServerWrapper> list = new ArrayList<ServerWrapper>();
ArrayList<LocalServerController> list = new ArrayList<LocalServerController>();
for (int i = 0; i < m_servers.size(); i++)
{
ServerWrapper server = (ServerWrapper)m_servers.get(i);
LocalServerController server = (LocalServerController)m_servers.get(i);
if (server != null && server.scheduleFuture != null && !server.scheduleFuture.isDone())
list.add (server);
}
ServerWrapper[] retValue = new ServerWrapper[list.size ()];
LocalServerController[] retValue = new LocalServerController[list.size ()];
list.toArray (retValue);
return retValue;
} // getActive
@ -439,16 +446,16 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
* Get InActive Servers
* @return array of inactive servers
*/
protected synchronized ServerWrapper[] getInActive()
protected synchronized LocalServerController[] getInActive()
{
ArrayList<ServerWrapper> list = new ArrayList<ServerWrapper>();
ArrayList<LocalServerController> list = new ArrayList<LocalServerController>();
for (int i = 0; i < m_servers.size(); i++)
{
ServerWrapper server = m_servers.get(i);
LocalServerController server = m_servers.get(i);
if (server != null && (server.scheduleFuture == null || server.scheduleFuture.isDone()))
list.add (server);
}
ServerWrapper[] retValue = new ServerWrapper[list.size()];
LocalServerController[] retValue = new LocalServerController[list.size()];
list.toArray (retValue);
return retValue;
} // getInActive
@ -457,33 +464,32 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
* Get all Servers
* @return array of servers
*/
public synchronized ServerWrapper[] getAll()
private synchronized LocalServerController[] getLocalServerControllers()
{
ServerWrapper[] retValue = new ServerWrapper[m_servers.size()];
LocalServerController[] retValue = new LocalServerController[m_servers.size()];
m_servers.toArray (retValue);
return retValue;
} // getAll
public synchronized int getStatus(AdempiereProcessor processor)
{
int status = SERVER_STATE_NOT_SCHEDULE;
for (int i = 0; i < m_servers.size(); i++)
{
ServerWrapper server = m_servers.get(i);
AdempiereProcessor model = server.server.getModel();
if (model.getClass().getName().equals(processor.getClass().getName()) && model.getServerID().equals(processor.getServerID()))
{
if (server.scheduleFuture == null || server.scheduleFuture.isDone())
{
status = SERVER_STATE_STOPPED;
}
else
{
status = SERVER_STATE_STARTED;
}
@Override
public ServerInstance[] getServerInstances() {
List<ServerInstance> responses = new ArrayList<>();
LocalServerController[] controllers = getLocalServerControllers();
for (LocalServerController controller : controllers) {
if (controller.getServer() != null) {
ServerInstance response = new ServerInstance(controller.getServer().getServerID(), controller.getServer().getModel(),
controller.isAlive(), controller.isInterrupted(), controller.getServer().isSleeping(),
controller.getServer().getStartTime(), controller.getServer().getStatistics(), controller.getServer().getServerInfo());
responses.add(response);
}
}
return status;
return responses.toArray(new ServerInstance[0]);
}
public synchronized int getStatus(AdempiereProcessor processor)
{
return getServerStatus(processor.getServerID());
}
/**
@ -491,13 +497,34 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
* @param serverID server id
* @return server or null
*/
public synchronized ServerWrapper getServer (String serverID)
@Override
public synchronized ServerInstance getServerInstance(String serverID)
{
if (serverID == null)
return null;
for (int i = 0; i < m_servers.size(); i++)
{
ServerWrapper server = m_servers.get(i);
LocalServerController server = m_servers.get(i);
if (serverID.equals(server.server.getServerID()))
return new ServerInstance(server.getServer().getServerID(), server.getServer().getModel(),
server.isAlive(), server.isInterrupted(), server.getServer().isSleeping(),
server.getServer().getStartTime(), server.getServer().getStatistics(), server.getServer().getServerInfo());
}
return null;
} // getServer
/**
* Get Server with ID
* @param serverID server id
* @return server or null
*/
private synchronized LocalServerController getLocalServerController (String serverID)
{
if (serverID == null)
return null;
for (int i = 0; i < m_servers.size(); i++)
{
LocalServerController server = m_servers.get(i);
if (serverID.equals(server.server.getServerID()))
return server;
}
@ -522,49 +549,48 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
* Get Description
* @return description
*/
@Override
public String getDescription()
{
return "$Revision: 1.4 $";
return Adempiere.getVersion();
} // getDescription
/**
* Get Number Servers
* @return no of servers
*/
public synchronized String getServerCount()
@Override
public synchronized ServerCount getServerCount()
{
int noRunning = 0;
int noStopped = 0;
ServerCount serverCount = new ServerCount();
for (int i = 0; i < m_servers.size(); i++)
{
ServerWrapper server = m_servers.get(i);
LocalServerController server = m_servers.get(i);
if (server.scheduleFuture != null && !server.scheduleFuture.isDone())
noRunning++;
serverCount.addStarted(1);
else
noStopped++;
serverCount.addStopped(1);
}
String info = String.valueOf(m_servers.size())
+ " - Running=" + noRunning
+ " - Stopped=" + noStopped;
return info;
return serverCount;
} // getServerCount
/**
* Get start date
* @return start date
*/
@Override
public Timestamp getStartTime()
{
return m_start;
} // getStartTime
public static class ServerWrapper implements Runnable
private class LocalServerController implements Runnable
{
protected AdempiereServer server;
protected volatile ScheduledFuture<?> scheduleFuture;
public ServerWrapper(AdempiereServer server) {
public LocalServerController(AdempiereServer server) {
this.server = server;
start();
}
@ -633,12 +659,12 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
}
public Boolean remove(String serverID) {
ServerWrapper server = getServer(serverID);
LocalServerController server = getLocalServerController(serverID);
if (server == null)
return false;
if (server.scheduleFuture != null && !server.scheduleFuture.isDone()) {
if (!stop(serverID)) {
if (stop(serverID) != null) {
return false;
}
}
@ -653,4 +679,38 @@ public class AdempiereServerMgr implements ServiceTrackerCustomizer<IServerFacto
return false;
}
@Override
public String runNow(String serverId) {
LocalServerController serverInstance = getLocalServerController(serverId);
if (serverInstance == null || serverInstance.getServer() == null) {
return "Server " + serverId + " not found";
}
if (serverInstance.getServer().isSleeping())
{
serverInstance.getServer().runNow();
}
else
{
int count = 0;
while(!serverInstance.getServer().isSleeping() && count < 5)
{
count++;
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
if (serverInstance.getServer().isSleeping())
serverInstance.getServer().runNow();
else
{
return "Timeout waiting for server process to be available for execution.";
}
}
return null;
}
} // AdempiereServerMgr

View File

@ -27,7 +27,6 @@ import java.util.Collection;
import java.util.logging.Level;
import org.adempiere.impexp.ArrayExcelExporter;
import org.compiere.Adempiere;
import org.compiere.model.MAlert;
import org.compiere.model.MAlertProcessor;
import org.compiere.model.MAlertProcessorLog;
@ -457,21 +456,5 @@ public class AlertProcessor extends AdempiereServer
public String getServerInfo()
{
return "#" + p_runCount + " - Last=" + m_summary.toString();
} // getServerInfo
/***************************************************************************
* Test
* @param args ignored
*/
public static void main (String[] args)
{
Adempiere.startup(true);
MAlertProcessor model = new MAlertProcessor (Env.getCtx(), 100, null);
AlertProcessor ap = new AlertProcessor(model);
AdempiereServerMgr.ServerWrapper wrapper = new AdempiereServerMgr.ServerWrapper(ap);
wrapper.start();
}
} // getServerInfo
}

View File

@ -0,0 +1,121 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.compiere.server;
import java.sql.Timestamp;
/**
*
* @author hengsin
*
*/
public interface IServerManager {
public static int SERVER_STATE_NOT_SCHEDULE = 0;
public static int SERVER_STATE_STARTED = 1;
public static int SERVER_STATE_STOPPED = 2;
/**
* Get server instance by id
* @param serverId
* @return ServerInstance or null if not found
*/
public ServerInstance getServerInstance(String serverId);
/**
*
* @param serverId
* @return server status
*/
public default int getServerStatus(String serverId) {
ServerInstance instance = getServerInstance(serverId);
if (instance == null || instance.getServerId() == null) {
return SERVER_STATE_NOT_SCHEDULE;
} else if (instance.isStarted()) {
return SERVER_STATE_STARTED;
} else {
return SERVER_STATE_STOPPED;
}
}
/**
*
* @param serverId
* @return error
*/
public String runNow(String serverId);
/**
*
* @param serverId
* @return error
*/
public String start(String serverId);
/**
*
* @param serverId
* @return error
*/
public String stop(String serverId);
/**
* @return error
*/
public String startAll();
/**
* @return error
*/
public String stopAll();
/**
* @return error
*/
public String reload();
/**
* @return start time stamp
*/
public Timestamp getStartTime();
/**
*
* @return ServerCount
*/
public ServerCount getServerCount();
/**
* @return all server instances
*/
public ServerInstance[] getServerInstances();
/**
* @return description
*/
public String getDescription();
}

View File

@ -0,0 +1,73 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.compiere.server;
import java.io.Serializable;
/**
*
* @author hengsin
*
*/
public class ServerCount implements Serializable {
/**
* generated serial id
*/
private static final long serialVersionUID = -5064676550658918430L;
private int noStarted = 0;
private int noStopped = 0;
/**
* @return no of started instance
*/
public int getStarted() {
return noStarted;
}
/**
* @return no of stopped instance
*/
public int getStopped() {
return noStopped;
}
/**
* increase no of started count
* @param started
*/
public void addStarted(int started) {
noStarted += started;
}
/**
* increase no of stopped count
* @param stopped
*/
public void addStopped(int stopped) {
noStopped += stopped;
}
}

View File

@ -0,0 +1,146 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.compiere.server;
import java.io.Serializable;
import java.sql.Timestamp;
import org.compiere.model.AdempiereProcessor;
import org.idempiere.distributed.IClusterMember;
/**
*
* @author hengsin
*
*/
public class ServerInstance implements Serializable {
/**
* generated serial id
*/
private static final long serialVersionUID = -6332080326921128215L;
private String serverId;
private AdempiereProcessor model;
private boolean started = false;
private boolean interrupted = false;
private boolean sleeping = false;
private Timestamp startTime;
private String statistics;
private String serverInfo;
private IClusterMember clusterMember;
/**
*
* @param server
* @param started
* @param interrupted
*/
public ServerInstance(String serverId, AdempiereProcessor model, boolean started, boolean interrupted,
boolean sleeping, Timestamp startTime, String statistics, String serverInfo) {
this.serverId = serverId;
this.model = model;
this.started = started;
this.sleeping = sleeping;
this.startTime = startTime;
this.statistics = statistics;
this.serverInfo = serverInfo;
}
/**
* @return is instance started
*/
public boolean isStarted() {
return started;
}
/**
* @return is instance interrupted/stopped
*/
public boolean isInterrupted() {
return interrupted;
}
/**
* is instance idle waiting for next run (at the time of getting this ServerInstance reference)
* @return true if instance is idle, false otherwise
*/
public boolean isSleeping() {
return sleeping;
}
/**
* @return latest start time
*/
public Timestamp getStartTime() {
return startTime;
}
/**
* Get Run Statistics
* @return Statistic info
*/
public String getStatistics() {
return statistics;
}
/**
* Get Server Info
* @return info
*/
public String getServerInfo() {
return serverInfo;
}
/**
* @return server id
*/
public String getServerId() {
return serverId;
}
/**
*
* @return {@link AdempiereProcessor}
*/
public AdempiereProcessor getModel() {
return model;
}
/**
*
* @param clusterMember
*/
public void setClusterMember(IClusterMember clusterMember) {
this.clusterMember = clusterMember;
}
/**
* @return {@link IClusterMember}
*/
public IClusterMember getClusterMember() {
return clusterMember;
}
}

View File

@ -0,0 +1,421 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.adempiere.base.IServiceHolder;
import org.adempiere.base.Service;
import org.compiere.Adempiere;
import org.compiere.server.IServerManager;
import org.compiere.server.ServerCount;
import org.compiere.server.ServerInstance;
import org.idempiere.distributed.IClusterMember;
import org.idempiere.distributed.IClusterService;
import org.idempiere.server.cluster.callable.GetAllCallable;
import org.idempiere.server.cluster.callable.GetServerCallable;
import org.idempiere.server.cluster.callable.GetServerCountCallable;
import org.idempiere.server.cluster.callable.GetStartTimeCallable;
import org.idempiere.server.cluster.callable.ReloadCallable;
import org.idempiere.server.cluster.callable.Response;
import org.idempiere.server.cluster.callable.RunNowCallable;
import org.idempiere.server.cluster.callable.StartAllCallable;
import org.idempiere.server.cluster.callable.StartCallable;
import org.idempiere.server.cluster.callable.StopAllCallable;
import org.idempiere.server.cluster.callable.StopCallable;
/**
*
* @author hengsin
*
*/
public class ClusterServerMgr implements IServerManager {
private final static ClusterServerMgr INSTANCE = new ClusterServerMgr();
/**
*
* @return share instance
*/
public static ClusterServerMgr getInstance() {
return INSTANCE;
}
private ClusterServerMgr() {
}
private IClusterService getClusterService() {
IServiceHolder<IClusterService> holder = Service.locator().locate(IClusterService.class);
IClusterService service = holder != null ? holder.getService() : null;
return service;
}
@Override
public ServerInstance getServerInstance(String serverId) {
IClusterService service = getClusterService();
if (service == null)
return null;
GetServerCallable callable = new GetServerCallable(serverId);
Map<IClusterMember, Future<ServerInstance>> futureMap = service.execute(callable, service.getMembers());
if (futureMap != null) {
try {
Set<Entry<IClusterMember, Future<ServerInstance>>> results = futureMap.entrySet();
for(Entry<IClusterMember, Future<ServerInstance>> f : results) {
ServerInstance i = f.getValue().get();
if (i != null) {
i.setClusterMember(f.getKey());
return i;
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
return null;
}
@Override
public String runNow(String serverId) {
IClusterService service = getClusterService();
if (service == null)
return "Cluster service not available";
RunNowCallable callable = new RunNowCallable(serverId);
Map<IClusterMember, Future<Response>> futureMap = service.execute(callable, service.getMembers());
if (futureMap != null) {
try {
Collection<Future<Response>> results = futureMap.values();
for(Future<Response> f : results) {
Response response = f.get();
if (response.getServerId() != null) {
return response.getError();
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getMessage(), e);
}
return "Server " + serverId + " not found";
}
return null;
}
@Override
public String start(String serverId) {
IClusterService service = getClusterService();
if (service == null)
return "Cluster service not available";
StartCallable callable = new StartCallable(serverId);
Map<IClusterMember, Future<Response>> futureMap = service.execute(callable, service.getMembers());
if (futureMap != null) {
try {
Collection<Future<Response>> results = futureMap.values();
for(Future<Response> f : results) {
Response response = f.get();
if (response != null && response.getServerId() != null) {
return response.getError();
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getMessage(), e);
}
return "Server " + serverId + " not found";
} else {
return "Failed to send start request through cluster service";
}
}
@Override
public String stop(String serverId) {
IClusterService service = getClusterService();
if (service == null)
return "Cluster service not available";
StopCallable callable = new StopCallable(serverId);
Map<IClusterMember, Future<Response>> futureMap = service.execute(callable, service.getMembers());
if (futureMap != null) {
try {
Collection<Future<Response>> results = futureMap.values();
for(Future<Response> f : results) {
Response response = f.get();
if (response != null && response.getServerId() != null) {
return response.getError();
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getMessage(), e);
}
return "Server " + serverId + " not found";
} else {
return "Failed to send stop request through cluster service";
}
}
@Override
public String reload() {
IClusterService service = getClusterService();
if (service == null)
return "Cluster service not available";
ReloadCallable callable = new ReloadCallable();
Map<IClusterMember, Future<String>> futureMap = service.execute(callable, service.getMembers());
if (futureMap != null) {
try {
Collection<Future<String>> results = futureMap.values();
for(Future<String> f : results) {
String response = f.get();
if (response != null) {
return response;
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getMessage(), e);
}
return null;
} else {
return "Failed to send reload request through cluster service";
}
}
@Override
public Timestamp getStartTime() {
IClusterService service = getClusterService();
if (service == null)
return null;
Timestamp earliest = null;
GetStartTimeCallable callable = new GetStartTimeCallable();
Map<IClusterMember, Future<Timestamp>> futureMap = service.execute(callable, service.getMembers());
if (futureMap != null) {
try {
Collection<Future<Timestamp>> results = futureMap.values();
for(Future<Timestamp> f : results) {
Timestamp response = f.get();
if (response != null) {
if (earliest == null)
earliest = response;
else if (response.before(earliest))
earliest = response;
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
return earliest;
}
@Override
public ServerCount getServerCount() {
IClusterService service = getClusterService();
if (service == null)
return null;
ServerCount serverCount = null;
GetServerCountCallable callable = new GetServerCountCallable();
Map<IClusterMember, Future<ServerCount>> futureMap = service.execute(callable, service.getMembers());
if (futureMap != null) {
try {
Collection<Future<ServerCount>> results = futureMap.values();
for(Future<ServerCount> f : results) {
ServerCount response = f.get();
if (response != null) {
if (serverCount == null) {
serverCount = response;
} else {
serverCount.addStarted(response.getStarted());
serverCount.addStopped(response.getStopped());
}
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
return serverCount;
}
@Override
public ServerInstance[] getServerInstances() {
IClusterService service = getClusterService();
if (service == null)
return null;
List<ServerInstance> servers = new ArrayList<>();
GetAllCallable callable = new GetAllCallable();
Map<IClusterMember, Future<ServerInstance[]>> futureMap = service.execute(callable, service.getMembers());
if (futureMap != null) {
try {
Set<Entry<IClusterMember, Future<ServerInstance[]>>> results = futureMap.entrySet();
for(Entry<IClusterMember, Future<ServerInstance[]>> f : results) {
ServerInstance[] response = f.getValue().get();
if (response != null) {
Arrays.stream(response).forEach(e -> {
e.setClusterMember(f.getKey());
servers.add(e);
});
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
return servers.toArray(new ServerInstance[0]);
}
@Override
public String getDescription() {
return Adempiere.getVersion();
}
@Override
public String startAll() {
IClusterService service = getClusterService();
if (service == null)
return "Cluster service not available";
StartAllCallable callable = new StartAllCallable();
Map<IClusterMember, Future<String>> futureMap = service.execute(callable, service.getMembers());
if (futureMap != null) {
try {
Collection<Future<String>> results = futureMap.values();
for(Future<String> f : results) {
String response = f.get();
if (response != null) {
return response;
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getMessage(), e);
}
return null;
} else {
return "Failed to send start all request through cluster servie";
}
}
@Override
public String stopAll() {
IClusterService service = getClusterService();
if (service == null)
return "Cluster service not available";
StopAllCallable callable = new StopAllCallable();
Map<IClusterMember, Future<String>> futureMap = service.execute(callable, service.getMembers());
if (futureMap != null) {
try {
Collection<Future<String>> results = futureMap.values();
for(Future<String> f : results) {
String response = f.get();
if (response != null) {
return response;
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getMessage(), e);
}
return null;
} else {
return "Failed to send stop all request through cluster servie";
}
}
/**
* find server instance from non-local nodes
* @param serverId
* @return ServerInstance
*/
public ServerInstance getServerInstanceAtOtherMembers(String serverId) {
IClusterService service = getClusterService();
if (service == null)
return null;
GetServerCallable callable = new GetServerCallable(serverId);
Collection<IClusterMember> members = service.getMembers();
if (members == null || members.isEmpty())
return null;
final IClusterMember local = service.getLocalMember();
if (local == null)
return null;
List<IClusterMember> others = new ArrayList<>();
members.forEach(e -> {
if (!e.getId().equals(local.getId())) {
others.add(e);
}
});
if (others.size() > 0) {
Map<IClusterMember, Future<ServerInstance>> futureMap = service.execute(callable, others);
if (futureMap != null) {
try {
Set<Entry<IClusterMember, Future<ServerInstance>>> results = futureMap.entrySet();
for(Entry<IClusterMember, Future<ServerInstance>> f : results) {
ServerInstance i = f.getValue().get();
if (i != null) {
i.setClusterMember(f.getKey());
return i;
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
return null;
}
}

View File

@ -0,0 +1,66 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster.callable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import org.compiere.server.AdempiereServerMgr;
import org.compiere.server.IServerManager;
import org.compiere.server.ServerInstance;
/**
* @author hengsin
*
*/
public class GetAllCallable implements Callable<ServerInstance[]>, Serializable {
/**
* generated serial
*/
private static final long serialVersionUID = -2658045266402067579L;
/**
* default constructor
*/
public GetAllCallable() {
}
@Override
public ServerInstance[] call() throws Exception {
List<ServerInstance> responses = new ArrayList<>();
IServerManager serverMgr = AdempiereServerMgr.get(false);
if (serverMgr != null) {
ServerInstance[] servers = serverMgr.getServerInstances();
for (ServerInstance server : servers) {
responses.add(server);
}
}
return responses.toArray(new ServerInstance[0]);
}
}

View File

@ -0,0 +1,63 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster.callable;
import java.io.Serializable;
import java.util.concurrent.Callable;
import org.compiere.server.AdempiereServerMgr;
import org.compiere.server.IServerManager;
import org.compiere.server.ServerInstance;
/**
* @author hengsin
*
*/
public class GetServerCallable implements Callable<ServerInstance>, Serializable {
/**
* generated serial
*/
private static final long serialVersionUID = -2658045266402067579L;
private String serverId;
/**
* @param serverId
*/
public GetServerCallable(String serverId) {
this.serverId = serverId;
}
@Override
public ServerInstance call() throws Exception {
IServerManager serverMgr = AdempiereServerMgr.get(false);
if (serverMgr != null) {
return serverMgr.getServerInstance(serverId);
}
return null;
}
}

View File

@ -0,0 +1,69 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster.callable;
import java.io.Serializable;
import java.util.concurrent.Callable;
import org.compiere.server.AdempiereServerMgr;
import org.compiere.server.IServerManager;
import org.compiere.server.ServerCount;
import org.compiere.server.ServerInstance;
/**
* @author hengsin
*
*/
public class GetServerCountCallable implements Callable<ServerCount>, Serializable {
/**
* generated serial
*/
private static final long serialVersionUID = 3496041492358893501L;
/**
* default constructor
*/
public GetServerCountCallable() {
}
@Override
public ServerCount call() throws Exception {
ServerCount serverCount = new ServerCount();
IServerManager serverMgr = AdempiereServerMgr.get(false);
if (serverMgr != null) {
ServerInstance[] servers = serverMgr.getServerInstances();
for (ServerInstance server : servers) {
if (server.isStarted())
serverCount.addStarted(1);
else
serverCount.addStopped(1);
}
}
return serverCount;
}
}

View File

@ -0,0 +1,62 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster.callable;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.concurrent.Callable;
import org.compiere.server.AdempiereServerMgr;
import org.compiere.server.IServerManager;
/**
* @author hengsin
*
*/
public class GetStartTimeCallable implements Callable<Timestamp>, Serializable {
/**
* generated serial
*/
private static final long serialVersionUID = 3496041492358893501L;
/**
* default constructor
*/
public GetStartTimeCallable() {
}
@Override
public Timestamp call() throws Exception {
IServerManager serverMgr = AdempiereServerMgr.get(false);
if (serverMgr != null) {
return serverMgr.getStartTime();
}
return null;
}
}

View File

@ -0,0 +1,62 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster.callable;
import java.io.Serializable;
import java.util.concurrent.Callable;
import org.compiere.server.AdempiereServerMgr;
import org.compiere.server.IServerManager;
/**
* @author hengsin
*
*/
public class ReloadCallable implements Callable<String>, Serializable {
/**
* generated serial
*/
private static final long serialVersionUID = -477156440432070776L;
/**
* default constructor
*/
public ReloadCallable() {
}
@Override
public String call() throws Exception {
IServerManager serverMgr = AdempiereServerMgr.get(false);
if (serverMgr != null) {
return serverMgr.reload();
}
return null;
}
}

View File

@ -0,0 +1,51 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster.callable;
import java.io.Serializable;
/**
*
* @author hengsin
*
*/
public class Response implements Serializable {
/**
* generated serial id
*/
private static final long serialVersionUID = -62222370378270354L;
protected String error = null;
protected String serverId = null;
public String getError() {
return error;
}
public String getServerId() {
return serverId;
}
}

View File

@ -0,0 +1,68 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster.callable;
import java.io.Serializable;
import java.util.concurrent.Callable;
import org.compiere.server.AdempiereServerMgr;
import org.compiere.server.IServerManager;
import org.compiere.server.ServerInstance;
/**
* @author hengsin
*
*/
public class RunNowCallable implements Callable<Response>, Serializable {
/**
* generated serial
*/
private static final long serialVersionUID = 3629305666372614289L;
private String serverId;
/**
* @param serverId
*/
public RunNowCallable(String serverId) {
this.serverId = serverId;
}
@Override
public Response call() throws Exception {
Response response = new Response();
IServerManager serverMgr = AdempiereServerMgr.get(false);
if (serverMgr != null) {
ServerInstance serverInstance = serverMgr.getServerInstance(serverId);
if (serverInstance != null) {
response.serverId = serverInstance.getServerId();
response.error = serverMgr.runNow(serverId);
}
}
return response;
}
}

View File

@ -0,0 +1,61 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster.callable;
import java.io.Serializable;
import java.util.concurrent.Callable;
import org.compiere.server.AdempiereServerMgr;
import org.compiere.server.IServerManager;
/**
* @author hengsin
*
*/
public class StartAllCallable implements Callable<String>, Serializable {
/**
* generated serial
*/
private static final long serialVersionUID = 3496041492358893501L;
/**
* default constructor
*/
public StartAllCallable() {
}
@Override
public String call() throws Exception {
IServerManager serverMgr = AdempiereServerMgr.get(false);
if (serverMgr != null) {
return serverMgr.startAll();
}
return null;
}
}

View File

@ -0,0 +1,69 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster.callable;
import java.io.Serializable;
import java.util.concurrent.Callable;
import org.compiere.server.AdempiereServerMgr;
import org.compiere.server.IServerManager;
import org.compiere.server.ServerInstance;
/**
* @author hengsin
*
*/
public class StartCallable implements Callable<Response>, Serializable {
/**
* generated serial
*/
private static final long serialVersionUID = 3496041492358893501L;
private String serverId;
/**
* @param serverId
*/
public StartCallable(String serverId) {
this.serverId = serverId;
}
@Override
public Response call() throws Exception {
Response response = new Response();
IServerManager serverMgr = AdempiereServerMgr.get(false);
if (serverMgr != null) {
ServerInstance server = serverMgr.getServerInstance(serverId);
if (server != null) {
response.error = serverMgr.start(serverId);
response.serverId = server.getServerId();
}
}
return response;
}
}

View File

@ -0,0 +1,61 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster.callable;
import java.io.Serializable;
import java.util.concurrent.Callable;
import org.compiere.server.AdempiereServerMgr;
import org.compiere.server.IServerManager;
/**
* @author hengsin
*
*/
public class StopAllCallable implements Callable<String>, Serializable {
/**
* generated serial
*/
private static final long serialVersionUID = 3496041492358893501L;
/**
* default constructor
*/
public StopAllCallable() {
}
@Override
public String call() throws Exception {
IServerManager serverMgr = AdempiereServerMgr.get(false);
if (serverMgr != null) {
return serverMgr.stopAll();
}
return null;
}
}

View File

@ -0,0 +1,68 @@
/**********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Trek Global Corporation *
* - Heng Sin Low *
**********************************************************************/
package org.idempiere.server.cluster.callable;
import java.io.Serializable;
import java.util.concurrent.Callable;
import org.compiere.server.AdempiereServerMgr;
import org.compiere.server.IServerManager;
import org.compiere.server.ServerInstance;
/**
* @author hengsin
*
*/
public class StopCallable implements Callable<Response>, Serializable {
/**
* generated serial
*/
private static final long serialVersionUID = 3496041492358893501L;
private String serverId;
/**
* @param serverId
*/
public StopCallable(String serverId) {
this.serverId = serverId;
}
@Override
public Response call() throws Exception {
Response response = new Response();
IServerManager serverMgr = AdempiereServerMgr.get(false);
if (serverMgr != null) {
ServerInstance server = serverMgr.getServerInstance(serverId);
if (server != null) {
response.error = serverMgr.stop(serverId);
response.serverId = server.getServerId();
}
}
return response;
}
}

View File

@ -26,6 +26,7 @@ import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
import java.net.InetAddress;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
@ -39,6 +40,8 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.adempiere.base.IServiceHolder;
import org.adempiere.base.Service;
import org.adempiere.util.LogAuthFailure;
import org.apache.ecs.HtmlColor;
import org.apache.ecs.xhtml.a;
@ -69,10 +72,11 @@ import org.compiere.model.MStore;
import org.compiere.model.MSysConfig;
import org.compiere.model.MSystem;
import org.compiere.model.Query;
import org.compiere.server.AdempiereServer;
import org.compiere.server.AdempiereServerGroup;
import org.compiere.server.AdempiereServerMgr;
import org.compiere.server.AdempiereServerMgr.ServerWrapper;
import org.compiere.server.IServerManager;
import org.compiere.server.ServerCount;
import org.compiere.server.ServerInstance;
import org.compiere.util.CLogFile;
import org.compiere.util.CLogMgt;
import org.compiere.util.CLogger;
@ -83,9 +87,12 @@ import org.compiere.util.Env;
import org.compiere.util.Ini;
import org.compiere.util.TimeUtil;
import org.compiere.util.Trx;
import org.compiere.util.Util;
import org.compiere.util.WebDoc;
import org.compiere.util.WebEnv;
import org.compiere.util.WebUtil;
import org.idempiere.distributed.IClusterService;
import org.idempiere.server.cluster.ClusterServerMgr;
/**
* Adempiere Server Monitor
@ -103,7 +110,7 @@ public class AdempiereMonitor extends HttpServlet
/** Logger */
private static CLogger log = CLogger.getCLogger(AdempiereMonitor.class);
/** The Server */
private static AdempiereServerMgr m_serverMgr = null;
private static IServerManager m_serverMgr = null;
/** Message */
private static p m_message = null;
@ -189,8 +196,8 @@ public class AdempiereMonitor extends HttpServlet
return false;
if (log.isLoggable(Level.INFO)) log.info ("ServerID=" + serverID);
ServerWrapper server = m_serverMgr.getServer(serverID);
if (server == null || server.getServer() == null)
ServerInstance server = m_serverMgr.getServerInstance(serverID);
if (server == null)
{
m_message = new p();
m_message.addElement(new strong("Server not found: "));
@ -207,7 +214,7 @@ public class AdempiereMonitor extends HttpServlet
para.addElement(link);
b.addElement(para);
//
b.addElement(new h2(server.getServer().getName()));
b.addElement(new h2(server.getModel().getName()));
//
table table = new table();
table.setBorder(1);
@ -224,7 +231,7 @@ public class AdempiereMonitor extends HttpServlet
// line.addElement(new th().addElement("Description"));
table.addElement(line);
AdempiereProcessorLog[] logs = server.getServer().getLogs();
AdempiereProcessorLog[] logs = server.getModel().getLogs();
for (int i = 0; i < logs.length; i++)
{
AdempiereProcessorLog pLog = logs[i];
@ -260,8 +267,8 @@ public class AdempiereMonitor extends HttpServlet
return false;
if (log.isLoggable(Level.INFO)) log.info ("ServerID=" + serverID);
ServerWrapper server = m_serverMgr.getServer(serverID);
if (server == null || server.getServer() == null)
ServerInstance server = m_serverMgr.getServerInstance(serverID);
if (server == null)
{
m_message = new p();
m_message.addElement(new strong("Server not found: "));
@ -269,32 +276,14 @@ public class AdempiereMonitor extends HttpServlet
return false;
}
//
AdempiereServer serverInstance = server.getServer();
if (serverInstance.isSleeping())
String error = m_serverMgr.runNow(serverID);
if (!Util.isEmpty(error, true))
{
serverInstance.runNow();
}
else
{
int count = 0;
while(!serverInstance.isSleeping() && count < 5)
{
count++;
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
if (serverInstance.isSleeping())
serverInstance.runNow();
else
{
m_message = new p();
m_message.addElement(new strong("Timeout waiting for server process to be available for execution."));
m_message.addElement(serverID);
}
m_message = new p();
m_message.addElement(new strong(error));
m_message.addElement(serverID);
}
//
return true;
} // processRunParameter
@ -323,9 +312,9 @@ public class AdempiereMonitor extends HttpServlet
{
if (start)
{
ok = m_serverMgr.startAll();
ok = m_serverMgr.startAll()==null;
} else{
ok = m_serverMgr.stopAll();
ok = m_serverMgr.stopAll()==null;
}
m_message.addElement("All");
@ -334,22 +323,22 @@ public class AdempiereMonitor extends HttpServlet
{
if (reload)
{
ok=m_serverMgr.reload();
ok=m_serverMgr.reload()==null;
this.createSummaryPage(request, response,true);
m_dirAccessList = getDirAcessList();
} else {
ServerWrapper server = m_serverMgr.getServer(serverID);
if (server == null || server.getServer() == null) {
ServerInstance server = m_serverMgr.getServerInstance(serverID);
if (server == null) {
m_message = new p();
m_message.addElement(new strong("Server not found: "));
m_message.addElement(serverID);
return;
} else {
if (start)
ok = m_serverMgr.start(serverID);
ok = m_serverMgr.start(serverID)==null;
else
ok = m_serverMgr.stop(serverID);
m_message.addElement(server.getServer().getName());
ok = m_serverMgr.stop(serverID)==null;
m_message.addElement(server.getModel().getName());
}
}
}
@ -631,13 +620,24 @@ public class AdempiereMonitor extends HttpServlet
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Servers"));
line.addElement(new td().addElement(WebEnv.getCellContent(m_serverMgr.getServerCount())));
line.addElement(new td().addElement(WebEnv.getCellContent(createServerCountMessage(m_serverMgr.getServerCount()))));
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Last Updated"));
line.addElement(new td().addElement(new Timestamp(System.currentTimeMillis()).toString()));
table.addElement(line);
bb.addElement(table);
IServiceHolder<IClusterService> holder = Service.locator().locate(IClusterService.class);
IClusterService service = holder != null ? holder.getService() : null;
if (service != null && service.getLocalMember() != null)
{
line = new tr();
line.addElement(new th().addElement("Cluster Node Id"));
line.addElement(new td().addElement(WebEnv.getCellContent(service.getLocalMember().getId())));
table.addElement(line);
bb.addElement(table);
}
//
p para = new p();
a link = new a ("idempiereMonitor?Action=Start_All", "Start All");
@ -656,16 +656,16 @@ public class AdempiereMonitor extends HttpServlet
// ***** Server Links *****
bb.addElement(new hr());
para = new p();
ServerWrapper[] servers = m_serverMgr.getAll();
ServerInstance[] servers = m_serverMgr.getServerInstances();
for (int i = 0; i < servers.length; i++)
{
if (i > 0)
para.addElement(new br());
ServerWrapper server = servers[i];
link = new a ("#" + server.getServer().getServerID(), server.getServer().getName());
ServerInstance server = servers[i];
link = new a ("#" + server.getServerId(), server.getModel().getName());
para.addElement(link);
font status = null;
if (server.isAlive())
if (server.isStarted())
status = new font().setColor(HtmlColor.GREEN).addElement(" (Running)");
else
status = new font().setColor(HtmlColor.RED).addElement(" (Stopped)");
@ -680,10 +680,10 @@ public class AdempiereMonitor extends HttpServlet
bb.removeEndEndModifier();
for (int i = 0; i < servers.length; i++)
{
ServerWrapper server = servers[i];
ServerInstance server = servers[i];
bb.addElement(new hr());
bb.addElement(new a().setName(server.getServer().getServerID()));
bb.addElement(new h2(server.getServer().getName()));
bb.addElement(new a().setName(server.getServerId()));
bb.addElement(new h2(server.getModel().getName()));
//
table = new table();
table.setBorder(1);
@ -691,11 +691,11 @@ public class AdempiereMonitor extends HttpServlet
table.setCellPadding(2);
// Status
line = new tr();
if (server.isAlive())
if (server.isStarted())
{
String msg = "Stop";
link = new a ("idempiereMonitor?Action=Stop_" + server.getServer().getServerID(), msg);
if (server.getServer().isSleeping())
link = new a ("idempiereMonitor?Action=Stop_" + server.getServerId(), msg);
if (server.isSleeping())
{
line.addElement(new th().addElement("Sleeping"));
line.addElement(new td().addElement(link));
@ -708,54 +708,74 @@ public class AdempiereMonitor extends HttpServlet
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Start - Elapsed"));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getServer().getStartTime())
+ " - " + TimeUtil.formatElapsed(server.getServer().getStartTime())));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getStartTime())
+ " - " + TimeUtil.formatElapsed(server.getStartTime())));
}
else
{
String msg = "Start";
line.addElement(new th().addElement("Not Started"));
link = new a ("idempiereMonitor?Action=Start_" + server.getServer().getServerID(), msg);
link = new a ("idempiereMonitor?Action=Start_" + server.getServerId(), msg);
line.addElement(new td().addElement(link));
}
table.addElement(line);
//
line = new tr();
line.addElement(new th().addElement("Description"));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getServer().getDescription())));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getModel().getDescription())));
table.addElement(line);
//
line = new tr();
line.addElement(new th().addElement("Last Run"));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getServer().getDateLastRun())));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getModel().getDateLastRun())));
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Info"));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getServer().getServerInfo())));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getServerInfo())));
table.addElement(line);
//
line = new tr();
line.addElement(new th().addElement("Next Run"));
td td = new td();
td.addElement(WebEnv.getCellContent(server.getServer().getDateNextRun(false)));
td.addElement(WebEnv.getCellContent(server.getModel().getDateNextRun(false)));
td.addElement(" - ");
link = new a ("idempiereMonitor?RunNow=" + server.getServer().getServerID(), "(Run Now)");
link = new a ("idempiereMonitor?RunNow=" + server.getServerId(), "(Run Now)");
td.addElement(link);
line.addElement(td);
table.addElement(line);
//
line = new tr();
line.addElement(new th().addElement("Statistics"));
line.addElement(new td().addElement(server.getServer().getStatistics()));
line.addElement(new td().addElement(server.getStatistics()));
table.addElement(line);
//
if (server.getClusterMember() != null)
{
InetAddress address = server.getClusterMember().getAddress();
String ip = address != null ? address.getHostAddress() : null;
if (ip != null &&
(ip.startsWith("10.") ||
ip.startsWith("172.16") ||
ip.startsWith("192.168")))
{
line = new tr();
line.addElement(new th().addElement("Cluster Node IP"));
line.addElement(new td().addElement(ip));
}
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Cluster Node Id"));
line.addElement(new td().addElement(server.getClusterMember().getId()));
table.addElement(line);
}
// Add table to Body
bb.addElement(table);
link = new a ("#top", "Top");
bb.addElement(link);
bb.addElement(" - ");
link = new a ("idempiereMonitor?Log=" + server.getServer().getServerID(), "Log");
link = new a ("idempiereMonitor?Log=" + server.getServerId(), "Log");
bb.addElement(link);
bb.addElement(" - ");
link = new a ("idempiereMonitor", "Refresh");
@ -766,6 +786,20 @@ public class AdempiereMonitor extends HttpServlet
WebUtil.createResponse (request, response, this, null, doc, false);
} // createSummaryPage
private String createServerCountMessage(ServerCount serverCount) {
StringBuilder builder = new StringBuilder();
if (serverCount != null) {
builder.append(serverCount.getStarted()+serverCount.getStopped())
.append(" - Running=")
.append(serverCount.getStarted())
.append(" - Stopped=")
.append(serverCount.getStopped());
}
return builder.toString();
}
/**************************************************************************
* Create & Return Summary Page
* @param request request
@ -817,29 +851,29 @@ public class AdempiereMonitor extends HttpServlet
writer.print(m_serverMgr.getServerCount());
writer.println("</server-count>");
ServerWrapper[] servers = m_serverMgr.getAll();
ServerInstance[] servers = m_serverMgr.getServerInstances();
for (int i = 0; i < servers.length; i++)
{
ServerWrapper server = servers[i];
ServerInstance server = servers[i];
writer.println("\t\t<server>");
writer.print("\t\t\t<id>");
writer.print(server.getServer().getServerID());
writer.print(server.getServerId());
writer.println("</id>");
writer.print("\t\t\t<name>");
writer.print(server.getServer().getName());
writer.print(server.getModel().getName());
writer.println("</name>");
writer.print("\t\t\t<description>");
writer.print(server.getServer().getDescription());
writer.print(server.getModel().getDescription());
writer.println("</description>");
writer.print("\t\t\t<info>");
writer.print(server.getServer().getServerInfo());
writer.print(server.getServerInfo());
writer.println("</info>");
writer.print("\t\t\t<status>");
if (server.isAlive())
if (server.isStarted())
{
if (server.isInterrupted())
writer.print("Interrupted");
else if (server.getServer().isSleeping())
else if (server.isSleeping())
writer.print("Sleeping");
else
writer.print("Running");
@ -848,16 +882,16 @@ public class AdempiereMonitor extends HttpServlet
writer.print("Stopped");
writer.println("</status>");
writer.print("\t\t\t<start-time>");
writer.print(server.getServer().getStartTime());
writer.print(server.getStartTime());
writer.println("</start-time>");
writer.print("\t\t\t<last-run>");
writer.print(server.getServer().getDateLastRun());
writer.print(server.getModel().getDateLastRun());
writer.println("</last-run>");
writer.print("\t\t\t<next-run>");
writer.print(server.getServer().getDateNextRun(false));
writer.print(server.getModel().getDateNextRun(false));
writer.println("</next-run>");
writer.print("\t\t\t<statistics>");
writer.print(server.getServer().getStatistics());
writer.print(server.getStatistics());
writer.println("</statistics>");
writer.println("\t\t</server>");
}
@ -1148,7 +1182,16 @@ public class AdempiereMonitor extends HttpServlet
{
WebEnv.initWeb(config);
log.info ("");
//always create the local server manager instance
m_serverMgr = AdempiereServerMgr.get();
//switch to cluster manager if cluster service is available
IServiceHolder<IClusterService> holder = Service.locator().locate(IClusterService.class);
IClusterService service = holder != null ? holder.getService() : null;
if (service != null)
m_serverMgr = ClusterServerMgr.getInstance();
m_dirAccessList = getDirAcessList();
} // init