diff --git a/src/common/api.hpp b/src/common/api.hpp index 6456e3c..270b78e 100644 --- a/src/common/api.hpp +++ b/src/common/api.hpp @@ -10,26 +10,4 @@ enum class Api { Chapter, Playground, Practice }; enum class Language : uint8_t { CPP, GO, HASKELL, PYTHON, RUST }; using Action = Api; -struct LanguageAction { - Language language; - Action action; - - bool operator==(LanguageAction const & other) const { - return language == other.language && action == other.action; - } -}; - -struct LanguageActionHasher { - size_t operator()(LanguageAction const & l) const { - constexpr size_t kBitsInByte = 8; - constexpr size_t kShift = sizeof(Language) * kBitsInByte; - - size_t seed = 0; - seed ^= static_cast(l.language); - seed <<= kShift; - seed ^= static_cast(l.action); - return seed; - } -}; - } // namespace watchman diff --git a/src/core/code_launcher/code_launcher_info.hpp b/src/core/code_launcher/code_launcher_info.hpp index 33678d4..1ef2317 100644 --- a/src/core/code_launcher/code_launcher_info.hpp +++ b/src/core/code_launcher/code_launcher_info.hpp @@ -8,7 +8,7 @@ namespace watchman { struct CodeLauncherInfo { std::string containerId; std::string image; - LanguageAction type; + Language type; }; } // namespace watchman diff --git a/src/core/code_launcher/code_launcher_interface.hpp b/src/core/code_launcher/code_launcher_interface.hpp index 07efa78..15264eb 100644 --- a/src/core/code_launcher/code_launcher_interface.hpp +++ b/src/core/code_launcher/code_launcher_interface.hpp @@ -13,7 +13,7 @@ class CodeLauncherInterface { virtual ~CodeLauncherInterface() = default; virtual Response runCode(std::string && inMemoryTarWithSources, - std::vector && cmdLineArgs) = 0; + std::vector && cmdLineArgs, Action action) = 0; virtual CodeLauncherInfo getInfo() const = 0; }; diff --git a/src/core/code_launcher/code_launcher_provider_interface.hpp b/src/core/code_launcher/code_launcher_provider_interface.hpp index 35cba05..6e7101d 100644 --- a/src/core/code_launcher/code_launcher_provider_interface.hpp +++ b/src/core/code_launcher/code_launcher_provider_interface.hpp @@ -10,7 +10,7 @@ class CodeLauncherProviderInterface { public: virtual ~CodeLauncherProviderInterface() = default; - virtual std::unique_ptr getCodeLauncher(LanguageAction type) = 0; + virtual std::unique_ptr getCodeLauncher(Language language) = 0; }; } // namespace watchman diff --git a/src/core/code_launcher/detail/callbacked_code_launcher.cpp b/src/core/code_launcher/detail/callbacked_code_launcher.cpp index ed27666..495fe02 100644 --- a/src/core/code_launcher/detail/callbacked_code_launcher.cpp +++ b/src/core/code_launcher/detail/callbacked_code_launcher.cpp @@ -10,8 +10,8 @@ CallbackedCodeLauncher::CallbackedCodeLauncher(std::unique_ptr && cmdLineArgs) { - return m_codeLauncher->runCode(std::move(inMemoryTarWithSources), std::move(cmdLineArgs)); + std::vector && cmdLineArgs, Action action) { + return m_codeLauncher->runCode(std::move(inMemoryTarWithSources), std::move(cmdLineArgs), action); } CodeLauncherInfo CallbackedCodeLauncher::getInfo() const { return m_codeLauncher->getInfo(); } diff --git a/src/core/code_launcher/detail/callbacked_code_launcher.hpp b/src/core/code_launcher/detail/callbacked_code_launcher.hpp index b88aec0..1920869 100644 --- a/src/core/code_launcher/detail/callbacked_code_launcher.hpp +++ b/src/core/code_launcher/detail/callbacked_code_launcher.hpp @@ -18,7 +18,7 @@ class CallbackedCodeLauncher : public CodeLauncherInterface { CallbackedCodeLauncher & operator=(CallbackedCodeLauncher &&) = delete; Response runCode(std::string && inMemoryTarWithSources, - std::vector && cmdLineArgs) override; + std::vector && cmdLineArgs, Action action) override; CodeLauncherInfo getInfo() const override; diff --git a/src/core/code_launcher/detail/code_launchers.cpp b/src/core/code_launcher/detail/code_launchers.cpp index 468a2a1..72bed79 100644 --- a/src/core/code_launcher/detail/code_launchers.cpp +++ b/src/core/code_launcher/detail/code_launchers.cpp @@ -21,6 +21,10 @@ std::map kDefaultPaths{{Action::Chapter, kTaskWorkdir} }; +BaseCodeLauncher::BaseCodeLauncher(std::string id, Language language) + : containerId(std::move(id)) + , type(std::move(language)) {} + bool BaseCodeLauncher::prepareCode(std::string && tarString, Action type) { auto defaultPath = kDefaultPaths.find(type); if (defaultPath == kDefaultPaths.end()) { @@ -41,71 +45,33 @@ bool BaseCodeLauncher::prepareCode(std::string && tarString, Action type) { return true; } -Response PlaygroundCodeLauncher::runCode(std::string && inMemoryTarWithSources, - std::vector && cmdLineArgs) { - if (!prepareCode(std::move(inMemoryTarWithSources), Action::Playground)) { +Response BaseCodeLauncher::runCode(std::string && inMemoryTarWithSources, + std::vector && cmdLineArgs, Action action) { + if (!prepareCode(std::move(inMemoryTarWithSources), action)) { return {}; } auto result = dockerWrapper.exec({.containerId = containerId, .cmd = std::move(cmdLineArgs)}); - if (!result.success) { - return {result.success, result.message}; - } - - return getPlaygroungResponse(result.message); -} -PracticeCodeLauncher::PracticeCodeLauncher(std::string id, Language type) - : BaseCodeLauncher(std::move(id), std::move(type)) {} - -PlaygroundCodeLauncher::PlaygroundCodeLauncher(std::string id, Language type) - : BaseCodeLauncher(std::move(id), type) {} - -Response ChapterCodeLauncher::runCode(std::string && inMemoryTarWithSources, - std::vector && cmdLineArgs) { - if (!prepareCode(std::move(inMemoryTarWithSources), Action::Chapter)) { - return {}; - } - auto result = dockerWrapper.exec({.containerId = containerId, .cmd = std::move(cmdLineArgs)}); if (!result.success) { return {result.success, result.message}; } - return getCourseResponse(result.message); -} + switch (action) { + case Action::Chapter: return getCourseResponse(result.message); -ChapterCodeLauncher::ChapterCodeLauncher(std::string id, Language type) - : BaseCodeLauncher(std::move(id), type) {} + case Action::Playground: return getPlaygroungResponse(result.message); -BaseCodeLauncher::BaseCodeLauncher(std::string id, Language type) - : containerId(std::move(id)) - , type(std::move(type)) {} - -CodeLauncherInfo ChapterCodeLauncher::getInfo() const { - return {containerId, dockerWrapper.getImage(containerId), {type, Action::Chapter}}; -} - -CodeLauncherInfo PlaygroundCodeLauncher::getInfo() const { - return {containerId, dockerWrapper.getImage(containerId), {type, Action::Playground}}; -} - -CodeLauncherInfo PracticeCodeLauncher::getInfo() const { - return {containerId, dockerWrapper.getImage(containerId), {type, Action::Practice}}; -} + case Action::Practice: return getPracticeResponse(result.message); -Response PracticeCodeLauncher::runCode(std::string && inMemoryTarWithSources, - std::vector && dockerCmdLineArgs) { - if (!prepareCode(std::move(inMemoryTarWithSources), Action::Practice)) { - return {}; + default: break; } - auto result = - dockerWrapper.exec({.containerId = containerId, .cmd = std::move(dockerCmdLineArgs)}); - if (!result.success) { - return {result.success, result.message}; - } + throw std::logic_error{"Error: unknown action"}; +} - return getPracticeResponse(result.message); +CodeLauncherInfo BaseCodeLauncher::getInfo() const { + return {containerId, dockerWrapper.getImage(containerId), type}; } } // namespace watchman diff --git a/src/core/code_launcher/detail/code_launchers.hpp b/src/core/code_launcher/detail/code_launchers.hpp index d87e567..1441e3d 100644 --- a/src/core/code_launcher/detail/code_launchers.hpp +++ b/src/core/code_launcher/detail/code_launchers.hpp @@ -10,30 +10,14 @@ struct BaseCodeLauncher : CodeLauncherInterface { std::string containerId; Language type; - BaseCodeLauncher(std::string id, Language type); + BaseCodeLauncher(std::string id, Language language); // Creates in-memory tar and passes it to docker bool prepareCode(std::string && tarString, Action type); -}; - -struct ChapterCodeLauncher final : BaseCodeLauncher { - ChapterCodeLauncher(std::string id, Language type); - Response runCode(std::string && inMemoryTarWithSources, - std::vector && cmdLineArgs) override; - CodeLauncherInfo getInfo() const override; -}; -struct PlaygroundCodeLauncher final : BaseCodeLauncher { - PlaygroundCodeLauncher(std::string id, Language type); - Response runCode(std::string && inMemoryTarWithSources, - std::vector && cmdLineArgs) override; - CodeLauncherInfo getInfo() const override; -}; + Response runCode(std::string && inMemoryTarWithSources, std::vector && cmdLineArgs, + Action action) override; -struct PracticeCodeLauncher final : BaseCodeLauncher { - PracticeCodeLauncher(std::string id, Language type); - Response runCode(std::string && inMemoryTarWithSources, - std::vector && dockerCmdLineArgs) override; CodeLauncherInfo getInfo() const override; }; diff --git a/src/core/code_launcher/detail/container_manipulator.cpp b/src/core/code_launcher/detail/container_manipulator.cpp index 92be79d..cdb43a1 100644 --- a/src/core/code_launcher/detail/container_manipulator.cpp +++ b/src/core/code_launcher/detail/container_manipulator.cpp @@ -15,8 +15,7 @@ namespace watchman::detail { constexpr std::string_view kSenjunPattern = "senjun"; std::unique_ptr -CodeLauncherOSManipulator::createCodeLauncher(std::string const & image, - LanguageAction languageAction) { +CodeLauncherOSManipulator::createCodeLauncher(std::string const & image, Language language) { RunContainer params; params.image = image; @@ -31,16 +30,7 @@ CodeLauncherOSManipulator::createCodeLauncher(std::string const & image, Log::info("Launch container: {}, id: {}", image, id); - std::unique_ptr container; - auto const l = languageAction.language; - - switch (languageAction.action) { - case Action::Chapter: return std::make_unique(std::move(id), l); - case Action::Playground: return std::make_unique(std::move(id), l); - case Action::Practice: return std::make_unique(std::move(id), l); - } - - throw std::logic_error{"Unknorn image type while creating code launcher"}; + return std::make_unique(std::move(id), language); } void CodeLauncherOSManipulator::removeCodeLauncher(std::string const & id) { @@ -62,8 +52,7 @@ void CodeLauncherOSManipulator::asyncRemoveCodeLauncher(std::string const & id) | unifex::then([this, &id] { removeCodeLauncher(id); }) | unifex::sync_wait(); } -void CodeLauncherOSManipulator::asyncCreateCodeLauncher(LanguageAction type, - std::string const & image) { +void CodeLauncherOSManipulator::asyncCreateCodeLauncher(Language type, std::string const & image) { unifex::schedule(m_containersContext.get_scheduler()) | unifex::then([this, type, image] { auto container = createCodeLauncher(image, type); if (container == nullptr) { @@ -90,11 +79,11 @@ void CodeLauncherOSManipulator::syncRemoveRunningCodeLanchers() { } void CodeLauncherOSManipulator::syncCreateCodeLaunchers(Config const & config) { - auto const launchContainers = [this](auto && containerTypes, Action action) { + auto const launchContainers = [this](auto && containerTypes) { for (auto const & [language, info] : containerTypes) { std::list> containers; for (size_t index = 0; index < info.launched; ++index) { - auto container = createCodeLauncher(info.imageName, {language, action}); + auto container = createCodeLauncher(info.imageName, language); if (container == nullptr) { continue; } @@ -102,14 +91,14 @@ void CodeLauncherOSManipulator::syncCreateCodeLaunchers(Config const & config) { } if (!containers.empty()) { - m_storage.addValues({language, action}, std::move(containers)); + m_storage.addValues(language, std::move(containers)); } } }; - launchContainers(config.courses, Action::Chapter); - launchContainers(config.playgrounds, Action::Playground); - launchContainers(config.practices, Action::Practice); + launchContainers(config.courses); + launchContainers(config.playgrounds); + launchContainers(config.practices); } } // namespace watchman::detail diff --git a/src/core/code_launcher/detail/container_manipulator.hpp b/src/core/code_launcher/detail/container_manipulator.hpp index f923efb..a465b99 100644 --- a/src/core/code_launcher/detail/container_manipulator.hpp +++ b/src/core/code_launcher/detail/container_manipulator.hpp @@ -9,14 +9,14 @@ namespace watchman::detail { -using Storage = ExtractingStorage; +using Storage = ExtractingStorage; class CodeLauncherOSManipulator { public: CodeLauncherOSManipulator(Config && config, Storage & storage); void asyncRemoveCodeLauncher(std::string const & id); - void asyncCreateCodeLauncher(LanguageAction type, std::string const & image); + void asyncCreateCodeLauncher(Language type, std::string const & image); private: void syncRemoveRunningCodeLanchers(); @@ -25,7 +25,7 @@ class CodeLauncherOSManipulator { // todo // user pair, not code launcher info std::unique_ptr createCodeLauncher(std::string const & image, - LanguageAction taskType); + Language language); void removeCodeLauncher(std::string const & id); // Original storage lies in restarting_code_launcher.hpp diff --git a/src/core/code_launcher/detail/restarting_code_launcher_provider.cpp b/src/core/code_launcher/detail/restarting_code_launcher_provider.cpp index 041c1c2..b302134 100644 --- a/src/core/code_launcher/detail/restarting_code_launcher_provider.cpp +++ b/src/core/code_launcher/detail/restarting_code_launcher_provider.cpp @@ -14,12 +14,12 @@ RestartingCodeLauncherProvider::RestartingCodeLauncherProvider(Config && config) } std::unique_ptr -RestartingCodeLauncherProvider::getCodeLauncher(LanguageAction type) { - if (!codeLauncherTypeIsValid(type)) { +RestartingCodeLauncherProvider::getCodeLauncher(Language language) { + if (!codeLauncherTypeIsValid(language)) { return nullptr; } - auto launcher = m_storage.extract(type); + auto launcher = m_storage.extract(language); auto info = launcher->getInfo(); auto ptr = std::make_unique( @@ -37,8 +37,8 @@ void RestartingCodeLauncherProvider::restartCodeLauncher(CodeLauncherInfo const m_manipulator->asyncCreateCodeLauncher(restartInfo.type, image); } -bool RestartingCodeLauncherProvider::codeLauncherTypeIsValid(LanguageAction const & name) const { - return m_storage.contains(name); +bool RestartingCodeLauncherProvider::codeLauncherTypeIsValid(Language language) const { + return m_storage.contains(language); } RestartingCodeLauncherProvider::~RestartingCodeLauncherProvider() = default; diff --git a/src/core/code_launcher/detail/restarting_code_launcher_provider.hpp b/src/core/code_launcher/detail/restarting_code_launcher_provider.hpp index 57ae656..aca1ab2 100644 --- a/src/core/code_launcher/detail/restarting_code_launcher_provider.hpp +++ b/src/core/code_launcher/detail/restarting_code_launcher_provider.hpp @@ -19,13 +19,13 @@ class RestartingCodeLauncherProvider : public CodeLauncherProviderInterface { operator=(RestartingCodeLauncherProvider const & other) = delete; RestartingCodeLauncherProvider & operator=(RestartingCodeLauncherProvider && other) = delete; - std::unique_ptr getCodeLauncher(LanguageAction type) override; + std::unique_ptr getCodeLauncher(Language language) override; private: void restartCodeLauncher(CodeLauncherInfo const & info); - bool codeLauncherTypeIsValid(LanguageAction const & name) const; + bool codeLauncherTypeIsValid(Language language) const; - ExtractingStorage m_storage; + ExtractingStorage m_storage; std::unique_ptr m_manipulator; }; diff --git a/src/core/code_launcher/detail/storage.hpp b/src/core/code_launcher/detail/storage.hpp index 5e94a51..066ac91 100644 --- a/src/core/code_launcher/detail/storage.hpp +++ b/src/core/code_launcher/detail/storage.hpp @@ -12,7 +12,7 @@ namespace watchman::detail { // Each element can be accessed only one time // It is required to add new element after extracting -template +template class ExtractingStorage { public: bool contains(K const & key) const { return storage.contains(key); } @@ -38,13 +38,15 @@ class ExtractingStorage { } void addValues(K const & key, std::list> values) { - storage.emplace(key, std::move(values)); + for (auto && value : values) { + storage[key].push_back(std::move(value)); + } } private: std::mutex mutex; std::condition_variable storageFree; - std::unordered_map>, H> storage; + std::unordered_map>> storage; }; } // namespace watchman::detail diff --git a/src/core/service.cpp b/src/core/service.cpp index d191782..f721d8c 100644 --- a/src/core/service.cpp +++ b/src/core/service.cpp @@ -78,15 +78,16 @@ Response Service::runChapter(ChapterTaskParams const & runTaskParams) { return {kUserCodeError, "Sources and tests are not provided", ""}; } - auto codeLauncher = m_codeLauncherProvider->getCodeLauncher( - {runTaskParams.language, Action::Chapter}); // here we have got a race + auto codeLauncher = + m_codeLauncherProvider->getCodeLauncher(runTaskParams.language); // here we have got a race if (codeLauncher == nullptr) { return {kInvalidCode, fmt::format("Probably wrong containerType")}; } auto result = codeLauncher->runCode(detail::prepareData(runTaskParams), - getArgsCourse(kFilenameTask, runTaskParams.cmdLineArgs)); + getArgsCourse(kFilenameTask, runTaskParams.cmdLineArgs), + Action::Chapter); if (errorCodeIsUnexpected(result.sourceCode)) { Log::error("Error return code {} from image {}", result.sourceCode, codeLauncher->getInfo().image); @@ -96,7 +97,7 @@ Response Service::runChapter(ChapterTaskParams const & runTaskParams) { Response Service::runPlayground(PlaygroundTaskParams const & runProjectParams) { auto codeLauncher = m_codeLauncherProvider->getCodeLauncher( - {runProjectParams.language, Action::Playground}); // here we have got a race + runProjectParams.language); // here we have got a race if (codeLauncher == nullptr) { return {}; @@ -104,19 +105,21 @@ Response Service::runPlayground(PlaygroundTaskParams const & runProjectParams) { return codeLauncher->runCode( detail::prepareData(runProjectParams), - getArgsPlayground(runProjectParams.project.name, runProjectParams.cmdLineArgs)); + getArgsPlayground(runProjectParams.project.name, runProjectParams.cmdLineArgs), + Action::Playground); } Response Service::runPractice(RunPracticeParams const & params) { - auto codeLauncher = m_codeLauncherProvider->getCodeLauncher( - {params.language, Action::Practice}); // here we have got a race + auto codeLauncher = + m_codeLauncherProvider->getCodeLauncher(params.language); // here we have got a race if (codeLauncher == nullptr) { return {}; } auto dockerCmdArgs = getPracticeDockerArgs(params); - return codeLauncher->runCode(detail::prepareData(params), std::move(dockerCmdArgs)); + return codeLauncher->runCode(detail::prepareData(params), std::move(dockerCmdArgs), + Action::Practice); } } // namespace watchman