- Overview
 - Implementors
 - Project Architecture
 - Building the Project
 - Running the Server and Client
 - Workload Generation
 - Resources
 - License
 
This project implements a concurrent Key-Value (KV) Server that communicates with a multi-threaded client via a shared memory region. The shared memory region is divided into:
- A Ring Buffer (for request submission by the client and consumption by the server), and
 - A Request-status Board (for the server to post results back to the client).
 
The key objectives are:
- Implementing a thread-safe, lockless (or partially lock-free) ring buffer using atomic operations or minimal locking.
 - Building a multi-threaded, thread-safe KV Store with fine-grained locking or atomic operations for fast concurrent access.
 - Demonstrating interprocess communication (IPC) using a file-backed 
mmap. - Ensuring high concurrency and minimal blocking between client and server threads.
 
- 
Dhruv Desai
- CS Login: ddesai
 - NetID: ddesai7
 - Email: ddesai7@wisc.edu
 
 - 
Srujay Jakkidi
- CS Login: srujay
 - NetID: jakkidi
 - Email: jakkidi@wisc.edu
 
 
Key-Value-Server/
├── README.md               # This README
├── Makefile                # Builds client and server
├── include/
│   ├── common.h            # Contains shared typedefs and hash function (DO NOT MODIFY)
│   └── ring_buffer.h       # Ring Buffer interface
├── src/
│   ├── client.c            # Client code (producer)
│   ├── ring_buffer.c       # Ring Buffer implementation
│   ├── kv_store.c          # KV Store + server main() implementation
│   └── kv_store.h          # If a separate header is created for KV Store
├── scripts/
│   └── gen_workload.py     # Helper script to generate workloads
├── tests/
│   ├── workload.txt        # Example workload file
│   └── resources.txt       # Document describing external resources used
├── solution.txt            # Explanation of the implementation approach
Note:
kv_store.his optional; create it if you prefer a separate header for your KV Store data structures and prototypes.solution.txtcan be used to provide further insights into your design.
- Location: 
src/ring_buffer.c/include/ring_buffer.h - Purpose: Acts as a lockless (or minimally locked) producer-consumer queue between client and server processes.
 - Key Operations:
init_ring(struct ring *r): Initializes the ring buffer’s head and tail indices and any synchronization primitives (e.g., atomic counters).ring_submit(struct ring *r, struct buffer_descriptor *bd): Thread-safe enqueue operation.ring_get(struct ring *r, struct buffer_descriptor *bd): Thread-safe dequeue operation.
 
- Location: 
src/kv_store.c(and optionallysrc/kv_store.h) - Purpose: Maintains key-value mappings. Must handle concurrent 
PUTandGEToperations from multiple server threads. - Features:
- Hashtable with open addressing (linear probing) or chaining.
 - Fine-Grained Locking or lock-free approach for concurrency.
 - Rehashing / Migration support (if implemented) to handle table growth.
 
 
A Makefile is provided at the project root. By default, it produces two executables: client and server.
- 
Navigate to the project directory.
 - 
Build both client and server by running:
make
This triggers the
alltarget, compilingclient.c,kv_store.c, andring_buffer.c. - 
Clean (optional):
make clean
Removes object files and any existing
client/serverbinaries. 
- 
Server
./server -n <num_server_threads> -s <initial_hashtable_size>-n: Number of server threads.-s: The initial hashtable size for the KV Store.
 - 
Client
./client -n <num_client_threads> -w <windows_per_client_thread>-n: Number of client threads.-w: Number of Request-status Board windows each client thread owns.
 
Note:
- The shared memory is created in the client using a file named
 shmem_file.- The server also maps the same file for interprocess communication.
 
- 
Starting the Server with 2 threads and an initial hashtable size of 5:
./server -n 2 -s 5
 - 
Starting the Client with 3 threads and 2 windows per thread:
./client -n 3 -w 2
 - 
Automation: You can run the client first (which might fork the server in some implementations) or manually start the server and then the client, depending on your design.
 
A script named gen_workload.py is provided under scripts/. Use it to generate input workloads (PUT/GET requests) for stress testing your KV store. The generated output can be redirected to workload.txt or any file of your choice.
Example usage:
python3 scripts/gen_workload.py 1000 > tests/workload.txt
- DPDK Ring concepts: DPDK Documentation
 - Concurrent Hash Tables: “Concurrent Hash Tables: Fast and General (?)” by Jacobson et al.
 
This project was developed as part of the CS 537: Introduction to Operating Systems course at the University of Wisconsin–Madison. It is shared strictly for educational and learning purposes only.
Important Notes:
- Redistribution or reuse of this code for academic submissions is prohibited and may violate academic integrity policies.
 - The project is licensed under the MIT License. Any usage outside academic purposes must include proper attribution.
 
Enjoy building and experimenting with your concurrent Key-Value Server!