From 03ad55130b4f0047eb64d3cc9947b98f0130623e Mon Sep 17 00:00:00 2001 From: Christian Krinitsin Date: Sun, 23 Mar 2025 17:50:37 +0100 Subject: fix terminology --- src/client/client.cpp | 8 ++++---- src/server/main.cpp | 2 +- src/server/shared_memory_server.h | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/client.cpp b/src/client/client.cpp index cbaddeb..e7853a8 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -98,13 +98,13 @@ bool Client::request_processed(SharedMemory* shared_memory, int index) return true; } - for (int i = shared_memory->head - 1; i != shared_memory->tail; i = (i - 1) % QUEUE_SIZE) { + for (int i = shared_memory->head; i != shared_memory->tail; i = (i + 1) % QUEUE_SIZE) { if (i == index) { return false; } } - return shared_memory->tail != index; + return true; } int Client::send_request( @@ -121,12 +121,12 @@ int Client::send_request( pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); } - index = shared_memory->head; + index = shared_memory->tail; 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->tail = (1 + shared_memory->tail) % QUEUE_SIZE; shared_memory->full = shared_memory->head == shared_memory->tail; pthread_cond_signal(&shared_memory->cond_var); diff --git a/src/server/main.cpp b/src/server/main.cpp index d724bd5..75939e0 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -8,7 +8,7 @@ int main(int argc, char* argv[]) { if (argc != 2) { - std::cout << "One argument required" << '\n'; + std::cout << "Usage: " << argv[0] << " \n"; return 1; } diff --git a/src/server/shared_memory_server.h b/src/server/shared_memory_server.h index 6c97e64..3ac375a 100644 --- a/src/server/shared_memory_server.h +++ b/src/server/shared_memory_server.h @@ -32,6 +32,7 @@ public: mmap(0, sizeof(SharedMemory), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); shared_memory->tail = shared_memory->head = 0; + shared_memory->full = false; pthread_mutexattr_t mutex_attr; pthread_condattr_t cond_attr; @@ -68,7 +69,7 @@ public: pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); } - Request* request = &shared_memory->request[shared_memory->tail]; + Request* request = &shared_memory->request[shared_memory->head]; K key = deserialize(request->key); V value = deserialize(request->value); @@ -130,7 +131,7 @@ public: default: break; } - shared_memory->tail = (1 + shared_memory->tail) % QUEUE_SIZE; + shared_memory->head = (1 + shared_memory->head) % QUEUE_SIZE; shared_memory->full = false; pthread_cond_signal(&shared_memory->cond_var); pthread_mutex_unlock(&shared_memory->mutex); -- cgit 1.4.1 From eef27810ce34d00d1d19a7ac6fbce794df4a9708 Mon Sep 17 00:00:00 2001 From: Christian Krinitsin Date: Sun, 23 Mar 2025 19:09:52 +0100 Subject: add server-shutdown with --- src/server/hashtable.h | 6 ++++++ src/server/main.cpp | 20 +++++++++++++++++++- src/server/shared_memory_server.h | 15 ++++++++++----- 3 files changed, 35 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/hashtable.h b/src/server/hashtable.h index e09fcd4..dfa9ca3 100644 --- a/src/server/hashtable.h +++ b/src/server/hashtable.h @@ -28,6 +28,12 @@ public: { } + /** + * @brief Constructs a new Hashtable. + * + */ + HashTable() {} + /** * @brief Insert a kv-pair into the hashtable. * diff --git a/src/server/main.cpp b/src/server/main.cpp index 75939e0..c20cde9 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,6 +6,21 @@ #include "shared_memory_server.h" +Server shm; + +/** + * @brief Shuts the server down, when pressing . + * + * @param signal Specifies the signal, which was caught. + */ +void signal_handler(int signal) { + if (signal == SIGINT) { + std::cout << "Server shutting down" << '\n'; + shm.terminate_server(); + exit(0); + } +} + int main(int argc, char* argv[]) { if (argc != 2) { @@ -20,7 +36,9 @@ int main(int argc, char* argv[]) return 1; } - Server shm(size); + shm.initialize_hashtable(size); + + std::signal(SIGINT, signal_handler); shm.process_requests(); diff --git a/src/server/shared_memory_server.h b/src/server/shared_memory_server.h index 3ac375a..46005fc 100644 --- a/src/server/shared_memory_server.h +++ b/src/server/shared_memory_server.h @@ -2,6 +2,7 @@ #include "hashtable.h" #include "shared_memory.h" +#include #include #include #include @@ -18,11 +19,8 @@ class Server { public: /** * @brief Constructs a new hashtable and initializes a shared memory buffer. - * - * @param size The number of buckets in the hashtable. */ - Server(size_t size) - : hash_table(size) + Server() { shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666); @@ -48,13 +46,20 @@ public: /** * @brief Unmaps and unlinks the shared memory. */ - ~Server() + void terminate_server() { munmap(shared_memory, sizeof(SharedMemory)); close(shm_fd); shm_unlink(SHM_NAME); } + /** + * @brief Initializes the hashtable. + * + * @param size The number of buckets in the hashtable. + */ + void initialize_hashtable(size_t size) { hash_table = HashTable(size); } + /** * @brief The main loop of the server. * -- cgit 1.4.1 From 9a82a125ce3fe4edc4519d7c2935e8266760e257 Mon Sep 17 00:00:00 2001 From: Christian Krinitsin Date: Sun, 23 Mar 2025 20:07:30 +0100 Subject: add server-destructor for termination --- src/server/main.cpp | 1 - src/server/shared_memory_server.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/main.cpp b/src/server/main.cpp index c20cde9..6315460 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -16,7 +16,6 @@ Server shm; void signal_handler(int signal) { if (signal == SIGINT) { std::cout << "Server shutting down" << '\n'; - shm.terminate_server(); exit(0); } } diff --git a/src/server/shared_memory_server.h b/src/server/shared_memory_server.h index 46005fc..e28fb6a 100644 --- a/src/server/shared_memory_server.h +++ b/src/server/shared_memory_server.h @@ -46,7 +46,7 @@ public: /** * @brief Unmaps and unlinks the shared memory. */ - void terminate_server() + ~Server() { munmap(shared_memory, sizeof(SharedMemory)); close(shm_fd); -- cgit 1.4.1 From 36dabafe242e8dc290ff76885c43c773b6d20b28 Mon Sep 17 00:00:00 2001 From: Christian Krinitsin Date: Sun, 23 Mar 2025 20:11:53 +0100 Subject: prevent multiple server instances --- src/server/shared_memory_server.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/shared_memory_server.h b/src/server/shared_memory_server.h index e28fb6a..d4be69f 100644 --- a/src/server/shared_memory_server.h +++ b/src/server/shared_memory_server.h @@ -22,7 +22,11 @@ public: */ Server() { - shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666); + shm_fd = shm_open(SHM_NAME, O_EXCL | O_CREAT | O_RDWR, 0666); + if (-1 == shm_fd) { + std::cout << "Server is already running!" << '\n'; + exit(-1); + } ftruncate(shm_fd, sizeof(SharedMemory)); -- cgit 1.4.1 From 876b2f8e699c1b24ae5e4f98a4affe9fa1a8650f Mon Sep 17 00:00:00 2001 From: Christian Krinitsin Date: Sun, 23 Mar 2025 20:34:26 +0100 Subject: add a request status, so that multiple clients cannot overwrite requests from other clients --- src/client/client.cpp | 20 ++++---------------- src/common/shared_memory.h | 4 +++- src/server/shared_memory_server.h | 5 ++--- 3 files changed, 9 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/client/client.cpp b/src/client/client.cpp index e7853a8..1c0727f 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -91,20 +91,7 @@ bool Client::request_processed(SharedMemory* shared_memory, int index) return false; } - if (shared_memory->full) { - return false; - } - if (shared_memory->tail == shared_memory->head && !shared_memory->full) { - return true; - } - - for (int i = shared_memory->head; i != shared_memory->tail; i = (i + 1) % QUEUE_SIZE) { - if (i == index) { - return false; - } - } - - return true; + return shared_memory->request[index].status == PROCESSED; } int Client::send_request( @@ -117,17 +104,17 @@ int Client::send_request( pthread_mutex_lock(&shared_memory->mutex); - while (shared_memory->full) { + while (shared_memory->request[shared_memory->tail].status != FREE) { pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); } index = shared_memory->tail; Request* request = &shared_memory->request[index]; request->type = type; + request->status = SENT; 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->tail = (1 + shared_memory->tail) % QUEUE_SIZE; - shared_memory->full = shared_memory->head == shared_memory->tail; pthread_cond_signal(&shared_memory->cond_var); pthread_mutex_unlock(&shared_memory->mutex); @@ -147,6 +134,7 @@ std::string Client::process_respond(SharedMemory* shared_memory, int index) pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); } std::string result(shared_memory->request[index].response); + shared_memory->request[index].status = FREE; pthread_mutex_unlock(&shared_memory->mutex); return result; } diff --git a/src/common/shared_memory.h b/src/common/shared_memory.h index fe101ea..1798ad1 100644 --- a/src/common/shared_memory.h +++ b/src/common/shared_memory.h @@ -14,11 +14,14 @@ */ enum Operations { INSERT, DELETE, GET, PRINT }; +enum Status { FREE, SENT, PROCESSED}; + /** * @brief One request constists out of the operation, the arguments and the response. */ struct Request { Operations type; + Status status = FREE; char key[MAX_KEY_SIZE]; char value[MAX_VALUE_SIZE]; char response[MAX_VALUE_SIZE]; @@ -38,7 +41,6 @@ struct SharedMemory { int tail; int head; - bool full; }; /** diff --git a/src/server/shared_memory_server.h b/src/server/shared_memory_server.h index d4be69f..e8e5c38 100644 --- a/src/server/shared_memory_server.h +++ b/src/server/shared_memory_server.h @@ -34,7 +34,6 @@ public: mmap(0, sizeof(SharedMemory), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); shared_memory->tail = shared_memory->head = 0; - shared_memory->full = false; pthread_mutexattr_t mutex_attr; pthread_condattr_t cond_attr; @@ -74,7 +73,7 @@ public: while (true) { pthread_mutex_lock(&shared_memory->mutex); - if (shared_memory->tail == shared_memory->head && !shared_memory->full) { + if (shared_memory->request[shared_memory->head].status != SENT) { pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); } @@ -140,8 +139,8 @@ public: default: break; } + shared_memory->request[shared_memory->head].status = PROCESSED; shared_memory->head = (1 + shared_memory->head) % QUEUE_SIZE; - shared_memory->full = false; pthread_cond_signal(&shared_memory->cond_var); pthread_mutex_unlock(&shared_memory->mutex); } -- cgit 1.4.1 From d6ea41e1bef4a312a8a1d6683bb29aad777ec9ae Mon Sep 17 00:00:00 2001 From: Christian Krinitsin Date: Sun, 23 Mar 2025 20:52:03 +0100 Subject: last small formatting fixes --- README.md | 2 +- src/client/client.h | 1 - src/common/shared_memory.h | 5 +- src/server/hashtable.h | 1 - src/server/main.cpp | 5 +- src/server/server.h | 164 ++++++++++++++++++++++++++++++++++++++ src/server/shared_memory_server.h | 164 -------------------------------------- 7 files changed, 172 insertions(+), 170 deletions(-) create mode 100644 src/server/server.h delete mode 100644 src/server/shared_memory_server.h (limited to 'src') diff --git a/README.md b/README.md index 6d41bc7..66ef50c 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ $ ./server ### Client -2. Execute the client: +2. Execute the client(s): ```bash $ ./client ``` diff --git a/src/client/client.h b/src/client/client.h index bc2d702..556e9bf 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -8,7 +8,6 @@ #include #include #include -#include #include "shared_memory.h" diff --git a/src/common/shared_memory.h b/src/common/shared_memory.h index 1798ad1..465e79f 100644 --- a/src/common/shared_memory.h +++ b/src/common/shared_memory.h @@ -14,7 +14,10 @@ */ enum Operations { INSERT, DELETE, GET, PRINT }; -enum Status { FREE, SENT, PROCESSED}; +/** + * @brief Possible statuses of a request. + */ +enum Status { FREE, SENT, PROCESSED }; /** * @brief One request constists out of the operation, the arguments and the response. diff --git a/src/server/hashtable.h b/src/server/hashtable.h index dfa9ca3..334a62e 100644 --- a/src/server/hashtable.h +++ b/src/server/hashtable.h @@ -30,7 +30,6 @@ public: /** * @brief Constructs a new Hashtable. - * */ HashTable() {} diff --git a/src/server/main.cpp b/src/server/main.cpp index 6315460..42b7668 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -4,7 +4,7 @@ #include #include -#include "shared_memory_server.h" +#include "server.h" Server shm; @@ -13,7 +13,8 @@ Server shm; * * @param signal Specifies the signal, which was caught. */ -void signal_handler(int signal) { +void signal_handler(int signal) +{ if (signal == SIGINT) { std::cout << "Server shutting down" << '\n'; exit(0); diff --git a/src/server/server.h b/src/server/server.h new file mode 100644 index 0000000..4c019f1 --- /dev/null +++ b/src/server/server.h @@ -0,0 +1,164 @@ +#pragma once + +#include "hashtable.h" +#include "shared_memory.h" +#include +#include +#include +#include +#include +#include + +/** + * @class Server + * @brief Represents the server, which performs operations on the hashtable based on the requests of + * the client. + */ +template +class Server { +public: + /** + * @brief Constructs a new hashtable and initializes a shared memory buffer. + */ + Server() + { + shm_fd = shm_open(SHM_NAME, O_EXCL | O_CREAT | O_RDWR, 0666); + if (shm_fd == -1) { + std::cout << "Server is already running!" << '\n'; + exit(-1); + } + + ftruncate(shm_fd, sizeof(SharedMemory)); + + shared_memory = (SharedMemory*) + mmap(0, sizeof(SharedMemory), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + + shared_memory->tail = shared_memory->head = 0; + + pthread_mutexattr_t mutex_attr; + pthread_condattr_t cond_attr; + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); + pthread_condattr_init(&cond_attr); + pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); + + pthread_mutex_init(&shared_memory->mutex, &mutex_attr); + pthread_cond_init(&shared_memory->cond_var, &cond_attr); + } + + /** + * @brief Unmaps and unlinks the shared memory. + */ + ~Server() + { + munmap(shared_memory, sizeof(SharedMemory)); + close(shm_fd); + shm_unlink(SHM_NAME); + } + + /** + * @brief Initializes the hashtable. + * + * @param size The number of buckets in the hashtable. + */ + void initialize_hashtable(size_t size) { hash_table = HashTable(size); } + + /** + * @brief The main loop of the server. + * + * @details The server checks the shared memory for new requests and executes them. + */ + void process_requests() + { + while (true) { + pthread_mutex_lock(&shared_memory->mutex); + + if (shared_memory->request[shared_memory->head].status != SENT) { + pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); + } + + Request* request = &shared_memory->request[shared_memory->head]; + + K key = deserialize(request->key); + V value = deserialize(request->value); + + switch (request->type) { + case INSERT: + 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 << "Get operation" << '\n'; + 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); + } else { + strncpy( + request->response, + serialize("Couldn't get any value").c_str(), + MAX_VALUE_SIZE); + } + break; + } + + case DELETE: + 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 the key").c_str(), + MAX_VALUE_SIZE); + } + break; + + case PRINT: + std::cout << "Print operation" << '\n'; + strncpy( + request->response, + serialize(hash_table.string()).c_str(), + MAX_VALUE_SIZE); + break; + + default: + break; + } + shared_memory->request[shared_memory->head].status = PROCESSED; + shared_memory->head = (1 + shared_memory->head) % QUEUE_SIZE; + pthread_cond_signal(&shared_memory->cond_var); + pthread_mutex_unlock(&shared_memory->mutex); + } + } + +private: + /** + * @brief The hashtable. + */ + HashTable hash_table; + + /** + * @brief Memory which is shared with the client. + */ + SharedMemory* shared_memory; + + /** + * @brief File descriptor for the shared memory, used to unmap and close the memory at the end. + */ + int shm_fd; +}; diff --git a/src/server/shared_memory_server.h b/src/server/shared_memory_server.h deleted file mode 100644 index e8e5c38..0000000 --- a/src/server/shared_memory_server.h +++ /dev/null @@ -1,164 +0,0 @@ -#pragma once - -#include "hashtable.h" -#include "shared_memory.h" -#include -#include -#include -#include -#include -#include - -/** - * @class Server - * @brief Represents the server, which performs operations on the hashtable based on the requests of - * the client. - */ -template -class Server { -public: - /** - * @brief Constructs a new hashtable and initializes a shared memory buffer. - */ - Server() - { - shm_fd = shm_open(SHM_NAME, O_EXCL | O_CREAT | O_RDWR, 0666); - if (-1 == shm_fd) { - std::cout << "Server is already running!" << '\n'; - exit(-1); - } - - ftruncate(shm_fd, sizeof(SharedMemory)); - - shared_memory = (SharedMemory*) - mmap(0, sizeof(SharedMemory), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); - - shared_memory->tail = shared_memory->head = 0; - - pthread_mutexattr_t mutex_attr; - pthread_condattr_t cond_attr; - pthread_mutexattr_init(&mutex_attr); - pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); - pthread_condattr_init(&cond_attr); - pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); - - pthread_mutex_init(&shared_memory->mutex, &mutex_attr); - pthread_cond_init(&shared_memory->cond_var, &cond_attr); - } - - /** - * @brief Unmaps and unlinks the shared memory. - */ - ~Server() - { - munmap(shared_memory, sizeof(SharedMemory)); - close(shm_fd); - shm_unlink(SHM_NAME); - } - - /** - * @brief Initializes the hashtable. - * - * @param size The number of buckets in the hashtable. - */ - void initialize_hashtable(size_t size) { hash_table = HashTable(size); } - - /** - * @brief The main loop of the server. - * - * @details The server checks the shared memory for new requests and executes them. - */ - void process_requests() - { - while (true) { - pthread_mutex_lock(&shared_memory->mutex); - - if (shared_memory->request[shared_memory->head].status != SENT) { - pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); - } - - Request* request = &shared_memory->request[shared_memory->head]; - - K key = deserialize(request->key); - V value = deserialize(request->value); - - switch (request->type) { - case INSERT: - 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 << "Get operation" << '\n'; - 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); - } else { - strncpy( - request->response, - serialize("Couldn't get any value").c_str(), - MAX_VALUE_SIZE); - } - break; - } - - case DELETE: - 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 the key").c_str(), - MAX_VALUE_SIZE); - } - break; - - case PRINT: - std::cout << "Print operation" << '\n'; - strncpy( - request->response, - serialize(hash_table.string()).c_str(), - MAX_VALUE_SIZE); - break; - - default: - break; - } - shared_memory->request[shared_memory->head].status = PROCESSED; - shared_memory->head = (1 + shared_memory->head) % QUEUE_SIZE; - pthread_cond_signal(&shared_memory->cond_var); - pthread_mutex_unlock(&shared_memory->mutex); - } - } - -private: - /** - * @brief The hashtable. - */ - HashTable hash_table; - - /** - * @brief Memory which is shared with the client. - */ - SharedMemory* shared_memory; - - /** - * @brief File descriptor for the shared memory, used to unmap and close the memory at the end. - */ - int shm_fd; -}; -- cgit 1.4.1