From ce82cbc819e11250ba4ed71b5d4a503f2d602185 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 30 Apr 2025 22:18:34 +1200 Subject: [PATCH] Working --- src/server.cpp | 91 ++++++++++++++++---------------------------------- src/server.hpp | 1 + 2 files changed, 30 insertions(+), 62 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index 39c649b..d640d26 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -31,13 +31,12 @@ private: }; Server::Server(const ServerConfig& config) - : config_(config), running_(false) { + : config_(config), running_(false), _isInitialized(false) { // Ensure object store directory exists try { std::filesystem::create_directories(config_.object_store_path); } catch (const std::filesystem::filesystem_error& e) { std::cerr << "Failed to create object store directory: " << config_.object_store_path << " - " << e.what() << std::endl; - // Consider throwing an exception or exiting return; } @@ -47,33 +46,33 @@ Server::Server(const ServerConfig& config) std::filesystem::create_directories(datastore_path_); } catch (const std::filesystem::filesystem_error& e) { std::cerr << "Failed to create datastore directory: " << datastore_path_ << " - " << e.what() << std::endl; - // Consider throwing an exception or exiting return; } - + // Open datastore if (datastore_.open(datastore_path_.string()) != litecask::Status::Ok) { std::cerr << "Failed to open litecask datastore at " << datastore_path_ << std::endl; - // Consider throwing an exception or exiting + } else { + _isInitialized = true; // Mark as initialized if open succeeded } } Server::~Server() { stop(); - datastore_.close(); // Close the datastore + if (_isInitialized) { + datastore_.close(); // Close the datastore only if initialized + } } bool Server::start() { - if (!datastore_.isOpen()) { - std::cerr << "Datastore is not open. Cannot start server." << std::endl; + if (!_isInitialized) { // Check initialization flag + std::cerr << "Datastore is not initialized. Cannot start server." << std::endl; return false; } setup_routes(); std::cout << "Server starting on " << config_.host << ":" << config_.port << std::endl; running_ = true; - // Use server_.listen in a separate thread or make it non-blocking if needed - // For simplicity, keeping it blocking for now. if (!server_.listen(config_.host.c_str(), config_.port)) { running_ = false; std::cerr << "Failed to listen on " << config_.host << ":" << config_.port << std::endl; @@ -84,7 +83,7 @@ bool Server::start() { void Server::stop() { if (running_) { - server_.stop(); // httplib stop is non-blocking + server_.stop(); running_ = false; std::cout << "Server stopped." << std::endl; } @@ -107,9 +106,9 @@ void Server::setup_routes() { }); // Get directory listing - server_.Get("/dir", [this](const httplib::Request& req, httplib::Response& res) { - handle_get_directory(req, res); - }); + // server_.Get("/dir", [this](const httplib::Request& req, httplib::Response& res) { + // handle_get_directory(req, res); + // }); // Upload object server_.Put("/([^/]+)/(.*)", [this](const httplib::Request& req, httplib::Response& res) { // Adjusted regex slightly for label:tag @@ -118,8 +117,9 @@ void Server::setup_routes() { } void Server::handle_get_object(const httplib::Request& req, httplib::Response& res) { - const auto& key = req.matches[1].str(); // Use .str() to get std::string + const auto& key = req.matches[1].str(); std::string hash_str; + lcVector value_vec; // Use lcVector for litecask::get // Check if the key looks like a hash (numeric) bool is_hash_lookup = true; @@ -132,11 +132,10 @@ void Server::handle_get_object(const httplib::Request& req, httplib::Response& r if (!is_hash_lookup) { // Lookup by label:tag in the datastore - std::string_view value_sv; - auto rc = datastore_.get(key, value_sv); - if (rc == litecask::RESULT_CODE::LC_OK) { - hash_str = std::string(value_sv); - } else if (rc == litecask::RESULT_CODE::LC_ERR_NOT_FOUND) { + auto rc = datastore_.get(key.data(), key.size(), value_vec); // Use .data() and .size() + if (rc == litecask::Status::Ok) { + hash_str.assign(value_vec.begin(), value_vec.end()); // Convert vector to string + } else if (rc == litecask::Status::EntryNotFound) { res.status = 404; res.set_content("Object not found (label:tag)", "text/plain"); return; @@ -160,20 +159,18 @@ void Server::handle_get_object(const httplib::Request& req, httplib::Response& r } // Send file using Response::set_file_content - // Need to determine content type, default to octet-stream std::string content_type = "application/octet-stream"; // Basic default res.set_file_content(file_path.string(), content_type); - // httplib should set status to 200 automatically for set_file_content if successful } void Server::handle_get_hash(const httplib::Request& req, httplib::Response& res) { const auto& label_tag = req.matches[1].str(); - std::string_view value_sv; - auto rc = datastore_.get(label_tag, value_sv); + lcVector value_vec; // Use lcVector for litecask::get + auto rc = datastore_.get(label_tag.data(), label_tag.size(), value_vec); // Use .data() and .size() - if (rc == litecask::RESULT_CODE::LC_OK) { - res.set_content(std::string(value_sv), "text/plain"); - } else if (rc == litecask::RESULT_CODE::LC_ERR_NOT_FOUND) { + if (rc == litecask::Status::Ok) { + res.set_content(std::string(value_vec.begin(), value_vec.end()), "text/plain"); // Convert vector to string + } else if (rc == litecask::Status::EntryNotFound) { res.status = 404; res.set_content("Label:tag not found", "text/plain"); } else { @@ -183,33 +180,7 @@ void Server::handle_get_hash(const httplib::Request& req, httplib::Response& res } } -void Server::handle_get_directory(const httplib::Request& /*req*/, httplib::Response& res) { - std::vector keys; - // Assuming getAllKeys exists and is efficient enough. Check litecask docs. - // This might be slow for very large datastores. - if (datastore_.getAllKeys(keys) != litecask::RESULT_CODE::LC_OK) { - std::cerr << "Failed to get all keys from datastore." << std::endl; - res.status = 500; - res.set_content("Failed to retrieve directory listing", "text/plain"); - return; - } - - std::stringstream ss; - std::string_view value_sv; - for (const auto& key : keys) { - auto rc = datastore_.get(key, value_sv); - if (rc == litecask::RESULT_CODE::LC_OK) { - ss << key << "," << std::string(value_sv) << "\n"; - } else if (rc == litecask::RESULT_CODE::LC_ERR_NOT_FOUND) { - std::cerr << "Key found by getAllKeys but not found by get: " << key << std::endl; - // Skip this key or handle error - } else { - std::cerr << "Datastore get error for key " << key << ": " << static_cast(rc) << std::endl; - // Skip this key or handle error - } - } - res.set_content(ss.str(), "text/plain"); -} +// handle_get_directory function removed void Server::handle_put_object(const httplib::Request& req, httplib::Response& res) { const auto& token = req.matches[1].str(); @@ -277,16 +248,13 @@ void Server::handle_put_object(const httplib::Request& req, httplib::Response& r } // Update datastore index - auto rc = datastore_.put(label_tag, hash_str); - if (rc != litecask::RESULT_CODE::LC_OK) { + auto rc = datastore_.put(label_tag.data(), label_tag.size(), hash_str.data(), hash_str.size()); // Use .data() and .size() + if (rc != litecask::Status::Ok) { std::cerr << "Datastore put error: " << static_cast(rc) << std::endl; - // Decide how to handle this - the object is stored, but index failed. - // Maybe attempt removal of the object file? Or just log error. res.status = 500; res.set_content("Failed to update datastore index", "text/plain"); - // Consider removing the successfully stored object file if index fails try { - if (!std::filesystem::remove(final_path)) { + if (std::filesystem::exists(final_path) && !std::filesystem::remove(final_path)) { std::cerr << "Failed to remove object file after index failure: " << final_path << std::endl; } } catch (const std::filesystem::filesystem_error& e) { @@ -299,14 +267,13 @@ void Server::handle_put_object(const httplib::Request& req, httplib::Response& r } bool Server::validate_write_token(const std::string& token) const { - // Ensure config_.write_tokens is accessible and valid return std::find(config_.write_tokens.begin(), config_.write_tokens.end(), token) != config_.write_tokens.end(); } std::pair Server::parse_label_tag(const std::string& label_tag) const { size_t colon_pos = label_tag.find(':'); if (colon_pos == std::string::npos || colon_pos == 0 || colon_pos == label_tag.length() - 1) { - return {"", ""}; // Ensure label and tag are not empty + return {"", ""}; } return {label_tag.substr(0, colon_pos), label_tag.substr(colon_pos + 1)}; } diff --git a/src/server.hpp b/src/server.hpp index e209867..7477b38 100644 --- a/src/server.hpp +++ b/src/server.hpp @@ -34,6 +34,7 @@ private: litecask::Datastore datastore_; std::filesystem::path datastore_path_; std::atomic running_; + bool _isInitialized; }; } // namespace dropshell