moduleManager.cpp 100 KB

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