# # # patch "src/monotone/MonotoneManager.cpp" # from [03d21bf3da3e159d125d11929945b2ed14550cdd] # to [ea647e4d5d9528c83e2a5fd9541ebb12d682e4b9] # # patch "src/monotone/MonotoneManager.h" # from [a41cbd2798cbc629d9525a01b9af41eabf3e21c1] # to [fe884ddb22ef2d7e759814fe07cafd4c9f507c18] # ============================================================ --- src/monotone/MonotoneManager.cpp 03d21bf3da3e159d125d11929945b2ed14550cdd +++ src/monotone/MonotoneManager.cpp ea647e4d5d9528c83e2a5fd9541ebb12d682e4b9 @@ -21,13 +21,28 @@ #include "MonotoneManager.h" #include "vocab.h" #include "BasicIOParser.h" +#include "SignalWaiter.h" const QString MonotoneManager::MinInterfaceVersion = MIN_MTN_INT_VERSION; const QString MonotoneManager::MaxInterfaceVersion = MAX_MTN_INT_VERSION; MonotoneManager::MonotoneManager() : threadNumber(0) {} -MonotoneManager::~MonotoneManager() {} +MonotoneManager::~MonotoneManager() +{ + QMapIterator it(threadMap); + while(it.hasNext()) + { + it.next(); + int threadNumber = it.key(); + MonotoneThread * thread = it.value(); + D(QString("aborting thread %1").arg(threadNumber)); + thread->abort(); + thread->wait(); + threadMap.remove(threadNumber); + delete thread; + } +} bool MonotoneManager::setMonotoneBinaryPath(const QString & mtnBinary, QString & pathVersion) { @@ -58,34 +73,41 @@ MonotoneThread * MonotoneManager::getThr MonotoneThread * MonotoneManager::getThread(const DatabaseFile & database, const WorkspacePath & workspace) { + QMutexLocker locker(&lock); + if (mtnPath.isEmpty()) throw GuitoneException(tr("Monotone binary path not set")); - // FIXME: since we cannot set the workspace directory after we've + // since we cannot set the workspace directory after we've // started the process, we need to ensure that each workspace runs with // its own process QString ident = database + "|" + workspace; - if (!threadMap.contains(ident)) + QList threadIDs = identMap.keys(ident); + + if (threadIDs.size() == 0) { - // TODO: connect to started(int) and aborted(int, ...) here - // and wait for started() + threadNumber++; + MonotoneThread * thread = - new MonotoneThread(threadNumber++, mtnPath, database, workspace); - threadMap.insert(ident, thread); + new MonotoneThread(threadNumber, mtnPath, database, workspace); + + threadMap.insert(threadNumber, thread); + identMap.insert(threadNumber, ident); + threadIDs.append(threadNumber); + + connect( + thread, SIGNAL(aborted(int, QProcess::ProcessError, const QString &)), + this, SLOT(aborted(int, QProcess::ProcessError, const QString &)) + ); + + thread->start(); } // TODO: we may want to add support for multiple threads for one - // and the same database here in the future... - MonotoneThread * thread = threadMap.value(ident); - if (!thread->isRunning()) - { - // TODO: disconnect from started(int) and aborted(int, ...) here - delete thread; - threadMap.remove(ident); - // up to the next round - return getThread(database, workspace); - } - return thread; + // and the same database here in the future... then we should probably + // also make a smarter choice of available threads here instead of just + // taking the first! + return threadMap.value(threadIDs.value(0)); } WorkspacePath MonotoneManager::normalizeWorkspacePath(const WorkspacePath & workspace) @@ -174,9 +196,26 @@ void MonotoneManager::aborted(int thread //! \todo many-to-one resolution void MonotoneManager::aborted(int threadNumber, QProcess::ProcessError error, const QString & message) { - Q_UNUSED(threadNumber); - Q_UNUSED(error); - Q_UNUSED(message); + QMutexLocker locker(&lock); + + I(threadMap.contains(threadNumber)); + + MonotoneThread * thread = threadMap.value(threadNumber); + + // FIXME: do we want to re-start the process right here? + + disconnect( + thread, SIGNAL(aborted(int, QProcess::ProcessError, const QString &)), + this, SLOT(aborted(int, QProcess::ProcessError, const QString &)) + ); + + threadMap.remove(threadNumber); + identMap.remove(threadNumber); + + delete thread; + + W(QString("thread %1 aborted (error %2: %3)") + .arg(threadNumber).arg(error).arg(message)); } bool MonotoneManager::singleRun(const QString & mtnBinary, ============================================================ --- src/monotone/MonotoneManager.h a41cbd2798cbc629d9525a01b9af41eabf3e21c1 +++ src/monotone/MonotoneManager.h fe884ddb22ef2d7e759814fe07cafd4c9f507c18 @@ -62,10 +62,13 @@ private: private: MonotoneThread * getThread(const DatabaseFile &, const WorkspacePath &); - QMap threadMap; + QMap threadMap; + QMap identMap; QMap workspaceMap; + QString mtnPath; int threadNumber; + QMutex lock; private slots: void aborted(int, QProcess::ProcessError, const QString &);