PageRenderTime 85ms CodeModel.GetById 18ms RepoModel.GetById 2ms app.codeStats 0ms

/src/sys/dotnet/fan/sys/Service_.cs

https://bitbucket.org/bedlaczech/fan-1.0
C# | 282 lines | 198 code | 36 blank | 48 comment | 40 complexity | c34108972d14cfce5e2770796e862a77 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. // 30 Mar 09 Andy Frank Creation
  7. //
  8. using System.Collections;
  9. namespace Fan.Sys
  10. {
  11. /// <summary>
  12. /// Service mixin implementation methods.
  13. /// </summary>
  14. public class Service_
  15. {
  16. //////////////////////////////////////////////////////////////////////////
  17. // Registry
  18. //////////////////////////////////////////////////////////////////////////
  19. private static object m_lock = new object();
  20. private static Hashtable byService = new Hashtable(); // Service:State
  21. private static Hashtable byType = new Hashtable(); // Type:Node
  22. public static List list()
  23. {
  24. lock (m_lock)
  25. {
  26. Service[] array = new Service[byService.Count];
  27. byService.Keys.CopyTo(array, 0);
  28. return new List(Sys.ServiceType, array);
  29. }
  30. }
  31. public static Service find(Type t) { return find(t.qname(), true); }
  32. public static Service find(Type t, bool check) { return find(t.qname(), check); }
  33. public static Service find(string qname, bool check)
  34. {
  35. lock (m_lock)
  36. {
  37. Node node = (Node)byType[qname];
  38. if (node != null) return node.service;
  39. if (check) throw UnknownServiceErr.make(qname).val;
  40. return null;
  41. }
  42. }
  43. public static List findAll(Type t)
  44. {
  45. string qname = t.qname();
  46. List list = new List(Sys.ServiceType);
  47. lock (m_lock)
  48. {
  49. Node node = (Node)byType[qname];
  50. while (node != null)
  51. {
  52. list.add(node.service);
  53. node = node.next;
  54. }
  55. }
  56. return list.ro();
  57. }
  58. static bool isServiceType(Type t)
  59. {
  60. return t != Sys.ObjType && t != Sys.ServiceType && t.isPublic();
  61. }
  62. //////////////////////////////////////////////////////////////////////////
  63. // Identity
  64. //////////////////////////////////////////////////////////////////////////
  65. public static long hash(Service self)
  66. {
  67. return Env.cur().idHash(self);
  68. }
  69. // TODO - there appears to be a bug in my
  70. // emit code that mixins look for this method
  71. // on the impl class
  72. public static bool Equals(Service self, object that)
  73. {
  74. return self == that;
  75. }
  76. public static bool equals(Service self, object that)
  77. {
  78. return self == that;
  79. }
  80. public static bool isInstalled(Service self)
  81. {
  82. lock (m_lock)
  83. {
  84. return byService[self] != null;
  85. }
  86. }
  87. public static bool isRunning(Service self)
  88. {
  89. lock (m_lock)
  90. {
  91. State state = (State)byService[self];
  92. return state != null && state.running;
  93. }
  94. }
  95. //////////////////////////////////////////////////////////////////////////
  96. // Lifecycle
  97. //////////////////////////////////////////////////////////////////////////
  98. public static Service install(Service self)
  99. {
  100. try
  101. {
  102. List types = FanObj.@typeof(self).inheritance();
  103. lock (m_lock)
  104. {
  105. // if already installed, short circuit
  106. if (self.isInstalled()) return self;
  107. // add to byService map
  108. byService[self] = new State(self);
  109. // add to map for each type service implements
  110. for (int i=0; i<types.sz(); ++i)
  111. {
  112. Type t = (Type)types.get(i);
  113. if (!isServiceType(t)) continue;
  114. Node node = new Node(self);
  115. Node x = (Node)byType[t.qname()];
  116. if (x == null) byType[t.qname()] = node;
  117. else
  118. {
  119. while (x.next != null) x = x.next;
  120. x.next = node;
  121. }
  122. }
  123. }
  124. }
  125. catch (System.Exception e)
  126. {
  127. Err.dumpStack(e);
  128. }
  129. return self;
  130. }
  131. public static Service uninstall(Service self)
  132. {
  133. try
  134. {
  135. List types = FanObj.@typeof(self).inheritance();
  136. lock (m_lock)
  137. {
  138. // ensure service is stopped
  139. stop(self);
  140. // remove from byService map, it not installed short circuit
  141. if (byService[self] == null) return self;
  142. byService.Remove(self);
  143. // remove from map for each type implemented by service
  144. for (int i=0; i<types.sz(); ++i)
  145. {
  146. // get next type in inheritance and check if service type
  147. Type t = (Type)types.get(i);
  148. if (!isServiceType(t)) continue;
  149. // lookup linked list for that type
  150. Node node = (Node)byType[t.qname()];
  151. if (node == null) continue;
  152. // find this thread in the linked list
  153. Node last = null;
  154. bool cont = false;
  155. while (node.service != self)
  156. {
  157. last = node;
  158. node = node.next;
  159. if (node == null) { cont=true; break; }
  160. }
  161. if (cont) continue;
  162. // update the map or linked list
  163. if (last == null)
  164. byType[t.qname()] = node.next;
  165. else
  166. last.next = node.next;
  167. }
  168. }
  169. }
  170. catch (System.Exception e)
  171. {
  172. Err.dumpStack(e);
  173. }
  174. return self;
  175. }
  176. public static Service start(Service self)
  177. {
  178. State state = null;
  179. try
  180. {
  181. lock (m_lock)
  182. {
  183. // start implies install
  184. install(self);
  185. // if already running, short circuit
  186. state = (State)byService[self];
  187. if (state.running) return self;
  188. // put into the running state
  189. state.running = true;
  190. }
  191. // onStart callback (outside of lock)
  192. self.onStart();
  193. }
  194. catch (System.Exception e)
  195. {
  196. if (state != null) state.running = false;
  197. Err.dumpStack(e);
  198. }
  199. return self;
  200. }
  201. public static Service stop(Service self)
  202. {
  203. try
  204. {
  205. lock (m_lock)
  206. {
  207. // if not running, short circuit
  208. State state = (State)byService[self];
  209. if (state == null || !state.running) return self;
  210. // take out of the running state
  211. state.running = false;
  212. }
  213. // onStop (outside of lock)
  214. self.onStop();
  215. }
  216. catch (System.Exception e)
  217. {
  218. Err.dumpStack(e);
  219. }
  220. return self;
  221. }
  222. public static void onStart(Service self) {}
  223. public static void onStop(Service self) {}
  224. //////////////////////////////////////////////////////////////////////////
  225. // State/Node
  226. //////////////////////////////////////////////////////////////////////////
  227. /// <summary>
  228. /// Value for byService map
  229. /// </summary>
  230. internal class State
  231. {
  232. public State(Service s) { service = s; }
  233. public Service service;
  234. public bool running;
  235. }
  236. /// <summary>
  237. /// Value for byType map
  238. /// </summary>
  239. internal class Node
  240. {
  241. public Node(Service s) { service = s; }
  242. public Service service;
  243. public Node next;
  244. }
  245. }
  246. }