/* ---- This file is part of SECONDO. Copyright (C) 2004, University in Hagen, Department of Computer Science, Database Systems for New Applications. SECONDO 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. SECONDO 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 SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---- //paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}] //[TOC] [\tableofcontents] [1] Header File of the class ~PregelAlgebra~ November 2018, J. Mende [TOC] 1 Overview This header file contains the declaration of the classes Commander, Runner and RemoteExecutionException. 2 Defines and includes */ #ifndef SECONDO_TES_COMMANDER_H #define SECONDO_TES_COMMANDER_H #include "../typedefs.h" #include #include "Algebras/Distributed2/ConnectionInfo.h" #include #include "../TESContext.h" #include "Algebras/Distributed2/CommandLog.h" namespace distributed3 { template using resultMapper = std::function; class Runner { private: WorkerConnection *connection; std::string query; bool hasRun = false; int err = 0; double runtime = 0.0; distributed2::CommandLog commandLog; //distributed2::CommandLog commandLog; public: Runner(WorkerConnection *connection, std::string &query); virtual ~Runner(); std::string run() noexcept(false); bool inline successful() { return err == 0; } }; class RemoteExecutionException : public std::exception { private: std::string message; public: RemoteExecutionException(const std::string &message); const std::string &getMessage() const; }; class Commander { public: const static resultMapper isTrue; const static resultMapper throwWhenFalse; template static result_type *remoteQuery(WorkerConnection *connection, std::string &query, const resultMapper &mapper) noexcept(false) { Runner runner(connection, query); std::string response = runner.run(); return mapper(response); } template static supplier broadcast(supplier runners, resultMapper mapper, bool parallel = false) { if (parallel) { return multiThreaded(runners, mapper); } else { return singleThreaded(runners, mapper); } } private: template static supplier singleThreaded( supplier &runners, resultMapper &mapper) { auto result = [&runners, &mapper]() -> result_type * { try { Runner *runner; if ((runner = runners()) == nullptr) { return nullptr; } std::string response = runner->run(); delete runner; return mapper(response); } catch (RemoteExecutionException &e) { return nullptr; } }; return (supplier) result; } template static supplier multiThreaded( supplier &runners, resultMapper &mapper) { boost::mutex resultLock; std::vector threads; std::vector *resultStore = new std::vector(); auto runAsynchronous = [&mapper, &resultLock, resultStore]( Runner *runner, bool &asynchExceptions) { result_type *result; try { std::string response = runner->run(); delete runner; result = mapper(response); } catch (RemoteExecutionException &e) { asynchExceptions = true; delete runner; return; } resultLock.lock(); if(result!=nullptr){ resultStore->push_back(result); } resultLock.unlock(); }; Runner *runner; bool asynchExceptions = false; while ((runner = runners()) != nullptr) { auto runnable = new boost::thread(boost::bind(runAsynchronous, runner, boost::ref( asynchExceptions))); threads.push_back(runnable); } for (boost::thread *thread : threads) { thread->join(); delete thread; } auto returnSupplier = [resultStore, &asynchExceptions]() mutable -> result_type * { if (asynchExceptions) { //for (auto result : *resultStore) { // delete result; //} resultStore->clear(); delete resultStore; resultStore = nullptr; throw RemoteExecutionException("There were failing remote queries."); } if (resultStore == nullptr) { return nullptr; } if (resultStore->empty()) { delete resultStore; resultStore = nullptr; return nullptr; } auto returnValue = resultStore->back(); resultStore->pop_back(); return returnValue; }; return (supplier) returnSupplier; } }; } #endif //SECONDO_COMMANDER_H