diff --git a/code/nel/tools/pipeline/pipeline_service/database_status.cpp b/code/nel/tools/pipeline/pipeline_service/database_status.cpp index bc46fe030..a4b66bf98 100644 --- a/code/nel/tools/pipeline/pipeline_service/database_status.cpp +++ b/code/nel/tools/pipeline/pipeline_service/database_status.cpp @@ -36,6 +36,7 @@ #include // Project includes +#include "pipeline_service.h" using namespace std; using namespace NLMISC; @@ -71,14 +72,24 @@ CDatabaseStatus::~CDatabaseStatus() bool CDatabaseStatus::getFileStatus(CFileStatus &fileStatus, const std::string &filePath) const { + // mutex here when reading return false; } -void CDatabaseStatus::updateFileStatus(const TFileStatusCallback &callback, const std::string &filePath) +void CDatabaseStatus::updateFileStatus(TFileStatusCallback &callback, const std::string &filePath) { - + // ONLY WHEN MASTER + // mutex when writing + // dummy + CFileStatus fs; + callback(filePath, fs); + // todo add to queue } +// ****************************************************************** + +namespace { + struct CDatabaseStatusUpdater { public: @@ -106,6 +117,38 @@ public: } }; +void updateDirectoryStatus(CDatabaseStatus* ds, CDatabaseStatusUpdater &updater, const std::string &dir) +{ + std::string dirPath = CPath::standardizePath(dir, true); + std::vector dirContents; + + CPath::getPathContent(dirPath, false, true, true, dirContents); + + for (std::vector::iterator it = dirContents.begin(), end = dirContents.end(); it != end; ++it) + { + const std::string subPath = *it; + + if (CFile::isDirectory(subPath)) // if the file is a directory! + { + updateDirectoryStatus(ds, updater, subPath); + } + else + { + updater.Mutex.enter(); + ++updater.FilesRequested; + updater.Mutex.leave(); + + CFileStatus fileStatus; + if (!ds->getFileStatus(fileStatus, subPath)) + { + ds->updateFileStatus(TFileStatusCallback(&updater, &CDatabaseStatusUpdater::fileUpdated), subPath); + } + } + } +} + +} /* anonymous namespace */ + void CDatabaseStatus::updateDatabaseStatus(const CCallback &callback) { CDatabaseStatusUpdater updater; @@ -115,14 +158,13 @@ void CDatabaseStatus::updateDatabaseStatus(const CCallback &callback) updater.Ready = false; updater.CallbackCalled = false; - // recursive loop ... - { - updater.Mutex.enter(); - ++updater.FilesRequested; - updater.Mutex.leave(); - updateFileStatus(TFileStatusCallback(&updater, &CDatabaseStatusUpdater::fileUpdated), ""); - } - + nlinfo("Starting iteration through database, queueing file status updates."); + + // recursive loop + updateDirectoryStatus(this, updater, g_DatabaseDirectory); + + nlinfo("Iteration through database, queueing file status updates complete."); + bool done = false; updater.Mutex.enter(); updater.Ready = true; @@ -136,6 +178,8 @@ void CDatabaseStatus::updateDatabaseStatus(const CCallback &callback) if (done) updater.Callback(); } +// ****************************************************************** + } /* namespace PIPELINE */ /* end of file */ diff --git a/code/nel/tools/pipeline/pipeline_service/database_status.h b/code/nel/tools/pipeline/pipeline_service/database_status.h index ca17dc7ae..80b171420 100644 --- a/code/nel/tools/pipeline/pipeline_service/database_status.h +++ b/code/nel/tools/pipeline/pipeline_service/database_status.h @@ -90,7 +90,7 @@ public: /// Tries to read the last file status. Return false if the status is invalid. Call updateFileStatus if the result is false to update asynchronously. bool getFileStatus(CFileStatus &fileStatus, const std::string &filePath) const; /// Updates the file status asynchronously. The new file status is broadcast to clients and slaves afterwards. - void updateFileStatus(const TFileStatusCallback &callback, const std::string &filePath); + void updateFileStatus(TFileStatusCallback &callback, const std::string &filePath); /// Forces an update of the complete database status. void updateDatabaseStatus(const CCallback &callback); diff --git a/code/nel/tools/pipeline/pipeline_service/pipeline_service.cpp b/code/nel/tools/pipeline/pipeline_service/pipeline_service.cpp index 5828e5677..fdb77409d 100644 --- a/code/nel/tools/pipeline/pipeline_service/pipeline_service.cpp +++ b/code/nel/tools/pipeline/pipeline_service/pipeline_service.cpp @@ -46,6 +46,7 @@ // Project includes #include "pipeline_workspace.h" +#include "database_status.h" // using namespace std; using namespace NLMISC; @@ -75,6 +76,7 @@ enum EState UFormLoader *s_FormLoader = NULL; CPipelineWorkspace *s_PipelineWorkspace = NULL; CTaskManager *s_TaskManager = NULL; +CDatabaseStatus *s_DatabaseStatus = NULL; EState s_State = STATE_IDLE; CMutex s_StateMutex; @@ -93,21 +95,35 @@ TUnifiedCallbackItem s_ShardCallbacks[] = // pipeline_server { "N", cbNull }, }; +bool tryStateTask(EState state, IRunnable *task) +{ + bool result = false; + s_StateMutex.enter(); + result = (s_State == STATE_IDLE); + if (result) + { + s_State = state; + } + s_StateMutex.leave(); + if (!result) return false; + + s_TaskManager->addTask(task); + + return true; +} + // ****************************************************************** void initSheets() { - std::string leveldesignDirectory = IService::getInstance()->ConfigFile.getVar("LeveldesignDirectory").asString(); std::string leveldesignDfnDirectory = IService::getInstance()->ConfigFile.getVar("LeveldesignDfnDirectory").asString(); - - if (leveldesignDfnDirectory.find(leveldesignDirectory) == std::string::npos) - { - nlinfo("Adding 'LeveldesignDfnDirectory' to search path"); - CPath::addSearchPath(leveldesignDfnDirectory, true, false); - } - - nlinfo("Adding 'LeveldesignDirectory' to search path"); - CPath::addSearchPath(leveldesignDirectory, true, false); + std::string leveldesignPipelineDirectory = IService::getInstance()->ConfigFile.getVar("LeveldesignPipelineDirectory").asString(); + + nlinfo("Adding 'LeveldesignDfnDirectory' to search path (%s)", leveldesignDfnDirectory.c_str()); + CPath::addSearchPath(leveldesignDfnDirectory, true, false); + + nlinfo("Adding 'LeveldesignPipelineDirectory' to search path (%s)", leveldesignPipelineDirectory.c_str()); + CPath::addSearchPath(leveldesignPipelineDirectory, true, false); s_FormLoader = UFormLoader::createLoader(); @@ -144,19 +160,33 @@ CReloadSheets s_ReloadSheets; bool reloadSheets() { - bool result = false; - s_StateMutex.enter(); - result = (s_State == STATE_IDLE); - if (result) + return tryStateTask(STATE_RELOAD_SHEETS, &s_ReloadSheets); +} + +// ****************************************************************** + +class CUpdateDatabaseStatus : public IRunnable +{ + virtual void getName (std::string &result) const + { result = "CUpdateDatabaseStatus"; } + + void databaseStatusUpdated() { - s_State = STATE_RELOAD_SHEETS; + s_StateMutex.enter(); + s_State = STATE_IDLE; + s_StateMutex.leave(); } - s_StateMutex.leave(); - if (!result) return false; - - s_TaskManager->addTask(&s_ReloadSheets); - - return true; + + virtual void run() + { + s_DatabaseStatus->updateDatabaseStatus(CCallback(this, &CUpdateDatabaseStatus::databaseStatusUpdated)); + } +}; +CUpdateDatabaseStatus s_UpdateDatabaseStatus; + +bool updateDatabaseStatus() +{ + return tryStateTask(STATE_DATABASE_STATUS, &s_UpdateDatabaseStatus); } // ****************************************************************** @@ -206,6 +236,8 @@ public: s_TaskManager = new CTaskManager(); initSheets(); + + s_DatabaseStatus = new CDatabaseStatus(); } /// This function is called every "frame" (you must call init() before). It returns false if the service is stopped. @@ -217,9 +249,13 @@ public: /// Finalization. Release the service. For example, this function frees all allocations made in the init() function. virtual void release() { + delete s_DatabaseStatus; + s_DatabaseStatus = NULL; + releaseSheets(); delete s_TaskManager; + s_TaskManager = NULL; } }; /* class CPipelineService */ @@ -252,15 +288,22 @@ NLMISC_COMMAND(reloadSheets, "Reload all sheets.", "") { if(args.size() != 0) return false; if (!PIPELINE::reloadSheets()) + { nlinfo("I'm afraid I cannot do this, my friend."); + return false; + } return true; } NLMISC_COMMAND(updateDatabaseStatus, "Updates the entire database status. This also happens on the fly during build.", "") { if(args.size() != 0) return false; - - + if (!PIPELINE::updateDatabaseStatus()) + { + nlinfo("I'm afraid I cannot do this, my friend."); + return false; + } + return true; } NLNET_SERVICE_MAIN(PIPELINE::CPipelineService, PIPELINE_SHORT_SERVICE_NAME, PIPELINE_LONG_SERVICE_NAME, 0, PIPELINE::s_ShardCallbacks, "", "") diff --git a/code/ryzom/common/data_leveldesign/leveldesign/pipeline/ryzom_core.pipeline_workspace b/code/ryzom/common/data_leveldesign/leveldesign/pipeline/ryzom_core.pipeline_workspace index 387036b04..1c650d554 100644 --- a/code/ryzom/common/data_leveldesign/leveldesign/pipeline/ryzom_core.pipeline_workspace +++ b/code/ryzom/common/data_leveldesign/leveldesign/pipeline/ryzom_core.pipeline_workspace @@ -13,5 +13,7 @@ Sat Feb 18 13:48:48 2012 (Kaetemi) .Name = Ryzom Core Sat Feb 18 13:48:48 2012 (Kaetemi) formName Resized = 1 Sat Feb 18 14:44:25 2012 (Kaetemi) .Description = Ryzom Core -Sat Feb 18 14:44:37 2012 (Kaetemi) .Projects[0] = common_interface.pipeline_project +Sat Feb 18 14:44:37 2012 (Kaetemi) .Projects[0] = common_interface.pipeline_project +Sat Feb 18 23:23:17 2012 (Kaetemi) .Description = Ryzom Core Test +Sat Feb 18 23:23:26 2012 (Kaetemi) .Description = Ryzom Core