Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions src/common/api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<size_t>(l.language);
seed <<= kShift;
seed ^= static_cast<size_t>(l.action);
return seed;
}
};

} // namespace watchman
2 changes: 1 addition & 1 deletion src/core/code_launcher/code_launcher_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace watchman {
struct CodeLauncherInfo {
std::string containerId;
std::string image;
LanguageAction type;
Language type;
};

} // namespace watchman
2 changes: 1 addition & 1 deletion src/core/code_launcher/code_launcher_interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class CodeLauncherInterface {
virtual ~CodeLauncherInterface() = default;

virtual Response runCode(std::string && inMemoryTarWithSources,
std::vector<std::string> && cmdLineArgs) = 0;
std::vector<std::string> && cmdLineArgs, Action action) = 0;

virtual CodeLauncherInfo getInfo() const = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class CodeLauncherProviderInterface {
public:
virtual ~CodeLauncherProviderInterface() = default;

virtual std::unique_ptr<CodeLauncherInterface> getCodeLauncher(LanguageAction type) = 0;
virtual std::unique_ptr<CodeLauncherInterface> getCodeLauncher(Language language) = 0;
};

} // namespace watchman
4 changes: 2 additions & 2 deletions src/core/code_launcher/detail/callbacked_code_launcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ CallbackedCodeLauncher::CallbackedCodeLauncher(std::unique_ptr<CodeLauncherInter
CallbackedCodeLauncher::~CallbackedCodeLauncher() { m_releaser(); }

Response CallbackedCodeLauncher::runCode(std::string && inMemoryTarWithSources,
std::vector<std::string> && cmdLineArgs) {
return m_codeLauncher->runCode(std::move(inMemoryTarWithSources), std::move(cmdLineArgs));
std::vector<std::string> && cmdLineArgs, Action action) {
return m_codeLauncher->runCode(std::move(inMemoryTarWithSources), std::move(cmdLineArgs), action);
}

CodeLauncherInfo CallbackedCodeLauncher::getInfo() const { return m_codeLauncher->getInfo(); }
Expand Down
2 changes: 1 addition & 1 deletion src/core/code_launcher/detail/callbacked_code_launcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class CallbackedCodeLauncher : public CodeLauncherInterface {
CallbackedCodeLauncher & operator=(CallbackedCodeLauncher &&) = delete;

Response runCode(std::string && inMemoryTarWithSources,
std::vector<std::string> && cmdLineArgs) override;
std::vector<std::string> && cmdLineArgs, Action action) override;

CodeLauncherInfo getInfo() const override;

Expand Down
66 changes: 16 additions & 50 deletions src/core/code_launcher/detail/code_launchers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ std::map<Action, std::string_view> 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()) {
Expand All @@ -41,71 +45,33 @@ bool BaseCodeLauncher::prepareCode(std::string && tarString, Action type) {
return true;
}

Response PlaygroundCodeLauncher::runCode(std::string && inMemoryTarWithSources,
std::vector<std::string> && cmdLineArgs) {
if (!prepareCode(std::move(inMemoryTarWithSources), Action::Playground)) {
Response BaseCodeLauncher::runCode(std::string && inMemoryTarWithSources,
std::vector<std::string> && 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<std::string> && 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<std::string> && 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
22 changes: 3 additions & 19 deletions src/core/code_launcher/detail/code_launchers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string> && cmdLineArgs) override;
CodeLauncherInfo getInfo() const override;
};

struct PlaygroundCodeLauncher final : BaseCodeLauncher {
PlaygroundCodeLauncher(std::string id, Language type);
Response runCode(std::string && inMemoryTarWithSources,
std::vector<std::string> && cmdLineArgs) override;
CodeLauncherInfo getInfo() const override;
};
Response runCode(std::string && inMemoryTarWithSources, std::vector<std::string> && cmdLineArgs,
Action action) override;

struct PracticeCodeLauncher final : BaseCodeLauncher {
PracticeCodeLauncher(std::string id, Language type);
Response runCode(std::string && inMemoryTarWithSources,
std::vector<std::string> && dockerCmdLineArgs) override;
CodeLauncherInfo getInfo() const override;
};

Expand Down
29 changes: 9 additions & 20 deletions src/core/code_launcher/detail/container_manipulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ namespace watchman::detail {
constexpr std::string_view kSenjunPattern = "senjun";

std::unique_ptr<BaseCodeLauncher>
CodeLauncherOSManipulator::createCodeLauncher(std::string const & image,
LanguageAction languageAction) {
CodeLauncherOSManipulator::createCodeLauncher(std::string const & image, Language language) {
RunContainer params;

params.image = image;
Expand All @@ -31,16 +30,7 @@ CodeLauncherOSManipulator::createCodeLauncher(std::string const & image,

Log::info("Launch container: {}, id: {}", image, id);

std::unique_ptr<BaseCodeLauncher> container;
auto const l = languageAction.language;

switch (languageAction.action) {
case Action::Chapter: return std::make_unique<ChapterCodeLauncher>(std::move(id), l);
case Action::Playground: return std::make_unique<PlaygroundCodeLauncher>(std::move(id), l);
case Action::Practice: return std::make_unique<PracticeCodeLauncher>(std::move(id), l);
}

throw std::logic_error{"Unknorn image type while creating code launcher"};
return std::make_unique<BaseCodeLauncher>(std::move(id), language);
}

void CodeLauncherOSManipulator::removeCodeLauncher(std::string const & id) {
Expand All @@ -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) {
Expand All @@ -90,26 +79,26 @@ 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<std::unique_ptr<BaseCodeLauncher>> 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;
}
containers.emplace_back(std::move(container));
}

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
6 changes: 3 additions & 3 deletions src/core/code_launcher/detail/container_manipulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@

namespace watchman::detail {

using Storage = ExtractingStorage<LanguageAction, BaseCodeLauncher, LanguageActionHasher>;
using Storage = ExtractingStorage<Language, BaseCodeLauncher>;

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();
Expand All @@ -25,7 +25,7 @@ class CodeLauncherOSManipulator {
// todo
// user pair, not code launcher info
std::unique_ptr<BaseCodeLauncher> createCodeLauncher(std::string const & image,
LanguageAction taskType);
Language language);
void removeCodeLauncher(std::string const & id);

// Original storage lies in restarting_code_launcher.hpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ RestartingCodeLauncherProvider::RestartingCodeLauncherProvider(Config && config)
}

std::unique_ptr<CodeLauncherInterface>
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<detail::CallbackedCodeLauncher>(
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ class RestartingCodeLauncherProvider : public CodeLauncherProviderInterface {
operator=(RestartingCodeLauncherProvider const & other) = delete;
RestartingCodeLauncherProvider & operator=(RestartingCodeLauncherProvider && other) = delete;

std::unique_ptr<CodeLauncherInterface> getCodeLauncher(LanguageAction type) override;
std::unique_ptr<CodeLauncherInterface> getCodeLauncher(Language language) override;

private:
void restartCodeLauncher(CodeLauncherInfo const & info);
bool codeLauncherTypeIsValid(LanguageAction const & name) const;
bool codeLauncherTypeIsValid(Language language) const;

ExtractingStorage<LanguageAction, BaseCodeLauncher, LanguageActionHasher> m_storage;
ExtractingStorage<Language, BaseCodeLauncher> m_storage;
std::unique_ptr<CodeLauncherOSManipulator> m_manipulator;
};

Expand Down
8 changes: 5 additions & 3 deletions src/core/code_launcher/detail/storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<typename K, typename V, typename H>
template<typename K, typename V>
class ExtractingStorage {
public:
bool contains(K const & key) const { return storage.contains(key); }
Expand All @@ -38,13 +38,15 @@ class ExtractingStorage {
}

void addValues(K const & key, std::list<std::unique_ptr<V>> 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<K, std::list<std::unique_ptr<V>>, H> storage;
std::unordered_map<K, std::list<std::unique_ptr<V>>> storage;
};

} // namespace watchman::detail
Loading