diff --git a/code/nel/tools/pipeline/service/database_status.cpp b/code/nel/tools/pipeline/service/database_status.cpp index 198aa6445..04bd3380c 100644 --- a/code/nel/tools/pipeline/service/database_status.cpp +++ b/code/nel/tools/pipeline/service/database_status.cpp @@ -324,9 +324,13 @@ public: std::vector RequestTasks; + TFileStatusCallback FileStatusCallback; + void fileUpdated(const std::string &filePath, const CFileStatus &fileStatus, bool success) { // warning: may be g_IsExiting during this callback! + if (!g_IsExiting) + FileStatusCallback(filePath, fileStatus, success); bool done = false; Mutex.enter(); @@ -409,6 +413,12 @@ void updatePathStatus(CDatabaseStatus* ds, CDatabaseStatusUpdater &updater, cons } updater.Mutex.leave(); } + else + { + // File was not updated, but the status was read successfully + // This only notifies the callback set by the user + updater.FileStatusCallback(subPath, fileStatus, true); + } } } @@ -499,6 +509,8 @@ void updateDirectoryStatus(CDatabaseStatus* ds, CDatabaseStatusUpdater &updater, } /* anonymous namespace */ +void dummyFileStatusCallback(const std::string &/*filePath*/, const CFileStatus &/*fileStatus*/, bool /*success*/) { } + void CDatabaseStatus::updateDatabaseStatus(const CCallback &callback) { /*if (!g_IsMaster) @@ -516,10 +528,10 @@ void CDatabaseStatus::updateDatabaseStatus(const CCallback &callback) std::string rootDirectoryPath = standardizePath(dir.asString(), true); paths.push_back(rootDirectoryPath); } - updateDatabaseStatus(callback, paths, false, true); + updateDatabaseStatus(callback, dummyFileStatusCallback, paths, false, true); } -void CDatabaseStatus::updateDatabaseStatus(const CCallback &callback, const std::vector &paths, bool wait, bool recurse) +void CDatabaseStatus::updateDatabaseStatus(const CCallback &callback, const TFileStatusCallback &fileStatusCallback, const std::vector &paths, bool wait, bool recurse) { /*if (!g_IsMaster) { @@ -532,6 +544,7 @@ void CDatabaseStatus::updateDatabaseStatus(const CCallback &callback, cons updater->FilesUpdated = 0; updater->Ready = false; updater->CallbackCalled = false; + updater->FileStatusCallback = fileStatusCallback; nlinfo("Starting iteration through database, queueing file status updates."); diff --git a/code/nel/tools/pipeline/service/database_status.h b/code/nel/tools/pipeline/service/database_status.h index 5ee3ce81b..baa44043b 100644 --- a/code/nel/tools/pipeline/service/database_status.h +++ b/code/nel/tools/pipeline/service/database_status.h @@ -74,7 +74,7 @@ public: /// Runs an update of the complete {{DatabaseDirectory}} status asynchronously. Warning: If g_IsExiting during callback then update is incomplete. Callback is always called when done (or failed). void updateDatabaseStatus(const CCallback &callback); /// Runs an update of the file status of given paths asynchronously. Warning: If g_IsExiting during callback then update is incomplete. Callback is always called when done (or failed). Do NOT use the wait parameter. Do NOT use recurse, please. Recurse directories beforehand. Paths may contain db and pl macros. - void updateDatabaseStatus(const CCallback &callback, const std::vector &paths, bool wait = false, bool recurse = false); + void updateDatabaseStatus(const CCallback &callback, const TFileStatusCallback &fileStatusCallback, const std::vector &paths, bool wait = false, bool recurse = false); /// Gets the last file statuses of given paths in a map. Directories are scanned for files, non recursively. Returns false if one of the statuses is bad (not updated; file changed inbetween). Considered as build error. bool getFileStatus(std::map &fileStatusMap, std::map &fileRemoveMap, const std::vector &paths); diff --git a/code/nel/tools/pipeline/service/module_pipeline_master.cpp b/code/nel/tools/pipeline/service/module_pipeline_master.cpp index ff0161544..2dad81d3a 100644 --- a/code/nel/tools/pipeline/service/module_pipeline_master.cpp +++ b/code/nel/tools/pipeline/service/module_pipeline_master.cpp @@ -222,12 +222,14 @@ public: return true; } + static void dummyFileStatusCallback(const std::string &/*filePath*/, const CFileStatus &/*fileStatus*/, bool /*success*/) { } + void updateSheetsDatabaseStatus(const CCallback &callback) { std::vector sheetPaths; // sheetPaths.push_back(NLNET::IService::getInstance()->ConfigFile.getVar("WorkspaceDfnDirectory").asString()); // not really necessary to check the dfn's sheetPaths.push_back(NLNET::IService::getInstance()->ConfigFile.getVar("WorkspaceSheetDirectory").asString()); - g_DatabaseStatus->updateDatabaseStatus(callback, sheetPaths, false, true); + g_DatabaseStatus->updateDatabaseStatus(callback, dummyFileStatusCallback, sheetPaths, false, true); } void cbMasterInitSheets() @@ -320,14 +322,16 @@ public: void handleUpdateTasks() { + uint maxRuns; IRunnable *currentRunnable; { NLMISC::CSynchronized >::CAccessor updateTasks(&m_UpdateTasks); if (updateTasks.value().size() == 0) return; + maxRuns = updateTasks.value().size(); currentRunnable = updateTasks.value().front(); } - for (; ; ) + for (uint i = 0; i < maxRuns; ++i) { currentRunnable->run(); { @@ -544,9 +548,48 @@ public: class CUpdateDatabaseStatusSlaveCallback : public CDelayedCallback { + class CSlaveFileCallback : public NLMISC::IRunnable + { + public: + CSlaveFileCallback(CModulePipelineMaster *master, NLNET::IModuleProxy *slaveProxy, const std::string &filePath, const CFileStatus &fileStatus) + : m_Master(master), m_SlaveProxy(slaveProxy), m_FilePath(filePath), m_FileStatus(fileStatus) { } + virtual void run() + { + m_Master->m_SlavesMutex.lock(); + TSlaveMap::iterator slaveIt = m_Master->m_Slaves.find(m_SlaveProxy); + if (slaveIt == m_Master->m_Slaves.end()) + { + // nlwarning("Slave disconnected before callback could be delivered"); + m_Master->m_SlavesMutex.unlock(); + delete this; + return; + } + CSlave *slave = slaveIt->second; + m_Master->m_SlavesMutex.unlock(); + + slave->Proxy.addFileStatusToCache(m_Master, macroPath(m_FilePath), m_FileStatus); + + delete this; + } + private: + CModulePipelineMaster *m_Master; + NLNET::IModuleProxy *m_SlaveProxy; + std::string m_FilePath; + CFileStatus m_FileStatus; + }; + public: CUpdateDatabaseStatusSlaveCallback(CModulePipelineMaster *master, NLNET::IModuleProxy *slaveProxy) : CDelayedCallback(master), m_SlaveProxy(slaveProxy) { } + void fileCallback(const std::string &filePath, const CFileStatus &fileStatus, bool success) + { + if (success) + { + Master->addUpdateTask(new CSlaveFileCallback(Master, m_SlaveProxy, filePath, fileStatus)); + } + } + + /// All status updated for this task virtual void run() // this is sanely run from the update thread { Master->m_SlavesMutex.lock(); @@ -583,7 +626,7 @@ public: virtual void run() // run from the master process task manager { CUpdateDatabaseStatusSlaveCallback *cb = new CUpdateDatabaseStatusSlaveCallback(m_Master, m_Sender); // deleted by update - g_DatabaseStatus->updateDatabaseStatus(cb->getCallback(), m_Vector, false, false); + g_DatabaseStatus->updateDatabaseStatus(cb->getCallback(), TFileStatusCallback(cb, &CUpdateDatabaseStatusSlaveCallback::fileCallback), m_Vector, false, false); delete this; } diff --git a/code/nel/tools/pipeline/service/module_pipeline_slave.cpp b/code/nel/tools/pipeline/service/module_pipeline_slave.cpp index 98bee6a5e..4c9c379cb 100644 --- a/code/nel/tools/pipeline/service/module_pipeline_slave.cpp +++ b/code/nel/tools/pipeline/service/module_pipeline_slave.cpp @@ -422,6 +422,8 @@ public: virtual void addFileStatusToCache(NLNET::IModuleProxy *sender, const std::string ¯oPath, const CFileStatus &fileStatus) { nlassert(sender == NULL || m_Master->getModuleProxy() == sender); // sanity check + + nldebug("Add file status: '%s' (macro path)", macroPath.c_str()); std::string filePath = unMacroPath(macroPath); nlassert(m_FileStatusCache.find(filePath) == m_FileStatusCache.end());