|
|
|
@ -5,15 +5,21 @@
|
|
|
|
|
#include <filesystem>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <spawn.h>
|
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
#include <toml++/toml.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
|
|
|
|
|
#include "config.hpp"
|
|
|
|
|
#include "zmq_addon.hpp"
|
|
|
|
|
|
|
|
|
|
static constexpr uint32_t JOB_ID_LEN = 32;
|
|
|
|
|
static constexpr uint32_t MIN_MESSAGE_LEN = JOB_ID_LEN + sizeof(uint32_t) * 2;
|
|
|
|
|
static constexpr uint32_t MIN_SUBMIT_MESSAGE_LEN = sk::JOB_ID_LEN + sizeof(uint32_t) * 2;
|
|
|
|
|
static constexpr uint32_t MIN_CANCEL_MESSAGE_LEN = sk::JOB_ID_LEN + sizeof(uint32_t);
|
|
|
|
|
|
|
|
|
|
static constexpr int SUBMIT_EXECUTOR_BOUND = 0;
|
|
|
|
|
static constexpr int CANCEL_EXECUTOR_BOUND = 1;
|
|
|
|
|
static constexpr int STDOUT_CLIENT_BOUND = 1;
|
|
|
|
|
static constexpr int STDERR_CLIENT_BOUND = 2;
|
|
|
|
|
static constexpr int EXIT_CLIENT_BOUND = 3;
|
|
|
|
|
|
|
|
|
|
sk::runner_backend detect_backend() {
|
|
|
|
|
const char *const argv[] = {"docker", "stats", "--no-stream", nullptr};
|
|
|
|
@ -90,37 +96,68 @@ int main(int argc, char **argv) {
|
|
|
|
|
zmq::socket_t sender(context, zmq::socket_type::push);
|
|
|
|
|
sender.connect(config.queue.push_addr);
|
|
|
|
|
|
|
|
|
|
auto send = [&sender](int type, const std::string &jobId, const std::string &text) {
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
std::cout << "Result: `" << text << "`\n";
|
|
|
|
|
#endif
|
|
|
|
|
auto [reply, reply_bytes] = sk::prepare_headers(sizeof(uint32_t) + text.size(), type, jobId);
|
|
|
|
|
sk::write_string(reply_bytes, text);
|
|
|
|
|
sender.send(reply, zmq::send_flags::none);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
zmq::message_t request;
|
|
|
|
|
receiver.recv(request);
|
|
|
|
|
if (request.size() < MIN_MESSAGE_LEN) {
|
|
|
|
|
std::cerr << "Invalid request" << std::endl;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
zmq::recv_result_t _ = receiver.recv(request);
|
|
|
|
|
const auto *message = static_cast<const char *>(request.data()) + 1;
|
|
|
|
|
auto *message_bytes = static_cast<const std::byte *>(request.data()) + 1;
|
|
|
|
|
int message_type = static_cast<int>(*static_cast<const unsigned char *>(request.data()));
|
|
|
|
|
switch (message_type) {
|
|
|
|
|
case SUBMIT_EXECUTOR_BOUND: {
|
|
|
|
|
if (request.size() < MIN_SUBMIT_MESSAGE_LEN) {
|
|
|
|
|
std::cerr << "Invalid request\n";
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
std::string jobId(message, sk::JOB_ID_LEN);
|
|
|
|
|
uint32_t imageLen = sk::read_uint32(message_bytes + sk::JOB_ID_LEN);
|
|
|
|
|
uint32_t codeLen = sk::read_uint32(message_bytes + sk::JOB_ID_LEN + sizeof(uint32_t));
|
|
|
|
|
|
|
|
|
|
std::string jobId(static_cast<char *>(request.data()), JOB_ID_LEN);
|
|
|
|
|
uint32_t imageLen = sk::read_uint32(static_cast<std::byte *>(request.data()) + JOB_ID_LEN);
|
|
|
|
|
uint32_t codeLen = sk::read_uint32(static_cast<std::byte *>(request.data()) + JOB_ID_LEN + sizeof(uint32_t));
|
|
|
|
|
if (request.size() < MIN_SUBMIT_MESSAGE_LEN + imageLen + codeLen) {
|
|
|
|
|
std::cerr << "Request is too short\n";
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
std::string imageString(message + MIN_SUBMIT_MESSAGE_LEN, imageLen);
|
|
|
|
|
std::string requestString(message + MIN_SUBMIT_MESSAGE_LEN + imageLen, codeLen);
|
|
|
|
|
|
|
|
|
|
if (request.size() < MIN_MESSAGE_LEN + imageLen + codeLen) {
|
|
|
|
|
std::cerr << "Invalid request" << std::endl;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
std::string imageString(static_cast<char *>(request.data()) + MIN_MESSAGE_LEN, imageLen);
|
|
|
|
|
std::string requestString(static_cast<char *>(request.data()) + MIN_MESSAGE_LEN + imageLen, codeLen);
|
|
|
|
|
|
|
|
|
|
std::cout << "Executing " << codeLen << " bytes code.\n";
|
|
|
|
|
sk::program program{jobId, requestString, imageString};
|
|
|
|
|
sk::run_result result = runner.run_blocking(program);
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
std::cout << "Executing " << codeLen << " bytes code.\n";
|
|
|
|
|
#endif
|
|
|
|
|
sk::program program{std::move(jobId), std::move(requestString), std::move(imageString)};
|
|
|
|
|
sk::run_result result = runner.run_blocking(program);
|
|
|
|
|
|
|
|
|
|
std::cout << "Result: " << result.out << std::endl;
|
|
|
|
|
|
|
|
|
|
// Send the job id, the exit code and result.out to sink
|
|
|
|
|
zmq::message_t reply(JOB_ID_LEN + sizeof(uint32_t) + result.out.size());
|
|
|
|
|
memcpy(reply.data(), jobId.data(), JOB_ID_LEN);
|
|
|
|
|
sk::write_uint32(static_cast<std::byte *>(reply.data()) + JOB_ID_LEN, result.exit_code);
|
|
|
|
|
memcpy(static_cast<char *>(reply.data()) + JOB_ID_LEN + sizeof(uint32_t), result.out.data(), result.out.size());
|
|
|
|
|
sender.send(reply, zmq::send_flags::none);
|
|
|
|
|
if (!result.out.empty()) {
|
|
|
|
|
send(STDOUT_CLIENT_BOUND, program.name, result.out);
|
|
|
|
|
}
|
|
|
|
|
if (!result.err.empty()) {
|
|
|
|
|
send(STDERR_CLIENT_BOUND, program.name, result.err);
|
|
|
|
|
}
|
|
|
|
|
auto [reply, reply_bytes] = sk::prepare_headers(sizeof(uint32_t), EXIT_CLIENT_BOUND, program.name);
|
|
|
|
|
sk::write_uint32(reply_bytes, result.exit_code);
|
|
|
|
|
sender.send(reply, zmq::send_flags::none);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CANCEL_EXECUTOR_BOUND: {
|
|
|
|
|
if (request.size() < MIN_CANCEL_MESSAGE_LEN) {
|
|
|
|
|
std::cerr << "Invalid request\n";
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
std::string jobId(message, sk::JOB_ID_LEN);
|
|
|
|
|
runner.kill_active(jobId);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
std::cerr << "Invalid " << std::hex << message_type << " message type\n";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|