-
Notifications
You must be signed in to change notification settings - Fork 0
/
my_db.py
100 lines (83 loc) · 3.38 KB
/
my_db.py
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
#!/usr/bin/python
# Solution for RelayRides interview challange - back end part
# Author: Karina Damico
# Date: 10/11/15
import sys
class MyDatabase(object):
#Constructor
def __init__(self):
#database itself is represented as dictionary (python key val data structure). In best case we have O(1)
#access complexity
self._db = {}
# initialize dedicated storage to keep track fo transaction history - order matters => using list.
# transaction history for each block is a dict capturing state of the db before it entered
# new block. Most recent db caprures are located at the end of the list. For space efficiency we don't
# store the whole capture of the db, but just diffs applied within command block
self._history = []
def begin(self):
# creates a new state capture
self._history.append({})
def get(self, name):
# check if name (key) is in db - if so print value, else print NULL
if name in self._db:
print self._db[name]
else:
print 'NULL'
def set(self, name, val):
# if we are currently in a transaction block - capture changes that are being made to the db into history
# so we can undo them if requested
if self._history:
# update the history for items that are changed in this transaction block
if name in self._db and name not in self._history[-1]:
self._history[-1][name] = self._db[name]
#case whenwe are setting new value that didn't exist before
if name not in self._db:
self._history[-1][name] = None
self._set(name, val)
def _set(self, name, val):
# set value for key (name) if value is is not None (no rollback flow)
if (val != None):
self._db[name] = val
#if we are rolling back changes - None is passed as a val, so we need to remove the corresponding
#key from db
else:
del self._db[name]
def rollback(self):
# read from the most recent state capture and apply rollbacks
if self._history:
for key, val in self._history[-1].items():
self._set(key, val)
# remove the most recent db capture of the last block
self._history.pop()
else:
print "Can't rollback, no state was captured..."
def commit(self):
# normally we would dump data to file or fix the new db state into some stable one
# but for this example we just maintain self.__db as it is and empty history to indicate that
# we are in new stable state
self._history = []
def unset(self, name):
# set val of key (name) to "None"
if name in self._db:
self.set(name, None)
###Define main function
def main():
db = MyDatabase()
# define accepted commands and method to be invoked for each command
commands = {'BEGIN' : db.begin, 'SET' : db.set,
'GET' : db.get, 'UNSET' : db.unset,
'ROLLBACK' : db.rollback, 'COMMIT': db.commit}
#go over each instruction in thd input stream and process it
instruction = sys.stdin.readline().strip()
while instruction != 'END':
args = instruction.split(' ')
cmd = args[0]
arguments = args[1:]
if cmd in commands:
#invoke appropriate method
commands[cmd](*arguments)
else:
print "Illigal instruction...skipping..."
instruction = sys.stdin.readline().strip()
if __name__ == "__main__":
sys.exit(main())