Skip to content

mhubert3/KeyValue-Store

Repository files navigation

C++ Key/Value Store

Overview

This repository contains a multithreaded in-memory key/value store built with a client-server architecture in C++. The project features a concurrent server capable of managing multiple simultaneous client connections over a network, performing atomic data operations on named, thread-safe tables.

This project was originally developed as a successful partner project for a Computer Systems Fundamentals class. It demonstrates an understanding of concurrent programming, POSIX threading (pthreads), network socket programming, and managing transactions to ensure data consistency.

Architecture & Transactional Design

The system is separated into modular components to handle network execution and data concurrency:

  • Multithreaded Server (Server & ClientConnection): A main thread listens for incoming TCP connections and spawns dedicated, detached POSIX worker pthreads for each client. This isolates client logic, allowing the server to handle simultaneous concurrent connections without blocking.
  • Core Data Structures (Table & ValueStack): Key/value data is managed in memory. Operations support multi-step transactions (BEGIN, COMMIT, ROLLBACK).
  • Transactional Logic: The Table class maintains two states (committed data and pending changes). Reads within an active transaction check pending data first to keep the data consistent. Changes only become permanent upon an explicit COMMIT.
  • Protocol & Serialization (Message): A custom, line-oriented text protocol dictates client/server interaction. The server handles the encoding and decoding of network strings into commands.

Concurrent Synchronization & Thread Safety

In a multi-threaded server architecture, preventing data corruption and deadlocks was critical:

  • Global Table Map Locking: A global mutex protects the server's map of active tables so creating a new table doesn't cause a race condition. A helper Guard class makes sure this lock is always released, even if an error occurs.
  • Individual Table Locks: Each Table has its own mutex lock. This means a client modifying one table won't block other clients from using different tables at the same time.
  • Deadlock Avoidance:
    • Autocommit Mode: Single operations only hold one lock at a time, which naturally prevents circular deadlocks.
    • Transaction Mode: Multi-step transactions use non-blocking "trylocks" (table->trylock()). If a lock is already taken by another client, the transaction fails safely, undoes its changes, and drops all its locks so it doesn't hold up the rest of the system.

Repository Structure

  • server.cpp / client_connection.cpp - Multithreaded server and client connection handling. The original assignment code files are preserved.
  • table.cpp / value_stack.cpp - Data structures for the tables and managing client operations.
  • message.cpp / message_serialization.cpp - Communication protocol for sending and receiving commands.
  • Makefile - Command-line build configuration.
  • csapp.h / csapp.c - I/O and networking wrappers.

Technologies & Tools

  • Programming Language: C++
  • Concepts: Multithreading (pthreads), Network Sockets, Mutexes, Client-Server Architecture.
  • Environment: Tested and compiled on x86 Linux servers (University environments).

About

This project implements a multithreaded, in-memory key/value store using a C++ client-server architecture. It features a concurrent server that handles multiple client connections, utilizing mutex locking and a custom deadlock-avoidance system to safely manage multi-step data transactions.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors