From f1af8679481cfc4199b6423d723f67188145ea46 Mon Sep 17 00:00:00 2001 From: Christian Krinitsin Date: Fri, 21 Mar 2025 16:17:20 +0100 Subject: client: add client class with input processing --- src/client/client.cpp | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/client/client.cpp (limited to 'src/client/client.cpp') diff --git a/src/client/client.cpp b/src/client/client.cpp new file mode 100644 index 0000000..d88df5f --- /dev/null +++ b/src/client/client.cpp @@ -0,0 +1,134 @@ +#include "client.h" +#include "shared_memory.h" +#include + +Client::Client() +{ + shm_fd = shm_open(SHM_NAME, O_RDWR, 0666); + if (shm_fd == -1) { + std::cout << "Server not running" << '\n'; + return; + } + + shared_memory = + (SharedMemory*)mmap(0, sizeof(SharedMemory), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); +} + +Client::~Client() +{ + munmap(shared_memory, sizeof(SharedMemory)); + close(shm_fd); +} + +void Client::start_client() +{ + while (true) { + char operation; + int k, v; + std::cout << "Choose the operation (i: Insert, g: Get, r: Remove, p: Print, e: Exit)" + << '\n'; + std::cin >> operation; + switch (operation) { + case 'e': + return; + case 'i': + std::cout << "Insert: Enter the k-v pair( ):" << '\n'; + if (!(std::cin >> k >> v)) { + std::cout << "Invalid input" << '\n'; + std::cin.clear(); + std::cin.ignore(std::numeric_limits::max(), '\n'); + break; + }; + send_request( + shared_memory, INSERT, std::optional(serialize(k)), std::optional(serialize(v))); + break; + case 'g': { + std::cout << "Get: Enter the key():" << '\n'; + if (!(std::cin >> k)) { + std::cout << "Invalid input" << '\n'; + std::cin.clear(); + std::cin.ignore(std::numeric_limits::max(), '\n'); + break; + }; + int index = send_request(shared_memory, GET, std::optional(serialize(k)), std::nullopt); + std::string response = process_result(shared_memory, index); + std::cout << "Got: " << response << '\n'; + break; + } + case 'r': + std::cout << "Remove: Enter key():" << '\n'; + if (!(std::cin >> k)) { + std::cout << "Invalid input" << '\n'; + std::cin.clear(); + std::cin.ignore(std::numeric_limits::max(), '\n'); + break; + }; + send_request(shared_memory, DELETE, std::optional(serialize(k)), std::nullopt); + break; + case 'p': + send_request(shared_memory, PRINT, std::nullopt, std::nullopt); + break; + default: + break; + } + std::cout << '\n'; + } +} + +bool Client::request_processed(SharedMemory* shared_memory, int index) +{ + if (shared_memory->full) { + return false; + } + if (shared_memory->tail == shared_memory->head && !shared_memory->full) { + return true; + } + + for (int i = shared_memory->head - 1; i != shared_memory->tail; i = (i - 1) % QUEUE_SIZE) { + if (i == index) { + return false; + } + } + + return shared_memory->tail != index; +} + +int Client::send_request( + SharedMemory* shared_memory, + Operations type, + std::optional k, + std::optional v) +{ + int index; + + pthread_mutex_lock(&shared_memory->mutex); + + while (shared_memory->full) { + pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); + } + + index = shared_memory->head; + Request* request = &shared_memory->request[index]; + request->type = type; + strncpy(request->key, k.value_or("null").c_str(), MAX_KEY_SIZE); + strncpy(request->value, v.value_or("null").c_str(), MAX_VALUE_SIZE); + shared_memory->head = (1 + shared_memory->head) % QUEUE_SIZE; + shared_memory->full = shared_memory->head == shared_memory->tail; + pthread_cond_signal(&shared_memory->cond_var); + + pthread_mutex_unlock(&shared_memory->mutex); + + return index; +} + +std::string Client::process_result(SharedMemory* shared_memory, int index) +{ + pthread_mutex_lock(&shared_memory->mutex); + + while (!request_processed(shared_memory, index)) { + pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); + } + std::string result(shared_memory->request[index].response); + pthread_mutex_unlock(&shared_memory->mutex); + return result; +} -- cgit 1.4.1 From 435ffba7c3005e643a8d6f7fed54d0f556ee2ad7 Mon Sep 17 00:00:00 2001 From: Christian Krinitsin Date: Fri, 21 Mar 2025 16:33:37 +0100 Subject: get response for every operation and print it --- src/client/client.cpp | 17 +++++++++------ src/server/hashtable.h | 13 ++++++++---- src/server/shared_memory_server.h | 44 ++++++++++++++++++++++++++++++++------- 3 files changed, 56 insertions(+), 18 deletions(-) (limited to 'src/client/client.cpp') diff --git a/src/client/client.cpp b/src/client/client.cpp index d88df5f..6f6f152 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -25,6 +25,7 @@ void Client::start_client() while (true) { char operation; int k, v; + int index = -1; std::cout << "Choose the operation (i: Insert, g: Get, r: Remove, p: Print, e: Exit)" << '\n'; std::cin >> operation; @@ -39,7 +40,7 @@ void Client::start_client() std::cin.ignore(std::numeric_limits::max(), '\n'); break; }; - send_request( + index = send_request( shared_memory, INSERT, std::optional(serialize(k)), std::optional(serialize(v))); break; case 'g': { @@ -50,9 +51,7 @@ void Client::start_client() std::cin.ignore(std::numeric_limits::max(), '\n'); break; }; - int index = send_request(shared_memory, GET, std::optional(serialize(k)), std::nullopt); - std::string response = process_result(shared_memory, index); - std::cout << "Got: " << response << '\n'; + index = send_request(shared_memory, GET, std::optional(serialize(k)), std::nullopt); break; } case 'r': @@ -63,14 +62,19 @@ void Client::start_client() std::cin.ignore(std::numeric_limits::max(), '\n'); break; }; - send_request(shared_memory, DELETE, std::optional(serialize(k)), std::nullopt); + index = send_request(shared_memory, DELETE, std::optional(serialize(k)), std::nullopt); break; case 'p': - send_request(shared_memory, PRINT, std::nullopt, std::nullopt); + index = send_request(shared_memory, PRINT, std::nullopt, std::nullopt); break; default: break; } + + if (index != -1) { + std::string response = process_result(shared_memory, index); + std::cout << response << '\n'; + } std::cout << '\n'; } } @@ -123,6 +127,7 @@ int Client::send_request( std::string Client::process_result(SharedMemory* shared_memory, int index) { + std::cout << "process result" << '\n'; pthread_mutex_lock(&shared_memory->mutex); while (!request_processed(shared_memory, index)) { diff --git a/src/server/hashtable.h b/src/server/hashtable.h index 786d8f5..2538e76 100644 --- a/src/server/hashtable.h +++ b/src/server/hashtable.h @@ -6,6 +6,7 @@ #include #include #include +#include #include template @@ -65,18 +66,22 @@ public: return false; } - void print() + std::string string() { + std::ostringstream output; + size_t index { 0 }; for (auto bucket : table) { - std::cout << "Bucket " << index << ": ["; + output << "Bucket " << index << ": ["; std::shared_lock lock(bucket_mutexes.at(index)); for (auto pair : bucket) { - std::cout << "(" << pair.first << ", " << pair.second << ")"; + output << "(" << pair.first << ", " << pair.second << ")"; } - std::cout << "]" << "\n"; + output << "]" << "\n"; ++index; } + + return output.str(); } private: diff --git a/src/server/shared_memory_server.h b/src/server/shared_memory_server.h index 74abedf..d50797c 100644 --- a/src/server/shared_memory_server.h +++ b/src/server/shared_memory_server.h @@ -57,33 +57,61 @@ public: switch (request->type) { case INSERT: - std::cout << "Inserting" << '\n'; - hash_table.insert(key, value); + std::cout << "Insert operation" << '\n'; + if (hash_table.insert(key, value)) { + strncpy( + request->response, + serialize("Inserted successfully").c_str(), + MAX_VALUE_SIZE); + } else { + strncpy( + request->response, + serialize("Key is already available").c_str(), + MAX_VALUE_SIZE); + } break; case GET: { - std::cout << "Getting" << '\n'; + std::cout << "Get operation" << '\n'; hash_table.insert(key, value); std::optional result = hash_table.get(key); if (result.has_value()) { std::string response = serialize(result.value()); strncpy(request->response, response.c_str(), MAX_VALUE_SIZE); - pthread_cond_signal(&shared_memory->cond_var); + } else { + strncpy( + request->response, + serialize("Couldn't get any value").c_str(), + MAX_VALUE_SIZE); } break; } case DELETE: - std::cout << "Deleting" << '\n'; - hash_table.remove(key); + std::cout << "Remove operation" << '\n'; + if (hash_table.remove(key)) { + strncpy( + request->response, + serialize("Key successfully deleted").c_str(), + MAX_VALUE_SIZE); + } else { + strncpy( + request->response, + serialize("Couldn't find key'").c_str(), + MAX_VALUE_SIZE); + } break; case PRINT: - std::cout << "Printing" << '\n'; - hash_table.print(); + std::cout << "Print operation" << '\n'; + strncpy( + request->response, + serialize(hash_table.string()).c_str(), + MAX_VALUE_SIZE); break; default: break; } shared_memory->tail = (1 + shared_memory->tail) % QUEUE_SIZE; shared_memory->full = false; + pthread_cond_signal(&shared_memory->cond_var); pthread_mutex_unlock(&shared_memory->mutex); } } -- cgit 1.4.1 From b67a507e2ef0db4970f04df5c5a52d9b9e9dd74d Mon Sep 17 00:00:00 2001 From: Christian Krinitsin Date: Fri, 21 Mar 2025 22:12:49 +0100 Subject: renaming and refactoring --- src/client/client.cpp | 21 +++++++++++++++++---- src/client/client.h | 2 +- src/client/main.cpp | 2 -- src/server/main.cpp | 2 +- src/server/shared_memory_server.h | 12 ++++++++---- 5 files changed, 27 insertions(+), 12 deletions(-) (limited to 'src/client/client.cpp') diff --git a/src/client/client.cpp b/src/client/client.cpp index 6f6f152..cbaddeb 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -7,7 +7,7 @@ Client::Client() shm_fd = shm_open(SHM_NAME, O_RDWR, 0666); if (shm_fd == -1) { std::cout << "Server not running" << '\n'; - return; + exit(-1); } shared_memory = @@ -29,9 +29,11 @@ void Client::start_client() std::cout << "Choose the operation (i: Insert, g: Get, r: Remove, p: Print, e: Exit)" << '\n'; std::cin >> operation; + switch (operation) { case 'e': return; + case 'i': std::cout << "Insert: Enter the k-v pair( ):" << '\n'; if (!(std::cin >> k >> v)) { @@ -43,6 +45,7 @@ void Client::start_client() index = send_request( shared_memory, INSERT, std::optional(serialize(k)), std::optional(serialize(v))); break; + case 'g': { std::cout << "Get: Enter the key():" << '\n'; if (!(std::cin >> k)) { @@ -54,6 +57,7 @@ void Client::start_client() index = send_request(shared_memory, GET, std::optional(serialize(k)), std::nullopt); break; } + case 'r': std::cout << "Remove: Enter key():" << '\n'; if (!(std::cin >> k)) { @@ -64,15 +68,17 @@ void Client::start_client() }; index = send_request(shared_memory, DELETE, std::optional(serialize(k)), std::nullopt); break; + case 'p': index = send_request(shared_memory, PRINT, std::nullopt, std::nullopt); break; + default: break; } if (index != -1) { - std::string response = process_result(shared_memory, index); + std::string response = process_respond(shared_memory, index); std::cout << response << '\n'; } std::cout << '\n'; @@ -81,6 +87,10 @@ void Client::start_client() bool Client::request_processed(SharedMemory* shared_memory, int index) { + if (index >= QUEUE_SIZE || index < 0) { + return false; + } + if (shared_memory->full) { return false; } @@ -125,9 +135,12 @@ int Client::send_request( return index; } -std::string Client::process_result(SharedMemory* shared_memory, int index) +std::string Client::process_respond(SharedMemory* shared_memory, int index) { - std::cout << "process result" << '\n'; + if (index >= QUEUE_SIZE || index < 0) { + return std::string(); + } + pthread_mutex_lock(&shared_memory->mutex); while (!request_processed(shared_memory, index)) { diff --git a/src/client/client.h b/src/client/client.h index 9ff5b47..852ade3 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -28,5 +28,5 @@ private: std::optional k, std::optional v); bool request_processed(SharedMemory* shared_memory, int index); - std::string process_result(SharedMemory* shared_memory, int index); + std::string process_respond(SharedMemory* shared_memory, int index); }; diff --git a/src/client/main.cpp b/src/client/main.cpp index ca2f4a3..7e61ffe 100644 --- a/src/client/main.cpp +++ b/src/client/main.cpp @@ -1,9 +1,7 @@ #include "client.h" - int main() { Client client; - client.start_client(); } diff --git a/src/server/main.cpp b/src/server/main.cpp index d4890aa..d724bd5 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -20,7 +20,7 @@ int main(int argc, char* argv[]) return 1; } - SharedMemoryServer shm(size); + Server shm(size); shm.process_requests(); diff --git a/src/server/shared_memory_server.h b/src/server/shared_memory_server.h index d50797c..aa0e261 100644 --- a/src/server/shared_memory_server.h +++ b/src/server/shared_memory_server.h @@ -9,9 +9,9 @@ #include template -class SharedMemoryServer { +class Server { public: - SharedMemoryServer(size_t size) + Server(size_t size) : hash_table(size) { shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666); @@ -34,7 +34,7 @@ public: pthread_cond_init(&shared_memory->cond_var, &cond_attr); } - ~SharedMemoryServer() + ~Server() { munmap(shared_memory, sizeof(SharedMemory)); close(shm_fd); @@ -70,6 +70,7 @@ public: MAX_VALUE_SIZE); } break; + case GET: { std::cout << "Get operation" << '\n'; hash_table.insert(key, value); @@ -85,6 +86,7 @@ public: } break; } + case DELETE: std::cout << "Remove operation" << '\n'; if (hash_table.remove(key)) { @@ -95,10 +97,11 @@ public: } else { strncpy( request->response, - serialize("Couldn't find key'").c_str(), + serialize("Couldn't find the key").c_str(), MAX_VALUE_SIZE); } break; + case PRINT: std::cout << "Print operation" << '\n'; strncpy( @@ -106,6 +109,7 @@ public: serialize(hash_table.string()).c_str(), MAX_VALUE_SIZE); break; + default: break; } -- cgit 1.4.1