index — client-server-shm @ 66d87280633590818261b89c50fe1830092174e4

preassignment for my bachelor-thesis

Merge pull request #5 from ckrinitsin/fixes

Fixes
ckrinitsin 101062646+ckrinitsin@users.noreply.github.com
Sun, 23 Mar 2025 20:55:14 +0100
commit

66d87280633590818261b89c50fe1830092174e4

parent

3939238f3fe46ed36919f29cbebe824341689960

M README.mdREADME.md

@@ -19,7 +19,7 @@ ```

### Client -2. Execute the client: +2. Execute the client(s): ```bash $ ./client ```
M src/client/client.cppsrc/client/client.cpp

@@ -91,20 +91,7 @@ if (index >= QUEUE_SIZE || index < 0) {

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 - 1; i != shared_memory->tail; i = (i - 1) % QUEUE_SIZE) { - if (i == index) { - return false; - } - } - - return shared_memory->tail != index; + return shared_memory->request[index].status == PROCESSED; } int Client::send_request(

@@ -117,17 +104,17 @@ int index;

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->head; + 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->head = (1 + shared_memory->head) % QUEUE_SIZE; - shared_memory->full = shared_memory->head == shared_memory->tail; + shared_memory->tail = (1 + shared_memory->tail) % QUEUE_SIZE; pthread_cond_signal(&shared_memory->cond_var); pthread_mutex_unlock(&shared_memory->mutex);

@@ -147,6 +134,7 @@ while (!request_processed(shared_memory, 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; }
M src/client/client.hsrc/client/client.h

@@ -8,7 +8,6 @@ #include <pthread.h>

#include <string> #include <sys/mman.h> #include <unistd.h> -#include <utility> #include "shared_memory.h"
M src/common/shared_memory.hsrc/common/shared_memory.h

@@ -15,10 +15,16 @@ */

enum Operations { INSERT, DELETE, GET, PRINT }; /** + * @brief Possible statuses of a request. + */ +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 +44,6 @@ pthread_cond_t cond_var;

int tail; int head; - bool full; }; /**
M src/server/hashtable.hsrc/server/hashtable.h

@@ -29,6 +29,11 @@ {

} /** + * @brief Constructs a new Hashtable. + */ + HashTable() {} + + /** * @brief Insert a kv-pair into the hashtable. * * @param key The key to determine the bucket.
M src/server/main.cppsrc/server/main.cpp

@@ -1,14 +1,30 @@

+#include <csignal> #include <cstdint> #include <iostream> #include <stdexcept> #include <string> -#include "shared_memory_server.h" +#include "server.h" + +Server<int, int> shm; + +/** + * @brief Shuts the server down, when pressing <Ctrl+C>. + * + * @param signal Specifies the signal, which was caught. + */ +void signal_handler(int signal) +{ + if (signal == SIGINT) { + std::cout << "Server shutting down" << '\n'; + exit(0); + } +} int main(int argc, char* argv[]) { if (argc != 2) { - std::cout << "One argument required" << '\n'; + std::cout << "Usage: " << argv[0] << " <number-of-buckets>\n"; return 1; }

@@ -20,7 +36,9 @@ std::cout << "Invalid argument" << '\n';

return 1; } - Server<int, int> shm(size); + shm.initialize_hashtable(size); + + std::signal(SIGINT, signal_handler); shm.process_requests();
M src/server/shared_memory_server.hsrc/server/server.h

@@ -2,6 +2,7 @@ #pragma once

#include "hashtable.h" #include "shared_memory.h" +#include <csignal> #include <cstring> #include <fcntl.h> #include <optional>

@@ -18,13 +19,14 @@ 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); + 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));

@@ -55,6 +57,13 @@ 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<K, V>(size); } + + /** * @brief The main loop of the server. * * @details The server checks the shared memory for new requests and executes them.

@@ -64,11 +73,11 @@ {

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); } - Request* request = &shared_memory->request[shared_memory->tail]; + Request* request = &shared_memory->request[shared_memory->head]; K key = deserialize<K>(request->key); V value = deserialize<V>(request->value);

@@ -130,8 +139,8 @@

default: break; } - shared_memory->tail = (1 + shared_memory->tail) % QUEUE_SIZE; - shared_memory->full = false; + 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); }