/**
* Copyright © 2013 enioka. All rights reserved
* Authors: Marc-Antoine GOUILLART (marc-antoine.gouillart@enioka.com)
* Pierre COPPEE (pierre.coppee@enioka.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.enioka.jqm.model;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import com.enioka.jqm.jdbc.DatabaseException;
import com.enioka.jqm.jdbc.DbConn;
import com.enioka.jqm.jdbc.NoResultException;
import com.enioka.jqm.jdbc.NonUniqueResultException;
import com.enioka.jqm.jdbc.QueryResult;
/**
* <strong>Not part of any API - this an internal JQM class and may change without notice.</strong> <br>
* Persistence class for storing the definition of the different nodes that are member of the JMQ cluster.<br>
* There can be some confusion between terms: an <code>engine</code> is a Java process that represents a {@link Node}. There can only be one
* engine running the same Node at the same time.<br>
* <br>
* A node is the holder of all the parameters needed for the engine to run: a list of {@link Queue}s to poll (through
* {@link DeploymentParameter}s), the different TCP ports to use, etc.
*/
public class Node
{
private Integer id = null;
private String name;
private String dns = "localhost";
private Integer port;
private String dlRepo;
private String tmpDirectory;
private String repo;
private String rootLogLevel = "DEBUG";
private Calendar lastSeenAlive;
private Integer jmxRegistryPort = 0;
private Integer jmxServerPort = 0;
private Boolean loapApiSimple = true, loadApiClient = false, loadApiAdmin = false;
private Boolean enabled = true;
private boolean stop = false;
/**
* A technical ID without any meaning. Generated by the database.
*/
public Integer getId()
{
return id;
}
/**
* See {@link #getId()}
*/
void setId(final Integer id)
{
this.id = id;
}
/**
* The functional key of the node. When starting an engine, it is given this name as its only parameter. It must be unique.<br>
* Max length is 100.
*/
public String getName()
{
return name;
}
/**
* See {@link #getName()}
*/
public void setName(final String name)
{
this.name = name;
}
/**
* The TCP port used for starting the engine Jetty server (it holds the servlet API as well as the We Service API).
*/
public Integer getPort()
{
return port;
}
/**
* See {@link #getPort()}
*/
public void setPort(final Integer port)
{
this.port = port;
}
/**
* The directory that will store all the {@link Deliverable}s created by job instances.<br>
* Max length is 1024.
*/
public String getDlRepo()
{
return dlRepo;
}
/**
* See {@link #getDlRepo()}
*/
public void setDlRepo(final String dlRepo)
{
this.dlRepo = dlRepo;
}
/**
* Directory holding the payload repository, i.e. all the jars that can be run by JQM.
*/
public String getRepo()
{
return repo;
}
/**
* See {@link #getRepo()}
*/
public void setRepo(final String repo)
{
this.repo = repo;
}
/**
* That field is polled be the engine: if true, it will stop at once. this is one of the three ways to send a stop order to an engine.
*/
public boolean isStop()
{
return stop;
}
/**
* See {@link #isStop()}
*/
public void setStop(boolean stop)
{
this.stop = stop;
}
/**
* The log level for the jqm.log file. Valid values are TRACE, DEBUG, INFO, WARN, ERROR, FATAL. Default is INFO.
*/
public String getRootLogLevel()
{
return rootLogLevel;
}
/**
* See {@link #getRootLogLevel()}
*/
public void setRootLogLevel(String rootLogLevel)
{
this.rootLogLevel = rootLogLevel;
}
/**
* The DNS name on which to create listeners. Default is localhost.
*/
public String getDns()
{
return dns;
}
/**
* See {@link #getDns()}
*/
public void setDns(String dns)
{
this.dns = dns;
}
/**
* Engine will periodically update this field, which can be used for monitoring. It is also used to prevent starting two engine on the
* same node.
*/
public Calendar getLastSeenAlive()
{
return lastSeenAlive;
}
/**
* See {@link #getLastSeenAlive()}
*/
public void setLastSeenAlive(Calendar lastSeenAlive)
{
this.lastSeenAlive = lastSeenAlive;
}
/**
* The port on which to start the JMX remote registry. No remote JMX item is started if this field or jmxserverport is < 1
*/
public Integer getJmxRegistryPort()
{
return jmxRegistryPort;
}
/**
* See {@link #getJmxRegistryPort()}
*/
public void setJmxRegistryPort(Integer jmxRegistryPort)
{
this.jmxRegistryPort = jmxRegistryPort;
}
/**
* The port on which to start the JMX remote server. No remote JMX item is started if this field or jmxregistryport is < 1
*/
public Integer getJmxServerPort()
{
return jmxServerPort;
}
/**
* See {@link #getJmxServerPort()}
*/
public void setJmxServerPort(Integer jmxServerPort)
{
this.jmxServerPort = jmxServerPort;
}
/**
* If true, the basic REST services will start. Ignored if the GlobalParameter 'disableWsApiSimple' is true.
*/
public Boolean getLoapApiSimple()
{
return loapApiSimple;
}
/**
* See {@link #getLoapApiSimple()}
*/
public void setLoapApiSimple(Boolean loapApiSimple)
{
this.loapApiSimple = loapApiSimple;
}
/**
* If true, the client REST services will start. Ignored if the GlobalParameter 'disableWsApiClient' is true.
*/
public Boolean getLoadApiClient()
{
return loadApiClient;
}
/**
* See {@link #getLoadApiClient()}
*/
public void setLoadApiClient(Boolean loadApiClient)
{
this.loadApiClient = loadApiClient;
}
/**
* If true, the administration REST services will start. Ignored if the GlobalParameter 'disableWsApiAdmin' is true.
*/
public Boolean getLoadApiAdmin()
{
return loadApiAdmin;
}
/**
* See {@link #getLoadApiAdmin()}
*/
public void setLoadApiAdmin(Boolean loadApiAdmin)
{
this.loadApiAdmin = loadApiAdmin;
}
/**
* The root directory inside which temporary files will be created (see JobManager.getWorkDir).
*/
public String getTmpDirectory()
{
return tmpDirectory;
}
/**
* See {@link #getTmpDirectory()}
*/
public void setTmpDirectory(String tmpDirectory)
{
this.tmpDirectory = tmpDirectory;
}
/**
* Disabled means all the queue bindings still exist but no job instances are polled (pollers are paused, with already running job
* instances going on normally).
*/
public Boolean getEnabled()
{
return enabled;
}
/**
* See {@link #getEnabled()}
*/
public void setEnabled(Boolean enabled)
{
this.enabled = enabled;
}
/**
* Create a new entry in the database. No commit performed.
*/
public static Node create(DbConn cnx, String nodeName, Integer port, String dlRepo, String repo, String tmpDir, String dns)
{
QueryResult r = cnx.runUpdate("node_insert", dlRepo, dns, true, 0, 0, false, false, true, nodeName, port, repo, "DEBUG", false,
tmpDir);
Node res = new Node();
res.id = r.getGeneratedId();
res.name = nodeName;
res.dns = dns;
res.port = port;
res.dlRepo = dlRepo;
res.tmpDirectory = tmpDir;
res.repo = repo;
res.loadApiAdmin = false;
res.loadApiClient = false;
res.loapApiSimple = false;
res.enabled = true;
res.stop = false;
return res;
}
static Node map(DbConn cnx, ResultSet rs, int colShift)
{
try
{
Node tmp = new Node();
tmp.id = rs.getInt(1 + colShift);
if (tmp.id == 0)
{
return null;
}
tmp.dlRepo = rs.getString(2 + colShift);
tmp.dns = rs.getString(3 + colShift);
tmp.enabled = rs.getBoolean(4 + colShift);
tmp.jmxRegistryPort = rs.getInt(5 + colShift);
tmp.jmxServerPort = rs.getInt(6 + colShift);
tmp.loadApiAdmin = rs.getBoolean(7 + colShift);
tmp.loadApiClient = rs.getBoolean(8 + colShift);
tmp.loapApiSimple = rs.getBoolean(9 + colShift);
tmp.name = rs.getString(10 + colShift);
tmp.port = rs.getInt(11 + colShift);
tmp.repo = rs.getString(12 + colShift);
tmp.rootLogLevel = rs.getString(13 + colShift);
tmp.stop = rs.getBoolean(14 + colShift);
tmp.tmpDirectory = rs.getString(15 + colShift);
tmp.lastSeenAlive = cnx.getCal(rs, 16 + colShift);
return tmp;
}
catch (SQLException e)
{
throw new DatabaseException(e);
}
}
public static List<Node> select(DbConn cnx, String query_key, Object... args)
{
List<Node> res = new ArrayList<Node>();
try
{
ResultSet rs = cnx.runSelect(query_key, args);
while (rs.next())
{
res.add(map(cnx, rs, 0));
}
}
catch (SQLException e)
{
throw new DatabaseException(e);
}
return res;
}
public static Node select_single(DbConn cnx, String query_key, Object... args)
{
List<Node> nn = select(cnx, query_key, args);
if (nn.size() == 0)
{
throw new NoResultException("No node with this ID");
}
if (nn.size() > 1)
{
throw new NonUniqueResultException("COnfiguration is broken: multiple nodes with the same ID");
}
return nn.get(0);
}
}