diff --git a/.gitignore b/.gitignore index c34f5a1..9c0d1de 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ a.out flake.lock db.json /.ccls-cache +compile_commands.json diff --git a/main.cpp b/main.cpp index 5817f23..db70532 100644 --- a/main.cpp +++ b/main.cpp @@ -17,7 +17,7 @@ #include #include -using Db = std::vector>; +using Db = std::unordered_map; Db database; void save_database(std::string file_name) { @@ -73,7 +73,7 @@ using asio::use_awaitable; boost::asio::io_context io_context; asio::awaitable handle_client(tcp::socket client_socket) { - char buffer[4096]; + char buffer[4096]; // this looks like a buffer overflow waiting to happen ngl :P try { while (true) { @@ -83,45 +83,24 @@ asio::awaitable handle_client(tcp::socket client_socket) { std::vector parsed = parse_resp_request(buffer); if (parsed[0] == "GET") { - bool found = false; - - for (const auto& inner_vec: database) { // Iterate through DB and find the required item - if (!inner_vec.empty() && inner_vec[0] == parsed[1]) { - int length = inner_vec[1].length(); - std::string return_string = std::format("${}\r\n{}\r\n", length, inner_vec[1]); // Serialise to RESP - std::cout << "[d] Sending: " << return_string << std::endl; - co_await asio::async_write(client_socket, asio::buffer(return_string.data(), return_string.length()), use_awaitable); - found = true; - } - } - - if (!found) { - co_await asio::async_write(client_socket, asio::buffer("$-1\r\n", strlen("$-1\r\n")), use_awaitable); // Not found - } - } else if (parsed[0] == "SET") { - bool found = false; // Avoids SEGFAULT - - for (auto& inner_vec: database) { - if (!inner_vec.empty() && inner_vec[0] == parsed[1]) { - inner_vec[1] = parsed[2]; - co_await asio::async_write(client_socket, asio::buffer("+OK\r\n", strlen("+OK\r\n")), use_awaitable); - found = true; - } - - if (!found) { - std::vector new_kv = { parsed[1], parsed[2] }; - database.push_back(new_kv); - co_await asio::async_write(client_socket, asio::buffer("+OK\r\n", strlen("+OK\r\n")), use_awaitable); - found = true; - } - } + auto it = database.find(parsed[1]); + if (it != database.end()) { + std::string found_object = it->second; + std::string return_string = std::format("${}\r\n{}\r\n", found_object.length(), found_object); // Serialise to RESP + co_await asio::async_write(client_socket, asio::buffer(return_string.data(), return_string.length()), use_awaitable); } else { - co_await asio::async_write(client_socket, asio::buffer("+OK\r\n", strlen("+OK\r\n")), use_awaitable); // Temporary catch-all (for more advanced handshake) + co_await asio::async_write(client_socket, asio::buffer("$-1\r\n", strlen("$-1\r\n")), use_awaitable); // Not found } + } else if (parsed[0] == "SET") { + database.insert_or_assign(parsed[1], parsed[2]); // it's as shrimple as that + co_await asio::async_write(client_socket, asio::buffer("+OK\r\n", strlen("+OK\r\n")), use_awaitable); + } else { + co_await asio::async_write(client_socket, asio::buffer("+OK\r\n", strlen("+OK\r\n")), use_awaitable); // "Temporary" catch-all (for more advanced handshake) } - } catch (const std::exception& e) { - std::cout << "[i] Client session ened/error" << e.what() << std::endl; } + } catch (const std::exception& e) { + std::cout << "[i] Client session end/error: " << e.what() << std::endl; + } } @@ -143,6 +122,7 @@ asio::awaitable shutdown_handler(asio::io_context& io_context, tcp::accept asio::signal_set signals(io_context, SIGINT, SIGTERM); co_await signals.async_wait(use_awaitable); std::cout << "[i] Stopping blueis server..." << std::endl; + save_database("db.json"); acceptor.cancel(); acceptor.close(); @@ -170,7 +150,7 @@ int main() { ); for (int i = 0; i < N_THREADS - 1; i++) { - threads.emplace_back([&io_context] { + threads.emplace_back([] { io_context.run(); }); } diff --git a/shell.nix b/shell.nix index 0cf68ef..c632232 100644 --- a/shell.nix +++ b/shell.nix @@ -1,8 +1,9 @@ -{ pkgs ? import }: -with pkgs; -mkShell { +{ pkgs ? import {} }: +pkgs.mkShell { buildInputs = with pkgs; [ gcc ccls + bear + boost ]; }