| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #include "boinc_wrapper.h"
|
| | #include <iostream>
|
| | #include <fstream>
|
| | #include <sstream>
|
| | #include <chrono>
|
| | #include <ctime>
|
| | #include <random>
|
| | #include <iomanip>
|
| |
|
| | namespace docking_at_home {
|
| | namespace boinc {
|
| |
|
| |
|
| |
|
| | BOINCWrapper::BOINCWrapper()
|
| | : is_initialized_(false), app_name_("DockingAtHOME"), worker_id_("") {
|
| | }
|
| |
|
| | BOINCWrapper::~BOINCWrapper() {
|
| | if (is_initialized_) {
|
| | finalize();
|
| | }
|
| | }
|
| |
|
| | bool BOINCWrapper::initialize() {
|
| | int retval = boinc_init();
|
| | if (retval) {
|
| | std::cerr << "BOINC initialization failed: " << boincerror(retval) << std::endl;
|
| | return false;
|
| | }
|
| |
|
| |
|
| | std::random_device rd;
|
| | std::mt19937 gen(rd());
|
| | std::uniform_int_distribution<> dis(100000, 999999);
|
| | worker_id_ = "WORKER_" + std::to_string(dis(gen));
|
| |
|
| | is_initialized_ = true;
|
| | std::cout << "BOINC initialized successfully. Worker ID: " << worker_id_ << std::endl;
|
| |
|
| | return true;
|
| | }
|
| |
|
| | bool BOINCWrapper::register_application(const std::string& app_name, const std::string& version) {
|
| | if (!is_initialized_) {
|
| | std::cerr << "BOINC not initialized" << std::endl;
|
| | return false;
|
| | }
|
| |
|
| | app_name_ = app_name;
|
| | std::cout << "Registered application: " << app_name << " v" << version << std::endl;
|
| |
|
| | return true;
|
| | }
|
| |
|
| | std::string BOINCWrapper::submit_task(const DockingTask& task) {
|
| | if (!is_initialized_) {
|
| | std::cerr << "BOINC not initialized" << std::endl;
|
| | return "";
|
| | }
|
| |
|
| | if (!validate_task(task)) {
|
| | std::cerr << "Invalid task" << std::endl;
|
| | return "";
|
| | }
|
| |
|
| | std::string task_id = generate_task_id();
|
| |
|
| |
|
| | if (!upload_input_files(task)) {
|
| | std::cerr << "Failed to upload input files" << std::endl;
|
| | return "";
|
| | }
|
| |
|
| | std::cout << "Task submitted successfully: " << task_id << std::endl;
|
| |
|
| | return task_id;
|
| | }
|
| |
|
| | bool BOINCWrapper::process_task(const DockingTask& task, DockingResult& result) {
|
| | if (!is_initialized_) {
|
| | std::cerr << "BOINC not initialized" << std::endl;
|
| | return false;
|
| | }
|
| |
|
| | auto start_time = std::chrono::high_resolution_clock::now();
|
| |
|
| | std::cout << "Processing task: " << task.task_id << std::endl;
|
| | std::cout << "Ligand: " << task.ligand_file << std::endl;
|
| | std::cout << "Receptor: " << task.receptor_file << std::endl;
|
| | std::cout << "GPU enabled: " << (task.use_gpu ? "Yes" : "No") << std::endl;
|
| |
|
| |
|
| | result.task_id = task.task_id;
|
| | result.worker_id = worker_id_;
|
| | result.successful_runs = 0;
|
| |
|
| |
|
| | for (int i = 0; i < task.num_runs; ++i) {
|
| |
|
| | double progress = static_cast<double>(i) / task.num_runs;
|
| | update_progress(progress);
|
| |
|
| |
|
| | if (i > 0 && i % 10 == 0) {
|
| | std::string checkpoint_file = task.output_dir + "/checkpoint_" + std::to_string(i);
|
| | create_checkpoint(checkpoint_file);
|
| | }
|
| |
|
| |
|
| | boinc_sleep(0.1);
|
| |
|
| | result.successful_runs++;
|
| | }
|
| |
|
| |
|
| | auto end_time = std::chrono::high_resolution_clock::now();
|
| | std::chrono::duration<double> elapsed = end_time - start_time;
|
| | result.computation_time = elapsed.count();
|
| |
|
| |
|
| | update_progress(1.0);
|
| | report_cpu_time(result.computation_time);
|
| |
|
| | std::cout << "Task completed: " << task.task_id << std::endl;
|
| | std::cout << "Computation time: " << result.computation_time << " seconds" << std::endl;
|
| |
|
| | return true;
|
| | }
|
| |
|
| | double BOINCWrapper::get_task_progress(const std::string& task_id) {
|
| |
|
| |
|
| | return 0.0;
|
| | }
|
| |
|
| | bool BOINCWrapper::get_task_results(const std::string& task_id, DockingResult& result) {
|
| | if (!is_initialized_) {
|
| | return false;
|
| | }
|
| |
|
| |
|
| | return download_output_files(task_id);
|
| | }
|
| |
|
| | void BOINCWrapper::update_progress(double fraction_done) {
|
| | boinc_fraction_done(fraction_done);
|
| | }
|
| |
|
| | void BOINCWrapper::report_cpu_time(double cpu_time) {
|
| | boinc_report_app_status(cpu_time, 0, 0);
|
| | }
|
| |
|
| | bool BOINCWrapper::create_checkpoint(const std::string& checkpoint_file) {
|
| | std::ofstream ckpt(checkpoint_file, std::ios::binary);
|
| | if (!ckpt.is_open()) {
|
| | return false;
|
| | }
|
| |
|
| |
|
| |
|
| | ckpt << "CHECKPOINT_V1" << std::endl;
|
| | ckpt << worker_id_ << std::endl;
|
| |
|
| | ckpt.close();
|
| |
|
| | boinc_checkpoint_completed();
|
| |
|
| | return true;
|
| | }
|
| |
|
| | bool BOINCWrapper::restore_checkpoint(const std::string& checkpoint_file) {
|
| | std::ifstream ckpt(checkpoint_file, std::ios::binary);
|
| | if (!ckpt.is_open()) {
|
| | return false;
|
| | }
|
| |
|
| |
|
| | std::string version, worker;
|
| | std::getline(ckpt, version);
|
| | std::getline(ckpt, worker);
|
| |
|
| | ckpt.close();
|
| |
|
| | return true;
|
| | }
|
| |
|
| | void BOINCWrapper::finalize() {
|
| | if (is_initialized_) {
|
| | boinc_finish(0);
|
| | is_initialized_ = false;
|
| | }
|
| | }
|
| |
|
| | bool BOINCWrapper::validate_task(const DockingTask& task) {
|
| | if (task.ligand_file.empty() || task.receptor_file.empty()) {
|
| | return false;
|
| | }
|
| | if (task.num_runs <= 0 || task.num_evals <= 0) {
|
| | return false;
|
| | }
|
| | return true;
|
| | }
|
| |
|
| | std::string BOINCWrapper::generate_task_id() {
|
| | auto now = std::chrono::system_clock::now();
|
| | auto now_time_t = std::chrono::system_clock::to_time_t(now);
|
| | auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
| | now.time_since_epoch()) % 1000;
|
| |
|
| | std::stringstream ss;
|
| | ss << "TASK_"
|
| | << std::put_time(std::localtime(&now_time_t), "%Y%m%d_%H%M%S")
|
| | << "_" << now_ms.count();
|
| |
|
| | return ss.str();
|
| | }
|
| |
|
| | bool BOINCWrapper::upload_input_files(const DockingTask& task) {
|
| |
|
| |
|
| | std::cout << "Uploading input files for task: " << task.task_id << std::endl;
|
| | return true;
|
| | }
|
| |
|
| | bool BOINCWrapper::download_output_files(const std::string& task_id) {
|
| |
|
| |
|
| | std::cout << "Downloading output files for task: " << task_id << std::endl;
|
| | return true;
|
| | }
|
| |
|
| |
|
| |
|
| | BOINCServer::BOINCServer()
|
| | : is_initialized_(false), active_work_units_(0), completed_work_units_(0) {
|
| | }
|
| |
|
| | BOINCServer::~BOINCServer() {
|
| | }
|
| |
|
| | bool BOINCServer::initialize(const std::string& config_file) {
|
| | std::cout << "Initializing BOINC server with config: " << config_file << std::endl;
|
| |
|
| |
|
| |
|
| | db_host_ = "localhost";
|
| | db_name_ = "docking_at_home";
|
| |
|
| | is_initialized_ = true;
|
| |
|
| | return true;
|
| | }
|
| |
|
| | int BOINCServer::create_work_units(const std::vector<DockingTask>& tasks) {
|
| | if (!is_initialized_) {
|
| | return 0;
|
| | }
|
| |
|
| | int created = 0;
|
| | for (const auto& task : tasks) {
|
| |
|
| |
|
| | std::cout << "Creating work unit for task: " << task.task_id << std::endl;
|
| | created++;
|
| | active_work_units_++;
|
| | }
|
| |
|
| | return created;
|
| | }
|
| |
|
| | bool BOINCServer::process_result(const std::string& result_file) {
|
| | if (!is_initialized_) {
|
| | return false;
|
| | }
|
| |
|
| | std::cout << "Processing result file: " << result_file << std::endl;
|
| |
|
| |
|
| | active_work_units_--;
|
| | completed_work_units_++;
|
| |
|
| | return true;
|
| | }
|
| |
|
| | std::string BOINCServer::get_statistics() {
|
| | std::stringstream ss;
|
| | ss << "{"
|
| | << "\"active_work_units\": " << active_work_units_ << ", "
|
| | << "\"completed_work_units\": " << completed_work_units_
|
| | << "}";
|
| |
|
| | return ss.str();
|
| | }
|
| |
|
| | }
|
| | }
|
| |
|