| |
| |
| #include "tfarmserver.h" |
| #include "tfarmexecutor.h" |
| #include "tfarmcontroller.h" |
| #include "tthreadmessage.h" |
| #include "tthread.h" |
| #include "tsystem.h" |
| #include "tsmartpointer.h" |
| #include "service.h" |
| #include "tlog.h" |
| #include "tfilepath_io.h" |
| #include "tcli.h" |
| |
| #include <string> |
| #include <map> |
| #include <sstream> |
| |
| #include <QString> |
| #include <QProcess> |
| #include <QCoreApplication> |
| #include <QEventLoop> |
| |
| #include "tthread.h" |
| |
| #ifdef _WIN32 |
| #include <iostream> |
| #else |
| #include <sys/param.h> |
| #include <unistd.h> |
| #include <sys/timeb.h> |
| #endif |
| |
| |
| |
| #ifdef _WIN32 |
| #define QUOTE_STR "\"" |
| #define CASMPMETER "casmpmeter.exe" |
| #else |
| #define QUOTE_STR "'" |
| #define CASMPMETER "casmpmeter" |
| #endif |
| |
| #ifndef _WIN32 |
| #define NO_ERROR 0 |
| #endif |
| |
| #ifdef MACOSX |
| #include <sys/sysctl.h> //To retrieve MAC HW infos |
| #endif |
| |
| #ifdef LINUX |
| #include <sys/sysctl.h> |
| #endif |
| |
| // forward declaration |
| class FarmServer; |
| |
| //------------------------------------------------------------------- |
| |
| namespace |
| { |
| |
| //-------------------------------------------------------------------- |
| TFilePath getGlobalRoot() |
| { |
| TFilePath rootDir; |
| |
| #ifdef _WIN32 |
| TFilePath name(L"SOFTWARE\\OpenToonz\\OpenToonz\\1.0\\FARMROOT"); |
| rootDir = TFilePath(TSystem::getSystemValue(name).toStdString()); |
| #else |
| // Leggo la localRoot da File txt |
| |
| Tifstream is(TFilePath("./OpenToonz_1.0.app/Contents/Resources/configfarmroot.txt")); |
| if (is) { |
| char line[1024]; |
| is.getline(line, 80); |
| |
| char *s = line; |
| while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\"') |
| s++; |
| if (*s != '\0') { |
| char *t = s; |
| while (*t) |
| t++; |
| |
| std::string pathName(s, t - 1); |
| |
| rootDir = TFilePath(pathName); |
| } |
| } |
| |
| #endif |
| return rootDir; |
| } |
| |
| |
| |
| TFilePath getLocalRoot() |
| { |
| TFilePath lroot; |
| |
| #ifdef _WIN32 |
| TFilePath name("SOFTWARE\\OpenToonz\\OpenToonz\\1.0\\TOONZROOT"); |
| lroot = TFilePath(TSystem::getSystemValue(name).toStdString()) + TFilePath("toonzfarm"); |
| #else |
| Tifstream is(TFilePath("./OpenToonz_1.0.app/Contents/Resources/configfarmroot.txt")); |
| if (is) { |
| char line[1024]; |
| is.getline(line, 80); |
| |
| char *s = line; |
| while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\"') |
| s++; |
| if (*s != '\0') { |
| char *t = s; |
| while (*t) |
| t++; |
| |
| std::string pathName(s, t - 1); |
| |
| lroot = TFilePath(pathName); |
| } |
| } |
| |
| #endif |
| return lroot; |
| } |
| |
| |
| |
| TFilePath getBinRoot() |
| { |
| #ifdef _WIN32 |
| return TSystem::getBinDir(); |
| #else |
| return getLocalRoot() + "bin"; |
| #endif |
| } |
| |
| |
| |
| bool dirExists(const TFilePath &dirFp) |
| { |
| bool exists = false; |
| #ifdef _WIN32 |
| TFileStatus fs(dirFp); |
| exists = fs.isDirectory(); |
| #else |
| int acc = access(::to_string(dirFp).c_str(), 00); |
| exists = acc != -1; |
| #endif |
| return exists; |
| } |
| |
| |
| |
| bool myDoesExists(const TFilePath &fp) |
| { |
| bool exists = false; |
| #ifdef _WIN32 |
| TFileStatus fs(fp); |
| exists = fs.doesExist(); |
| #else |
| int acc = access(::to_string(fp).c_str(), 00); |
| exists = acc != -1; |
| #endif |
| return exists; |
| } |
| |
| |
| |
| inline bool isBlank(char c) |
| { |
| return c == ' ' || c == '\t' || c == '\n'; |
| } |
| |
| } |
| |
| |
| |
| |
| class FarmServerService : public TService |
| { |
| public: |
| FarmServerService(std::ostream &os) |
| : TService("ToonzFarm Server", "ToonzFarm Server"), m_os(os), m_userLog(0) {} |
| |
| ~FarmServerService() |
| { |
| delete m_userLog; |
| } |
| |
| void onStart(int argc, char *argv[]); |
| void onStop(); |
| |
| void loadControllerData(QString &hostName, string &ipAddr, int &port); |
| #ifdef _WIN32 |
| void loadDiskMountingPoints(const TFilePath &fp); |
| |
| void mountDisks(); |
| void unmountDisks(); |
| |
| std::map<std::string, std::string> m_disks; |
| vector<std::string> m_disksMounted; |
| #endif |
| |
| int m_port; |
| QString m_addr; |
| |
| FarmServer *m_farmServer; |
| std::ostream &m_os; |
| |
| TUserLog *m_userLog; |
| }; |
| |
| FarmServerService service(std::cout); |
| |
| |
| |
| |
| class FarmControllerProxy : public TSmartObject |
| { |
| TFarmController *m_controller; |
| |
| public: |
| FarmControllerProxy(TFarmController *controller) |
| : m_controller(controller) {} |
| |
| ~FarmControllerProxy() |
| { |
| delete m_controller; |
| } |
| TFarmController *getController() const { return m_controller; } |
| |
| private: |
| |
| FarmControllerProxy(const FarmControllerProxy &); |
| FarmControllerProxy &operator=(const FarmControllerProxy &); |
| }; |
| |
| |
| |
| class FarmControllerProxyP |
| { |
| FarmControllerProxy *m_proxy; |
| |
| public: |
| FarmControllerProxyP() : m_proxy(0) {} |
| ~FarmControllerProxyP() |
| { |
| if (m_proxy) |
| m_proxy->release(); |
| } |
| FarmControllerProxyP(const FarmControllerProxyP &src) : m_proxy(src.m_proxy) |
| { |
| if (m_proxy) |
| m_proxy->addRef(); |
| } |
| FarmControllerProxyP &operator=(const FarmControllerProxyP &src) |
| { |
| FarmControllerProxyP tmp(*this); |
| tswap(tmp.m_proxy, m_proxy); |
| return *this; |
| } |
| |
| FarmControllerProxyP &operator=(TFarmController *controller) |
| { |
| if (m_proxy && m_proxy->getController() == controller) |
| return *this; |
| if (m_proxy) |
| m_proxy->release(); |
| m_proxy = new FarmControllerProxy(controller); |
| m_proxy->addRef(); |
| return *this; |
| } |
| |
| TFarmController *operator->() |
| { |
| return getPointer(); |
| } |
| TFarmController *getPointer() const |
| { |
| return m_proxy ? m_proxy->getController() : 0; |
| } |
| }; |
| |
| |
| |
| |
| class FarmServer : public TFarmExecutor, public TFarmServer |
| { |
| public: |
| FarmServer(int port, TUserLog *log); |
| ~FarmServer(); |
| |
| void setController(const ControllerData &data) |
| { |
| m_controllerData = data; |
| TFarmController *controller = 0; |
| TFarmControllerFactory factory; |
| factory.create(data, &controller); |
| m_controller = controller; |
| } |
| TFarmController *getController() const |
| { |
| return m_controller.getPointer(); |
| } |
| void setAppPaths(const vector<TFilePath> &); |
| |
| QString execute(const vector<QString> &argv); |
| |
| |
| int addTask(const QString &taskid, const QString &cmdline); |
| int terminateTask(const QString &taskid); |
| int getTasks(vector<QString> &tasks); |
| |
| void queryHwInfo(HwInfo &hwInfo); |
| |
| void attachController(const ControllerData &data); |
| void attachController(const QString &name, const QString &addr, int port) |
| { |
| attachController(ControllerData(name, addr, port)); |
| } |
| |
| void detachController(const ControllerData &data); |
| void detachController(const QString &name, const QString &addr, int port) |
| { |
| detachController(ControllerData(name, addr, port)); |
| } |
| |
| |
| void removeTask(const QString &id); |
| |
| private: |
| TThread::Executor *m_executor; |
| |
| ControllerData m_controllerData; |
| FarmControllerProxyP m_controller; |
| |
| TThread::Mutex m_mux; |
| vector<QString> m_tasks; |
| |
| TUserLog *m_userLog; |
| |
| public: |
| |
| |
| private: |
| |
| FarmServer(const FarmServer &); |
| FarmServer &operator=(const FarmServer &); |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| class Task : public TThread::Runnable |
| { |
| public: |
| Task(const QString &id, |
| const QString &cmdline, |
| TUserLog *log, |
| FarmServer *server, |
| const FarmControllerProxyP &controller) |
| : m_id(id), m_cmdline(cmdline), m_log(log), m_server(server), m_controller(controller) {} |
| |
| void run(); |
| |
| private: |
| QString m_id; |
| QString m_cmdline; |
| TUserLog *m_log; |
| FarmServer *m_server; |
| FarmControllerProxyP m_controller; |
| |
| private: |
| |
| Task(const Task &); |
| Task &operator=(const Task &); |
| }; |
| |
| |
| |
| void Task::run() |
| { |
| QString logMsg("Starting task at "); |
| logMsg += QDateTime::currentDateTime().toString(); |
| logMsg += "\n"; |
| logMsg += "\"" + m_cmdline + "\""; |
| logMsg += "\n\n"; |
| |
| m_log->info(logMsg); |
| |
| |
| |
| #ifdef _WIN32 |
| if (m_cmdline.contains("runcasm")) |
| service.mountDisks(); |
| #endif |
| |
| QString cmdline; |
| |
| if (m_cmdline.contains(".bat")) |
| cmdline = "cmd /C " + m_cmdline; |
| else |
| cmdline = m_cmdline; |
| #ifdef LEVO |
| else |
| { |
| |
| |
| |
| QStringList l = m_cmdline.split(" "); |
| |
| QString appName = l.at(1); |
| int i; |
| for (i = 2; i < l.size(); i++) |
| cmdline += l.at(i); |
| |
| |
| bool foundApp = false; |
| vector<TFilePath>::iterator it = m_server->m_appPaths.begin(); |
| for (; it != m_server->m_appPaths.end(); ++it) { |
| TFilePath appPath = *it; |
| if (appPath.getName() == appName.toStdString()) { |
| exename = QString::fromStdWString(appPath.getWideString()); |
| break; |
| } |
| } |
| } |
| #endif //LEVO |
| |
| |
| |
| |
| QProcess process; |
| |
| process.start(cmdline); |
| process.waitForFinished(-1); |
| |
| int exitCode = process.exitCode(); |
| int errorCode = process.error(); |
| bool ret = (errorCode != QProcess::UnknownError) || exitCode; |
| |
| |
| |
| if (ret != 0) { |
| QString logMsg("Task aborted "); |
| logMsg += "\n\n"; |
| m_log->warning(logMsg); |
| m_controller->taskSubmissionError(m_id, exitCode); |
| } else { |
| logMsg = "Task completed at "; |
| logMsg += QDateTime::currentDateTime().toString(); |
| logMsg += "\n\n"; |
| |
| m_log->info(logMsg); |
| m_controller->taskCompleted(m_id, exitCode); |
| |
| |
| } |
| |
| m_server->removeTask(m_id); |
| |
| |
| |
| |
| |
| } |
| |
| |
| |
| |
| FarmServer::FarmServer(int port, TUserLog *log) |
| : TFarmExecutor(port), m_controller(), m_userLog(log) |
| { |
| TFarmServer::HwInfo hwInfo; |
| queryHwInfo(hwInfo); |
| m_executor = new TThread::Executor; |
| m_executor->setMaxActiveTasks(1); |
| } |
| |
| |
| |
| FarmServer::~FarmServer() |
| { |
| delete m_executor; |
| } |
| |
| |
| QString FarmServer::execute(const vector<QString> &argv) |
| { |
| if (argv.size() > 0) { |
| if (argv[0] == "addTask" && argv.size() == 3) { |
| |
| int ret = addTask(argv[1], argv[2]); |
| return QString::number(ret); |
| } else if (argv[0] == "terminateTask" && argv.size() > 1) { |
| int ret = terminateTask(argv[1]); |
| return QString::number(ret); |
| } else if (argv[0] == "getTasks") { |
| vector<QString> tasks; |
| int ret = getTasks(tasks); |
| |
| QString reply(QString::number(ret)); |
| reply += ","; |
| |
| vector<QString>::iterator it = tasks.begin(); |
| for (; it != tasks.end(); ++it) { |
| reply += *it; |
| reply += ","; |
| } |
| |
| if (!reply.isEmpty()) |
| reply.left(reply.size() - 1); |
| |
| return reply; |
| } else if (argv[0] == "queryHwInfo") { |
| TFarmServer::HwInfo hwInfo; |
| queryHwInfo(hwInfo); |
| |
| QString ret; |
| ret += QString::number((unsigned long)hwInfo.m_cpuCount); |
| ret += ","; |
| ret += QString::number((unsigned long)(hwInfo.m_totPhysMem / 1024)); |
| ret += ","; |
| ret += QString::number((unsigned long)(hwInfo.m_availPhysMem / 1024)); |
| ret += ","; |
| ret += QString::number((unsigned long)(hwInfo.m_totVirtMem / 1024)); |
| ret += ","; |
| ret += QString::number((unsigned long)(hwInfo.m_availVirtMem / 1024)); |
| ret += ","; |
| ret += QString::number(hwInfo.m_type); |
| return ret; |
| } else if (argv[0] == "attachController" && argv.size() > 3) { |
| int port; |
| fromStr(port, argv[3]); |
| attachController(ControllerData(argv[1], argv[2], port)); |
| return ""; |
| } else if (argv[0] == "detachController" && argv.size() > 3) { |
| int port; |
| fromStr(port, argv[3]); |
| detachController(ControllerData(argv[1], argv[2], port)); |
| return ""; |
| } |
| } |
| |
| return QString::number(-1); |
| ; |
| } |
| |
| |
| |
| int FarmServer::addTask(const QString &id, const QString &cmdline) |
| { |
| |
| |
| QString lcmdline = cmdline; |
| |
| if (lcmdline.contains("runcasm")) { |
| |
| TFilePath rootDir = getGlobalRoot(); |
| TFilePath logfilePath = (rootDir + "logs" + id.toStdString()).withType(".log"); |
| |
| lcmdline += " -logfile " + QString::fromStdWString(logfilePath.getWideString()); |
| |
| TFilePath casmpmeterFp = getBinRoot() + CASMPMETER; |
| |
| lcmdline += " -ac " + QString::fromStdWString(casmpmeterFp.getWideString()); |
| lcmdline += " -ac_args " + QString(QUOTE_STR); |
| lcmdline += "$count $total $frame $filename " + id + QUOTE_STR; |
| } |
| |
| if (lcmdline.contains("zrender")) |
| lcmdline += " -taskid " + id; |
| |
| if (lcmdline.contains("tcomposer")) { |
| lcmdline += " -farm " + QString::number(m_controllerData.m_port) + "@" + m_controllerData.m_hostName; |
| lcmdline += " -id " + id; |
| } |
| |
| m_executor->addTask(new Task(id, lcmdline, m_userLog, this, m_controller)); |
| |
| QMutexLocker sl(&m_mux); |
| m_tasks.push_back(id); |
| return 0; |
| } |
| |
| |
| |
| int FarmServer::terminateTask(const QString &taskid) |
| { |
| #ifdef _WIN32 |
| HANDLE hJob = OpenJobObject( |
| MAXIMUM_ALLOWED, |
| TRUE, |
| #if QT_VERSION >= 0x050500 |
| taskid.toUtf8()); |
| #else |
| taskid.toAscii()); |
| #endif |
| |
| if (hJob != NULL) { |
| BOOL res = TerminateJobObject( |
| hJob, |
| 2); |
| } |
| #else |
| #endif |
| return 0; |
| } |
| |
| |
| |
| int FarmServer::getTasks(vector<QString> &tasks) |
| { |
| QMutexLocker sl(&m_mux); |
| tasks = m_tasks; |
| return m_tasks.size(); |
| } |
| |
| |
| |
| void FarmServer::queryHwInfo(HwInfo &hwInfo) |
| { |
| #ifdef _WIN32 |
| MEMORYSTATUS buff; |
| GlobalMemoryStatus(&buff); |
| |
| hwInfo.m_totPhysMem = buff.dwTotalPhys; |
| hwInfo.m_availPhysMem = buff.dwAvailPhys; |
| hwInfo.m_totVirtMem = buff.dwTotalVirtual; |
| hwInfo.m_availVirtMem = buff.dwAvailVirtual; |
| hwInfo.m_cpuCount = TSystem::getProcessorCount(); |
| hwInfo.m_type = Windows; |
| #else |
| #ifdef __sgi |
| hwInfo.m_cpuCount = sysconf(_SC_NPROC_CONF); |
| hwInfo.m_type = Irix; |
| #else |
| |
| #ifdef MACOSX |
| int mib[2]; |
| TINT64 physMemSize; |
| size_t len; |
| |
| mib[0] = CTL_HW; |
| mib[1] = HW_MEMSIZE; |
| len = sizeof(physMemSize); |
| sysctl(mib, 2, &physMemSize, &len, NULL, 0); |
| #endif |
| |
| #ifdef LINUX |
| TINT64 physMemSize = (TINT64)sysconf(_SC_PHYS_PAGES) * (TINT64)sysconf(_SC_PAGE_SIZE); |
| #endif |
| |
| hwInfo.m_cpuCount = TSystem::getProcessorCount(); |
| |
| |
| hwInfo.m_totPhysMem = physMemSize; |
| hwInfo.m_availPhysMem = 500000000; |
| hwInfo.m_totVirtMem = 500000000; |
| hwInfo.m_availVirtMem = 500000000; |
| hwInfo.m_type = Linux; |
| #endif |
| #endif |
| } |
| |
| |
| |
| void FarmServer::attachController(const ControllerData &data) |
| { |
| setController(data); |
| } |
| |
| |
| |
| void FarmServer::detachController(const ControllerData &data) |
| { |
| if (m_controllerData == data) { |
| |
| m_controller = 0; |
| } |
| } |
| |
| |
| |
| void FarmServer::removeTask(const QString &id) |
| { |
| QMutexLocker sl(&m_mux); |
| vector<QString>::iterator it = find(m_tasks.begin(), m_tasks.end(), id); |
| if (it != m_tasks.end()) |
| m_tasks.erase(it); |
| } |
| |
| |
| |
| namespace |
| { |
| |
| std::string getLine(std::istream &is) |
| { |
| std::string out; |
| char c; |
| |
| while (!is.eof()) { |
| is.get(c); |
| if (c != '\r') |
| if (c != '\n') |
| if (!is.fail()) |
| out.append(1, c); |
| else |
| break; |
| else |
| break; |
| } |
| return out; |
| } |
| |
| } |
| |
| int inline STRICMP(const QString &a, const QString &b) { return a.compare(b, Qt::CaseSensitive); } |
| int inline STRICMP(const char *a, const char *b) |
| { |
| QString str(a); |
| return str.compare(QString(b), Qt::CaseSensitive); |
| } |
| |
| bool loadServerData(const QString &hostname, QString &addr, int &port) |
| { |
| TFilePath rootDir = getGlobalRoot(); |
| |
| TFilePath fp = rootDir + "config" + "servers.txt"; |
| |
| #ifndef _WIN32 |
| int acc = access(::to_string(fp).c_str(), 00); |
| bool fileExists = acc != -1; |
| if (!fileExists) |
| return false; |
| #endif |
| |
| Tifstream is(fp); |
| if (!is.good()) |
| return false; |
| while (!is.eof()) { |
| std::string line = getLine(is); |
| std::istringstream iss(line); |
| |
| std::string name; |
| std::string ipAddress; |
| |
| iss >> name >> ipAddress >> port; |
| if (name[0] == '#') |
| continue; |
| #if QT_VERSION >= 0x050500 |
| if (STRICMP(hostname.toUtf8(), name.c_str()) == 0) |
| #else |
| if (STRICMP(hostname.toAscii(), name.c_str()) == 0) |
| #endif |
| { |
| addr = QString(ipAddress.c_str()); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| |
| |
| void FarmServerService::onStart(int argc, char *argv[]) |
| { |
| |
| TThread::init(); |
| |
| #ifdef _WIN32 |
| |
| #endif |
| |
| TFilePath lRootDir = getLocalRoot(); |
| TFileStatus fs(lRootDir); |
| bool lRootDirExists = fs.isDirectory(); |
| |
| if (!lRootDirExists) { |
| std::string errMsg("Unable to start the Server"); |
| errMsg += "\n"; |
| errMsg += "The directory specified as Local Root does not exist"; |
| errMsg += "\n"; |
| |
| addToMessageLog(errMsg); |
| |
| |
| #ifdef MACOSX |
| system("echo 'local root does not exist' >> err.log"); |
| #endif |
| |
| |
| setStatus(TService::Stopped, NO_ERROR, 0); |
| } |
| |
| TFilePath gRootDir = getGlobalRoot(); |
| if (::to_string(gRootDir) == "") { |
| std::string errMsg("Unable to get TFARMGLOBALROOT environment variable"); |
| addToMessageLog(errMsg); |
| |
| |
| #ifdef MACOSX |
| system("echo 'Unable to set the global root' >> err.log"); |
| #endif |
| |
| |
| setStatus(TService::Stopped, NO_ERROR, 0); |
| } |
| |
| bool gRootDirExists = dirExists(gRootDir); |
| ; |
| if (!gRootDirExists) { |
| std::string errMsg("Unable to start the Server"); |
| errMsg += "\n"; |
| errMsg += "The directory " + ::to_string(gRootDir) + " specified as Global Root does not exist"; |
| ; |
| |
| addToMessageLog(errMsg); |
| |
| |
| #ifdef MACOSX |
| system("echo 'Global root does not exist' >> err.log"); |
| #endif |
| |
| |
| setStatus(TService::Stopped, NO_ERROR, 0); |
| } |
| |
| |
| |
| TFilePath fp = gRootDir + "config" + "controller.txt"; |
| |
| ControllerData controllerData; |
| |
| try { |
| ::loadControllerData(fp, controllerData); |
| } catch (TException &e) { |
| std::string errMsg("Unable to start the Server"); |
| errMsg += "\n"; |
| errMsg += ::to_string(e.getMessage()); |
| addToMessageLog(errMsg); |
| setStatus(TService::Stopped, NO_ERROR, 0); |
| } |
| |
| if (isRunningAsConsoleApp()) { |
| |
| m_userLog = new TUserLog(); |
| } else { |
| TFilePath logFilePath = lRootDir + "server.log"; |
| m_userLog = new TUserLog(logFilePath); |
| } |
| |
| m_userLog->info("ToonzFarm Server 1.0"); |
| |
| |
| |
| bool ret = loadServerData(TSystem::getHostName(), m_addr, m_port); |
| |
| if (!ret) { |
| QString msg("Unable to get the port number of "); |
| msg += TSystem::getHostName(); |
| msg += " from the servers config file"; |
| msg += "\n"; |
| msg += "Using the default port number 8002"; |
| msg += "\n"; |
| msg += "\n"; |
| |
| m_userLog->info(msg); |
| m_port = 8002; |
| } |
| |
| #ifdef __sgi |
| { |
| std::ofstream os("/tmp/.tfarmserverd.dat"); |
| os << m_port; |
| } |
| #endif |
| |
| m_farmServer = new FarmServer(m_port, m_userLog); |
| m_farmServer->setController(controllerData); |
| |
| try { |
| m_farmServer->getController()->attachServer(TSystem::getHostName(), m_addr, m_port); |
| } catch (TException const&) { |
| } |
| |
| #ifdef _WIN32 |
| TFilePath diskMountingsFilePath = lRootDir + "config" + "diskmap.cfg"; |
| if (myDoesExists(diskMountingsFilePath)) { |
| loadDiskMountingPoints(diskMountingsFilePath); |
| |
| |
| |
| |
| |
| } |
| #endif |
| |
| |
| |
| |
| |
| |
| QEventLoop eventLoop; |
| |
| |
| QObject::connect(m_farmServer, SIGNAL(finished()), &eventLoop, SLOT(quit())); |
| |
| |
| m_farmServer->start(); |
| |
| |
| eventLoop.exec(); |
| |
| |
| |
| int rc = m_farmServer->getExitCode(); |
| |
| #ifdef __sgi |
| remove("/tmp/.tfarmserver.dat"); |
| #endif |
| |
| if (rc != 0) { |
| std::string msg("An error occurred starting the ToonzFarm Server"); |
| msg += "\n"; |
| |
| #ifdef _WIN32 |
| LPVOID lpMsgBuf; |
| FormatMessage( |
| FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| FORMAT_MESSAGE_FROM_SYSTEM | |
| FORMAT_MESSAGE_IGNORE_INSERTS, |
| NULL, |
| rc, |
| 0, |
| (LPTSTR)&lpMsgBuf, |
| 0, |
| NULL); |
| |
| msg += std::string((char *)lpMsgBuf); |
| |
| |
| LocalFree(lpMsgBuf); |
| #else |
| #endif |
| |
| addToMessageLog(msg); |
| m_userLog->error(QString::fromStdString(msg)); |
| setStatus(TService::Stopped, NO_ERROR, 0); |
| } |
| |
| std::string msg("Exiting with code "); |
| msg += std::to_string(ret); |
| msg += "\n"; |
| m_userLog->info(QString::fromStdString(msg)); |
| } |
| |
| |
| |
| void FarmServerService::onStop() |
| { |
| try { |
| m_farmServer->getController()->detachServer(TSystem::getHostName(), m_addr, m_port); |
| } catch (TException & ) { |
| } |
| |
| |
| |
| |
| #ifdef _WIN32 |
| unmountDisks(); |
| #endif |
| |
| TTcpIpClient client; |
| |
| int socketId; |
| int ret = client.connect(TSystem::getHostName(), "", m_farmServer->getPort(), socketId); |
| if (ret == OK) { |
| client.send(socketId, "shutdown"); |
| } |
| } |
| |
| #ifdef _WIN32 |
| |
| |
| |
| void FarmServerService::loadDiskMountingPoints(const TFilePath &fp) |
| { |
| Tifstream is(fp); |
| if (!is) |
| throw std::string("File " + ::to_string(fp) + " not found"); |
| char buffer[1024]; |
| while (is.getline(buffer, sizeof(buffer))) { |
| char *s = buffer; |
| while (isBlank(*s)) |
| s++; |
| if (*s == '\0' || *s == '#' || *s == '!') |
| continue; |
| if (*s == '=') |
| continue; |
| char *t = s; |
| while (*t && *t != '=') |
| t++; |
| if (*t != '=') |
| continue; |
| char *q = t; |
| while (q > s && isBlank(*(q - 1))) |
| q--; |
| if (q == s) |
| continue; |
| std::string from(s, q - s); |
| s = t + 1; |
| while (isBlank(*s)) |
| s++; |
| if (*s == '\0') |
| continue; |
| t = s; |
| while (*t) |
| t++; |
| while (t > s && isBlank(*(t - 1))) |
| t--; |
| if (t == s) |
| continue; |
| string dst(s, t - s); |
| m_disks[from] = dst; |
| } |
| } |
| |
| |
| |
| void FarmServerService::mountDisks() |
| { |
| std::map<std::string, std::string>::iterator it = m_disks.begin(); |
| for (; it != m_disks.end(); ++it) { |
| std::string drive = it->first; |
| std::string remoteName = it->second; |
| |
| NETRESOURCE NetResource; |
| NetResource.dwType = RESOURCETYPE_DISK; |
| NetResource.lpLocalName = (LPSTR)drive.c_str(); |
| NetResource.lpRemoteName = (LPSTR)remoteName.c_str(); |
| NetResource.lpProvider = NULL; |
| |
| DWORD res = WNetAddConnection2( |
| &NetResource, |
| 0, |
| #if QT_VERSION >= 0x050500 |
| TSystem::getUserName().toUtf8(), |
| #else |
| TSystem::getUserName().toAscii(), |
| #endif |
| 0); |
| |
| if (res == NO_ERROR) |
| m_disksMounted.push_back(drive); |
| |
| if (res != NO_ERROR && res != ERROR_ALREADY_ASSIGNED) { |
| |
| |
| DWORD dwLastError; |
| char errorBuf[1024]; |
| char nameBuf[1024]; |
| |
| DWORD rett = WNetGetLastError( |
| &dwLastError, |
| errorBuf, |
| sizeof(errorBuf), |
| nameBuf, |
| sizeof(nameBuf)); |
| |
| std::string errorMessage("Unable to map "); |
| errorMessage += NetResource.lpRemoteName; |
| errorMessage += " to logic volume "; |
| errorMessage += NetResource.lpLocalName; |
| |
| addToMessageLog(errorMessage); |
| } |
| } |
| } |
| |
| |
| |
| void FarmServerService::unmountDisks() |
| { |
| vector<std::string>::iterator it = m_disksMounted.begin(); |
| for (; it != m_disksMounted.end(); ++it) { |
| std::string drive = *it; |
| |
| DWORD res = WNetCancelConnection2( |
| drive.c_str(), |
| CONNECT_UPDATE_PROFILE, |
| TRUE); |
| |
| if (res != NO_ERROR && res != ERROR_NOT_CONNECTED) { |
| std::string errorMessage("Unable to unmap "); |
| errorMessage += drive.c_str(); |
| addToMessageLog(errorMessage); |
| } |
| } |
| |
| m_disksMounted.clear(); |
| } |
| |
| #endif |
| |
| |
| |
| |
| |
| int main(int argc, char **argv) |
| { |
| QCoreApplication a(argc, argv); |
| |
| bool console = false; |
| |
| if (argc > 1) { |
| std::string serviceName("ToonzFarmServer"); |
| std::string serviceDisplayName = serviceName; |
| |
| TCli::SimpleQualifier consoleQualifier("-console", "Run as console app"); |
| TCli::StringQualifier installQualifier("-install name", "Install service as 'name'"); |
| TCli::SimpleQualifier removeQualifier("-remove", "Remove service"); |
| |
| TCli::Usage usage(argv[0]); |
| usage.add(consoleQualifier + installQualifier + removeQualifier); |
| if (!usage.parse(argc, argv)) |
| exit(1); |
| |
| #ifdef _WIN32 |
| if (installQualifier.isSelected()) { |
| char szPath[512]; |
| |
| if (installQualifier.getValue() != "") |
| serviceDisplayName = installQualifier.getValue(); |
| |
| if (GetModuleFileName(NULL, szPath, 512) == 0) { |
| std::cout << "Unable to install"; |
| std::cout << serviceName << " - "; |
| std::cout << getLastErrorText().c_str() << std::endl |
| << std::endl; |
| |
| return 0; |
| } |
| |
| TService::install( |
| serviceName, |
| serviceDisplayName, |
| TFilePath(szPath)); |
| |
| return 0; |
| } |
| |
| if (removeQualifier.isSelected()) { |
| TService::remove(serviceName); |
| return 0; |
| } |
| #endif |
| |
| if (consoleQualifier.isSelected()) |
| console = true; |
| } |
| |
| TSystem::hasMainLoop(false); |
| TService::instance()->run(argc, argv, console); |
| |
| return 0; |
| } |
| |