1
0

svcmgr.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. #include <precomp.h>
  2. #ifndef NOSVCMGR
  3. #include "svcmgr.h"
  4. #ifdef WASABI_COMPILE_COMPONENTS
  5. #include <api/wac/wac.h>
  6. #include <api/wac/compon.h>
  7. #endif
  8. #ifdef WASABI_COMPILE_SYSCB
  9. #include <api/syscb/cbmgr.h>
  10. #include <api/syscb/callbacks/syscb.h>
  11. #include <api/syscb/callbacks/svccb.h>
  12. #endif
  13. #include <bfc/multimap.h>
  14. #include <bfc/map.h>
  15. #include <bfc/critsec.h>
  16. static MultiMap<FOURCC, waServiceFactory> services;// list of factories by class
  17. static Map<waServiceFactory*, GUID> ownermap; // who presented it
  18. static Map<GUID, waServiceFactory*> services_by_guid;// unique services
  19. static Map<void *, waServiceFactory*> lockmap; // who to tell when it's unlocked
  20. //CUTstatic Map<void *, GUID> clientmap; // who locked it
  21. static CriticalSection cs;
  22. int ServiceManager::registerService(waServiceFactory *service, GUID owner) {
  23. ASSERT(owner != INVALID_GUID);
  24. if (owner == INVALID_GUID) return 0;
  25. FOURCC svctype = service->getServiceType();
  26. cs.enter();
  27. if (!services.multiHaveItem(svctype, service)) {
  28. services.multiAddItem(svctype, service);
  29. ownermap.addItem(service, owner);
  30. GUID svcguid = service->getGuid();
  31. if (svcguid != INVALID_GUID) services_by_guid.addItem(svcguid, service);
  32. }
  33. cs.leave();
  34. service->serviceNotify(SvcNotify::ONREGISTERED);
  35. #ifdef WASABI_COMPILE_SYSCB
  36. CallbackManager::issueCallback(SysCallback::SERVICE,
  37. SvcCallback::ONREGISTER,
  38. (int)svctype, reinterpret_cast<int>(service));
  39. #endif
  40. return 1;
  41. }
  42. int ServiceManager::deregisterService(waServiceFactory *service, int internal) {
  43. FOURCC svctype = service->getServiceType();
  44. // make sure it was there
  45. cs.enter();
  46. if (services.multiHaveItem(svctype, service)) {
  47. // make sure there aren't still services issued by this guy
  48. // ASSERT(internal || !lockmap.reverseGetItem(service));
  49. services.multiDelItem(svctype, service);
  50. ownermap.delItem(service);
  51. services_by_guid.reverseDelItem(service);
  52. }
  53. cs.leave();
  54. service->serviceNotify(SvcNotify::ONDEREGISTERED);
  55. #ifdef WASABI_COMPILE_SYSCB
  56. CallbackManager::issueCallback(SysCallback::SERVICE,
  57. SvcCallback::ONDEREGISTER,
  58. (int)svctype, reinterpret_cast<int>(service));
  59. #endif
  60. return 1;
  61. }
  62. int ServiceManager::getNumServices(FOURCC svc_type) {
  63. INCRITICALSECTION(cs);
  64. return services.multiGetNumItems(svc_type);
  65. }
  66. int ServiceManager::getNumServices() {
  67. return services.getNumItems();
  68. }
  69. waServiceFactory *ServiceManager::enumService(int n) {
  70. return services_by_guid.enumItemByPos(n, NULL);
  71. }
  72. int ServiceManager::getNumOwners() {
  73. return ownermap.getNumItems();
  74. }
  75. int ServiceManager::getNumServicesByGuid() {
  76. return services_by_guid.getNumItems();
  77. }
  78. int ServiceManager::getNumLocks() {
  79. return lockmap.getNumItems();
  80. }
  81. waServiceFactory *ServiceManager::enumService(FOURCC svc_type, int n) {
  82. INCRITICALSECTION(cs);
  83. waServiceFactory *ret = NULL;
  84. services.multiGetItem(svc_type, n, &ret);
  85. return ret;
  86. }
  87. waServiceFactory *ServiceManager::getServiceByGuid(GUID guid) {
  88. INCRITICALSECTION(cs);
  89. if (guid == INVALID_GUID) return NULL;
  90. waServiceFactory *ret=NULL;
  91. services_by_guid.getItem(guid, &ret);
  92. return ret;
  93. }
  94. void ServiceManager::sendNotification(int msg, int param1, int param2) {
  95. cs.enter();
  96. for (int x = 0; x < services.multiGetNumPairs(); x++) {
  97. for (int y = 0; ; y++) {
  98. waServiceFactory *svc;
  99. if (!services.multiGetItemDirect(x, y, &svc)) {
  100. break;
  101. }
  102. svc->serviceNotify(msg, param1, param2);
  103. }
  104. }
  105. cs.leave();
  106. #ifdef WASABI_COMPILE_COMPONENTS
  107. // also notify components
  108. for (int i = 0; ; i++) {
  109. WaComponent *wac = ComponentManager::enumComponent(i);
  110. if (wac == NULL) break;
  111. wac->onNotify(WAC_NOTIFY_SERVICE_NOTIFY, msg, param1, param2);
  112. }
  113. #endif
  114. #ifdef WASABI_COMPILE_SYSCB
  115. // and syscallbacks
  116. CallbackManager::issueCallback(SysCallback::RUNLEVEL, msg);
  117. #endif
  118. }
  119. int ServiceManager::lock(waServiceFactory *owner, void *svcptr) {
  120. INCRITICALSECTION(cs);
  121. if (owner == NULL || svcptr == NULL) return 0;
  122. // we allow multiple entries for same service
  123. lockmap.addItem(svcptr, owner);
  124. return 1;
  125. }
  126. int ServiceManager::unlock(void *svcptr) {
  127. if (svcptr == NULL) return 0;
  128. waServiceFactory *wsvc = NULL;
  129. cs.enter();
  130. if (!lockmap.getItem(svcptr, &wsvc)) {
  131. cs.leave();
  132. DebugString("WARNING: got unlock with no lock record!");
  133. return 0;
  134. }
  135. int r = lockmap.delItem(svcptr);
  136. ASSERT(r);
  137. //CUT // this might fail, client locking isn't enforceable
  138. //CUT clientmap.delItem(svcptr);
  139. cs.leave();
  140. return 1;
  141. }
  142. int ServiceManager::clientLock(void *svcptr, GUID lockedby) {
  143. //CUT INCRITICALSECTION(cs);
  144. //CUT ASSERT(svcptr != NULL);
  145. //CUT if (svcptr == NULL) return 0;
  146. //CUT ASSERT(lockedby != INVALID_GUID);
  147. //CUT if (lockedby == INVALID_GUID) return 0;
  148. //CUT clientmap.addItem(svcptr, lockedby);
  149. return 1;
  150. }
  151. int ServiceManager::release(void *svcptr) {
  152. if (svcptr == NULL) return 0;
  153. waServiceFactory *wsvc = NULL;
  154. cs.enter(); // note cs getting locked twice via release+unlock
  155. if (!lockmap.getItem(svcptr, &wsvc)) {
  156. cs.leave();
  157. DebugString("WARNING: got release with no lock record!");
  158. return 0;
  159. }
  160. unlock(svcptr);
  161. cs.leave();
  162. ASSERT(wsvc != NULL);
  163. return wsvc->releaseInterface(svcptr);
  164. }
  165. #ifdef WASABI_COMPILE_COMPONENTS
  166. GUID ServiceManager::getOwningComponent(void *svcptr) {
  167. INCRITICALSECTION(cs);
  168. GUID ret = INVALID_GUID;
  169. waServiceFactory *svc=NULL;
  170. if (lockmap.getItem(svcptr, &svc)) ownermap.getItem(svc, &ret);
  171. return ret;
  172. }
  173. GUID ServiceManager::getLockingComponent(void *svcptr) {
  174. INCRITICALSECTION(cs);
  175. GUID ret = INVALID_GUID;
  176. //CUT clientmap.getItem(svcptr, &ret);
  177. return ret;
  178. }
  179. #endif
  180. using namespace WaSvc;
  181. static struct {
  182. FOURCC type;
  183. const char *name;
  184. } svc_names[] = {
  185. { DEVICE, "Portable Device" },
  186. { FILEREADER, "File Reader" },
  187. { FILESELECTOR, "File Selector" },
  188. { IMAGEGENERATOR, "Image Generator" },
  189. { IMAGELOADER, "Image Loader" },
  190. { ITEMMANAGER, "Item Manager" },
  191. { MEDIACONVERTER, "Media Converter" },
  192. { MEDIACORE, "Media Core" },
  193. { PLAYLISTREADER, "Playlist Reader" },
  194. { PLAYLISTWRITER, "Playlist Writer" },
  195. { SCRIPTOBJECT, "Script Class" },
  196. { XMLPROVIDER, "XML Provider" },
  197. { DB, "Database" },
  198. { EVALUATOR, "Evaluator" },
  199. { COREADMIN, "Core Administrator" },
  200. { NONE, NULL }, // this one has to be last
  201. };
  202. const char *ServiceManager::getServiceTypeName(FOURCC svc_type) {
  203. for (int i = 0; ; i++) {
  204. if (svc_names[i].name == NULL) break;
  205. if (svc_names[i].type == svc_type) return svc_names[i].name;
  206. }
  207. return NULL;
  208. }
  209. FOURCC ServiceManager::safe_getServiceType(waServiceFactory *was) {
  210. #ifndef _DEBUG
  211. return 0;
  212. #endif
  213. FOURCC type = 0;
  214. _TRY
  215. {
  216. type = was->getServiceType();
  217. }
  218. _EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  219. {
  220. OutputDebugString("EXCEPTION_EXECUTE_HANDLER\n");
  221. }
  222. return type;
  223. }
  224. const char *ServiceManager::safe_getServiceName(waServiceFactory *was) {
  225. #ifndef _DEBUG
  226. return 0;
  227. #endif
  228. const char *name = NULL;
  229. _TRY
  230. {
  231. name = was->getServiceName();
  232. }
  233. _EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  234. {
  235. OutputDebugString("EXCEPTION_EXECUTE_HANDLER\n");
  236. }
  237. return name;
  238. }
  239. void ServiceManager::onShutdown() {
  240. /*
  241. ownermap.purge();
  242. services.purge();
  243. services_by_guid.purge();
  244. clientmap.purge();
  245. */
  246. int nlocks = lockmap.getNumPairs();
  247. if (nlocks <= 0) {
  248. //lockmap.purge();
  249. #ifdef GEN_FF // i need this to have clean session restart, feel free to remove the ifdef if you fgeel that should always be done
  250. ownermap.deleteAll();
  251. services.multiRemoveAll();
  252. services_by_guid.deleteAll();
  253. lockmap.deleteAll();
  254. #endif
  255. return;
  256. }
  257. #ifndef _DEBUG
  258. DebugString("-----------------\n");
  259. for (int i = 0; i < nlocks; i++) {
  260. void *ptr = lockmap.enumIndexByPos(i, NULL); ASSERT(ptr != NULL);
  261. StringPrintf s("lock: %d type:'", (int)ptr);
  262. // GUID g = lockermap.enumItemByPos(i, INVALID_GUID);ASSERT(g != INVALID_GUID);
  263. // s += g;
  264. // WaComponent *wac = ComponentManager::getComponentFromGuid(g);
  265. waServiceFactory *was=NULL;
  266. was = lockmap.enumItemByPos(i, NULL);
  267. ASSERT(was != NULL);
  268. FOURCC type = safe_getServiceType(was);
  269. const char *tname = ServiceManager::getServiceTypeName(type);
  270. if (tname != NULL) {
  271. s += tname;
  272. } else {
  273. FOURCC v = BSWAP(type);
  274. unsigned char bleh[5]=" ";
  275. MEMCPY(bleh, &v, 4);
  276. s += String((char *)bleh);
  277. }
  278. s += "' from service:'";
  279. s += safe_getServiceName(was);
  280. // s += " wac:";
  281. // if (wac) s += wac->getName();
  282. #ifdef WASABI_COMPILE_COMPONENTS
  283. s += "' owned by:'";
  284. GUID g = INVALID_GUID;
  285. ownermap.getItem(was, &g);
  286. if (g != INVALID_GUID) {
  287. s += g;
  288. WaComponent *wac = ComponentManager::getComponentFromGuid(g);
  289. if (wac) s += wac->getName();
  290. } else s += "(unregistered)";
  291. #else
  292. GUID g;
  293. #endif
  294. s += "' registered lock to '";
  295. g = INVALID_GUID;
  296. //clientmap.getItem(ptr, &g);
  297. s += g;
  298. s += "'\n";
  299. DebugString(s.v());
  300. }
  301. DebugString("-----------------\n");
  302. #endif
  303. #ifdef GEN_FF // i need this to have clean session restart, feel free to remove the ifdef if you fgeel that should always be done
  304. ownermap.deleteAll();
  305. services.multiRemoveAll();
  306. services_by_guid.deleteAll();
  307. lockmap.deleteAll();
  308. #endif
  309. }
  310. int ServiceManager::isValidService(FOURCC svctype, waServiceFactory *service) {
  311. INCRITICALSECTION(cs);
  312. return services.multiHaveItem(svctype, service);
  313. }
  314. #endif