-
Notifications
You must be signed in to change notification settings - Fork 0
/
dm.py
205 lines (172 loc) · 5.45 KB
/
dm.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
from lm import LockManager
from variable_version import VariableVersion
import globalz
class DataManager(object):
"""
Data manager object.
There is one data manager for each site,
managing the reads and writes for that site.
Each data manager has its own Lock Manager.
"""
def __init__(self,site):
self.site = site
self.lm = LockManager(self)
def get_read_version(self,t,vid):
"""
read the appropriate version of variable vid at this site.
Args: the transaction wanting to read, the variable to read
Return value: the value read, or None
if no appropriate version exists at the site.
"""
version_list = self.site.variables[vid].versions
for v in version_list:
# if encounter a version not avilable to read,
# there must have been a failure, so no
# older version will be acceptable for read,
# so can stop iterating
if not v.available_for_read:
return None
# read-only looks for most recent committed before t began
if t.is_read_only and v.is_committed and v.time_committed<=t.start_time:
return v.value
# read-write looks for most recent committed or written by itself
if not t.is_read_only and (v.is_committed or v.written_by==t):
return v.value
# if applicable version not found, return None
return None
def print_read_result(self,t,val,vid):
print str(t) + " read " + vid + "=" + str(val) + " from " + str(self.site)
def print_write_result(self,t,val,vid):
print "\t" + str(t) + " wrote " + vid + "=" + str(val) + " at " + str(self.site) + " (uncommitted)"
def process_ro_read(self,t,vid):
"""
Process a read request from the TM
for a read-only transaction.
Arguments:
- t: the read-only transaction
- vid: the variable name to be read
Side effects
- t's buffer is reset
- read result printed to console
"""
read_result = self.get_read_version(t,vid)
self.print_read_result(t,read_result,vid)
t.reset_buffer()
return read_result
def do_read(self,t,vid):
"""
Perform the actual read
Arguments:
- t: a read-write transaction
- vid: a variable to read
Return value:
- the value read, or None if none read
Side effects:
- read value is printed to console
- t's buffer reset
"""
# add the site to sites_accessed
t.add_site_access(self.site)
# get and return the read result
read_result = self.get_read_version(t,vid)
# if there was a result, print it
if read_result:
self.print_read_result(t,read_result,vid)
t.reset_buffer()
return read_result # might be None
def process_rw_read(self,t,vid):
"""
Process a read request from the TM
for a read-write transaction.
Arguments:
- t: the transaction requesting the read
- vid: the variable name to be read
Side effects:
- a lock might be grated to t,
or it might end up enqueued for a lock
Return value:
- a two-item list with
1) a message about the success of the lock request
2) the read result
"""
# try to get the lock
request_result = self.lm.request_lock(t,vid,'r',None)
if request_result == globalz.Message.Success:
read_result = self.do_read(t,vid)
return [request_result, read_result]
else: # read not achieved yet, so let TM know why
return [request_result, None]
def apply_write(self,t,vid,val):
"""
Actually perform the write
Arguments
- transaction writing
- variable being written
- value to write
Side effects:
- a new version is created and applied
- write alert printed to console
- intstruction buffer for t may be reset
"""
# add the site to sites_accessed
t.add_site_access(self.site)
# create new (uncommitted) version
# and insert at the beginning of the list
new_version = VariableVersion(val,None,t,False)
version_list = self.site.variables[vid].versions
version_list.insert(0,new_version)
# alert console that it was written
self.print_write_result(t,val,vid)
# update t's sites in progress list
# to show that the lock has been
# obtained at present site
t.grant_lock(self.site)
# reset t's instruction buffer
# if all writes at all pending sites
# have completed
instruction_complete = True
for s,lock_granted in t.sites_in_progress:
if not lock_granted:
instruction_complete = False
if instruction_complete:
t.reset_buffer( )
def process_write(self,t,vid,val):
"""
Process a write request from the TM.
Arguments:
- t: the transaction requesting the write
- vid: the variable name to be written
- val: the value to be written
"""
request_result = self.lm.request_lock(t,vid,'w',val)
if request_result == globalz.Message.Success:
self.apply_write(t,vid,val)
return request_result
def process_commit(self,t):
"""
Process a commit request from the TM
Argument:
- t: the transaction to be committed.
Side effects:
- writes marked as committed
- locks released
"""
var_accessed = self.lm.transaction_locks[t]
#print( str(len(var_accessed)) + " variables accessed at " +
# self.site.name + " to be committed" )
for vid in var_accessed:
var = self.site.variables[vid]
latest_version = var.versions[0] # only need to commit most recent write
if latest_version.written_by == t:
latest_version.time_committed = globalz.clock
latest_version.is_committed = True
self.lm.release_locks(t)
def process_abort(self,t):
"""
Process an abort request from the TM.
Argument:
- t: the transaction to be aborted.
Side effect:
- locks released
"""
self.lm.release_locks(t)