package org.quickbundle.project.init; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dom4j.Element; import org.quickbundle.base.web.servlet.RmHolderServlet; import org.quickbundle.config.RmClusterConfig; import org.quickbundle.config.RmClusterConfig.NodeKey; import org.quickbundle.config.RmConfig; import org.quickbundle.project.common.vo.RmCommonVo; import org.quickbundle.tools.context.RmBeanHelper; import org.quickbundle.tools.helper.RmDateHelper; import org.quickbundle.tools.helper.RmSqlHelper; import org.quickbundle.tools.helper.RmUUIDHelper; import org.quickbundle.tools.support.log.RmLogHelper; public class ClusterConfigLoaderDb extends AbstractClusterConfigLoader { public ClusterConfigLoaderDb(Element eleClusterConfigLoader) { super(eleClusterConfigLoader); } public void init() { if (RmHolderServlet.getDefaultServletContext() != null) { try { selfNode.put(RmClusterConfig.NodeKey.contentPath.name(), RmHolderServlet.getDefaultServletContext().getContextPath()); } catch (Throwable e) { e.printStackTrace(); RmLogHelper.getLogger(this.getClass()).error("JavaEE version to low: " + e.toString()); } } //集群模式的判断 String sql = "select count(*) from RM_NODE_HEARTBEAT where " + buildWhereActive(); long activeNodes = RmBeanHelper.getCommonServiceInstance().doQueryForInt(sql); RmConfig.getSingleton().setClusterMode(activeNodes > 1); initSelfNode(); NodeHeartbeatDaemon.getSingleton().start(); } private void initSelfNode() { selfNode.put(NodeKey.id.name(), RmUUIDHelper.generateUUID()); selfNode.put(NodeKey.user.name(), RmClusterConfig.DEFAULT_AUTH_KEY_VALUE.get(NodeKey.user.name())); selfNode.put(NodeKey.password.name(), RmClusterConfig.DEFAULT_AUTH_KEY_VALUE.get(NodeKey.password.name())); String shardingPrefix = createShardingPrefix(); selfNode.put(NodeKey.shardingPrefix.name(), shardingPrefix); if(RmClusterConfig.getLocalhostInfo() != null) { refreshHostInfo(RmClusterConfig.getLocalhostInfo()); } } private String buildWhereActive() { return RmSqlHelper.getFunction(RmSqlHelper.Function.SYSDATE, RmConfig.getSingleton().getDatabaseProductName()) + "-LAST_HEARTBEAT<" + RmConfig.getSingleton().getNodeHeartbeatInterval()/1000*1.8; } private String createShardingPrefix() { String sqlMax = "select max(SHARDING_PREFIX) from RM_NODE_HEARTBEAT where " + buildWhereActive(); List<String> maxIds = RmBeanHelper.getCommonServiceInstance().queryForList(sqlMax, String.class); long shardingPrefix = getMaxIdOrDefault(maxIds.size() == 0 ? null : maxIds.get(0)); String sqlInsert = "insert into RM_NODE_HEARTBEAT (ID, VERSION, SHARDING_PREFIX, LAST_HEARTBEAT) " + "values (?, ?, ?, ?)"; RmBeanHelper.getCommonServiceInstance().doUpdate(sqlInsert, new Object[]{getSelfId(), 1, shardingPrefix, RmDateHelper.getSysTimestamp()}); return String.valueOf(shardingPrefix); } //根据 集群+table的前缀和maxId,获取下一个可用值或默认起始值 protected long getMaxIdOrDefault(String maxId) { long result = 0L; if(maxId != null && maxId.length() > 0) { if(maxId.length() > 19) { result = Long.parseLong(maxId.substring(0, 19)) + 1; } else { result = Long.parseLong(maxId) + 1; } } else { result = Long.parseLong(firstValue()); } return result; } protected String firstValue() { String result = eleLoadCluster.valueOf("@firstShardingPrefix"); if(result.length() == 0) { result = "1000"; } return result; } public Map<String, Map<String, String>> getNodes() { Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>(); String sql = "select ID, VERSION, SHARDING_PREFIX, BASE_URL, LAST_HEARTBEAT from RM_NODE_HEARTBEAT where " + buildWhereActive(); List<RmCommonVo> nodes = RmBeanHelper.getCommonServiceInstance().doQuery(sql); for(RmCommonVo node : nodes) { Map<String, String> nodeMap = new HashMap<String, String>(); nodeMap.put(NodeKey.id.name(), node.getString("ID")); nodeMap.put(NodeKey.shardingPrefix.name(), node.getString("SHARDING_PREFIX")); nodeMap.put(NodeKey.baseUrl.name(), node.getString("BASE_URL")); nodeMap.put(NodeKey.webServiceUrl.name(), node.getString("BASE_URL") + "/services/"); result.put(node.getString("ID"), nodeMap); } return result; } @Override public void destroy() { NodeHeartbeatDaemon.getSingleton().shutdown(); String sql = "delete from RM_NODE_HEARTBEAT where ID=?"; RmBeanHelper.getCommonServiceInstance().doUpdate(sql, new Object[]{getSelfId()}); } }