PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/solr/core/src/test/org/apache/solr/cloud/ZkTestServer.java

http://github.com/apache/lucene-solr
Java | 345 lines | 256 code | 48 blank | 41 comment | 28 complexity | ec37806145479f39cc75befa7611004d MD5 | raw file
Possible License(s): LGPL-2.1, CPL-1.0, MPL-2.0-no-copyleft-exception, JSON, Apache-2.0, AGPL-1.0, GPL-2.0, GPL-3.0, MIT, BSD-3-Clause
  1. package org.apache.solr.cloud;
  2. /**
  3. * Licensed to the Apache Software Foundation (ASF) under one or more
  4. * contributor license agreements. See the NOTICE file distributed with this
  5. * work for additional information regarding copyright ownership. The ASF
  6. * licenses this file to You under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  15. * License for the specific language governing permissions and limitations under
  16. * the License.
  17. */
  18. import java.io.BufferedReader;
  19. import java.io.File;
  20. import java.io.IOException;
  21. import java.io.InputStreamReader;
  22. import java.io.OutputStream;
  23. import java.net.InetAddress;
  24. import java.net.InetSocketAddress;
  25. import java.net.Socket;
  26. import java.net.UnknownHostException;
  27. import java.util.ArrayList;
  28. import java.util.List;
  29. import javax.management.JMException;
  30. import org.apache.zookeeper.jmx.ManagedUtil;
  31. import org.apache.zookeeper.server.NIOServerCnxn;
  32. import org.apache.zookeeper.server.ServerConfig;
  33. import org.apache.zookeeper.server.SessionTracker.Session;
  34. import org.apache.zookeeper.server.ZKDatabase;
  35. import org.apache.zookeeper.server.ZooKeeperServer;
  36. import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
  37. import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
  38. import org.slf4j.Logger;
  39. import org.slf4j.LoggerFactory;
  40. public class ZkTestServer {
  41. public static final int TICK_TIME = 3000;
  42. private static Logger log = LoggerFactory.getLogger(ZkTestServer.class);
  43. protected final ZKServerMain zkServer = new ZKServerMain();
  44. private String zkDir;
  45. private int clientPort;
  46. private Thread zooThread;
  47. private int theTickTime = TICK_TIME;
  48. class ZKServerMain {
  49. private NIOServerCnxn.Factory cnxnFactory;
  50. private ZooKeeperServer zooKeeperServer;
  51. protected void initializeAndRun(String[] args) throws ConfigException,
  52. IOException {
  53. try {
  54. ManagedUtil.registerLog4jMBeans();
  55. } catch (JMException e) {
  56. }
  57. ServerConfig config = new ServerConfig();
  58. if (args.length == 1) {
  59. config.parse(args[0]);
  60. } else {
  61. config.parse(args);
  62. }
  63. runFromConfig(config);
  64. }
  65. /**
  66. * Run from a ServerConfig.
  67. * @param config ServerConfig to use.
  68. * @throws IOException
  69. */
  70. public void runFromConfig(ServerConfig config) throws IOException {
  71. try {
  72. // Note that this thread isn't going to be doing anything else,
  73. // so rather than spawning another thread, we will just call
  74. // run() in this thread.
  75. // create a file logger url from the command line args
  76. zooKeeperServer = new ZooKeeperServer();
  77. FileTxnSnapLog ftxn = new FileTxnSnapLog(new File(config
  78. .getDataLogDir()), new File(config.getDataDir()));
  79. zooKeeperServer.setTxnLogFactory(ftxn);
  80. zooKeeperServer.setTickTime(config.getTickTime());
  81. cnxnFactory = new NIOServerCnxn.Factory(config.getClientPortAddress(), config
  82. .getMaxClientCnxns());
  83. cnxnFactory.startup(zooKeeperServer);
  84. cnxnFactory.join();
  85. if (zooKeeperServer.isRunning()) {
  86. zooKeeperServer.shutdown();
  87. }
  88. } catch (InterruptedException e) {
  89. }
  90. }
  91. /**
  92. * Shutdown the serving instance
  93. * @throws IOException
  94. */
  95. protected void shutdown() throws IOException {
  96. zooKeeperServer.shutdown();
  97. ZKDatabase zkDb = zooKeeperServer.getZKDatabase();
  98. if (zkDb != null) {
  99. zkDb.close();
  100. }
  101. if (cnxnFactory != null && cnxnFactory.getLocalPort() != 0) {
  102. waitForServerDown(getZkHost() + ":" + getPort(), 5000);
  103. }
  104. if (cnxnFactory != null) {
  105. cnxnFactory.shutdown();
  106. }
  107. }
  108. public int getLocalPort() {
  109. if (cnxnFactory == null) {
  110. throw new IllegalStateException("A port has not yet been selected");
  111. }
  112. int port;
  113. try {
  114. port = cnxnFactory.getLocalPort();
  115. } catch (NullPointerException e) {
  116. throw new IllegalStateException("A port has not yet been selected");
  117. }
  118. if (port == 0) {
  119. throw new IllegalStateException("A port has not yet been selected");
  120. }
  121. return port;
  122. }
  123. }
  124. public ZkTestServer(String zkDir) {
  125. this.zkDir = zkDir;
  126. }
  127. public ZkTestServer(String zkDir, int port) {
  128. this.zkDir = zkDir;
  129. this.clientPort = port;
  130. }
  131. public String getZkHost() {
  132. return "127.0.0.1:" + zkServer.getLocalPort();
  133. }
  134. public String getZkAddress() {
  135. return "127.0.0.1:" + zkServer.getLocalPort() + "/solr";
  136. }
  137. public int getPort() {
  138. return zkServer.getLocalPort();
  139. }
  140. public void expire(final long sessionId) {
  141. zkServer.zooKeeperServer.expire(new Session() {
  142. @Override
  143. public long getSessionId() {
  144. return sessionId;
  145. }
  146. @Override
  147. public int getTimeout() {
  148. return 4000;
  149. }
  150. @Override
  151. public boolean isClosing() {
  152. return false;
  153. }});
  154. }
  155. public void run() throws InterruptedException {
  156. log.info("STARTING ZK TEST SERVER");
  157. // we don't call super.setUp
  158. zooThread = new Thread() {
  159. @Override
  160. public void run() {
  161. ServerConfig config = new ServerConfig() {
  162. {
  163. setClientPort(ZkTestServer.this.clientPort);
  164. this.dataDir = zkDir;
  165. this.dataLogDir = zkDir;
  166. this.tickTime = theTickTime;
  167. }
  168. public void setClientPort(int clientPort) {
  169. if (clientPortAddress != null) {
  170. try {
  171. this.clientPortAddress = new InetSocketAddress(
  172. InetAddress.getByName(clientPortAddress.getHostName()), clientPort);
  173. } catch (UnknownHostException e) {
  174. throw new RuntimeException(e);
  175. }
  176. } else {
  177. this.clientPortAddress = new InetSocketAddress(clientPort);
  178. }
  179. }
  180. };
  181. try {
  182. zkServer.runFromConfig(config);
  183. } catch (Throwable e) {
  184. throw new RuntimeException(e);
  185. }
  186. }
  187. };
  188. zooThread.setDaemon(true);
  189. zooThread.start();
  190. int cnt = 0;
  191. int port = -1;
  192. try {
  193. port = getPort();
  194. } catch(IllegalStateException e) {
  195. }
  196. while (port < 1) {
  197. Thread.sleep(100);
  198. try {
  199. port = getPort();
  200. } catch(IllegalStateException e) {
  201. }
  202. if (cnt == 100) {
  203. throw new RuntimeException("Could not get the port for ZooKeeper server");
  204. }
  205. cnt++;
  206. }
  207. }
  208. @SuppressWarnings("deprecation")
  209. public void shutdown() throws IOException {
  210. // TODO: this can log an exception while trying to unregister a JMX MBean
  211. zkServer.shutdown();
  212. }
  213. public static boolean waitForServerDown(String hp, long timeout) {
  214. long start = System.currentTimeMillis();
  215. while (true) {
  216. try {
  217. HostPort hpobj = parseHostPortList(hp).get(0);
  218. send4LetterWord(hpobj.host, hpobj.port, "stat");
  219. } catch (IOException e) {
  220. return true;
  221. }
  222. if (System.currentTimeMillis() > start + timeout) {
  223. break;
  224. }
  225. try {
  226. Thread.sleep(250);
  227. } catch (InterruptedException e) {
  228. // ignore
  229. }
  230. }
  231. return false;
  232. }
  233. public static class HostPort {
  234. String host;
  235. int port;
  236. HostPort(String host, int port) {
  237. this.host = host;
  238. this.port = port;
  239. }
  240. }
  241. /**
  242. * Send the 4letterword
  243. * @param host the destination host
  244. * @param port the destination port
  245. * @param cmd the 4letterword
  246. * @return
  247. * @throws IOException
  248. */
  249. public static String send4LetterWord(String host, int port, String cmd)
  250. throws IOException
  251. {
  252. Socket sock = new Socket(host, port);
  253. BufferedReader reader = null;
  254. try {
  255. OutputStream outstream = sock.getOutputStream();
  256. outstream.write(cmd.getBytes("US-ASCII"));
  257. outstream.flush();
  258. // this replicates NC - close the output stream before reading
  259. sock.shutdownOutput();
  260. reader =
  261. new BufferedReader(
  262. new InputStreamReader(sock.getInputStream()));
  263. StringBuilder sb = new StringBuilder();
  264. String line;
  265. while((line = reader.readLine()) != null) {
  266. sb.append(line + "\n");
  267. }
  268. return sb.toString();
  269. } finally {
  270. sock.close();
  271. if (reader != null) {
  272. reader.close();
  273. }
  274. }
  275. }
  276. public static List<HostPort> parseHostPortList(String hplist) {
  277. ArrayList<HostPort> alist = new ArrayList<HostPort>();
  278. for (String hp : hplist.split(",")) {
  279. int idx = hp.lastIndexOf(':');
  280. String host = hp.substring(0, idx);
  281. int port;
  282. try {
  283. port = Integer.parseInt(hp.substring(idx + 1));
  284. } catch (RuntimeException e) {
  285. throw new RuntimeException("Problem parsing " + hp + e.toString());
  286. }
  287. alist.add(new HostPort(host, port));
  288. }
  289. return alist;
  290. }
  291. public int getTheTickTime() {
  292. return theTickTime;
  293. }
  294. public void setTheTickTime(int theTickTime) {
  295. this.theTickTime = theTickTime;
  296. }
  297. }