PageRenderTime 61ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/src/java/systest/org/apache/zookeeper/test/system/InstanceContainer.java

https://github.com/yuvrajm/zookeeper
Java | 310 lines | 253 code | 15 blank | 42 comment | 47 complexity | ec9bf8714b17e4ae228a309fc33128b6 MD5 | raw file
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. 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,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.apache.zookeeper.test.system;
  19. import java.io.IOException;
  20. import java.net.InetAddress;
  21. import java.net.UnknownHostException;
  22. import java.util.HashMap;
  23. import java.util.List;
  24. import java.util.Map;
  25. import org.slf4j.Logger;
  26. import org.slf4j.LoggerFactory;
  27. import org.apache.zookeeper.AsyncCallback;
  28. import org.apache.zookeeper.CreateMode;
  29. import org.apache.zookeeper.KeeperException;
  30. import org.apache.zookeeper.WatchedEvent;
  31. import org.apache.zookeeper.Watcher;
  32. import org.apache.zookeeper.ZooKeeper;
  33. import org.apache.zookeeper.KeeperException.ConnectionLossException;
  34. import org.apache.zookeeper.KeeperException.NoNodeException;
  35. import org.apache.zookeeper.KeeperException.NodeExistsException;
  36. import org.apache.zookeeper.Watcher.Event.KeeperState;
  37. import org.apache.zookeeper.ZooDefs.Ids;
  38. import org.apache.zookeeper.data.Stat;
  39. import org.apache.zookeeper.test.system.Instance.Reporter;
  40. /**
  41. * This class starts up,
  42. */
  43. public class InstanceContainer implements Watcher, AsyncCallback.ChildrenCallback {
  44. private final class MyWatcher implements Watcher {
  45. String myNode;
  46. DataCallback dc;
  47. MyWatcher(String myNode, DataCallback dc) {
  48. this.myNode = myNode;
  49. this.dc = dc;
  50. }
  51. public void process(WatchedEvent event) {
  52. if (event.getPath() != null && event.getPath().equals(myNode)) {
  53. zk.getData(myNode, this, dc, this);
  54. }
  55. }
  56. }
  57. private final class MyDataCallback implements DataCallback {
  58. int lastVer;
  59. String myNode;
  60. Instance myInstance;
  61. MyDataCallback(String myNode, Instance myInstance, int ver) {
  62. this.myNode = myNode;
  63. this.myInstance = myInstance;
  64. lastVer = ver;
  65. }
  66. public void processResult(int rc, String path,
  67. Object ctx, byte[] data, Stat stat) {
  68. if (rc == KeeperException.Code.NONODE.intValue()) {
  69. // we can just ignore because the child watcher takes care of this
  70. return;
  71. }
  72. if (rc != KeeperException.Code.OK.intValue()) {
  73. zk.getData(myNode, (Watcher)ctx, this, ctx);
  74. }
  75. int currVer = stat.getVersion();
  76. if (currVer != lastVer) {
  77. String parts[] = new String(data).split(" ", 2);
  78. myInstance.configure(parts[1]);
  79. lastVer = currVer;
  80. }
  81. }
  82. }
  83. private final class MyReporter implements Reporter {
  84. String myReportNode;
  85. public MyReporter(String child) {
  86. myReportNode = reportsNode + '/' + child;
  87. }
  88. public void report(String report) throws KeeperException, InterruptedException {
  89. for(int j = 0; j < maxTries; j++) {
  90. try {
  91. try {
  92. zk.setData(myReportNode, report.getBytes(), -1);
  93. } catch(NoNodeException e) {
  94. zk.create(myReportNode, report.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
  95. }
  96. break;
  97. } catch(ConnectionLossException e) {}
  98. }
  99. }
  100. }
  101. private static final Logger LOG = LoggerFactory.getLogger(InstanceContainer.class);
  102. String name;
  103. String zkHostPort;
  104. // We only run if the readyNode exists
  105. String prefixNode;
  106. String statusNode = "available";
  107. String reportsNode = "reports";
  108. String assignmentsNode = "assignments";
  109. ZooKeeper zk;
  110. static final int sessTimeout = 5000;
  111. static final int maxTries = 3;
  112. public InstanceContainer(String name, String zkHostPort, String prefix) throws UnknownHostException {
  113. if (name.length() == 0 || name.equals("hostname")) {
  114. name = InetAddress.getLocalHost().getCanonicalHostName();
  115. }
  116. this.name = name;
  117. this.zkHostPort = zkHostPort;
  118. this.prefixNode = prefix;
  119. this.statusNode = prefix + '/' + this.statusNode + '/' + name;
  120. this.reportsNode = prefix + '/' + this.reportsNode;
  121. this.assignmentsNode = prefix + '/' + this.assignmentsNode + '/' + name;
  122. }
  123. private void rmnod(String path) throws InterruptedException, KeeperException {
  124. KeeperException lastException = null;
  125. for(int i = 0; i < maxTries; i++) {
  126. try {
  127. zk.delete(path, -1);
  128. lastException = null;
  129. break;
  130. } catch (KeeperException.NoNodeException e) {
  131. // cool this is what we want
  132. break;
  133. } catch (KeeperException e) {
  134. lastException = e;
  135. }
  136. }
  137. if (lastException != null) {
  138. throw lastException;
  139. }
  140. }
  141. private void mknod_inner(String path, CreateMode mode) throws KeeperException, InterruptedException {
  142. for(int i = 0; i < maxTries; i++) {
  143. try {
  144. zk.create(path, null, Ids.OPEN_ACL_UNSAFE, mode);
  145. break;
  146. } catch (NodeExistsException e) {
  147. if (mode != CreateMode.EPHEMERAL) {
  148. return;
  149. }
  150. Stat stat = zk.exists(path, false);
  151. if (stat == null) {
  152. continue;
  153. }
  154. if (stat.getEphemeralOwner() != zk.getSessionId()) {
  155. throw e;
  156. }
  157. break;
  158. } catch (ConnectionLossException e) {
  159. e.printStackTrace();
  160. }
  161. }
  162. }
  163. private void mknod(String path, CreateMode mode) throws KeeperException, InterruptedException {
  164. String subpath[] = path.split("/");
  165. StringBuilder sb = new StringBuilder();
  166. // We start at 1 because / will create an empty part first
  167. for(int i = 1; i < subpath.length; i++) {
  168. sb.append("/");
  169. sb.append(subpath[i]);
  170. CreateMode m = CreateMode.PERSISTENT;
  171. if (i == subpath.length-1) {
  172. m = mode;
  173. }
  174. mknod_inner(sb.toString(), m);
  175. }
  176. }
  177. public void run() throws IOException, InterruptedException, KeeperException {
  178. zk = new ZooKeeper(zkHostPort, sessTimeout, this);
  179. mknod(assignmentsNode, CreateMode.PERSISTENT);
  180. mknod(statusNode, CreateMode.EPHEMERAL);
  181. mknod(reportsNode, CreateMode.PERSISTENT);
  182. // Now we just start watching the assignments directory
  183. zk.getChildren(assignmentsNode, true, this, null);
  184. }
  185. /**
  186. * @param args the first parameter is the instance name, the second
  187. * is the ZooKeeper spec. if the instance name is the empty string
  188. * or "hostname", the hostname will be used.
  189. * @throws InterruptedException
  190. * @throws IOException
  191. * @throws UnknownHostException
  192. * @throws KeeperException
  193. */
  194. public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException, KeeperException {
  195. if (args.length != 3) {
  196. System.err.println("USAGE: " + InstanceContainer.class.getName() + " name zkHostPort znodePrefix");
  197. System.exit(2);
  198. }
  199. new InstanceContainer(args[0], args[1], args[2]).run();
  200. while(true) {
  201. Thread.sleep(1000);
  202. }
  203. }
  204. public void process(WatchedEvent event) {
  205. if (KeeperState.Expired == event.getState()) {
  206. // It's all over
  207. LOG.error("Lost session");
  208. System.exit(4);
  209. }
  210. if (event.getPath() != null && event.getPath().equals(assignmentsNode)) {
  211. // children have changed, so read in the new list
  212. zk.getChildren(assignmentsNode, true, this, null);
  213. }
  214. }
  215. HashMap<String, Instance> instances = new HashMap<String, Instance>();
  216. public void processResult(int rc, String path, Object ctx,
  217. List<String> children) {
  218. if (rc != KeeperException.Code.OK.intValue()) {
  219. // try it again
  220. zk.getChildren(assignmentsNode, true, this, null);
  221. return;
  222. }
  223. HashMap<String, Instance> newList = new HashMap<String, Instance>();
  224. // check for differences
  225. Stat stat = new Stat();
  226. for(String child: children) {
  227. Instance i = instances.remove(child);
  228. if (i == null) {
  229. // Start up a new instance
  230. byte data[] = null;
  231. String myNode = assignmentsNode + '/' + child;
  232. while(true) {
  233. try {
  234. data = zk.getData(myNode, true, stat);
  235. break;
  236. } catch (NoNodeException e) {
  237. // The node doesn't exist anymore, so skip it
  238. break;
  239. } catch (KeeperException e) {
  240. e.printStackTrace();
  241. } catch (InterruptedException e) {
  242. return;
  243. }
  244. }
  245. if (data != null) {
  246. String instanceSpec = new String(data);
  247. int spaceIndex = instanceSpec.indexOf(' ');
  248. String clazz;
  249. String conf;
  250. if (spaceIndex == -1) {
  251. clazz = instanceSpec;
  252. conf = null;
  253. } else {
  254. clazz = instanceSpec.substring(0, spaceIndex);
  255. conf = instanceSpec.substring(spaceIndex+1);
  256. }
  257. try {
  258. Class c = Class.forName(clazz);
  259. i = (Instance)c.newInstance();
  260. Reporter reporter = new MyReporter(child);
  261. i.setReporter(reporter);
  262. i.configure(conf);
  263. i.start();
  264. newList.put(child, i);
  265. int ver = stat.getVersion();
  266. Instance myInstance = i;
  267. DataCallback dc = new MyDataCallback(myNode, myInstance, ver);
  268. Watcher watcher = new MyWatcher(myNode, dc);
  269. zk.getData(myNode, watcher, dc, watcher);
  270. } catch (Exception e) {
  271. LOG.warn("Skipping " + child, e);
  272. if (e.getCause() != null) {
  273. LOG.warn("Caused by", e.getCause());
  274. }
  275. }
  276. }
  277. } else {
  278. // just move it to the new list
  279. newList.put(child, i);
  280. }
  281. }
  282. // kill anything that was removed for the children
  283. for(Map.Entry<String,Instance> i: instances.entrySet()) {
  284. i.getValue().stop();
  285. try {
  286. rmnod(reportsNode + '/' + i.getKey());
  287. } catch (InterruptedException e) {
  288. Thread.currentThread().interrupt();
  289. } catch (KeeperException e) {
  290. e.printStackTrace();
  291. }
  292. }
  293. instances = newList;
  294. }
  295. }