Functional Scope (In-Scope)
- Basic Operations: Supports standard key-value map GET, SET, and DELETE methods.
- Nested Transactions: Support BEGIN transactions inside parent operations recursively.
- Read-Your-Writes Consistency: Operations inside an active transaction instantly perceive local dirty changes before committed values.
- ACID Rollback Protection: ROLLBACK operations atomically discard all nested mutations, preserving global keys.
Explicit Boundaries (Out-of-Scope)
- No Durable Disk Log Persistence: All mutations reside entirely in memory. Out-of-scope to manage write-ahead logs to local file systems.
- No Range Queries / Custom Scans: The engine does not evaluate key prefix ranges or conditional sweeps.
Thread-safe reference implementations in Java and Python:
// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
interface DatabaseCommand {
void execute(Map<String, String> buffer, Set<String> deletes);
}
class PutCommand implements DatabaseCommand {
private final String key;
private final String value;
public PutCommand(String key, String value) {
this.key = key;
this.value = value;
}
@Override
public void execute(Map<String, String> buffer, Set<String> deletes) {
deletes.remove(key);
buffer.put(key, value);
}
}
class DeleteCommand implements DatabaseCommand {
private final String key;
public DeleteCommand(String key) {
this.key = key;
}
@Override
public void execute(Map<String, String> buffer, Set<String> deletes) {
buffer.remove(key);
deletes.add(key);
}
}
class Transaction {
private final Map<String, String> localBuffer = new HashMap<>();
private final Set<String> deletedKeys = new HashSet<>();
private final List<DatabaseCommand> commandHistory = new ArrayList<>();
private final Transaction parent;
public Transaction(Transaction parent) {
this.parent = parent;
}
public Transaction getParent() { return parent; }
public Map<String, String> getLocalBuffer() { return localBuffer; }
public Set<String> getDeletedKeys() { return deletedKeys; }
public void applyCommand(DatabaseCommand cmd) {
cmd.execute(localBuffer, deletedKeys);
commandHistory.add(cmd);
}
public String get(String key) {
if (deletedKeys.contains(key)) return null;
if (localBuffer.containsKey(key)) return localBuffer.get(key);
if (parent != null) return parent.get(key);
return null;
}
}
class InMemoryKVStore {
private final Map<String, String> globalStore = new ConcurrentHashMap<>();
private final ThreadLocal<Stack<Transaction>> transactionStack = ThreadLocal.withInitial(Stack::new);
private final ReentrantReadWriteLock globalLock = new ReentrantReadWriteLock();
public void begin() {
Stack<Transaction> stack = transactionStack.get();
Transaction parent = stack.isEmpty() ? null : stack.peek();
stack.push(new Transaction(parent));
System.out.println("[Thread-" + Thread.currentThread().getId() + "] BEGIN Transaction. Stack depth: " + stack.size());
}
public void set(String key, String value) {
DatabaseCommand cmd = new PutCommand(key, value);
Stack<Transaction> stack = transactionStack.get();
if (stack.isEmpty()) {
globalLock.writeLock().lock();
try {
globalStore.put(key, value);
System.out.println("[Thread-" + Thread.currentThread().getId() + "] Global SET: " + key + " = " + value);
} finally {
globalLock.writeLock().unlock();
}
} else {
stack.peek().applyCommand(cmd);
System.out.println("[Thread-" + Thread.currentThread().getId() + "] Transaction SET: " + key + " = " + value);
}
}
public String get(String key) {
Stack<Transaction> stack = transactionStack.get();
if (!stack.isEmpty()) {
Transaction activeTx = stack.peek();
String val = activeTx.get(key);
if (val != null || activeTx.getDeletedKeys().contains(key)) {
return val;
}
}
globalLock.readLock().lock();
try {
return globalStore.get(key);
} finally {
globalLock.readLock().unlock();
}
}
public void delete(String key) {
DatabaseCommand cmd = new DeleteCommand(key);
Stack<Transaction> stack = transactionStack.get();
if (stack.isEmpty()) {
globalLock.writeLock().lock();
try {
globalStore.remove(key);
System.out.println("[Thread-" + Thread.currentThread().getId() + "] Global DELETE: " + key);
} finally {
globalLock.writeLock().unlock();
}
} else {
stack.peek().applyCommand(cmd);
System.out.println("[Thread-" + Thread.currentThread().getId() + "] Transaction DELETE: " + key);
}
}
public void commit() {
Stack<Transaction> stack = transactionStack.get();
if (stack.isEmpty()) {
throw new IllegalStateException("No active transaction to commit");
}
Transaction activeTx = stack.pop();
if (stack.isEmpty()) {
globalLock.writeLock().lock();
try {
for (String key : activeTx.getDeletedKeys()) {
globalStore.remove(key);
}
globalStore.putAll(activeTx.getLocalBuffer());
System.out.println("[Thread-" + Thread.currentThread().getId() + "] Transaction committed to global store.");
} finally {
globalLock.writeLock().unlock();
}
} else {
Transaction parent = stack.peek();
for (String key : activeTx.getDeletedKeys()) {
parent.applyCommand(new DeleteCommand(key));
}
for (Map.Entry<String, String> entry : activeTx.getLocalBuffer().entrySet()) {
parent.applyCommand(new PutCommand(entry.getKey(), entry.getValue()));
}
System.out.println("[Thread-" + Thread.currentThread().getId() + "] Transaction committed to parent context.");
}
}
public void rollback() {
Stack<Transaction> stack = transactionStack.get();
if (stack.isEmpty()) {
throw new IllegalStateException("No active transaction to rollback");
}
stack.pop();
System.out.println("[Thread-" + Thread.currentThread().getId() + "] Transaction rolled back.");
}
}
public class InMemoryKVStoreDriver {
public static void main(String[] args) throws Exception {
System.out.println("=== IN-MEMORY KEY-VALUE STORE DRIVER ===");
InMemoryKVStore store = new InMemoryKVStore();
// 1. Basic Global Operations
store.set("a", "100");
System.out.println("Global GET a: " + store.get("a"));
// 2. Transaction isolation and nested rollback test
store.begin();
store.set("a", "200");
store.set("b", "300");
System.out.println("Tx GET a: " + store.get("a")); // 200 (dirty read)
System.out.println("Tx GET b: " + store.get("b")); // 300
store.begin();
store.set("b", "400");
System.out.println("Nested Tx GET b: " + store.get("b")); // 400
store.rollback(); // Rollback nested transaction
System.out.println("Post-rollback Tx GET b: " + store.get("b")); // 300 (restored parent state)
store.commit(); // Commit main transaction
System.out.println("Post-commit Global GET a: " + store.get("a")); // 200
System.out.println("Post-commit Global GET b: " + store.get("b")); // 300
// 3. Multi-threaded isolation demonstration
System.out.println("\n--- Concurrent Thread Isolation Simulation ---");
Thread thread1 = new Thread(() -> {
store.begin();
store.set("threadLocalKey", "val1");
System.out.println("Thread-1 Local GET: " + store.get("threadLocalKey"));
try { Thread.sleep(100); } catch (InterruptedException e) {}
store.rollback();
System.out.println("Thread-1 Post-rollback Local GET: " + store.get("threadLocalKey")); // null
});
Thread thread2 = new Thread(() -> {
store.begin();
store.set("threadLocalKey", "val2");
System.out.println("Thread-2 Local GET: " + store.get("threadLocalKey"));
try { Thread.sleep(200); } catch (InterruptedException e) {}
store.commit();
System.out.println("Thread-2 Post-commit Global GET: " + store.get("threadLocalKey")); // val2
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Global Final GET threadLocalKey: " + store.get("threadLocalKey")); // val2
}
}