moduleManager.cpp 100 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "moduleManager.h"
  23. #ifndef _MODULE_MERGE_DEFINITION_H
  24. #include "moduleMergeDefinition.h"
  25. #endif
  26. #ifndef _TAML_MODULE_ID_UPDATE_VISITOR_H_
  27. #include "tamlModuleIdUpdateVisitor.h"
  28. #endif
  29. #ifndef _MODULE_CALLBACKS_H_
  30. #include "moduleCallbacks.h"
  31. #endif
  32. #ifndef _CONSOLETYPES_H_
  33. #include "console/consoleTypes.h"
  34. #endif
  35. #include "cinterface/cinterface.h"
  36. #ifndef _MODULE_DEFINITION_H
  37. #include "module/moduleDefinition.h"
  38. #endif
  39. #ifndef _STRINGFUNCTIONS_H_
  40. #include "core/strings/stringFunctions.h"
  41. #endif
  42. // Script bindings.
  43. #include "moduleManager_ScriptBinding.h"
  44. //-----------------------------------------------------------------------------
  45. IMPLEMENT_CONOBJECT( ModuleManager );
  46. //-----------------------------------------------------------------------------
  47. ModuleManager ModuleDatabase;
  48. //-----------------------------------------------------------------------------
  49. S32 QSORT_CALLBACK moduleDefinitionVersionIdSort( const void* a, const void* b )
  50. {
  51. // Fetch module definitions.
  52. ModuleDefinition* pDefinition1 = *(ModuleDefinition**)a;
  53. ModuleDefinition* pDefinition2 = *(ModuleDefinition**)b;
  54. // Fetch version Ids.
  55. const U32 versionId1 = pDefinition1->getVersionId();
  56. const U32 versionId2 = pDefinition2->getVersionId();
  57. // We sort higher version Id first.
  58. return versionId1 > versionId2 ? -1 : versionId1 < versionId2 ? 1 : 0;
  59. }
  60. S32 ModuleManager::moduleDependencySort(ModuleDefinition* const* a, ModuleDefinition* const* b)
  61. {
  62. // if A depends on B move A down the list
  63. ModuleDefinition::typeModuleDependencyVector moduleDependencies = (*a)->getDependencies();
  64. for (ModuleDefinition::typeModuleDependencyVector::const_iterator dependencyItr = moduleDependencies.begin(); dependencyItr != moduleDependencies.end(); ++dependencyItr)
  65. {
  66. if ((String::compare(dependencyItr->mModuleId, (*b)->getModuleId()) == 0)
  67. && (dependencyItr->mVersionId == (*b)->getVersionId()))
  68. return 1;
  69. }
  70. //If B depends on A, move A up the list
  71. ModuleDefinition::typeModuleDependencyVector moduleDependencies2 = (*b)->getDependencies();
  72. for (ModuleDefinition::typeModuleDependencyVector::const_iterator dependencyItr2 = moduleDependencies2.begin(); dependencyItr2 != moduleDependencies2.end(); ++dependencyItr2)
  73. {
  74. if ((String::compare(dependencyItr2->mModuleId, (*a)->getModuleId()) == 0)
  75. && (dependencyItr2->mVersionId == (*a)->getVersionId()))
  76. return -1;
  77. }
  78. //didn't find any explicit dependencies between the two, so sort by which has more
  79. if (moduleDependencies.size() > moduleDependencies2.size()) return 1;
  80. if (moduleDependencies.size() < moduleDependencies2.size()) return -1;
  81. return 0;
  82. }
  83. //-----------------------------------------------------------------------------
  84. ModuleManager::ModuleManager() :
  85. mEnforceDependencies(true),
  86. mEchoInfo(false),
  87. mFailGroupIfModuleFail(false),
  88. mDatabaseLocks( 0 ),
  89. mIgnoreLoadedGroups(false)
  90. {
  91. // Set module extension.
  92. dStrcpy( mModuleExtension, MODULE_MANAGER_MODULE_DEFINITION_EXTENSION, 256 );
  93. }
  94. //-----------------------------------------------------------------------------
  95. bool ModuleManager::onAdd()
  96. {
  97. if( !Parent::onAdd() )
  98. return false;
  99. // Register listeners.
  100. mNotificationListeners.registerObject();
  101. return true;
  102. }
  103. //-----------------------------------------------------------------------------
  104. void ModuleManager::onRemove()
  105. {
  106. // Clear database.
  107. clearDatabase();
  108. // Unregister object.
  109. mNotificationListeners.unregisterObject();
  110. // Call parent.
  111. Parent::onRemove();
  112. }
  113. //-----------------------------------------------------------------------------
  114. void ModuleManager::initPersistFields()
  115. {
  116. docsURL;
  117. // Call parent.
  118. Parent::initPersistFields();
  119. addField( "EnforceDependencies", TypeBool, Offset(mEnforceDependencies, ModuleManager), "Whether the module manager enforces any dependencies on module definitions it discovers or not." );
  120. addField( "EchoInfo", TypeBool, Offset(mEchoInfo, ModuleManager), "Whether the module manager echos extra information to the console or not." );
  121. addField( "FailGroupIfModuleFail", TypeBool, Offset(mFailGroupIfModuleFail, ModuleManager), "Whether the module manager will fail to load an entire module group if a single module fails to load.");
  122. }
  123. //-----------------------------------------------------------------------------
  124. void ModuleManager::onDeleteNotify( SimObject *object )
  125. {
  126. // Cast to a module definition.
  127. ModuleDefinition* pModuleDefinition = dynamic_cast<ModuleDefinition*>( object );
  128. // Ignore if not appropriate.
  129. if ( pModuleDefinition == NULL )
  130. return;
  131. // Warn.
  132. Con::warnf( "Module Manager::onDeleteNotify() - Notified of a module definition deletion for module Id '%s' of version Id '%d' however this should not happen and can cause module database corruption.",
  133. pModuleDefinition->getModuleId(), pModuleDefinition->getVersionId() );
  134. }
  135. //-----------------------------------------------------------------------------
  136. bool ModuleManager::setModuleExtension( const char* pExtension )
  137. {
  138. // Sanity!
  139. AssertFatal( pExtension != NULL, "Cannot set module extension with NULL extension." );
  140. // Did we find an extension period?
  141. if ( *pExtension == '.' )
  142. {
  143. // Yes, so warn.
  144. Con::warnf("Module Manager: Failed to set extension as supplied extension contains an initial period: '%s'.", pExtension );
  145. return false;
  146. }
  147. // Is the extension too large?
  148. if ( dStrlen( pExtension ) > sizeof( mModuleExtension ) )
  149. {
  150. // Yes, so warn.
  151. Con::warnf("Module Manager: Failed to set extension as supplied extension is too large: '%s'.", pExtension );
  152. return false;
  153. }
  154. // Set module extension.
  155. dStrcpy( mModuleExtension, pExtension, 256 );
  156. return true;
  157. }
  158. //-----------------------------------------------------------------------------
  159. bool ModuleManager::scanModules( const char* pPath, const bool rootOnly )
  160. {
  161. // Lock database.
  162. LockDatabase( this );
  163. // Sanity!
  164. AssertFatal( pPath != NULL, "Cannot scan module with NULL path." );
  165. String relBasePath = Platform::makeRelativePathName(pPath, NULL);
  166. // Info.
  167. if ( mEchoInfo )
  168. {
  169. Con::printSeparator();
  170. Con::printf("Module Manager: Started scanning '%s'...", relBasePath.c_str());
  171. }
  172. String pattern = "*.";
  173. pattern += mModuleExtension;
  174. Torque::Path scanPath = Torque::FS::GetCwd();
  175. scanPath.setPath(relBasePath);
  176. Vector<String> fileList;
  177. S32 numModules = Torque::FS::FindByPattern(scanPath, pattern, !rootOnly, fileList, true);
  178. for (S32 i = 0; i < numModules; ++i)
  179. {
  180. Torque::Path modulePath = fileList[i];
  181. registerModule(modulePath.getPath(), modulePath.getFullFileName());
  182. }
  183. // Info.
  184. if ( mEchoInfo )
  185. {
  186. Con::printf("Module Manager: Finished scanning '%s'.", relBasePath.c_str());
  187. }
  188. return true;
  189. }
  190. //-----------------------------------------------------------------------------
  191. bool ModuleManager::loadModuleGroup( const char* pModuleGroup )
  192. {
  193. // Lock database.
  194. LockDatabase( this );
  195. // Sanity!
  196. AssertFatal( pModuleGroup != NULL, "Cannot load module group with NULL group name." );
  197. typeModuleLoadEntryVector moduleResolvingQueue;
  198. typeModuleLoadEntryVector moduleReadyQueue;
  199. // Fetch module group.
  200. StringTableEntry moduleGroup = StringTable->insert( pModuleGroup );
  201. // Info.
  202. if ( mEchoInfo )
  203. {
  204. Con::printSeparator();
  205. Con::printf( "Module Manager: Loading group '%s':" ,moduleGroup );
  206. }
  207. // Is the module group already loaded?
  208. if ( findGroupLoaded( moduleGroup ) != NULL )
  209. {
  210. // Yes, so warn.
  211. Con::warnf( "Module Manager: Cannot load group '%s' as it is already loaded.", moduleGroup );
  212. return false;
  213. }
  214. // Find module group.
  215. typeGroupModuleHash::iterator moduleGroupItr = mGroupModules.find( moduleGroup );
  216. // Did we find the module group?
  217. if ( moduleGroupItr == mGroupModules.end() )
  218. {
  219. // No, so info.
  220. if ( mEchoInfo )
  221. {
  222. Con::printf( "Module Manager: No modules found for module group '%s'.", moduleGroup );
  223. }
  224. return true;
  225. }
  226. // Yes, so fetch the module Ids.
  227. typeModuleIdVector* pModuleIds = moduleGroupItr->value;
  228. // Iterate module groups.
  229. for( typeModuleIdVector::iterator moduleIdItr = pModuleIds->begin(); moduleIdItr != pModuleIds->end(); ++moduleIdItr )
  230. {
  231. // Fetch module Id.
  232. StringTableEntry moduleId = *moduleIdItr;
  233. // Finish if we could not resolve the dependencies for module Id (of any version Id).
  234. if (!resolveModuleDependencies(moduleId, 0, moduleGroup, false, moduleResolvingQueue, moduleReadyQueue) && mFailGroupIfModuleFail)
  235. return false;
  236. }
  237. // Check the modules we want to load to ensure that we do not have incompatible modules loaded already.
  238. for ( typeModuleLoadEntryVector::iterator moduleReadyItr = moduleReadyQueue.begin(); moduleReadyItr != moduleReadyQueue.end(); ++moduleReadyItr )
  239. {
  240. // Fetch load ready module definition.
  241. ModuleDefinition* pLoadReadyModuleDefinition = moduleReadyItr->mpModuleDefinition;;
  242. // Fetch the module Id loaded entry.
  243. ModuleLoadEntry* pLoadedModuleEntry = findModuleLoaded( pLoadReadyModuleDefinition->getModuleId() );
  244. // Did we find a loaded entry?
  245. if ( pLoadedModuleEntry != NULL )
  246. {
  247. // Yes, so is it the one we need to load?
  248. if ( pLoadedModuleEntry->mpModuleDefinition != pLoadReadyModuleDefinition )
  249. {
  250. // Yes, so warn.
  251. Con::warnf( "Module Manager: Cannot load module group '%s' as the module Id '%s' at version Id '%d' is required but the module Id is already loaded but at version Id '%d'.",
  252. moduleGroup, pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId(), pLoadedModuleEntry->mpModuleDefinition->getVersionId() );
  253. return false;
  254. }
  255. }
  256. }
  257. // Info.
  258. if ( mEchoInfo )
  259. {
  260. // Info.
  261. Con::printf( "Module Manager: Group '%s' and its dependencies is comprised of the following '%d' module(s):", moduleGroup, moduleReadyQueue.size() );
  262. // Iterate the modules echoing them.
  263. for ( typeModuleLoadEntryVector::iterator moduleReadyItr = moduleReadyQueue.begin(); moduleReadyItr != moduleReadyQueue.end(); ++moduleReadyItr )
  264. {
  265. // Fetch the ready entry.
  266. ModuleDefinition* pModuleDefinition = moduleReadyItr->mpModuleDefinition;
  267. // Info.
  268. Con::printf( "> module Id '%s' at version Id '%d':", pModuleDefinition->getModuleId(), pModuleDefinition->getVersionId() );
  269. }
  270. }
  271. // Add module group.
  272. mGroupsLoaded.push_back( moduleGroup );
  273. // Reset modules loaded count.
  274. U32 modulesLoadedCount = 0;
  275. // Iterate the modules, executing their script files and call their create function.
  276. for ( typeModuleLoadEntryVector::iterator moduleReadyItr = moduleReadyQueue.begin(); moduleReadyItr != moduleReadyQueue.end(); ++moduleReadyItr )
  277. {
  278. // Fetch the ready entry.
  279. ModuleLoadEntry* pReadyEntry = moduleReadyItr;
  280. // Fetch load ready module definition.
  281. ModuleDefinition* pLoadReadyModuleDefinition = pReadyEntry->mpModuleDefinition;
  282. // Fetch any loaded entry for the module Id.
  283. ModuleLoadEntry* pLoadedEntry = findModuleLoaded( pLoadReadyModuleDefinition->getModuleId() );
  284. // Is the module already loaded.
  285. if ( pLoadedEntry != NULL )
  286. {
  287. // Yes, so increase load count.
  288. pLoadedEntry->mpModuleDefinition->increaseLoadCount();
  289. // Skip.
  290. continue;
  291. }
  292. // No, so info.
  293. if ( mEchoInfo )
  294. {
  295. Con::printSeparator();
  296. Con::printf( "Module Manager: Loading group '%s' : module Id '%s' at version Id '%d' in group '%s' using the script file '%s'.",
  297. moduleGroup, pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId(), pLoadReadyModuleDefinition->getModuleGroup(), pLoadReadyModuleDefinition->getModuleScriptFilePath() );
  298. }
  299. // Is the module deprecated?
  300. if ( pLoadReadyModuleDefinition->getDeprecated() )
  301. {
  302. // Yes, so warn.
  303. Con::warnf( "Module Manager: Caution: module Id '%s' at version Id '%d' in group '%s' is deprecated. You should use a newer version!",
  304. pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId(), pLoadReadyModuleDefinition->getModuleGroup() );
  305. }
  306. // Add the path expando for module.
  307. Con::addPathExpando( pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getModulePath() );
  308. // Create a scope set.
  309. SimSet* pScopeSet = new SimSet;
  310. pScopeSet->registerObject( pLoadReadyModuleDefinition->getModuleId() );
  311. pScopeSet->setClassNamespace("ModuleRoot");
  312. pReadyEntry->mpModuleDefinition->mScopeSet = pScopeSet->getId();
  313. // Increase load count.
  314. pReadyEntry->mpModuleDefinition->increaseLoadCount();
  315. // Queue module loaded.
  316. mModulesLoaded.push_back( *pReadyEntry );
  317. // Bump modules loaded count.
  318. modulesLoadedCount++;
  319. // Raise notifications.
  320. raiseModulePreLoadNotifications( pLoadReadyModuleDefinition );
  321. // Do we have a script file-path specified?
  322. if ( pLoadReadyModuleDefinition->getModuleScriptFilePath() != StringTable->EmptyString() )
  323. {
  324. // Yes, so execute the script file.
  325. ConsoleValue cValue = Con::executef("exec", pLoadReadyModuleDefinition->getModuleScriptFilePath());
  326. const bool scriptFileExecuted = cValue.getBool();
  327. // Did we execute the script file?
  328. if ( scriptFileExecuted )
  329. {
  330. // Yes, so is the create method available?
  331. if ( pScopeSet->isMethod( pLoadReadyModuleDefinition->getCreateFunction() ) )
  332. {
  333. // Yes, so call the create method.
  334. //But first, check if we're overriding objects, and if so, set our console var to make that happen while we exec our create function
  335. if (pLoadReadyModuleDefinition->getOverrideExistingObjects())
  336. {
  337. String redefineBehaviorPrev = Con::getVariable("$Con::redefineBehavior");
  338. Con::setVariable("$Con::redefineBehavior", "replaceExisting");
  339. Con::executef(pScopeSet, pLoadReadyModuleDefinition->getCreateFunction());
  340. //And now that we've executed, switch back to the prior behavior
  341. Con::setVariable("$Con::redefineBehavior", redefineBehaviorPrev.c_str());
  342. }
  343. else
  344. {
  345. //Nothing to do, just run the create function
  346. Con::executef(pScopeSet, pLoadReadyModuleDefinition->getCreateFunction());
  347. }
  348. }
  349. }
  350. else
  351. {
  352. // No, so warn.
  353. Con::errorf( "Module Manager: Cannot load module group '%s' as the module Id '%s' at version Id '%d' as it failed to have the script file '%s' loaded.",
  354. moduleGroup, pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId(), pLoadReadyModuleDefinition->getModuleScriptFilePath() );
  355. }
  356. }
  357. else
  358. {
  359. // Is the create method available?
  360. if (pScopeSet->isMethod(pLoadReadyModuleDefinition->getCreateFunction()))
  361. {
  362. // Yes, so call the create method.
  363. Con::executef(pScopeSet, pLoadReadyModuleDefinition->getCreateFunction());
  364. }
  365. }
  366. // Raise notifications.
  367. raiseModulePostLoadNotifications( pLoadReadyModuleDefinition );
  368. }
  369. // Info.
  370. if ( mEchoInfo )
  371. {
  372. Con::printSeparator();
  373. Con::printf( "Module Manager: Finish loading '%d' module(s) for group '%s'.", modulesLoadedCount, moduleGroup );
  374. Con::printSeparator();
  375. }
  376. return true;
  377. }
  378. //-----------------------------------------------------------------------------
  379. bool ModuleManager::unloadModuleGroup( const char* pModuleGroup )
  380. {
  381. // Lock database.
  382. LockDatabase( this );
  383. // Sanity!
  384. AssertFatal( pModuleGroup != NULL, "Cannot unload module group with NULL group name." );
  385. typeModuleLoadEntryVector moduleResolvingQueue;
  386. typeModuleLoadEntryVector moduleReadyQueue;
  387. // Fetch module group.
  388. StringTableEntry moduleGroup = StringTable->insert( pModuleGroup );
  389. // Info.
  390. if ( mEchoInfo )
  391. {
  392. Con::printSeparator();
  393. Con::printf( "Module Manager: Unloading group '%s':" , moduleGroup );
  394. }
  395. // Find the group loaded iterator.
  396. typeGroupVector::iterator groupLoadedItr = findGroupLoaded( moduleGroup );
  397. // Is the module group already unloaded?
  398. if ( groupLoadedItr == NULL )
  399. {
  400. // No, so warn.
  401. Con::warnf( "Module Manager: Cannot unload group '%s' as it is not loaded.", moduleGroup );
  402. return false;
  403. }
  404. // Find module group.
  405. typeGroupModuleHash::iterator moduleGroupItr = mGroupModules.find( moduleGroup );
  406. // Did we find the module group?
  407. if ( moduleGroupItr == mGroupModules.end() )
  408. {
  409. // No, so info.
  410. if ( mEchoInfo )
  411. {
  412. Con::printf( "Module Manager: No modules found for module group '%s'.", moduleGroup );
  413. return true;
  414. }
  415. }
  416. // Yes, so fetch the module Ids.
  417. typeModuleIdVector* pModuleIds = moduleGroupItr->value;
  418. // Iterate module groups.
  419. for( typeModuleIdVector::iterator moduleIdItr = pModuleIds->begin(); moduleIdItr != pModuleIds->end(); ++moduleIdItr )
  420. {
  421. // Fetch module Id.
  422. StringTableEntry moduleId = *moduleIdItr;
  423. // Finish if we could not resolve the dependencies for module Id (of any version Id).
  424. if (!resolveModuleDependencies(moduleId, 0, moduleGroup, false, moduleResolvingQueue, moduleReadyQueue) && mFailGroupIfModuleFail)
  425. return false;
  426. }
  427. // Check the modules we want to load to ensure that we do not have incompatible modules loaded already.
  428. for ( typeModuleLoadEntryVector::iterator moduleReadyItr = moduleReadyQueue.begin(); moduleReadyItr != moduleReadyQueue.end(); ++moduleReadyItr )
  429. {
  430. // Fetch load ready module definition.
  431. ModuleDefinition* pLoadReadyModuleDefinition = moduleReadyItr->mpModuleDefinition;;
  432. // Fetch the module Id loaded entry.
  433. ModuleLoadEntry* pLoadedModuleEntry = findModuleLoaded( pLoadReadyModuleDefinition->getModuleId() );
  434. // Did we find a loaded entry?
  435. if ( pLoadedModuleEntry != NULL )
  436. {
  437. // Yes, so is it the one we need to load?
  438. if ( pLoadedModuleEntry->mpModuleDefinition != pLoadReadyModuleDefinition )
  439. {
  440. // Yes, so warn.
  441. Con::warnf( "Module Manager: Cannot unload module group '%s' as the module Id '%s' at version Id '%d' is required but the module Id is loaded but at version Id '%d'.",
  442. moduleGroup, pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId(), pLoadedModuleEntry->mpModuleDefinition->getVersionId() );
  443. return false;
  444. }
  445. }
  446. }
  447. // Remove module group.
  448. mGroupsLoaded.erase_fast( groupLoadedItr );
  449. // Reset modules unloaded count.
  450. U32 modulesUnloadedCount = 0;
  451. // Iterate the modules in reverse order calling their destroy function.
  452. for ( typeModuleLoadEntryVector::iterator moduleReadyItr = moduleReadyQueue.end()-1; moduleReadyItr >= moduleReadyQueue.begin(); --moduleReadyItr )
  453. {
  454. // Fetch the ready entry.
  455. ModuleLoadEntry* pReadyEntry = moduleReadyItr;
  456. // Fetch load ready module definition.
  457. ModuleDefinition* pLoadReadyModuleDefinition = pReadyEntry->mpModuleDefinition;;
  458. // Fetch any loaded entry for the module Id.
  459. ModuleLoadEntry* pLoadedEntry = findModuleLoaded( pLoadReadyModuleDefinition->getModuleId() );
  460. // Is the module loaded.
  461. if ( pLoadedEntry == NULL )
  462. {
  463. // No, so warn.
  464. if ( mEchoInfo )
  465. {
  466. Con::printf( "Module Manager: Unloading group '%s' but could not unload module Id '%s' at version Id '%d'.",
  467. moduleGroup, pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId());
  468. }
  469. // Skip.
  470. continue;
  471. }
  472. // Reduce load count.
  473. pLoadedEntry->mpModuleDefinition->reduceLoadCount();
  474. // Sanity!
  475. AssertFatal( pLoadedEntry->mpModuleDefinition->getLoadCount() >= 0, "ModuleManager::unloadModuleGroup() - Encountered an invalid load count." );
  476. // Do we need to unload?
  477. if ( pLoadedEntry->mpModuleDefinition->getLoadCount() == 0 )
  478. {
  479. // Yes, so info.
  480. if ( mEchoInfo )
  481. {
  482. Con::printSeparator();
  483. Con::printf( "Module Manager: Unload group '%s' with module Id '%s' at version Id '%d' in group '%s'.",
  484. moduleGroup, pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId(), pLoadReadyModuleDefinition->getModuleGroup() );
  485. }
  486. // Raise notifications.
  487. raiseModulePreUnloadNotifications( pLoadReadyModuleDefinition );
  488. // Fetch the module Id loaded entry.
  489. typeModuleLoadEntryVector::iterator moduleLoadedItr = findModuleLoaded( pLoadReadyModuleDefinition->getModuleId() );
  490. // Sanity!
  491. AssertFatal( moduleLoadedItr != NULL, "ModuleManager::unloadModuleGroup() - Cannot find module to unload it." );
  492. // Dequeue module loaded.
  493. mModulesLoaded.erase_fast( moduleLoadedItr );
  494. // Fetch scope set.
  495. SimSet* pScopeSet = dynamic_cast<SimSet*>(Sim::findObject(pLoadReadyModuleDefinition->mScopeSet));
  496. // Is the destroy method available?
  497. if ( pScopeSet->isMethod( pLoadReadyModuleDefinition->getDestroyFunction() ) )
  498. {
  499. // Yes, so call the destroy method.
  500. Con::executef( pScopeSet, pLoadReadyModuleDefinition->getDestroyFunction() );
  501. }
  502. // Remove scope set.
  503. pScopeSet->deleteAllObjects();
  504. pScopeSet->unregisterObject();
  505. pLoadReadyModuleDefinition->mScopeSet = 0;
  506. // Remove path expando for module.
  507. Con::removePathExpando( pLoadReadyModuleDefinition->getModuleId() );
  508. // Bump modules unloaded count.
  509. modulesUnloadedCount++;
  510. // Raise notifications.
  511. raiseModulePostUnloadNotifications( pLoadReadyModuleDefinition );
  512. }
  513. }
  514. // Info.
  515. if ( mEchoInfo )
  516. {
  517. Con::printSeparator();
  518. Con::printf( "Module Manager: Finish unloading '%d' module(s) for group '%s'.", modulesUnloadedCount, moduleGroup );
  519. Con::printSeparator();
  520. }
  521. return true;
  522. }
  523. //-----------------------------------------------------------------------------
  524. bool ModuleManager::loadModuleExplicit( const char* pModuleId, const U32 versionId )
  525. {
  526. // Lock database.
  527. LockDatabase( this );
  528. // Sanity!
  529. AssertFatal( pModuleId != NULL, "Cannot load explicit module Id with NULL module Id." );
  530. typeModuleLoadEntryVector moduleResolvingQueue;
  531. typeModuleLoadEntryVector moduleReadyQueue;
  532. // Fetch module Id.
  533. StringTableEntry moduleId = StringTable->insert( pModuleId );
  534. // Fetch modules definitions.
  535. ModuleDefinitionEntry* pDefinitions = findModuleId( moduleId );
  536. // Did we find the module Id?
  537. if ( pDefinitions == NULL )
  538. {
  539. // No, so warn.
  540. Con::warnf( "Module Manager: Cannot load explicit module Id '%s' as it does not exist.", moduleId );
  541. return false;
  542. }
  543. // Fetch module group.
  544. StringTableEntry moduleGroup = pDefinitions->mModuleGroup;
  545. // Info.
  546. if ( mEchoInfo )
  547. {
  548. Con::printSeparator();
  549. Con::printf( "Module Manager: Loading explicit module Id '%s' at version Id '%d':", moduleId, versionId );
  550. }
  551. // Finish if we could not resolve the dependencies for module Id (of any version Id).
  552. if ( !resolveModuleDependencies( moduleId, versionId, moduleGroup, false, moduleResolvingQueue, moduleReadyQueue ) )
  553. return false;
  554. // Check the modules we want to load to ensure that we do not have incompatible modules loaded already.
  555. for ( typeModuleLoadEntryVector::iterator moduleReadyItr = moduleReadyQueue.begin(); moduleReadyItr != moduleReadyQueue.end(); ++moduleReadyItr )
  556. {
  557. // Fetch load ready module definition.
  558. ModuleDefinition* pLoadReadyModuleDefinition = moduleReadyItr->mpModuleDefinition;
  559. // Fetch the module Id loaded entry.
  560. ModuleLoadEntry* pLoadedModuleEntry = findModuleLoaded( pLoadReadyModuleDefinition->getModuleId() );
  561. // Did we find a loaded entry?
  562. if ( pLoadedModuleEntry != NULL )
  563. {
  564. // Yes, so is it the one we need to load?
  565. if ( pLoadedModuleEntry->mpModuleDefinition != pLoadReadyModuleDefinition )
  566. {
  567. // Yes, so warn.
  568. Con::warnf( "Module Manager: Cannot load explicit module Id '%s' at version Id '%d' as the module Id is already loaded but at version Id '%d'.",
  569. pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId(), pLoadedModuleEntry->mpModuleDefinition->getVersionId() );
  570. return false;
  571. }
  572. }
  573. }
  574. // Info.
  575. if ( mEchoInfo )
  576. {
  577. // Info.
  578. Con::printf( "Module Manager: Explicit load of module Id '%s' at version Id '%d' and its dependencies is comprised of the following '%d' module(s):", moduleId, versionId, moduleReadyQueue.size() );
  579. // Iterate the modules echoing them.
  580. for ( typeModuleLoadEntryVector::iterator moduleReadyItr = moduleReadyQueue.begin(); moduleReadyItr != moduleReadyQueue.end(); ++moduleReadyItr )
  581. {
  582. // Fetch the ready entry.
  583. ModuleDefinition* pModuleDefinition = moduleReadyItr->mpModuleDefinition;
  584. // Info.
  585. Con::printf( "> module Id '%s' at version Id '%d'", pModuleDefinition->getModuleId(), pModuleDefinition->getVersionId() );
  586. }
  587. }
  588. // Reset modules loaded count.
  589. U32 modulesLoadedCount = 0;
  590. // Iterate the modules, executing their script files and call their create function.
  591. for ( typeModuleLoadEntryVector::iterator moduleReadyItr = moduleReadyQueue.begin(); moduleReadyItr != moduleReadyQueue.end(); ++moduleReadyItr )
  592. {
  593. // Fetch the ready entry.
  594. ModuleLoadEntry* pReadyEntry = moduleReadyItr;
  595. // Fetch load ready module definition.
  596. ModuleDefinition* pLoadReadyModuleDefinition = pReadyEntry->mpModuleDefinition;
  597. // Fetch any loaded entry for the module Id.
  598. ModuleLoadEntry* pLoadedEntry = findModuleLoaded( pLoadReadyModuleDefinition->getModuleId() );
  599. // Is the module already loaded.
  600. if ( pLoadedEntry != NULL )
  601. {
  602. // Yes, so increase load count.
  603. pLoadedEntry->mpModuleDefinition->increaseLoadCount();
  604. // Skip.
  605. continue;
  606. }
  607. // No, so info.
  608. if ( mEchoInfo )
  609. {
  610. Con::printSeparator();
  611. Con::printf( "Module Manager: Loading explicit module Id '%s' at version Id '%d' using the script file '%s'.",
  612. pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId(), pLoadReadyModuleDefinition->getModuleScriptFilePath() );
  613. }
  614. // Is the module deprecated?
  615. if ( pLoadReadyModuleDefinition->getDeprecated() )
  616. {
  617. // Yes, so warn.
  618. Con::warnf( "Module Manager: Caution: module Id '%s' at version Id '%d' is deprecated, You should use a newer version!",
  619. pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId() );
  620. }
  621. // Add the path expando for module.
  622. Con::addPathExpando( pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getModulePath() );
  623. // Create a scope set.
  624. SimSet* pScopeSet = new SimSet;
  625. pScopeSet->registerObject( pLoadReadyModuleDefinition->getModuleId() );
  626. pScopeSet->setClassNamespace("ModuleRoot");
  627. pReadyEntry->mpModuleDefinition->mScopeSet = pScopeSet->getId();
  628. // Increase load count.
  629. pReadyEntry->mpModuleDefinition->increaseLoadCount();
  630. // Queue module loaded.
  631. mModulesLoaded.push_back( *pReadyEntry );
  632. // Bump modules loaded count.
  633. modulesLoadedCount++;
  634. // Raise notifications.
  635. raiseModulePreLoadNotifications( pLoadReadyModuleDefinition );
  636. // Do we have a script file-path specified?
  637. if ( pLoadReadyModuleDefinition->getModuleScriptFilePath() != StringTable->EmptyString() )
  638. {
  639. // Yes, so execute the script file.
  640. ConsoleValue cValue = Con::executef("exec", pLoadReadyModuleDefinition->getModuleScriptFilePath());
  641. const bool scriptFileExecuted = cValue.getBool();
  642. // Did we execute the script file?
  643. if ( !scriptFileExecuted )
  644. {
  645. // No, so warn.
  646. Con::errorf( "Module Manager: Cannot load explicit module Id '%s' at version Id '%d' as it failed to have the script file '%s' loaded.",
  647. pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId(), pLoadReadyModuleDefinition->getModuleScriptFilePath() );
  648. }
  649. }
  650. // Is the create method available?
  651. if (pScopeSet->isMethod(pLoadReadyModuleDefinition->getCreateFunction()))
  652. {
  653. // Yes, so call the create method.
  654. Con::executef(pScopeSet, pLoadReadyModuleDefinition->getCreateFunction());
  655. }
  656. // Raise notifications.
  657. raiseModulePostLoadNotifications( pLoadReadyModuleDefinition );
  658. }
  659. // Info.
  660. if ( mEchoInfo )
  661. {
  662. Con::printSeparator();
  663. Con::printf( "Module Manager: Finish loading '%d' explicit module(s).", modulesLoadedCount );
  664. Con::printSeparator();
  665. }
  666. return true;
  667. }
  668. //-----------------------------------------------------------------------------
  669. bool ModuleManager::unloadModuleExplicit( const char* pModuleId )
  670. {
  671. // Lock database.
  672. LockDatabase( this );
  673. // Sanity!
  674. AssertFatal( pModuleId != NULL, "Cannot unload explicit module Id with NULL module Id." );
  675. typeModuleLoadEntryVector moduleResolvingQueue;
  676. typeModuleLoadEntryVector moduleReadyQueue;
  677. // Fetch module Id.
  678. StringTableEntry moduleId = StringTable->insert( pModuleId );
  679. // Fetch modules definitions.
  680. ModuleDefinitionEntry* pDefinitions = findModuleId( moduleId );
  681. // Did we find the module Id?
  682. if ( pDefinitions == NULL )
  683. {
  684. // No, so warn.
  685. Con::warnf( "Module Manager: Cannot unload explicit module Id '%s' as it does not exist.", moduleId );
  686. return false;
  687. }
  688. // Find if the module is actually loaded.
  689. ModuleDefinition* pLoadedModule = findLoadedModule( moduleId );
  690. // Is the module loaded?
  691. if ( pLoadedModule == NULL )
  692. {
  693. // No, so warn.
  694. Con::warnf( "Module Manager: Cannot unload explicit module Id '%s' as it is not loaded.", moduleId );
  695. return false;
  696. }
  697. // Fetch module group.
  698. StringTableEntry moduleGroup = pDefinitions->mModuleGroup;
  699. // Info.
  700. if ( mEchoInfo )
  701. {
  702. Con::printSeparator();
  703. Con::printf( "Module Manager: Unloading explicit module Id '%s':" , moduleId );
  704. }
  705. // Finish if we could not resolve the dependencies for module Id (of any version Id).
  706. if ( !resolveModuleDependencies( moduleId, pLoadedModule->getVersionId(), moduleGroup, false, moduleResolvingQueue, moduleReadyQueue ) )
  707. return false;
  708. // Check the modules we want to unload to ensure that we do not have incompatible modules loaded already.
  709. for ( typeModuleLoadEntryVector::iterator moduleReadyItr = moduleReadyQueue.begin(); moduleReadyItr != moduleReadyQueue.end(); ++moduleReadyItr )
  710. {
  711. // Fetch load ready module definition.
  712. ModuleDefinition* pLoadReadyModuleDefinition = moduleReadyItr->mpModuleDefinition;;
  713. // Fetch the module Id loaded entry.
  714. ModuleLoadEntry* pLoadedModuleEntry = findModuleLoaded( pLoadReadyModuleDefinition->getModuleId() );
  715. // Did we find a loaded entry?
  716. if ( pLoadedModuleEntry != NULL )
  717. {
  718. // Yes, so is it the one we need to load?
  719. if ( pLoadedModuleEntry->mpModuleDefinition != pLoadReadyModuleDefinition )
  720. {
  721. // Yes, so warn.
  722. Con::warnf( "Module Manager: Cannot unload explicit module Id '%s' at version Id '%d' as the module Id is loaded but at version Id '%d'.",
  723. pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId(), pLoadedModuleEntry->mpModuleDefinition->getVersionId() );
  724. return false;
  725. }
  726. }
  727. }
  728. // Reset modules unloaded count.
  729. U32 modulesUnloadedCount = 0;
  730. // Iterate the modules in reverse order calling their destroy function.
  731. for ( typeModuleLoadEntryVector::iterator moduleReadyItr = moduleReadyQueue.end()-1; moduleReadyItr >= moduleReadyQueue.begin(); --moduleReadyItr )
  732. {
  733. // Fetch the ready entry.
  734. ModuleLoadEntry* pReadyEntry = moduleReadyItr;
  735. // Fetch load ready module definition.
  736. ModuleDefinition* pLoadReadyModuleDefinition = pReadyEntry->mpModuleDefinition;;
  737. // Fetch any loaded entry for the module Id.
  738. ModuleLoadEntry* pLoadedEntry = findModuleLoaded( pLoadReadyModuleDefinition->getModuleId() );
  739. // Is the module loaded.
  740. if ( pLoadedEntry == NULL )
  741. {
  742. // No, so warn.
  743. if ( mEchoInfo )
  744. {
  745. Con::printf( "Module Manager: Unloading explicit module Id '%s' at version Id '%d' but ignoring as it is not loaded.",
  746. pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId() );
  747. }
  748. // Skip.
  749. continue;
  750. }
  751. // Reduce load count.
  752. pLoadedEntry->mpModuleDefinition->reduceLoadCount();
  753. // Sanity!
  754. AssertFatal( pLoadedEntry->mpModuleDefinition->getLoadCount() >= 0, "ModuleManager::unloadModuleGroup() - Encountered an invalid load count." );
  755. // Do we need to unload?
  756. if ( pLoadedEntry->mpModuleDefinition->getLoadCount() == 0 )
  757. {
  758. // Yes, so info.
  759. if ( mEchoInfo )
  760. {
  761. Con::printSeparator();
  762. Con::printf( "Module Manager: Unload explicit module Id '%s' at version Id '%d'.",
  763. pLoadReadyModuleDefinition->getModuleId(), pLoadReadyModuleDefinition->getVersionId() );
  764. }
  765. // Raise notifications.
  766. raiseModulePreUnloadNotifications( pLoadReadyModuleDefinition );
  767. // Fetch the module Id loaded entry.
  768. typeModuleLoadEntryVector::iterator moduleLoadedItr = findModuleLoaded( pLoadReadyModuleDefinition->getModuleId() );
  769. // Sanity!
  770. AssertFatal( moduleLoadedItr != NULL, "ModuleManager::unloadModuleExplicit() - Cannot find module to unload it." );
  771. // Dequeue module loaded.
  772. mModulesLoaded.erase_fast( moduleLoadedItr );
  773. // Fetch scope set.
  774. SimSet* pScopeSet = dynamic_cast<SimSet*>(Sim::findObject(pLoadReadyModuleDefinition->mScopeSet));
  775. // Is the destroy method available?
  776. if ( pScopeSet->isMethod( pLoadReadyModuleDefinition->getDestroyFunction() ) )
  777. {
  778. // Yes, so call the destroy method.
  779. Con::executef( pScopeSet, pLoadReadyModuleDefinition->getDestroyFunction() );
  780. }
  781. // Remove scope set.
  782. pScopeSet->deleteAllObjects();
  783. pScopeSet->unregisterObject();
  784. pLoadReadyModuleDefinition->mScopeSet = 0;
  785. // Remove path expando for module.
  786. Con::removePathExpando( pLoadReadyModuleDefinition->getModuleId() );
  787. // Bump modules unloaded count.
  788. modulesUnloadedCount++;
  789. // Raise notifications.
  790. raiseModulePostUnloadNotifications( pLoadReadyModuleDefinition );
  791. }
  792. }
  793. // Info.
  794. if ( mEchoInfo )
  795. {
  796. Con::printSeparator();
  797. Con::printf( "Module Manager: Finish unloading '%d' explicit module(s).", modulesUnloadedCount );
  798. Con::printSeparator();
  799. }
  800. return true;
  801. }
  802. //-----------------------------------------------------------------------------
  803. ModuleDefinition* ModuleManager::findModule( const char* pModuleId, const U32 versionId )
  804. {
  805. // Sanity!
  806. AssertFatal( pModuleId != NULL, "Cannot find module with NULL module Id." );
  807. // Find module definition.
  808. ModuleDefinitionEntry::iterator moduleItr = findModuleDefinition( StringTable->insert( pModuleId ), versionId );
  809. // Finish if module was not found.
  810. if ( moduleItr == NULL )
  811. return NULL;
  812. return *moduleItr;
  813. }
  814. //-----------------------------------------------------------------------------
  815. ModuleDefinition* ModuleManager::findModuleByFilePath(StringTableEntry filePath)
  816. {
  817. // Sanity!
  818. AssertFatal(filePath != StringTable->EmptyString(), "Cannot find module with an empty filePath.");
  819. String desiredPath = filePath;
  820. StringTableEntry coreModuleId = StringTable->insert("CoreModule");
  821. for (typeModuleIdDatabaseHash::iterator moduleIdItr = mModuleIdDatabase.begin(); moduleIdItr != mModuleIdDatabase.end(); ++moduleIdItr)
  822. {
  823. // Fetch module definition entry.
  824. ModuleDefinitionEntry* pModuleDefinitionEntry = moduleIdItr->value;
  825. for (typeModuleDefinitionVector::iterator moduleDefinitionItr = pModuleDefinitionEntry->begin(); moduleDefinitionItr != pModuleDefinitionEntry->end(); ++moduleDefinitionItr)
  826. {
  827. // Fetch module definition.
  828. ModuleDefinition* pModuleDefinition = *moduleDefinitionItr;
  829. Torque::Path modulePath = pModuleDefinition->getModulePath();
  830. StringTableEntry asdasd = StringTable->insert(modulePath.getFullPath());
  831. //We don't deal with CoreModule or ToolsModule having assets for now
  832. if (desiredPath.startsWith(asdasd) && pModuleDefinition->mModuleId != coreModuleId)
  833. {
  834. return pModuleDefinition;
  835. }
  836. }
  837. }
  838. return nullptr;
  839. }
  840. //-----------------------------------------------------------------------------
  841. ModuleDefinition* ModuleManager::findLoadedModule( const char* pModuleId )
  842. {
  843. // Sanity!
  844. AssertFatal( pModuleId != NULL, "Cannot find module with NULL module Id." );
  845. // Fetch module Id.
  846. StringTableEntry moduleId = StringTable->insert( pModuleId );
  847. // Iterate loaded modules.
  848. for ( typeModuleLoadEntryVector::iterator loadedModuleItr = mModulesLoaded.begin(); loadedModuleItr != mModulesLoaded.end(); ++loadedModuleItr )
  849. {
  850. // Skip if not the module.
  851. if ( loadedModuleItr->mpModuleDefinition->getModuleId() != moduleId )
  852. continue;
  853. return loadedModuleItr->mpModuleDefinition;
  854. }
  855. return NULL;
  856. }
  857. //-----------------------------------------------------------------------------
  858. void ModuleManager::findModules(const bool loadedOnly, typeModuleDefinitionVector& moduleDefinitions)
  859. {
  860. if (loadedOnly)
  861. {
  862. for (U32 i = 0; i < mModulesLoaded.size(); i++)
  863. {
  864. moduleDefinitions.push_back(mModulesLoaded[i].mpModuleDefinition);
  865. }
  866. }
  867. else
  868. {
  869. // Iterate module Ids.
  870. for (typeModuleIdDatabaseHash::iterator moduleIdItr = mModuleIdDatabase.begin(); moduleIdItr != mModuleIdDatabase.end(); ++moduleIdItr)
  871. {
  872. // Fetch module definition entry.
  873. ModuleDefinitionEntry* pModuleDefinitionEntry = moduleIdItr->value;
  874. // Iterate module definitions.
  875. for (typeModuleDefinitionVector::iterator moduleDefinitionItr = pModuleDefinitionEntry->begin(); moduleDefinitionItr != pModuleDefinitionEntry->end(); ++moduleDefinitionItr)
  876. {
  877. // Fetch module definition.
  878. ModuleDefinition* pModuleDefinition = *moduleDefinitionItr;
  879. // Are we searching for loaded modules only?
  880. if (loadedOnly)
  881. {
  882. // Yes, so skip if the module is not loaded.
  883. if (pModuleDefinition->getLoadCount() == 0)
  884. continue;
  885. // Use module definition.
  886. moduleDefinitions.push_back(pModuleDefinition);
  887. // Finish iterating module definitions as only a single module in this entry can be loaded concurrently.
  888. break;
  889. }
  890. // use module definition.
  891. moduleDefinitions.push_back(pModuleDefinition);
  892. }
  893. }
  894. moduleDefinitions.sort(&moduleDependencySort);
  895. }
  896. }
  897. //-----------------------------------------------------------------------------
  898. void ModuleManager::findModuleTypes( const char* pModuleType, const bool loadedOnly, typeConstModuleDefinitionVector& moduleDefinitions )
  899. {
  900. // Fetch module type.
  901. StringTableEntry moduleType = StringTable->insert( pModuleType );
  902. // Iterate module Ids.
  903. for( typeModuleIdDatabaseHash::iterator moduleIdItr = mModuleIdDatabase.begin(); moduleIdItr != mModuleIdDatabase.end(); ++moduleIdItr )
  904. {
  905. // Fetch module definition entry.
  906. ModuleDefinitionEntry* pModuleDefinitionEntry = moduleIdItr->value;
  907. // Skip if note the module type we're searching for.
  908. if ( pModuleDefinitionEntry->mModuleType != moduleType )
  909. continue;
  910. // Iterate module definitions.
  911. for ( typeModuleDefinitionVector::iterator moduleDefinitionItr = pModuleDefinitionEntry->begin(); moduleDefinitionItr != pModuleDefinitionEntry->end(); ++moduleDefinitionItr )
  912. {
  913. // Fetch module definition.
  914. ModuleDefinition* pModuleDefinition = *moduleDefinitionItr;
  915. // Are we searching for loaded modules only?
  916. if ( loadedOnly )
  917. {
  918. // Yes, so skip if the module is not loaded.
  919. if ( pModuleDefinition->getLoadCount() == 0 )
  920. continue;
  921. // Use module definition.
  922. moduleDefinitions.push_back( pModuleDefinition );
  923. // Finish iterating module definitions as only a single module in this entry can be loaded concurrently.
  924. break;
  925. }
  926. // use module definition.
  927. moduleDefinitions.push_back( pModuleDefinition );
  928. }
  929. }
  930. }
  931. //-----------------------------------------------------------------------------
  932. StringTableEntry ModuleManager::copyModule( ModuleDefinition* pSourceModuleDefinition, const char* pTargetModuleId, const char* pTargetPath, const bool useVersionPathing )
  933. {
  934. // Sanity!
  935. AssertFatal( pSourceModuleDefinition != NULL, "Cannot copy module using a NULL source module definition." );
  936. AssertFatal( pTargetModuleId != NULL, "Cannot copy module using a NULL target module Id." );
  937. AssertFatal( pTargetPath != NULL, "Cannot copy module using a NULL target path." );
  938. // Fetch the source module Id.
  939. StringTableEntry sourceModuleId = pSourceModuleDefinition->getModuleId();
  940. // Is the source module definition registered with this module manager?
  941. if ( pSourceModuleDefinition->getModuleManager() != this )
  942. {
  943. // No, so warn.
  944. Con::warnf("Module Manager: Cannot copy module Id '%s' as it is not registered with this module manager.", sourceModuleId );
  945. return StringTable->EmptyString();
  946. }
  947. // Fetch the target module Id.
  948. StringTableEntry targetModuleId = StringTable->insert( pTargetModuleId );
  949. // Extend moduleId/VersionId pathing.
  950. char versionPathBuffer[1024];
  951. // Are we using version pathing?
  952. if ( useVersionPathing )
  953. {
  954. // Yes, so format it.
  955. dSprintf( versionPathBuffer, sizeof(versionPathBuffer), "%s/%s/%d",
  956. pTargetPath, targetModuleId, pSourceModuleDefinition->getVersionId() );
  957. }
  958. else
  959. {
  960. // No, so a straight copy.
  961. dSprintf( versionPathBuffer, sizeof(versionPathBuffer), "%s", pTargetPath );
  962. }
  963. // Expand the path.
  964. char targetPathBuffer[1024];
  965. Con::expandPath( targetPathBuffer, sizeof(targetPathBuffer), versionPathBuffer );
  966. pTargetPath = targetPathBuffer;
  967. // Info.
  968. if ( mEchoInfo )
  969. {
  970. Con::printf( "Module Manager: Started copying module Id '%s' to target directory '%s'.", sourceModuleId, pTargetPath );
  971. }
  972. // Is the target folder a directory?
  973. if ( !Platform::isDirectory( pTargetPath ) )
  974. {
  975. // No, so we have to ensure that there is a trailing slash as that indicates a folder (not a file) when creating a path in the platform code.
  976. char createDirectoryBuffer[1024];
  977. Con::expandPath( createDirectoryBuffer, sizeof(createDirectoryBuffer), pTargetPath, NULL, true );
  978. // No, so can we create it?
  979. if ( !Platform::createPath( createDirectoryBuffer ) )
  980. {
  981. // No, so warn.
  982. Con::warnf("Module Manager: Cannot copy module Id '%s' using target directory '%s' as directory was not found and could not be created.",
  983. sourceModuleId, pTargetPath );
  984. return StringTable->EmptyString();
  985. }
  986. }
  987. // Copy the source module to the target folder.
  988. if ( !dPathCopy( pSourceModuleDefinition->getModulePath(), pTargetPath, false ) )
  989. {
  990. // Warn.
  991. Con::warnf("Module Manager: Cannot copy module Id '%s' using target directory '%s' as directory copy failed.",
  992. sourceModuleId, pTargetPath );
  993. return StringTable->EmptyString();
  994. }
  995. // Format the new source module definition file-path.
  996. char newModuleDefinitionSourceFileBuffer[1024];
  997. dSprintf( newModuleDefinitionSourceFileBuffer, sizeof(newModuleDefinitionSourceFileBuffer), "%s/%s", pTargetPath, pSourceModuleDefinition->getModuleFile() );
  998. // Finish if source/target module Ids are identical.
  999. if ( sourceModuleId == targetModuleId )
  1000. return StringTable->insert( newModuleDefinitionSourceFileBuffer );
  1001. // Format the new target module definition file-path.
  1002. char newModuleDefinitionTargetFileBuffer[1024];
  1003. dSprintf( newModuleDefinitionTargetFileBuffer, sizeof(newModuleDefinitionTargetFileBuffer), "%s/%s.%s", pTargetPath, targetModuleId, MODULE_MANAGER_MODULE_DEFINITION_EXTENSION );
  1004. // Rename the module definition.
  1005. if ( !dFileRename( newModuleDefinitionSourceFileBuffer, newModuleDefinitionTargetFileBuffer ) )
  1006. {
  1007. // Warn.
  1008. Con::warnf("Module Manager: Cannot copy module Id '%s' using target directory '%s' as renaming the module from '%s' to '%s' failed.",
  1009. sourceModuleId, pTargetPath, newModuleDefinitionSourceFileBuffer, newModuleDefinitionTargetFileBuffer );
  1010. return StringTable->EmptyString();
  1011. }
  1012. Vector<StringTableEntry> directories;
  1013. // Find directories.
  1014. if ( !Platform::dumpDirectories( pTargetPath, directories, -1 ) )
  1015. {
  1016. // Warn.
  1017. Con::warnf("Module Manager: Cannot copy module Id '%s' using target directory '%s' as sub-folder scanning/renaming failed.",
  1018. sourceModuleId, pTargetPath );
  1019. return StringTable->EmptyString();
  1020. }
  1021. TamlModuleIdUpdateVisitor moduleIdUpdateVisitor;
  1022. moduleIdUpdateVisitor.setModuleIdFrom( sourceModuleId );
  1023. moduleIdUpdateVisitor.setModuleIdTo( targetModuleId );
  1024. Vector<Platform::FileInfo> files;
  1025. const char* pExtension = (const char*)"Taml";
  1026. const U32 extensionLength = dStrlen(pExtension);
  1027. // Iterate directories.
  1028. for( Vector<StringTableEntry>::iterator basePathItr = directories.begin(); basePathItr != directories.end(); ++basePathItr )
  1029. {
  1030. // Fetch base path.
  1031. StringTableEntry basePath = *basePathItr;
  1032. // Find files.
  1033. files.clear();
  1034. if ( !Platform::dumpPath( basePath, files, 0 ) )
  1035. {
  1036. // Warn.
  1037. Con::warnf("Module Manager: Cannot copy module Id '%s' using target directory '%s' as sub-folder scanning/renaming failed.",
  1038. sourceModuleId, pTargetPath );
  1039. return StringTable->EmptyString();
  1040. }
  1041. // Iterate files.
  1042. for ( Vector<Platform::FileInfo>::iterator fileItr = files.begin(); fileItr != files.end(); ++fileItr )
  1043. {
  1044. // Fetch file info.
  1045. Platform::FileInfo* pFileInfo = fileItr;
  1046. // Fetch filename.
  1047. const char* pFilename = pFileInfo->pFileName;
  1048. // Find filename length.
  1049. const U32 filenameLength = dStrlen( pFilename );
  1050. // Skip if extension is longer than filename.
  1051. if ( extensionLength >= filenameLength )
  1052. continue;
  1053. // Skip if extension not found.
  1054. if ( dStricmp( pFilename + filenameLength - extensionLength, pExtension ) != 0 )
  1055. continue;
  1056. char parseFileBuffer[1024];
  1057. dSprintf( parseFileBuffer, sizeof(parseFileBuffer), "%s/%s", pFileInfo->pFullPath, pFilename );
  1058. // Parse file.
  1059. if ( !mTaml.parse( parseFileBuffer, moduleIdUpdateVisitor ) )
  1060. {
  1061. // Warn.
  1062. Con::warnf("Module Manager: Failed to parse file '%s' whilst copying module Id '%s' using target directory '%s'.",
  1063. parseFileBuffer, sourceModuleId, pTargetPath );
  1064. return StringTable->EmptyString();
  1065. }
  1066. }
  1067. }
  1068. // Info.
  1069. if ( mEchoInfo )
  1070. {
  1071. Con::printf( "Module Manager: Finished copying module Id '%s' to target directory '%s'.", sourceModuleId, pTargetPath );
  1072. }
  1073. return StringTable->insert( newModuleDefinitionTargetFileBuffer );
  1074. }
  1075. //-----------------------------------------------------------------------------
  1076. bool ModuleManager::renameModule(ModuleDefinition* pSourceModuleDefinition, const char* pNewModuleName)
  1077. {
  1078. // Sanity!
  1079. AssertFatal(pSourceModuleDefinition != NULL, "Cannot copy module using a NULL source module definition.");
  1080. AssertFatal(pNewModuleName != NULL, "Cannot rename a module using a NULL module name.");
  1081. // Fetch the source module Id.
  1082. StringTableEntry sourceModuleId = pSourceModuleDefinition->getModuleId();
  1083. // Is the source module definition registered with this module manager?
  1084. if (pSourceModuleDefinition->getModuleManager() != this)
  1085. {
  1086. // No, so warn.
  1087. Con::warnf("Module Manager: Cannot rename module Id '%s' as it is not registered with this module manager.", sourceModuleId);
  1088. return StringTable->EmptyString();
  1089. }
  1090. TamlModuleIdUpdateVisitor moduleIdUpdateVisitor;
  1091. moduleIdUpdateVisitor.setModuleIdFrom(sourceModuleId);
  1092. moduleIdUpdateVisitor.setModuleIdTo(pNewModuleName);
  1093. Vector<Platform::FileInfo> files;
  1094. const char* pExtension = (const char*)"Taml";
  1095. const U32 extensionLength = dStrlen(pExtension);
  1096. Vector<StringTableEntry> directories;
  1097. StringTableEntry modulePath = pSourceModuleDefinition->getModulePath();
  1098. // Find directories.
  1099. if (!Platform::dumpDirectories(modulePath, directories, -1))
  1100. {
  1101. // Warn.
  1102. Con::warnf("Module Manager: Cannot rename module Id '%s' in directory '%s' as sub-folder scanning/renaming failed.",
  1103. sourceModuleId, modulePath);
  1104. return false;
  1105. }
  1106. // Iterate directories.
  1107. for (Vector<StringTableEntry>::iterator basePathItr = directories.begin(); basePathItr != directories.end(); ++basePathItr)
  1108. {
  1109. // Fetch base path.
  1110. StringTableEntry basePath = *basePathItr;
  1111. // Find files.
  1112. files.clear();
  1113. if (!Platform::dumpPath(basePath, files, 0))
  1114. {
  1115. // Warn.
  1116. Con::warnf("Module Manager: Cannot rename module Id '%s' in directory '%s' as sub-folder scanning/renaming failed.",
  1117. sourceModuleId, modulePath);
  1118. return false;
  1119. }
  1120. // Iterate files.
  1121. for (Vector<Platform::FileInfo>::iterator fileItr = files.begin(); fileItr != files.end(); ++fileItr)
  1122. {
  1123. // Fetch file info.
  1124. Platform::FileInfo* pFileInfo = fileItr;
  1125. // Fetch filename.
  1126. const char* pFilename = pFileInfo->pFileName;
  1127. // Find filename length.
  1128. const U32 filenameLength = dStrlen(pFilename);
  1129. // Skip if extension is longer than filename.
  1130. if (extensionLength >= filenameLength)
  1131. continue;
  1132. // Skip if extension not found.
  1133. if (dStricmp(pFilename + filenameLength - extensionLength, pExtension) != 0)
  1134. continue;
  1135. char parseFileBuffer[1024];
  1136. dSprintf(parseFileBuffer, sizeof(parseFileBuffer), "%s/%s", pFileInfo->pFullPath, pFilename);
  1137. // Parse file.
  1138. if (!mTaml.parse(parseFileBuffer, moduleIdUpdateVisitor))
  1139. {
  1140. // Warn.
  1141. Con::warnf("Module Manager: Failed to parse file '%s' whilst renaming module Id '%s' in directory '%s'.",
  1142. parseFileBuffer, sourceModuleId, modulePath);
  1143. return false;
  1144. }
  1145. }
  1146. }
  1147. // Info.
  1148. if (mEchoInfo)
  1149. {
  1150. Con::printf("Module Manager: Finished renaming module Id '%s' to '%s'.", sourceModuleId, pNewModuleName);
  1151. }
  1152. return true;
  1153. }
  1154. //-----------------------------------------------------------------------------
  1155. bool ModuleManager::synchronizeDependencies( ModuleDefinition* pRootModuleDefinition, const char* pTargetDependencyPath )
  1156. {
  1157. // Sanity!
  1158. AssertFatal( pRootModuleDefinition != NULL, "Cannot synchronize dependencies with NULL root module definition." );
  1159. AssertFatal( pTargetDependencyPath != NULL, "Cannot synchronize dependencies with NULL target dependency path." );
  1160. // Fetch the root module Id.
  1161. StringTableEntry rootModuleId = pRootModuleDefinition->getModuleId();
  1162. // Is the root module definition registered with this module manager?
  1163. if ( pRootModuleDefinition->getModuleManager() != this )
  1164. {
  1165. // No, so warn.
  1166. Con::warnf("Cannot synchronize dependencies for module Id '%s' as it is not registered with this module manager.", rootModuleId );
  1167. return false;
  1168. }
  1169. // Expand the path.
  1170. char targetPathBuffer[1024];
  1171. Con::expandPath( targetPathBuffer, sizeof(targetPathBuffer), pTargetDependencyPath );
  1172. pTargetDependencyPath = targetPathBuffer;
  1173. // Is the target dependency folder a directory?
  1174. if ( !Platform::isDirectory( pTargetDependencyPath ) )
  1175. {
  1176. // No, so we have to ensure that there is a trailing slash as that indicates a folder (not a file) when creating a path in the platform code.
  1177. char createDirectoryBuffer[1024];
  1178. Con::expandPath( createDirectoryBuffer, sizeof(createDirectoryBuffer), pTargetDependencyPath, NULL, true );
  1179. // No, so can we create it?
  1180. if ( !Platform::createPath( createDirectoryBuffer ) )
  1181. {
  1182. // No, so warn.
  1183. Con::warnf("Cannot synchronize dependencies for module Id '%s' using target directory '%s' as directory was not found and could not be created.",
  1184. rootModuleId, pTargetDependencyPath );
  1185. return false;
  1186. }
  1187. }
  1188. typeModuleLoadEntryVector resolvingQueue;
  1189. typeModuleLoadEntryVector sourceModulesNeeded;
  1190. // Could we resolve source dependencies?
  1191. if ( !resolveModuleDependencies( rootModuleId, pRootModuleDefinition->getVersionId(), pRootModuleDefinition->getModuleGroup(), true, resolvingQueue, sourceModulesNeeded ) )
  1192. {
  1193. // No, so warn.
  1194. Con::warnf("Cannot synchronize dependencies for root module Id '%s' as its dependencies could not be resolved.", rootModuleId );
  1195. return false;
  1196. }
  1197. // Sanity!
  1198. AssertFatal( sourceModulesNeeded.size() > 0, "Cannot synchronize dependencies as no modules were returned." );
  1199. // Remove the root module definition.
  1200. sourceModulesNeeded.pop_back();
  1201. // Initialize the target module manager and scan the target folder for modules.
  1202. ModuleManager targetModuleManager;
  1203. targetModuleManager.mEnforceDependencies = true;
  1204. targetModuleManager.mEchoInfo = false;
  1205. targetModuleManager.scanModules( pTargetDependencyPath );
  1206. char targetFolderGenerateBuffer[1024];
  1207. // Iterate module definitions.
  1208. for ( typeModuleLoadEntryVector::iterator sourceModuleItr = sourceModulesNeeded.begin(); sourceModuleItr != sourceModulesNeeded.end(); ++sourceModuleItr )
  1209. {
  1210. // Fetch module definition.
  1211. ModuleDefinition* pSourceModuleDefinition = sourceModuleItr->mpModuleDefinition;
  1212. // Fetch the source module Id,
  1213. StringTableEntry sourceModuleId = pSourceModuleDefinition->getModuleId();
  1214. // Fetch the source module version Id.
  1215. const U32 sourceVersionId = pSourceModuleDefinition->getVersionId();
  1216. // Fetch the source module build Id.
  1217. const U32 sourceBuildId = pSourceModuleDefinition->getBuildId();
  1218. // Fetch module definition entry for this module Id in the target.
  1219. ModuleDefinitionEntry* pDefinitions = targetModuleManager.findModuleId( sourceModuleId );
  1220. // Is the module Id present in the target?
  1221. if ( pDefinitions == NULL )
  1222. {
  1223. // No, so format module Id folder path.
  1224. dSprintf( targetFolderGenerateBuffer, sizeof(targetFolderGenerateBuffer), "%s/%s/", pTargetDependencyPath, sourceModuleId );
  1225. // Create module Id folder.
  1226. if ( !Platform::createPath( targetFolderGenerateBuffer ) )
  1227. {
  1228. // Warn.
  1229. Con::warnf("Cannot synchronize dependencies for module Id '%s' as the target directory '%s' could not be created.", sourceModuleId, targetFolderGenerateBuffer );
  1230. return false;
  1231. }
  1232. }
  1233. else
  1234. {
  1235. // Yes, so fetch the module definition for this module Id and version Id in the target.
  1236. ModuleDefinitionEntry::iterator definitionItr = targetModuleManager.findModuleDefinition( sourceModuleId, sourceVersionId );
  1237. // Is the specific module definition present in the target?
  1238. if ( definitionItr != NULL )
  1239. {
  1240. // Yes, so fetch the module definition.
  1241. ModuleDefinition* pTargetModuleDefinition = *definitionItr;
  1242. // Fetch the target module build Id.
  1243. const U32 targetBuildId = pTargetModuleDefinition->getBuildId();
  1244. // Fetch the target module path.
  1245. StringTableEntry targetModulePath = pTargetModuleDefinition->getModulePath();
  1246. // Remove the target module definition from the database.
  1247. targetModuleManager.removeModuleDefinition( pTargetModuleDefinition );
  1248. // Skip if the target definition is the same build Id.
  1249. if ( targetBuildId == sourceBuildId )
  1250. continue;
  1251. // Delete the target module definition folder.
  1252. if ( !Platform::deleteDirectory( targetModulePath ) )
  1253. {
  1254. // Warn.
  1255. Con::warnf("Cannot synchronize dependencies for module Id '%s' at version Id '%d' as the old module at '%s' could not be deleted.",
  1256. sourceModuleId, sourceVersionId, targetModulePath );
  1257. return false;
  1258. }
  1259. }
  1260. }
  1261. // Format source module path.
  1262. char sourceFolderPath[1024];
  1263. Con::expandPath( sourceFolderPath, sizeof(sourceFolderPath), pSourceModuleDefinition->getModulePath() );
  1264. // Format target module path.
  1265. dSprintf( targetFolderGenerateBuffer, sizeof(targetFolderGenerateBuffer), "%s/%s/%d", pTargetDependencyPath, sourceModuleId, sourceVersionId );
  1266. // Copy the source module to the target folder.
  1267. if (!dPathCopy(sourceFolderPath, targetFolderGenerateBuffer, false))
  1268. {
  1269. // Warn.
  1270. Con::warnf("Cannot synchronize dependencies for module Id '%s' at version Id '%d' as the module could not be copied to '%s'.",
  1271. sourceModuleId, sourceVersionId, targetFolderGenerateBuffer );
  1272. return false;
  1273. }
  1274. }
  1275. // Find any target modules left, These are orphaned modules not depended upon by any other module.
  1276. typeModuleDefinitionVector orphanedTargetModules;
  1277. targetModuleManager.findModules( false, orphanedTargetModules );
  1278. // Iterate module definitions.
  1279. for ( typeConstModuleDefinitionVector::const_iterator moduleDefinitionItr = orphanedTargetModules.begin(); moduleDefinitionItr != orphanedTargetModules.end(); ++moduleDefinitionItr )
  1280. {
  1281. // Fetch orphaned module definition.
  1282. const ModuleDefinition* pOrphanedModuleDefinition = *moduleDefinitionItr;
  1283. // Delete the target module definition folder.
  1284. if ( !Platform::deleteDirectory( pOrphanedModuleDefinition->getModulePath() ) )
  1285. {
  1286. // Warn.
  1287. Con::warnf("Cannot delete orphaned module Id '%s' at version Id '%d' from '%s'.",
  1288. pOrphanedModuleDefinition->getModuleId(), pOrphanedModuleDefinition->getVersionId(), pOrphanedModuleDefinition->getModulePath() );
  1289. }
  1290. }
  1291. return true;
  1292. }
  1293. //-----------------------------------------------------------------------------
  1294. bool ModuleManager::canMergeModules( const char* pMergeSourcePath )
  1295. {
  1296. // Sanity!
  1297. AssertFatal( pMergeSourcePath != NULL, "Cannot check merge modules with NULL source path." );
  1298. // Expand the source path.
  1299. char sourcePathBuffer[1024];
  1300. Con::expandPath( sourcePathBuffer, sizeof(sourcePathBuffer), pMergeSourcePath );
  1301. pMergeSourcePath = sourcePathBuffer;
  1302. // Is the path a valid directory?
  1303. if ( !Platform::isDirectory( sourcePathBuffer ) )
  1304. {
  1305. // No, so warn.
  1306. Con::warnf( "Cannot check merge modules as path is invalid '%s'.", sourcePathBuffer );
  1307. return false;
  1308. }
  1309. // Initialize the source module manager and scan the source folder for modules.
  1310. ModuleManager mergeModuleManager;
  1311. mergeModuleManager.mEnforceDependencies = false;
  1312. mergeModuleManager.mEchoInfo = false;
  1313. mergeModuleManager.scanModules( pMergeSourcePath );
  1314. // Find all the merge modules.
  1315. typeModuleDefinitionVector mergeModules;
  1316. mergeModuleManager.findModules( false, mergeModules );
  1317. // Iterate found merge module definitions.
  1318. for ( typeConstModuleDefinitionVector::const_iterator mergeModuleItr = mergeModules.begin(); mergeModuleItr != mergeModules.end(); ++mergeModuleItr )
  1319. {
  1320. // Fetch module definition.
  1321. const ModuleDefinition* pMergeModuleDefinition = *mergeModuleItr;
  1322. // Fetch module Id.
  1323. StringTableEntry moduleId = pMergeModuleDefinition->getModuleId();
  1324. // Fetch version Id.
  1325. const U32 versionId = pMergeModuleDefinition->getVersionId();
  1326. // Fetch module group.
  1327. StringTableEntry moduleGroup = pMergeModuleDefinition->getModuleGroup();
  1328. // Cannot merge if module already exists.
  1329. if ( findModuleDefinition( moduleId, versionId ) != NULL )
  1330. return false;
  1331. // Cannot merge if module is part of a loaded group.
  1332. if ( findGroupLoaded( moduleGroup ) != NULL )
  1333. return false;
  1334. }
  1335. // Can merge modules.
  1336. return true;
  1337. }
  1338. //-----------------------------------------------------------------------------
  1339. bool ModuleManager::mergeModules( const char* pMergeTargetPath, const bool removeMergeDefinition, const bool registerNewModules )
  1340. {
  1341. // Sanity!
  1342. AssertFatal( pMergeTargetPath != NULL, "Cannot merge modules with a target path of NULL." );
  1343. // Is a module merge available?
  1344. if ( !isModuleMergeAvailable() )
  1345. {
  1346. // No, so warn.
  1347. Con::warnf( "Cannot merge modules as a module merge is not available." );
  1348. return false;
  1349. }
  1350. // Expand the target path.
  1351. char targetPathBuffer[1024];
  1352. Con::expandPath( targetPathBuffer, sizeof(targetPathBuffer), pMergeTargetPath );
  1353. pMergeTargetPath = targetPathBuffer;
  1354. // Fetch module merge file path.
  1355. StringTableEntry moduleMergeFilePath = getModuleMergeFilePath();
  1356. // Read module merge definition.
  1357. Taml taml;
  1358. ModuleMergeDefinition* pModuleMergeDefinition = taml.read<ModuleMergeDefinition>( moduleMergeFilePath );
  1359. // Do we have a module merge definition.
  1360. if ( pModuleMergeDefinition == NULL )
  1361. {
  1362. // No, so warn.
  1363. Con::warnf( "Cannot merge modules as the module merge definition file failed to load '%s'.", moduleMergeFilePath );
  1364. return false;
  1365. }
  1366. // Fetch the merge source path.
  1367. StringTableEntry mergeSourcePath = pModuleMergeDefinition->getModuleMergePath();
  1368. // Remove the module merge definition.
  1369. pModuleMergeDefinition->deleteObject();
  1370. pModuleMergeDefinition = NULL;
  1371. // If we cannot merge the modules then we only process modules flagged as critical merge.
  1372. const bool criticalMergeOnly = !canMergeModules( mergeSourcePath );
  1373. // Initialize the target module manager and scan the target folder for modules.
  1374. ModuleManager targetModuleManager;
  1375. targetModuleManager.mEnforceDependencies = false;
  1376. targetModuleManager.mEchoInfo = false;
  1377. targetModuleManager.scanModules( pMergeTargetPath );
  1378. // Initialize the source module manager and scan the source folder for modules.
  1379. ModuleManager sourceModuleManager;
  1380. sourceModuleManager.mEnforceDependencies = false;
  1381. sourceModuleManager.mEchoInfo = false;
  1382. sourceModuleManager.scanModules( mergeSourcePath );
  1383. // Find all the source modules.
  1384. typeModuleDefinitionVector sourceModules;
  1385. sourceModuleManager.findModules( false, sourceModules );
  1386. // Iterate found merge module definitions.
  1387. for ( typeConstModuleDefinitionVector::const_iterator sourceModuleItr = sourceModules.begin(); sourceModuleItr != sourceModules.end(); ++sourceModuleItr )
  1388. {
  1389. // Fetch the source module definition.
  1390. const ModuleDefinition* pSourceModuleDefinition = *sourceModuleItr;
  1391. // Skip if we're performing a critical merge only and the module is not flagged as critical merge.
  1392. if ( criticalMergeOnly && pSourceModuleDefinition->getCriticalMerge() )
  1393. continue;
  1394. // Fetch source module Id.
  1395. const StringTableEntry sourceModuleId = pSourceModuleDefinition->getModuleId();
  1396. // Fetch source version Id.
  1397. const U32 sourceVersionId = pSourceModuleDefinition->getVersionId();
  1398. // Fetch source build Id.
  1399. const U32 sourceBuildId = pSourceModuleDefinition->getBuildId();
  1400. // Format module Id folder path.
  1401. char targetModuleIdBuffer[1024];
  1402. dSprintf( targetModuleIdBuffer, sizeof(targetModuleIdBuffer), "%s/%s/", pMergeTargetPath, sourceModuleId );
  1403. // Flag to indicate if the merged module needs registering.
  1404. bool shouldRegisterModule;
  1405. // Does the module Id exist?
  1406. if ( targetModuleManager.findModuleId( sourceModuleId ) == NULL )
  1407. {
  1408. // No, so create module Id folder.
  1409. if ( !Platform::createPath( targetModuleIdBuffer ) )
  1410. {
  1411. // Warn.
  1412. Con::warnf("Cannot merge modules for module '%s' as the path '%s' could not be created.", sourceModuleId, targetModuleIdBuffer );
  1413. return false;
  1414. }
  1415. // Module Should be registered.
  1416. shouldRegisterModule = true;
  1417. }
  1418. else
  1419. {
  1420. // Yes, so find the target module definition that matches the source module definition.
  1421. ModuleDefinitionEntry::iterator targetModuleDefinitionItr = targetModuleManager.findModuleDefinition( sourceModuleId, sourceVersionId );
  1422. // Is there an existing target module definition entry?
  1423. if ( targetModuleDefinitionItr != NULL )
  1424. {
  1425. // Yes, so fetch the target module definition.
  1426. const ModuleDefinition* pTargetModuleDefinition = *targetModuleDefinitionItr;
  1427. // Fetch target module path.
  1428. StringTableEntry targetModulePath = pTargetModuleDefinition->getModulePath();
  1429. // Yes, so we have to remove it first.
  1430. if ( !Platform::deleteDirectory( targetModulePath ) )
  1431. {
  1432. // Module was not deleted so warn.
  1433. Con::warnf( "Failed to remove module folder located at '%s'. Module will be copied over.", targetModulePath );
  1434. }
  1435. // Is the build Id being downgraded?
  1436. if ( sourceBuildId < pTargetModuleDefinition->getBuildId() )
  1437. {
  1438. // Yes, so warn.
  1439. Con::warnf( "Encountered a downgraded build Id for module Id '%s' at version Id '%d'.", sourceModuleId, sourceBuildId );
  1440. }
  1441. // Module should not be registered.
  1442. shouldRegisterModule = false;
  1443. }
  1444. else
  1445. {
  1446. // Module Should be registered.
  1447. shouldRegisterModule = true;
  1448. }
  1449. }
  1450. // Fetch source module path.
  1451. StringTableEntry sourceModulePath = pSourceModuleDefinition->getModulePath();
  1452. // Format target version Id folder path.
  1453. char targetVersionIdBuffer[1024];
  1454. dSprintf( targetVersionIdBuffer, sizeof(targetVersionIdBuffer), "%s%d", targetModuleIdBuffer, sourceVersionId );
  1455. // Copy module (allow overwrites as we may have failed to remove the old folder in which case this is likely to fail as well).
  1456. if (!dPathCopy(sourceModulePath, targetVersionIdBuffer, false))
  1457. {
  1458. // Failed to copy module.
  1459. Con::warnf( "Failed to copy module folder located at '%s' to location '%s'. The modules may now be corrupted.", sourceModulePath, targetVersionIdBuffer );
  1460. }
  1461. // Are we registering new modules and the module needs registering?
  1462. if ( registerNewModules && shouldRegisterModule )
  1463. {
  1464. // Yes, so scan module.
  1465. scanModules( targetVersionIdBuffer, true );
  1466. }
  1467. // Is the module part of a critical merge?
  1468. if ( criticalMergeOnly )
  1469. {
  1470. // Yes, so we need to remove the source module definition.
  1471. if ( !Platform::deleteDirectory( sourceModulePath ) )
  1472. {
  1473. // Module was not deleted so warn.
  1474. Con::warnf( "Failed to remove CRITICAL merge module folder located at '%s'. Module will be copied over.", sourceModulePath );
  1475. }
  1476. }
  1477. }
  1478. // Do we need to remove the module merge definition file?
  1479. if ( removeMergeDefinition )
  1480. {
  1481. // Yes, so remove it.
  1482. dFileDelete( moduleMergeFilePath );
  1483. }
  1484. return true;
  1485. }
  1486. //-----------------------------------------------------------------------------
  1487. void ModuleManager::addListener( SimObject* pListener )
  1488. {
  1489. // Sanity!
  1490. AssertFatal( pListener != NULL, "Cannot add notifications to a NULL object." );
  1491. // Ignore if already added.
  1492. if (mNotificationListeners.find( pListener) != mNotificationListeners.end())
  1493. return;
  1494. // Add as a listener.
  1495. mNotificationListeners.addObject( pListener );
  1496. }
  1497. //-----------------------------------------------------------------------------
  1498. void ModuleManager::removeListener( SimObject* pListener )
  1499. {
  1500. // Sanity!
  1501. AssertFatal( pListener != NULL, "Cannot remove notifications from a NULL object." );
  1502. // Remove as a listener.
  1503. mNotificationListeners.removeObject( pListener );
  1504. }
  1505. //-----------------------------------------------------------------------------
  1506. void ModuleManager::clearDatabase( void )
  1507. {
  1508. // Lock database.
  1509. AssertFatal( mDatabaseLocks == 0, "Cannot clear database if database is locked." );
  1510. // Iterate groups loaded.
  1511. while ( mGroupsLoaded.size() > 0 )
  1512. {
  1513. // Unload module group.
  1514. unloadModuleGroup( *mGroupsLoaded.begin() );
  1515. }
  1516. // Iterate any other explicit modules that are loaded.
  1517. while ( mModulesLoaded.size() > 0 )
  1518. {
  1519. // Fetch module definition.
  1520. ModuleDefinition* pModuleDefinition = mModulesLoaded.begin()->mpModuleDefinition;
  1521. // Unload explicit module.
  1522. unloadModuleExplicit( pModuleDefinition->getModuleId() );
  1523. }
  1524. // Iterate modules to delete module definitions.
  1525. for ( typeModuleIdDatabaseHash::iterator moduleItr = mModuleIdDatabase.begin(); moduleItr != mModuleIdDatabase.end(); ++moduleItr )
  1526. {
  1527. // Fetch modules definitions.
  1528. ModuleDefinitionEntry* pDefinitions = moduleItr->value;
  1529. // Iterate module definitions.
  1530. for ( ModuleDefinitionEntry::iterator definitionItr = pDefinitions->begin(); definitionItr != pDefinitions->end(); ++definitionItr )
  1531. {
  1532. // Fetch module definition.
  1533. ModuleDefinition* pModuleDefinition = *definitionItr;
  1534. // Remove notification before we delete it.
  1535. clearNotify( pModuleDefinition );
  1536. // Delete module definition.
  1537. pModuleDefinition->deleteObject();
  1538. }
  1539. // Clear definitions.
  1540. delete pDefinitions;
  1541. }
  1542. // Clear database.
  1543. mModuleIdDatabase.clear();
  1544. // Iterate module groups.
  1545. for ( typeGroupModuleHash::iterator moduleGroupItr = mGroupModules.begin(); moduleGroupItr != mGroupModules.end(); ++moduleGroupItr )
  1546. {
  1547. // Delete module group vector.
  1548. delete moduleGroupItr->value;
  1549. }
  1550. // Clear module groups.
  1551. mGroupModules.clear();
  1552. }
  1553. //-----------------------------------------------------------------------------
  1554. bool ModuleManager::removeModuleDefinition( ModuleDefinition* pModuleDefinition )
  1555. {
  1556. // Sanity!
  1557. AssertFatal( pModuleDefinition != NULL, "Cannot remove module definition if it is NULL." );
  1558. // Fetch module Id.
  1559. StringTableEntry moduleId = pModuleDefinition->getModuleId();
  1560. // Is the module definition registered with this module manager?
  1561. if ( pModuleDefinition->getModuleManager() != this )
  1562. {
  1563. // No, so warn.
  1564. Con::warnf("Cannot remove module definition '%s' as it is not registered with this module manager.", moduleId );
  1565. return false;
  1566. }
  1567. // Is the module definition loaded?
  1568. if ( pModuleDefinition->getLoadCount() > 0 )
  1569. {
  1570. // No, so warn.
  1571. Con::warnf("Cannot remove module definition '%s' as it is loaded.", moduleId );
  1572. return false;
  1573. }
  1574. // Find module Id.
  1575. typeModuleIdDatabaseHash::iterator moduleItr = mModuleIdDatabase.find( moduleId );
  1576. // Sanity!
  1577. AssertFatal( moduleItr != mModuleIdDatabase.end(), "Failed to find module definition." );
  1578. // Fetch modules definitions.
  1579. ModuleDefinitionEntry* pDefinitions = moduleItr->value;
  1580. // Fetch version Id.
  1581. const U32 versionId = pModuleDefinition->getVersionId();
  1582. // Iterate module definitions.
  1583. for ( ModuleDefinitionEntry::iterator definitionItr = pDefinitions->begin(); definitionItr != pDefinitions->end(); ++definitionItr )
  1584. {
  1585. // Skip if this isn't the version Id we're searching for.
  1586. if ( versionId != (*definitionItr)->getVersionId() )
  1587. continue;
  1588. // Remove definition entry.
  1589. pDefinitions->erase( definitionItr );
  1590. // Remove notification before we delete it.
  1591. clearNotify( pModuleDefinition );
  1592. // Delete module definition.
  1593. pModuleDefinition->deleteObject();
  1594. // Are there any modules left for this module Id?
  1595. if ( findModuleId( moduleId ) == NULL )
  1596. {
  1597. bool moduleIdFound = false;
  1598. // No, so remove from groups.
  1599. for( typeGroupModuleHash::iterator moduleGroupItr = mGroupModules.begin(); moduleGroupItr != mGroupModules.end(); ++moduleGroupItr )
  1600. {
  1601. // Fetch module Ids.
  1602. typeModuleIdVector* pModuleIds = moduleGroupItr->value;
  1603. // Iterate module Id.
  1604. for( typeModuleIdVector::iterator moduleIdItr = pModuleIds->begin(); moduleIdItr != pModuleIds->end(); ++moduleIdItr )
  1605. {
  1606. // Skip if this isn't the Id.
  1607. if ( *moduleIdItr != moduleId )
  1608. continue;
  1609. // Remove the module Id.
  1610. pModuleIds->erase( moduleIdItr );
  1611. // Flag as found.
  1612. moduleIdFound = true;
  1613. break;
  1614. }
  1615. // Finish if found.
  1616. if ( moduleIdFound )
  1617. break;
  1618. }
  1619. }
  1620. return true;
  1621. }
  1622. // Sanity!
  1623. AssertFatal( false, "Failed to find module definition." );
  1624. return false;
  1625. }
  1626. //-----------------------------------------------------------------------------
  1627. bool ModuleManager::registerModule( const char* pModulePath, const char* pModuleFile )
  1628. {
  1629. // Sanity!
  1630. AssertFatal( pModulePath != NULL, "Cannot scan module with NULL module path." );
  1631. AssertFatal( pModuleFile != NULL, "Cannot scan module with NULL module file." );
  1632. char formatBuffer[1024];
  1633. // Fetch module path trail character.
  1634. char modulePathTrail = pModulePath[dStrlen(pModulePath) - 1];
  1635. // Format module file-path.
  1636. dSprintf( formatBuffer, sizeof(formatBuffer), modulePathTrail == '/' ? "%s%s" : "%s/%s", pModulePath, pModuleFile );
  1637. // Read the module file.
  1638. ModuleDefinition* pModuleDefinition = mTaml.read<ModuleDefinition>( formatBuffer );
  1639. // Did we read a module definition?
  1640. if ( pModuleDefinition == NULL )
  1641. {
  1642. // No, so warn.
  1643. Con::warnf( "Module Manager: Failed to read module definition in file '%s'.", formatBuffer );
  1644. return false;
  1645. }
  1646. // Set the module manager.
  1647. pModuleDefinition->setModuleManager( this );
  1648. // Set module definition path.
  1649. pModuleDefinition->setModulePath( pModulePath );
  1650. // Set module file.
  1651. pModuleDefinition->setModuleFile( pModuleFile );
  1652. // Set module file-path.
  1653. pModuleDefinition->setModuleFilePath( formatBuffer );
  1654. // Fetch module Id.
  1655. StringTableEntry moduleId = pModuleDefinition->getModuleId();
  1656. // Fetch module version Id.
  1657. const U32 versionId = pModuleDefinition->getVersionId();
  1658. // Fetch module group.
  1659. StringTableEntry moduleGroup = pModuleDefinition->getModuleGroup();
  1660. // Fetch module type.
  1661. StringTableEntry moduleType = pModuleDefinition->getModuleType();
  1662. // Is the module enabled?
  1663. if ( !pModuleDefinition->getEnabled() )
  1664. {
  1665. // No, so warn.
  1666. Con::warnf( "Module Manager: Found module: '%s' but it is disabled.", pModuleDefinition->getModuleFilePath() );
  1667. // Destroy module definition and finish.
  1668. pModuleDefinition->deleteObject();
  1669. return false;
  1670. }
  1671. // Is the module Id valid?
  1672. if (moduleId == StringTable->EmptyString())
  1673. {
  1674. // No, so warn.
  1675. Con::warnf( "Module Manager: Found module: '%s' but it has an unspecified module Id.",
  1676. pModuleDefinition->getModuleFilePath() );
  1677. // Destroy module definition and finish.
  1678. pModuleDefinition->deleteObject();
  1679. return false;
  1680. }
  1681. // Is the module version Id valid?
  1682. if ( versionId == 0 )
  1683. {
  1684. // No, so warn.
  1685. Con::warnf( "Module Manager: Found Manager: Registering module: '%s' but it has an invalid Version Id of '0'.",
  1686. pModuleDefinition->getModuleFilePath() );
  1687. // Destroy module definition and finish.
  1688. pModuleDefinition->deleteObject();
  1689. return false;
  1690. }
  1691. // Is the module group already loaded?
  1692. if ( findGroupLoaded( moduleGroup ) != NULL && !mIgnoreLoadedGroups)
  1693. {
  1694. // Yes, so warn.
  1695. Con::warnf( "Module Manager: Found module: '%s' but it is in a module group '%s' which has already been loaded.",
  1696. pModuleDefinition->getModuleFilePath(),
  1697. moduleGroup );
  1698. // Destroy module definition and finish.
  1699. pModuleDefinition->deleteObject();
  1700. return false;
  1701. }
  1702. // Was a script-file specified?
  1703. if ( pModuleDefinition->getScriptFile() != StringTable->EmptyString() )
  1704. {
  1705. // Yes, so format module script file-path.
  1706. dSprintf( formatBuffer, sizeof(formatBuffer), modulePathTrail == '/' ? "%s%s" : "%s/%s", pModulePath, pModuleDefinition->getScriptFile() );
  1707. pModuleDefinition->setModuleScriptFilePath( formatBuffer );
  1708. }
  1709. // Format module signature,
  1710. dSprintf( formatBuffer, sizeof(formatBuffer), "%s_%d_%d", moduleId, versionId, pModuleDefinition->getBuildId() );
  1711. pModuleDefinition->setSignature( formatBuffer );
  1712. // Locked the module definition.
  1713. pModuleDefinition->setModuleLocked( true );
  1714. // Fetch modules definitions.
  1715. ModuleDefinitionEntry* pDefinitions = findModuleId( moduleId );
  1716. // Did we find the module Id?
  1717. if ( pDefinitions != NULL )
  1718. {
  1719. // Yes, so find the module definition.
  1720. ModuleDefinitionEntry::iterator definitionItr = findModuleDefinition( moduleId, versionId );
  1721. // Does this version Id already exist?
  1722. if ( definitionItr != NULL )
  1723. {
  1724. // Yes, so warn.
  1725. Con::warnf( "Module Manager: Found module: '%s' but it is already registered as module Id '%s' at version Id '%d'.",
  1726. pModuleDefinition->getModuleFilePath(), moduleId, versionId );
  1727. // Destroy module definition and finish.
  1728. pModuleDefinition->deleteObject();
  1729. return false;
  1730. }
  1731. // Is the module group the same as the module definitions we already have?
  1732. if ( moduleGroup != pDefinitions->mModuleGroup )
  1733. {
  1734. // No, so warn.
  1735. Con::warnf( "Module Manager: Found module: '%s' but its module group '%s' is not the same as other module definitions of the same module Id.",
  1736. pModuleDefinition->getModuleFilePath(), moduleGroup );
  1737. // Destroy module definition and finish.
  1738. pModuleDefinition->deleteObject();
  1739. return false;
  1740. }
  1741. // Is the module type the same as the module definitions we already have?
  1742. if ( moduleType != pDefinitions->mModuleType )
  1743. {
  1744. // No, so warn.
  1745. Con::warnf( "Module Manager: Found module: '%s' but its module type '%s' is not the same as other module definitions of the same module Id.",
  1746. pModuleDefinition->getModuleFilePath(), moduleGroup );
  1747. // Destroy module definition and finish.
  1748. pModuleDefinition->deleteObject();
  1749. return false;
  1750. }
  1751. }
  1752. else
  1753. {
  1754. // No, so create a vector of definitions.
  1755. pDefinitions = new ModuleDefinitionEntry( moduleId, moduleGroup, moduleType );
  1756. // Insert module Id definitions.
  1757. mModuleIdDatabase.insert( moduleId, pDefinitions );
  1758. }
  1759. // Add module definition.
  1760. pDefinitions->push_back( pModuleDefinition );
  1761. // Sort module definitions by version Id so that higher versions appear first.
  1762. dQsort( pDefinitions->address(), pDefinitions->size(), sizeof(ModuleDefinition*), moduleDefinitionVersionIdSort );
  1763. // Find module group.
  1764. typeGroupModuleHash::iterator moduleGroupItr = mGroupModules.find( moduleGroup );
  1765. // Did we find the module group?
  1766. if ( moduleGroupItr != mGroupModules.end() )
  1767. {
  1768. // Yes, so fetch module Ids.
  1769. typeModuleIdVector* pModuleIds = moduleGroupItr->value;
  1770. // Is the module Id already present?
  1771. bool moduleIdFound = false;
  1772. for( typeModuleIdVector::iterator moduleIdItr = pModuleIds->begin(); moduleIdItr != pModuleIds->end(); ++moduleIdItr )
  1773. {
  1774. // Skip if this isn't the Id.
  1775. if ( *moduleIdItr != moduleId )
  1776. continue;
  1777. // Flag as found.
  1778. moduleIdFound = true;
  1779. break;
  1780. }
  1781. // Add if module Id was not found.
  1782. if ( !moduleIdFound )
  1783. pModuleIds->push_back( moduleId );
  1784. }
  1785. else
  1786. {
  1787. // No, so insert a module Id vector.
  1788. moduleGroupItr = mGroupModules.insert( pModuleDefinition->getModuleGroup(), new typeModuleIdVector() );
  1789. // Add module Id.
  1790. moduleGroupItr->value->push_back( moduleId );
  1791. }
  1792. // Notify if the module definition is destroyed.
  1793. deleteNotify( pModuleDefinition );
  1794. // Info.
  1795. if ( mEchoInfo )
  1796. {
  1797. #if 1
  1798. Con::printf( "Module Manager: Registering: '%s' [ ID='%s', VersionId='%d', BuildId='%d', Description='%s' ].",
  1799. pModuleDefinition->getModuleFilePath(),
  1800. pModuleDefinition->getModuleId(),
  1801. pModuleDefinition->getVersionId(),
  1802. pModuleDefinition->getBuildId(),
  1803. pModuleDefinition->getModuleDescription()
  1804. );
  1805. #else
  1806. Con::printf( "Module Manager: Registering: '%s' [ ID='%s', VersionId='%d', BuildId='%d', Description='%s', Group='%s', Dependencies='%s', ScriptFile='%s', CreateFunction='%s', DestroyFunction='%s' ].",
  1807. pModuleDefinition->getModuleFilePath(),
  1808. pModuleDefinition->getModuleId(),
  1809. pModuleDefinition->getVersionId(),
  1810. pModuleDefinition->getBuildId(),
  1811. pModuleDefinition->getModuleDescription(),
  1812. pModuleDefinition->getModuleGroup(),
  1813. pModuleDefinition->getDataField( StringTable->insert("Dependencies"), NULL ),
  1814. pModuleDefinition->getScriptFile(),
  1815. pModuleDefinition->getCreateFunction(),
  1816. pModuleDefinition->getDestroyFunction()
  1817. );
  1818. #endif
  1819. }
  1820. // Emit notifications.
  1821. for( SimSet::iterator notifyItr = mNotificationListeners.begin(); notifyItr != mNotificationListeners.end(); ++notifyItr )
  1822. {
  1823. Con::executef( *notifyItr, "onModuleRegister", pModuleDefinition->getIdString() );
  1824. }
  1825. return true;
  1826. }
  1827. //-----------------------------------------------------------------------------
  1828. bool ModuleManager::unregisterModule( const char* pModuleId, const U32 versionId )
  1829. {
  1830. // Sanity!
  1831. AssertFatal( pModuleId != NULL, "A module Id cannot be NULL." );
  1832. // Fetch module Id.
  1833. StringTableEntry moduleId = StringTable->insert( pModuleId );
  1834. // Find the module definition.
  1835. ModuleDefinition* pModuleDefinition = findModule( pModuleId, versionId );
  1836. // Did we find the module definition?
  1837. if ( pModuleDefinition == NULL )
  1838. {
  1839. // No, so warn.
  1840. Con::warnf( "Module Manager: Cannot unregister module Id '%s' as it is not registered.", moduleId );
  1841. return false;
  1842. }
  1843. // Remove the module definition.
  1844. return removeModuleDefinition( pModuleDefinition );
  1845. }
  1846. //-----------------------------------------------------------------------------
  1847. void ModuleManager::raiseModulePreLoadNotifications( ModuleDefinition* pModuleDefinition )
  1848. {
  1849. // Raise notifications.
  1850. for( SimSet::iterator notifyItr = mNotificationListeners.begin(); notifyItr != mNotificationListeners.end(); ++notifyItr )
  1851. {
  1852. // Fetch listener object.
  1853. SimObject* pListener = *notifyItr;
  1854. // Perform object callback.
  1855. ModuleCallbacks* pCallbacks = dynamic_cast<ModuleCallbacks*>( pListener );
  1856. if ( pCallbacks != NULL )
  1857. pCallbacks->onModulePreLoad( pModuleDefinition );
  1858. // Perform script callback.
  1859. if ( pListener->isMethod( "onModulePreLoad" ) )
  1860. Con::executef( pListener, "onModulePreLoad", pModuleDefinition->getIdString() );
  1861. }
  1862. }
  1863. //-----------------------------------------------------------------------------
  1864. void ModuleManager::raiseModulePostLoadNotifications( ModuleDefinition* pModuleDefinition )
  1865. {
  1866. // Raise notifications.
  1867. for( SimSet::iterator notifyItr = mNotificationListeners.begin(); notifyItr != mNotificationListeners.end(); ++notifyItr )
  1868. {
  1869. // Fetch listener object.
  1870. SimObject* pListener = *notifyItr;
  1871. // Perform object callback.
  1872. ModuleCallbacks* pCallbacks = dynamic_cast<ModuleCallbacks*>( pListener );
  1873. if ( pCallbacks != NULL )
  1874. pCallbacks->onModulePostLoad( pModuleDefinition );
  1875. // Perform script callback.
  1876. if ( pListener->isMethod( "onModulePostLoad" ) )
  1877. Con::executef( pListener, "onModulePostLoad", pModuleDefinition->getIdString() );
  1878. }
  1879. }
  1880. //-----------------------------------------------------------------------------
  1881. void ModuleManager::raiseModulePreUnloadNotifications( ModuleDefinition* pModuleDefinition )
  1882. {
  1883. // Raise notifications.
  1884. for( SimSet::iterator notifyItr = mNotificationListeners.begin(); notifyItr != mNotificationListeners.end(); ++notifyItr )
  1885. {
  1886. // Fetch listener object.
  1887. SimObject* pListener = *notifyItr;
  1888. // Perform object callback.
  1889. ModuleCallbacks* pCallbacks = dynamic_cast<ModuleCallbacks*>( pListener );
  1890. if ( pCallbacks != NULL )
  1891. pCallbacks->onModulePreUnload( pModuleDefinition );
  1892. // Perform script callback.
  1893. if ( pListener->isMethod( "onModulePreUnload" ) )
  1894. Con::executef( pListener, "onModulePreUnload", pModuleDefinition->getIdString() );
  1895. }
  1896. }
  1897. //-----------------------------------------------------------------------------
  1898. void ModuleManager::raiseModulePostUnloadNotifications( ModuleDefinition* pModuleDefinition )
  1899. {
  1900. // Raise notifications.
  1901. for( SimSet::iterator notifyItr = mNotificationListeners.begin(); notifyItr != mNotificationListeners.end(); ++notifyItr )
  1902. {
  1903. // Fetch listener object.
  1904. SimObject* pListener = *notifyItr;
  1905. // Perform object callback.
  1906. ModuleCallbacks* pCallbacks = dynamic_cast<ModuleCallbacks*>( pListener );
  1907. if ( pCallbacks != NULL )
  1908. pCallbacks->onModulePostUnload( pModuleDefinition );
  1909. // Perform script callback.
  1910. if ( pListener->isMethod( "onModulePostUnload" ) )
  1911. Con::executef( pListener, "onModulePostUnload", pModuleDefinition->getIdString() );
  1912. }
  1913. }
  1914. //-----------------------------------------------------------------------------
  1915. ModuleManager::ModuleDefinitionEntry* ModuleManager::findModuleId( StringTableEntry moduleId )
  1916. {
  1917. // Sanity!
  1918. AssertFatal( moduleId != NULL, "A module Id cannot be NULL." );
  1919. // Is the module Id valid?
  1920. if ( moduleId == StringTable->EmptyString() )
  1921. {
  1922. // No, so warn.
  1923. Con::warnf( "Module Manager: Invalid Module Id." );
  1924. return NULL;
  1925. }
  1926. // Find module Id.
  1927. typeModuleIdDatabaseHash::iterator moduleItr = mModuleIdDatabase.find( moduleId );
  1928. // Return appropriately.
  1929. return moduleItr != mModuleIdDatabase.end() ? moduleItr->value : NULL;
  1930. }
  1931. //-----------------------------------------------------------------------------
  1932. ModuleManager::ModuleDefinitionEntry::iterator ModuleManager::findModuleDefinition( StringTableEntry moduleId, const U32 versionId )
  1933. {
  1934. // Fetch modules definitions.
  1935. ModuleDefinitionEntry* pDefinitions = findModuleId( moduleId );
  1936. // Finish if no module definitions for the module Id.
  1937. if ( pDefinitions == NULL )
  1938. return NULL;
  1939. // Iterate module definitions.
  1940. for ( ModuleDefinitionEntry::iterator definitionItr = pDefinitions->begin(); definitionItr != pDefinitions->end(); ++definitionItr )
  1941. {
  1942. // Skip if this isn't the version Id we're searching for.
  1943. if ( versionId != (*definitionItr)->getVersionId() )
  1944. continue;
  1945. // Return module definition iterator.
  1946. return definitionItr;
  1947. }
  1948. // Not found.
  1949. return NULL;
  1950. }
  1951. //-----------------------------------------------------------------------------
  1952. bool ModuleManager::resolveModuleDependencies( StringTableEntry moduleId, const U32 versionId, StringTableEntry moduleGroup, bool synchronizedOnly, typeModuleLoadEntryVector& moduleResolvingQueue, typeModuleLoadEntryVector& moduleReadyQueue )
  1953. {
  1954. // Fetch the module Id ready entry.
  1955. ModuleLoadEntry* pLoadReadyEntry = findModuleReady( moduleId, moduleReadyQueue );
  1956. // Is there a load entry?
  1957. if ( pLoadReadyEntry )
  1958. {
  1959. // Yes, so finish if the version Id is not important,
  1960. if ( versionId == 0 )
  1961. return true;
  1962. // Finish if the version Id are compatible.
  1963. if ( versionId == pLoadReadyEntry->mpModuleDefinition->getVersionId() )
  1964. return true;
  1965. // Is it a strict version Id?
  1966. if ( pLoadReadyEntry->mStrictVersionId )
  1967. {
  1968. // Yes, so warn.
  1969. Con::warnf( "Module Manager: A module dependency was detected loading module Id '%s' at version Id '%d' in group '%s' but an version Id '%d' is also required.",
  1970. moduleId, versionId, pLoadReadyEntry->mpModuleDefinition->getVersionId(), moduleGroup );
  1971. return false;
  1972. }
  1973. // No, so find the required module version Id.
  1974. ModuleDefinitionEntry::iterator definitionItr = findModuleDefinition( moduleId, versionId );
  1975. // Did we find the requested module definition.
  1976. if ( definitionItr == NULL )
  1977. {
  1978. // No, so we can safely ignore the missing dependency if we're not enforcing dependencies.
  1979. if ( !mEnforceDependencies )
  1980. return true;
  1981. // Warn!
  1982. Con::warnf( "Module Manager: A missing module dependency was detected loading module Id '%s' at version Id '%d' in group '%s'.",
  1983. moduleId, versionId, moduleGroup );
  1984. return false;
  1985. }
  1986. // Set the new module definition.
  1987. pLoadReadyEntry->mpModuleDefinition = *definitionItr;
  1988. // Set strict version Id.
  1989. pLoadReadyEntry->mStrictVersionId = true;
  1990. return true;
  1991. }
  1992. // Is the module Id load resolving?
  1993. if ( findModuleResolving( moduleId, moduleResolvingQueue ) != NULL )
  1994. {
  1995. // Yes, so a cycle has been detected so warn.
  1996. Con::warnf( "Module Manager: A cyclic dependency was detected resolving module Id '%s' at version Id '%d' in group '%s'.",
  1997. moduleId, versionId, moduleGroup );
  1998. return false;
  1999. }
  2000. // Reset selected module definition.
  2001. ModuleDefinition* pSelectedModuleDefinition = NULL;
  2002. // Do we want the latest version Id?
  2003. if ( versionId == 0 )
  2004. {
  2005. // Yes, so find the module Id.
  2006. typeModuleIdDatabaseHash::iterator moduleIdItr = mModuleIdDatabase.find( moduleId );
  2007. // Did we find the module Id?
  2008. if ( moduleIdItr == mModuleIdDatabase.end() )
  2009. {
  2010. // No, so we can safely ignore the missing dependency if we're not enforcing dependencies.
  2011. if ( !mEnforceDependencies )
  2012. return true;
  2013. // Warn!
  2014. Con::warnf( "Module Manager: A missing module dependency was detected loading module Id '%s' at version Id '%d' in group '%s'.",
  2015. moduleId, versionId, moduleGroup );
  2016. return false;
  2017. }
  2018. // Fetch first module definition which should be the highest version Id.
  2019. pSelectedModuleDefinition = (*moduleIdItr->value)[0];
  2020. }
  2021. else
  2022. {
  2023. // No, so find the module Id at the specific version Id.
  2024. ModuleDefinitionEntry::iterator definitionItr = findModuleDefinition( moduleId, versionId );
  2025. // Did we find the module definition?
  2026. if ( definitionItr == NULL )
  2027. {
  2028. // No, so we can safely ignore the missing dependency if we're not enforcing dependencies.
  2029. if ( !mEnforceDependencies )
  2030. return true;
  2031. // Warn!
  2032. Con::warnf( "Module Manager: A missing module dependency was detected loading module Id '%s' at version Id '%d' in group '%s'.",
  2033. moduleId, versionId, moduleGroup );
  2034. return false;
  2035. }
  2036. // Select the module definition.
  2037. pSelectedModuleDefinition = *definitionItr;
  2038. }
  2039. // If we're only resolving synchronized modules and the module is not synchronized then finish.
  2040. if ( synchronizedOnly && !pSelectedModuleDefinition->getSynchronized() )
  2041. return true;
  2042. // Create a load entry.
  2043. ModuleLoadEntry loadEntry( pSelectedModuleDefinition, false );
  2044. // Fetch module dependencies.
  2045. const ModuleDefinition::typeModuleDependencyVector& moduleDependencies = pSelectedModuleDefinition->getDependencies();
  2046. // Do we have any module dependencies?
  2047. if ( moduleDependencies.size() > 0 )
  2048. {
  2049. // Yes, so queue this module as resolving.
  2050. moduleResolvingQueue.push_back( loadEntry );
  2051. // Iterate module dependencies.
  2052. for( ModuleDefinition::typeModuleDependencyVector::const_iterator dependencyItr = moduleDependencies.begin(); dependencyItr != moduleDependencies.end(); ++dependencyItr )
  2053. {
  2054. // Finish if we could not the dependent module Id at the version Id.
  2055. if ( !resolveModuleDependencies( dependencyItr->mModuleId, dependencyItr->mVersionId, moduleGroup, synchronizedOnly, moduleResolvingQueue, moduleReadyQueue ) )
  2056. return false;
  2057. }
  2058. // Remove module as resolving.
  2059. moduleResolvingQueue.pop_back();
  2060. }
  2061. // Queue module as ready.
  2062. moduleReadyQueue.push_back( loadEntry );
  2063. return true;
  2064. }
  2065. //-----------------------------------------------------------------------------
  2066. ModuleManager::ModuleLoadEntry* ModuleManager::findModuleResolving( StringTableEntry moduleId, typeModuleLoadEntryVector& moduleResolvingQueue )
  2067. {
  2068. // Iterate module load resolving queue.
  2069. for( typeModuleLoadEntryVector::iterator loadEntryItr = moduleResolvingQueue.begin(); loadEntryItr != moduleResolvingQueue.end(); ++loadEntryItr )
  2070. {
  2071. // Finish if found.
  2072. if ( moduleId == loadEntryItr->mpModuleDefinition->getModuleId() )
  2073. return loadEntryItr;
  2074. }
  2075. // Not found.
  2076. return NULL;
  2077. }
  2078. //-----------------------------------------------------------------------------
  2079. ModuleManager::ModuleLoadEntry* ModuleManager::findModuleReady( StringTableEntry moduleId, typeModuleLoadEntryVector& moduleReadyQueue )
  2080. {
  2081. // Iterate module load ready queue.
  2082. for( typeModuleLoadEntryVector::iterator loadEntryItr = moduleReadyQueue.begin(); loadEntryItr != moduleReadyQueue.end(); ++loadEntryItr )
  2083. {
  2084. // Finish if found.
  2085. if ( moduleId == loadEntryItr->mpModuleDefinition->getModuleId() )
  2086. return loadEntryItr;
  2087. }
  2088. // Not found.
  2089. return NULL;
  2090. }
  2091. //-----------------------------------------------------------------------------
  2092. ModuleManager::typeModuleLoadEntryVector::iterator ModuleManager::findModuleLoaded( StringTableEntry moduleId, const U32 versionId )
  2093. {
  2094. // Iterate module loaded queue.
  2095. for( typeModuleLoadEntryVector::iterator loadEntryItr = mModulesLoaded.begin(); loadEntryItr != mModulesLoaded.end(); ++loadEntryItr )
  2096. {
  2097. // Skip if not the module Id we're looking for.
  2098. if ( moduleId != loadEntryItr->mpModuleDefinition->getModuleId() )
  2099. continue;
  2100. // Skip if we are searching for a specific version and it does not match.
  2101. if ( versionId != 0 && versionId != loadEntryItr->mpModuleDefinition->getVersionId() )
  2102. continue;
  2103. return loadEntryItr;
  2104. }
  2105. // Not found.
  2106. return NULL;
  2107. }
  2108. //-----------------------------------------------------------------------------
  2109. ModuleManager::typeGroupVector::iterator ModuleManager::findGroupLoaded( StringTableEntry moduleGroup )
  2110. {
  2111. // Iterate groups loaded queue.
  2112. for( typeGroupVector::iterator groupsLoadedItr = mGroupsLoaded.begin(); groupsLoadedItr != mGroupsLoaded.end(); ++groupsLoadedItr )
  2113. {
  2114. // Finish if found.
  2115. if ( moduleGroup == *groupsLoadedItr )
  2116. return groupsLoadedItr;
  2117. }
  2118. // Not found.
  2119. return NULL;
  2120. }
  2121. //-----------------------------------------------------------------------------
  2122. StringTableEntry ModuleManager::getModuleMergeFilePath( void ) const
  2123. {
  2124. // Format merge file path.
  2125. char filePathBuffer[1024];
  2126. dSprintf( filePathBuffer, sizeof(filePathBuffer), "%s/%s", Platform::getExecutablePath(), MODULE_MANAGER_MERGE_FILE );
  2127. return StringTable->insert( filePathBuffer );
  2128. }