PageRenderTime 54ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sys/java/fan/sys/Service$.java

https://bitbucket.org/bedlaczech/fan-1.0
Java | 274 lines | 196 code | 37 blank | 41 comment | 40 complexity | a0314c9f55aa9eaede4ac8845bb10a08 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //
  2. // Copyright (c) 2009, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 26 Mar 09 Brian Frank Creation
  7. //
  8. package fan.sys;
  9. import java.util.HashMap;
  10. /**
  11. * Service mixin implementation methods
  12. */
  13. public class Service$
  14. {
  15. //////////////////////////////////////////////////////////////////////////
  16. // Registry
  17. //////////////////////////////////////////////////////////////////////////
  18. private static Object lock = new Object();
  19. private static HashMap byService = new HashMap(); // Service:State
  20. private static HashMap byType = new HashMap(); // Type:Node
  21. public static List list()
  22. {
  23. synchronized (lock)
  24. {
  25. return new List(Sys.ServiceType, byService.keySet().toArray(new Service[byService.size()]));
  26. }
  27. }
  28. public static Service find(Type t) { return find(t.qname(), true); }
  29. public static Service find(Type t, boolean checked) { return find(t.qname(), checked); }
  30. public static Service find(String qname, boolean checked)
  31. {
  32. synchronized (lock)
  33. {
  34. Node node = (Node)byType.get(qname);
  35. if (node != null) return node.service;
  36. if (checked) throw UnknownServiceErr.make(qname);
  37. return null;
  38. }
  39. }
  40. public static List findAll(Type t)
  41. {
  42. String qname = t.qname();
  43. List list = new List(Sys.ServiceType);
  44. synchronized (lock)
  45. {
  46. Node node = (Node)byType.get(qname);
  47. while (node != null)
  48. {
  49. list.add(node.service);
  50. node = node.next;
  51. }
  52. }
  53. return list.ro();
  54. }
  55. static boolean isServiceType(Type t)
  56. {
  57. return t != Sys.ObjType && t != Sys.ServiceType && t.isPublic();
  58. }
  59. //////////////////////////////////////////////////////////////////////////
  60. // Identity
  61. //////////////////////////////////////////////////////////////////////////
  62. public static long hash(Service self)
  63. {
  64. return System.identityHashCode(self);
  65. }
  66. public static boolean equals(Service self, Object that)
  67. {
  68. return self == that;
  69. }
  70. public static boolean isInstalled(Service self)
  71. {
  72. synchronized (lock)
  73. {
  74. return byService.get(self) != null;
  75. }
  76. }
  77. public static boolean isRunning(Service self)
  78. {
  79. synchronized (lock)
  80. {
  81. State state = (State)byService.get(self);
  82. return state != null && state.running;
  83. }
  84. }
  85. //////////////////////////////////////////////////////////////////////////
  86. // Lifecycle
  87. //////////////////////////////////////////////////////////////////////////
  88. public static Service install(Service self)
  89. {
  90. try
  91. {
  92. List types = FanObj.typeof(self).inheritance();
  93. synchronized (lock)
  94. {
  95. // if already installed, short circuit
  96. if (self.isInstalled()) return self;
  97. // add to byService map
  98. byService.put(self, new State(self));
  99. // add to map for each type service implements
  100. for (int i=0; i<types.sz(); ++i)
  101. {
  102. Type t = (Type)types.get(i);
  103. if (!isServiceType(t)) continue;
  104. Node node = new Node(self);
  105. Node x = (Node)byType.get(t.qname());
  106. if (x == null) byType.put(t.qname(), node);
  107. else
  108. {
  109. while (x.next != null) x = x.next;
  110. x.next = node;
  111. }
  112. }
  113. }
  114. }
  115. catch (Throwable e)
  116. {
  117. e.printStackTrace();
  118. }
  119. return self;
  120. }
  121. public static Service uninstall(Service self)
  122. {
  123. try
  124. {
  125. List types = FanObj.typeof(self).inheritance();
  126. synchronized (lock)
  127. {
  128. // ensure service is stopped
  129. stop(self);
  130. // remove from byService map, it not installed short circuit
  131. if (byService.remove(self) == null) return self;
  132. // remove from map for each type implemented by service
  133. nextType: for (int i=0; i<types.sz(); ++i)
  134. {
  135. // get next type in inheritance and check if service type
  136. Type t = (Type)types.get(i);
  137. if (!isServiceType(t)) continue nextType;
  138. // lookup linked list for that type
  139. Node node = (Node)byType.get(t.qname());
  140. if (node == null) continue nextType;
  141. // find this thread in the linked list
  142. Node last = null;
  143. while (node.service != self)
  144. {
  145. last = node;
  146. node = node.next;
  147. if (node == null) continue nextType;
  148. }
  149. // update the map or linked list
  150. if (last == null)
  151. byType.put(t.qname(), node.next);
  152. else
  153. last.next = node.next;
  154. }
  155. }
  156. }
  157. catch (Throwable e)
  158. {
  159. e.printStackTrace();
  160. }
  161. return self;
  162. }
  163. public static Service start(Service self)
  164. {
  165. State state = null;
  166. try
  167. {
  168. synchronized (lock)
  169. {
  170. // start implies install
  171. install(self);
  172. // if already running, short circuit
  173. state = (State)byService.get(self);
  174. if (state.running) return self;
  175. // put into the running state
  176. state.running = true;
  177. }
  178. // onStart callback (outside of lock)
  179. self.onStart();
  180. }
  181. catch (Throwable e)
  182. {
  183. if (state != null) state.running = false;
  184. dumpErr(self, "onStart", e);
  185. }
  186. return self;
  187. }
  188. public static Service stop(Service self)
  189. {
  190. try
  191. {
  192. synchronized (lock)
  193. {
  194. // if not running, short circuit
  195. State state = (State)byService.get(self);
  196. if (state == null || !state.running) return self;
  197. // take out of the running state
  198. state.running = false;
  199. }
  200. // onStop (outside of lock)
  201. self.onStop();
  202. }
  203. catch (Throwable e)
  204. {
  205. dumpErr(self, "onStop", e);
  206. }
  207. return self;
  208. }
  209. public static void onStart(Service self) {}
  210. public static void onStop(Service self) {}
  211. private static void dumpErr(Service self, String method, Throwable e)
  212. {
  213. if (e.toString().equals("sys::Err: test-nodump")) return;
  214. System.out.println("ERROR: " + self.getClass().getName() + "." + method);
  215. if (e instanceof Err)
  216. ((Err)e).trace();
  217. else
  218. e.printStackTrace();
  219. }
  220. //////////////////////////////////////////////////////////////////////////
  221. // State/Node
  222. //////////////////////////////////////////////////////////////////////////
  223. /** Value for byService map */
  224. static class State
  225. {
  226. State(Service s) { service = s; }
  227. Service service;
  228. volatile boolean running;
  229. }
  230. /** Value for byType map */
  231. static class Node
  232. {
  233. Node(Service s) { service = s; }
  234. Service service;
  235. Node next;
  236. }
  237. }