-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathin_memory_database.py
More file actions
109 lines (80 loc) · 2.98 KB
/
in_memory_database.py
File metadata and controls
109 lines (80 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
from collections import defaultdict
import signal
import sys
def sigint_handler(signal, frame):
sys.exit(0)
signal.signal(signal.SIGINT, sigint_handler)
class Transaction:
def __init__(self):
self._rollback_instructions = []
def add_rollback_instruction(self, instruction):
self._rollback_instructions.append(instruction)
def rollback(self):
for instruction in reversed(self._rollback_instructions):
instruction()
class InMemoryDatabase:
NO_TRANSACTION_ERROR = 'NO TRANSACTION'
def __init__(self):
self._db = {}
self._values_count = defaultdict(int)
self._transactions = []
def handle(self, request):
COMMANDS = {
'SET': self._set,
'GET': self._get,
'DELETE': self._delete,
'COUNT': self._count,
'BEGIN': self._begin,
'ROLLBACK': self._rollback,
'COMMIT': self._commit,
}
request = request.split()
command = COMMANDS[request[0]]
if len(request) == 1:
return command()
name = request[1]
if len(request) == 2:
return command(name)
value = request[2]
return command(name, value)
def _set(self, name, value, handle_rollback=True):
previous_value = self._db.get(name, None)
if previous_value:
self._values_count[previous_value] -= 1
self._db[name] = value
self._values_count[value] += 1
if handle_rollback:
rollback_instruction = lambda: self._set(name, previous_value, handle_rollback=False) if previous_value else self._delete(name, handle_rollback=False)
self._add_rollback_instruction_if_transaction(rollback_instruction)
def _get(self, name):
return self._db.get(name, None)
def _delete(self, name, handle_rollback=True):
if name not in self._db:
return
value = self._db[name]
del self._db[name]
self._values_count[value] -= 1
if handle_rollback:
self._add_rollback_instruction_if_transaction(lambda: self._set(name, value, handle_rollback=False))
def _count(self, value):
return self._values_count[value]
def _begin(self):
self._transactions.append(Transaction())
def _rollback(self):
if not self._transactions:
return self.NO_TRANSACTION_ERROR
self._transactions.pop().rollback()
def _commit(self):
if not self._transactions:
return self.NO_TRANSACTION_ERROR
self._transactions = []
def _add_rollback_instruction_if_transaction(self, instruction):
if self._transactions:
self._transactions[-1].add_rollback_instruction(instruction)
if __name__ == '__main__':
db = InMemoryDatabase()
while True:
request = input()
output = db.handle(request)
if output is not None:
print(output)