about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile6
-rw-r--r--src/client/main.cpp115
-rw-r--r--src/common/shared_memory.h46
-rw-r--r--src/server/main.cpp26
-rw-r--r--src/server/shared_memory_server.h96
6 files changed, 267 insertions, 24 deletions
diff --git a/.gitignore b/.gitignore
index ee2da23..dd00bc4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
 /server
 /client
+/compile_commands.json
+/.cache
 !/src/server/
 !/src/client/
diff --git a/Makefile b/Makefile
index 16376f5..b526fed 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,11 @@
 CXX = g++
-CXXFLAGS := -std=c++23 -Wall -Wextra -Wpedantic -O3
+CXXFLAGS := -std=c++23 -Wall -Wextra -Wpedantic -O3 -Isrc/common
 
+.PHONY: all server client
+all: server client
 server: src/server/main.cpp
 	${CXX} ${CXXFLAGS} $^ -o $@ 
-client:
+client: src/client/main.cpp
 	${CXX} ${CXXFLAGS} $^ -o $@
 
 .PHONY: clean
diff --git a/src/client/main.cpp b/src/client/main.cpp
new file mode 100644
index 0000000..6dfd48f
--- /dev/null
+++ b/src/client/main.cpp
@@ -0,0 +1,115 @@
+#include "shared_memory.h"
+#include <cstring>
+#include <fcntl.h>
+#include <iostream>
+#include <pthread.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <utility>
+
+bool 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;
+}
+
+void send_request(
+    SharedMemory* shared_memory,
+    Operations type,
+    std::pair<const std::string&, const std::string&> arguments)
+{
+    int index;
+
+    pthread_mutex_lock(&shared_memory->mutex);
+
+    if (shared_memory->full) {
+        std::cout << "Queue is full" << '\n';
+        pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex);
+        return;
+    }
+
+    index = shared_memory->head;
+    Request* request = &shared_memory->request[index];
+    request->type = type;
+    strncpy(request->key, serialize(arguments.first).c_str(), MAX_KEY_SIZE);
+    strncpy(request->value, serialize(arguments.second).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);
+
+    std::cout << "Command sent" << '\n';
+
+    if (type == Operations::GET) {
+        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);
+        std::cout << "Result: " << result << std::endl;
+    }
+}
+
+int main()
+{
+    int shm_fd = shm_open(SHM_NAME, O_RDWR, 0666);
+    if (shm_fd == -1) {
+        std::cout << "Server not running" << '\n';
+        return -1;
+    }
+
+    SharedMemory* shared_memory =
+        (SharedMemory*)mmap(0, sizeof(SharedMemory), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
+
+    std::cout << "Start inserting.." << '\n';
+    send_request(shared_memory, INSERT, std::pair(serialize(3), serialize(3)));
+
+    std::cout << "Start inserting.." << '\n';
+    send_request(shared_memory, INSERT, std::pair(serialize(4), serialize(5)));
+
+    std::cout << "Start inserting.." << '\n';
+    send_request(shared_memory, INSERT, std::pair(serialize(6), serialize(6)));
+
+    std::cout << "Start inserting.." << '\n';
+    send_request(shared_memory, INSERT, std::pair(serialize(7), serialize(3)));
+
+    std::cout << "Start inserting.." << '\n';
+    send_request(shared_memory, INSERT, std::pair(serialize(8), serialize(3)));
+
+    std::cout << "Start inserting.." << '\n';
+    send_request(shared_memory, INSERT, std::pair(serialize(9), serialize(3)));
+
+    std::cout << "Start inserting.." << '\n';
+    send_request(shared_memory, INSERT, std::pair(serialize(10), serialize(3)));
+
+    std::cout << "Start inserting.." << '\n';
+    send_request(shared_memory, INSERT, std::pair(serialize(11), serialize(3)));
+
+    std::cout << "Start inserting.." << '\n';
+    send_request(shared_memory, INSERT, std::pair(serialize(12), serialize(3)));
+
+    std::cout << "Start inserting.." << '\n';
+    send_request(shared_memory, INSERT, std::pair(serialize(13), serialize(4)));
+
+    std::cout << "Start PRINTING.." << '\n';
+    send_request(shared_memory, PRINT, std::pair(serialize(0), serialize(0)));
+
+    munmap(shared_memory, sizeof(SharedMemory));
+    close(shm_fd);
+    return 0;
+}
diff --git a/src/common/shared_memory.h b/src/common/shared_memory.h
new file mode 100644
index 0000000..70554e4
--- /dev/null
+++ b/src/common/shared_memory.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <pthread.h>
+#include <sstream>
+
+#define SHM_NAME "/hashtable_queue"
+#define QUEUE_SIZE 10
+
+#define MAX_KEY_SIZE 64
+#define MAX_VALUE_SIZE 128
+
+enum Operations { INSERT, DELETE, GET, PRINT };
+
+struct Request {
+    Operations type;
+    char key[MAX_KEY_SIZE];
+    char value[MAX_VALUE_SIZE];
+    char response[MAX_VALUE_SIZE];
+};
+
+struct SharedMemory {
+    Request request[QUEUE_SIZE];
+    pthread_mutex_t mutex;
+    pthread_cond_t cond_var;
+
+    int tail;
+    int head;
+    bool full;
+};
+
+template <typename T>
+std::string serialize(const T& data)
+{
+    std::ostringstream oss;
+    oss << data;
+    return oss.str();
+}
+
+template <typename T>
+T deserialize(const std::string& str)
+{
+    std::istringstream iss(str);
+    T data;
+    iss >> data;
+    return data;
+}
diff --git a/src/server/main.cpp b/src/server/main.cpp
index b2f8bed..424326f 100644
--- a/src/server/main.cpp
+++ b/src/server/main.cpp
@@ -1,8 +1,9 @@
 #include <cstdint>
+#include <iostream>
 #include <stdexcept>
 #include <string>
 
-#include "hashtable.h"
+#include "shared_memory_server.h"
 
 int main(int argc, char* argv[])
 {
@@ -18,29 +19,10 @@ int main(int argc, char* argv[])
         std::cout << "Invalid argument" << '\n';
         return 1;
     }
-  
-    HashTable<int, std::string> hash_table { size };
 
-    std::cout << "Add various kv-pairs" << '\n';
-    hash_table.insert(1, "1");
-    hash_table.insert(2, "2");
-    hash_table.insert(3, "3");
-    hash_table.insert(4, "4");
-    hash_table.insert(5, "5");
-    hash_table.insert(6, "6");
-    hash_table.insert(7, "7");
+    SharedMemoryServer<int, std::string> shm(size);
 
-    hash_table.print();
-
-    std::cout << '\n';
-
-    std::cout << "Value for key 8: " << hash_table.get(8).value_or("Key not found!") << '\n';
-    std::cout << "Value for key 4: " << hash_table.get(4).value_or("Key not found!") << '\n';
-
-    std::cout << '\n';
-    std::cout << "Remove pair with key 5" << '\n';
-    hash_table.remove(5);
-    hash_table.print();
+    shm.process_requests();
 
     return 0;
 }
diff --git a/src/server/shared_memory_server.h b/src/server/shared_memory_server.h
new file mode 100644
index 0000000..74abedf
--- /dev/null
+++ b/src/server/shared_memory_server.h
@@ -0,0 +1,96 @@
+#pragma once
+
+#include "hashtable.h"
+#include "shared_memory.h"
+#include <cstring>
+#include <fcntl.h>
+#include <optional>
+#include <sys/mman.h>
+#include <unistd.h>
+
+template <typename K, typename V>
+class SharedMemoryServer {
+public:
+    SharedMemoryServer(size_t size)
+        : hash_table(size)
+    {
+        shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);
+
+        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);
+    }
+
+    ~SharedMemoryServer()
+    {
+        munmap(shared_memory, sizeof(SharedMemory));
+        close(shm_fd);
+        shm_unlink(SHM_NAME);
+    }
+
+    void process_requests()
+    {
+        while (true) {
+            pthread_mutex_lock(&shared_memory->mutex);
+
+            if (shared_memory->tail == shared_memory->head && !shared_memory->full) {
+                pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex);
+            }
+
+            Request* request = &shared_memory->request[shared_memory->tail];
+
+            K key = deserialize<K>(request->key);
+            V value = deserialize<V>(request->value);
+
+            switch (request->type) {
+            case INSERT:
+                std::cout << "Inserting" << '\n';
+                hash_table.insert(key, value);
+                break;
+            case GET: {
+                std::cout << "Getting" << '\n';
+                hash_table.insert(key, value);
+                std::optional<V> result = hash_table.get(key);
+                if (result.has_value()) {
+                    std::string response = serialize<V>(result.value());
+                    strncpy(request->response, response.c_str(), MAX_VALUE_SIZE);
+                    pthread_cond_signal(&shared_memory->cond_var);
+                }
+                break;
+            }
+            case DELETE:
+                std::cout << "Deleting" << '\n';
+                hash_table.remove(key);
+                break;
+            case PRINT:
+                std::cout << "Printing" << '\n';
+                hash_table.print();
+                break;
+            default:
+                break;
+            }
+            shared_memory->tail = (1 + shared_memory->tail) % QUEUE_SIZE;
+            shared_memory->full = false;
+            pthread_mutex_unlock(&shared_memory->mutex);
+        }
+    }
+
+private:
+    HashTable<K, V> hash_table;
+
+    int shm_fd;
+    SharedMemory* shared_memory;
+};