/* -*- c++ -*- * * corelauncher.cpp * * Copyright (C) 2004 Petter E. Stokke * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "corelauncher.h" #include "coreterminationdialog.h" #include "hostmanager.h" #include "hostiface.h" #include #include #include #include #include #include CoreLauncher::CoreLauncher(QObject* parent, const char* name) : QObject(parent, name) { m_cores.setAutoDelete(true); m_hosts = new HostManager(this); connect(m_hosts, SIGNAL(hostListUpdated()), this, SLOT(hostListUpdated())); m_dcop = DCOPClient::mainClient(); m_dcop->setNotifications(true); connect(m_dcop, SIGNAL(applicationRegistered(const QCString&)), this, SLOT(applicationRegistered(const QCString&))); connect(m_dcop, SIGNAL(applicationRemoved(const QCString&)), this, SLOT(applicationRemoved(const QCString&))); QCString kName = "kmldonkey"; QCStringList apps = m_dcop->registeredApplications(); QCStringList::iterator it; m_kmldonkeyRunning = false; for (it = apps.begin(); it != apps.end(); ++it) { if (*it == kName) { m_kmldonkeyRunning = true; break; } } launchCores(m_kmldonkeyRunning ? -1 : HostInterface::AtKDEStart); } CoreLauncher::~CoreLauncher() { shutdownCores(-1); } bool CoreLauncher::isCoreRunning(const QString& id) const { return m_cores[id]; } bool CoreLauncher::isValidCore(const QString& id) const { return m_hosts->validHostName(id); } QStringList CoreLauncher::coreNames() const { return m_hosts->hostList(); } void CoreLauncher::startCore(const QString& id) { HostInterface* i = m_hosts->hostProperties(id); if (i) startCore(i); } void CoreLauncher::startCore(HostInterface* i) { if (m_cores[i->name()]) return; CoreProcess* core = new CoreProcess(); connect(core, SIGNAL(processExited(KProcess*)), this, SLOT(processExited(KProcess*))); m_cores.replace(i->name(), core); core->startCore(i); } void CoreLauncher::stopCore(const QString& id) { if (m_cores[id]) m_cores[id]->killCore(); } void CoreLauncher::stopCore(HostInterface* i) { stopCore(i->name()); } void CoreLauncher::launchCores(int filter) { QStringList l(m_hosts->hostList(HostInterface::Managed)); QStringList::Iterator it; for (it = l.begin(); it != l.end(); ++it) { if (m_cores[*it]) continue; HostInterface* i = m_hosts->hostProperties(*it); if (filter == -1 || i->startupMode() == filter) startCore(i); } } void CoreLauncher::shutdownCores(int filter) { QDictIterator it(m_cores); for (; it.current(); ++it) { HostInterface* i = m_hosts->hostProperties(it.currentKey()); if (filter == -1 || (!i && filter == -2) || (i && i->startupMode() == filter) || (!m_kmldonkeyRunning && filter == -2 && i->startupMode() == HostInterface::AtKMLDonkeyStart)) { it.current()->killCore(); if (filter == -1) it.current()->detach(); } } } void CoreLauncher::processExited(KProcess* c) { CoreProcess* core = dynamic_cast(c); if (!core) return; m_cores.take(core->id()); if (core->normalExit()) kdDebug() << "Process '" << core->id() << "' terminated with return code " << core->exitStatus() << endl; else kdDebug() << "Process '" << core->id() << "' was terminated by a signal." << endl; if (!core->isDying()) { CoreTerminationDialog* dlg = new CoreTerminationDialog(core); connect(dlg, SIGNAL(restartCore(const QString&)), SLOT(startCore(const QString&))); dlg->show(); } delete core; } void CoreLauncher::hostListUpdated() { shutdownCores(-2); launchCores(m_kmldonkeyRunning ? -1 : HostInterface::AtKDEStart); } void CoreLauncher::applicationRegistered(const QCString& appId) { if (appId == QCString("kmldonkey")) { m_kmldonkeyRunning = true; launchCores(HostInterface::AtKMLDonkeyStart); } } void CoreLauncher::applicationRemoved(const QCString& appId) { if (appId == QCString("kmldonkey")) { m_kmldonkeyRunning = false; shutdownCores(HostInterface::AtKMLDonkeyStart); } } CoreProcess::CoreProcess() : KProcIO() , m_id(QString::null) , m_dying(false) { connect(this, SIGNAL(readReady(KProcIO*)), this, SLOT(outputReady(KProcIO*))); } const QString& CoreProcess::id() const { return m_id; } bool CoreProcess::isDying() const { return m_dying; } void CoreProcess::startCore(HostInterface* i) { m_id = i->name(); kdDebug() << "Starting process " << m_id << endl; *this << i->binaryPath().path(); kdDebug() << "Set executable path: '" << i->binaryPath().path() << "'" << endl; if (!i->rootDirectory().isLocalFile() || !i->rootDirectory().hasPath()) { setWorkingDirectory(QDir::home().canonicalPath()); kdDebug() << "Set working directory (defaulting): '" << QDir::home().canonicalPath() << "'" << endl; } else { setWorkingDirectory(i->rootDirectory().path()); kdDebug() << "Set working directory: '" << i->rootDirectory().path() << "'" << endl; } kdDebug() << "Starting process..." << endl; bool rv = start(KProcess::NotifyOnExit, true); kdDebug() << "Process started: " << (rv ? "true" : "false") << endl; } void CoreProcess::killCore() { m_dying = true; kdDebug() << "Process termination requested for " << m_id << endl; bool rv = kill(); kdDebug() << "Termination: " << (rv ? "true" : "false") << endl; } QString CoreProcess::output() const { return m_output.join("\n"); } void CoreProcess::outputReady(KProcIO*) { QString l; while (readln(l) != -1) { kdDebug() << "Output from process '" << m_id << "': '" << l << "'" << endl; m_output.append(l); while (m_output.count() > 128) m_output.pop_front(); } } #include "corelauncher.moc"