Mercurial > repos > rhope
comparison runtime/transaction.c @ 139:a68e6828d896
Global stores and transactions are working. Definately leaks memory on retries. Probably a fair number of bugs to work out. However, a basic test program works.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 19 Nov 2010 04:04:14 -0500 |
parents | |
children | ba35ab624ec2 |
comparison
equal
deleted
inserted
replaced
138:1411de6050e1 | 139:a68e6828d896 |
---|---|
1 #include "transaction.h" | |
2 #include <stdarg.h> | |
3 #include <string.h> | |
4 #include <stdlib.h> | |
5 | |
6 rh_mutex(trans_lock) | |
7 | |
8 trans_cell * find_obj_cell(transaction * trans, mutable_object * to_find) | |
9 { | |
10 int32_t idx; | |
11 while(trans) | |
12 { | |
13 for (idx = 0; idx < trans->num_cells; ++idx) | |
14 if (trans->cells[idx].obj = to_find) | |
15 return &(trans->cells[idx]); | |
16 trans = trans->chain; | |
17 } | |
18 return NULL; | |
19 } | |
20 | |
21 void begin_transaction(context * ct, int numobjs,...) | |
22 { | |
23 mutable_object *obj; | |
24 transaction *parent; | |
25 va_list args; | |
26 int32_t idx,got_global_lock=0; | |
27 | |
28 parent = ct->transaction ? ct->transaction : NULL; | |
29 | |
30 ct->transaction = malloc(sizeof(transaction)+((numobjs-1)*sizeof(trans_cell))); | |
31 ct->transaction->parent = parent; | |
32 ct->transaction->chain = NULL; | |
33 rh_mutex_init(ct->lock); | |
34 ct->transaction->num_cells = numobjs; | |
35 va_start(args, numobjs); | |
36 if (parent) | |
37 { | |
38 rh_lock(parent->lock); | |
39 for (idx = 0; idx < numobjs; ++idx) | |
40 { | |
41 obj = va_arg(args, mutable_object *); | |
42 ct->transaction->cells[idx].obj = obj; | |
43 ct->transaction->cells[idx].parent = find_obj_cell(parent, obj); | |
44 if (ct->transaction->cells[idx].parent) | |
45 { | |
46 ct->transaction->cells[idx].local_data = ct->transaction->cells[idx].parent->local_data; | |
47 ct->transaction->cells[idx].orig_version = ct->transaction->cells[idx].parent->local_version; | |
48 } else { | |
49 if (!got_global_lock) | |
50 { | |
51 rh_lock(trans_lock); | |
52 got_global_lock = 1; | |
53 } | |
54 ct->transaction->cells[idx].local_data = obj->data; | |
55 ct->transaction->cells[idx].orig_version = obj->version; | |
56 } | |
57 ct->transaction->cells[idx].local_version = 0; | |
58 } | |
59 if (got_global_lock) | |
60 { | |
61 rh_unlock(trans_lock); | |
62 } | |
63 rh_unlock(parent->lock); | |
64 } else { | |
65 rh_lock(trans_lock); | |
66 for (idx = 0; idx < numobjs; ++idx) | |
67 { | |
68 obj = va_arg(args, mutable_object *); | |
69 ct->transaction->cells[idx].obj = obj; | |
70 ct->transaction->cells[idx].parent = NULL; | |
71 ct->transaction->cells[idx].local_data = add_ref(obj->data); | |
72 ct->transaction->cells[idx].orig_version = obj->version; | |
73 ct->transaction->cells[idx].local_version = 0; | |
74 } | |
75 rh_unlock(trans_lock); | |
76 } | |
77 } | |
78 | |
79 void free_trans(transaction * trans) | |
80 { | |
81 if (trans) | |
82 { | |
83 free_trans(trans->chain); | |
84 free(trans); | |
85 } | |
86 } | |
87 | |
88 int32_t commit_transaction(context * ct, int32_t readonly) | |
89 { | |
90 transaction *tmp_trans, *current; | |
91 object * tmp_obj; | |
92 int32_t idx,numaddparent; | |
93 | |
94 if (ct->transaction->parent) | |
95 { | |
96 rh_lock(ct->transaction->parent->lock); | |
97 current = ct->transaction; | |
98 while(current) | |
99 { | |
100 for (idx = 0; idx < current->num_cells; ++idx) | |
101 { | |
102 if (current->cells[idx].parent) | |
103 { | |
104 if (current->cells[idx].parent->local_version != current->cells[idx].orig_version) | |
105 { | |
106 rh_unlock(ct->transaction->parent->lock); | |
107 return 0; | |
108 } | |
109 } else { | |
110 if(find_obj_cell(ct->transaction->parent->chain, current->cells[idx].obj)) | |
111 { | |
112 rh_unlock(ct->transaction->parent->lock); | |
113 return 0; | |
114 } else | |
115 numaddparent++; | |
116 } | |
117 } | |
118 current = current->chain; | |
119 } | |
120 if (numaddparent) | |
121 { | |
122 tmp_trans = malloc(sizeof(transaction)+(numaddparent - 1)*sizeof(trans_cell)); | |
123 tmp_trans->chain = ct->transaction->parent->chain; | |
124 tmp_trans->num_cells = 0; | |
125 ct->transaction->parent->chain = tmp_trans; | |
126 } | |
127 current = ct->transaction; | |
128 while(current) | |
129 { | |
130 for (idx = 0; idx < ct->transaction->num_cells; ++idx) | |
131 { | |
132 if (ct->transaction->cells[idx].parent) | |
133 { | |
134 //Only commit a particular object if a change has been made | |
135 if (ct->transaction->cells[idx].local_version) | |
136 { | |
137 tmp_obj = ct->transaction->cells[idx].parent->local_data; | |
138 ct->transaction->cells[idx].parent->local_data = ct->transaction->cells[idx].local_data; | |
139 release_ref(tmp_obj); | |
140 ct->transaction->cells[idx].parent->local_version++; | |
141 } else { | |
142 release_ref(ct->transaction->cells[idx].local_data); | |
143 } | |
144 } else { | |
145 memcpy(&(tmp_trans->cells[tmp_trans->num_cells++]), &(ct->transaction->cells[idx]), sizeof(trans_cell)); | |
146 } | |
147 } | |
148 current = current->chain; | |
149 } | |
150 rh_unlock(ct->transaction->parent->lock); | |
151 } else { | |
152 if(readonly) | |
153 { | |
154 for (idx = 0; idx < ct->transaction->num_cells; ++idx) | |
155 { | |
156 release_ref(ct->transaction->cells[idx].local_data); | |
157 } | |
158 } else { | |
159 rh_lock(trans_lock); | |
160 current = ct->transaction; | |
161 while(current) | |
162 { | |
163 for (idx = 0; idx < current->num_cells; ++idx) | |
164 { | |
165 if (current->cells[idx].obj->version != current->cells[idx].orig_version) | |
166 { | |
167 rh_unlock(trans_lock); | |
168 return 0; | |
169 } | |
170 } | |
171 current = current->chain; | |
172 } | |
173 current = ct->transaction; | |
174 while(current) | |
175 { | |
176 for (idx = 0; idx < current->num_cells; ++idx) | |
177 { | |
178 //Only commit a particular object if a change has been made | |
179 if (current->cells[idx].local_version) | |
180 { | |
181 tmp_obj = current->cells[idx].obj->data; | |
182 current->cells[idx].obj->data = current->cells[idx].local_data; | |
183 release_ref(tmp_obj); | |
184 current->cells[idx].obj->version++; | |
185 } else { | |
186 release_ref(current->cells[idx].local_data); | |
187 } | |
188 } | |
189 current = current->chain; | |
190 } | |
191 rh_unlock(trans_lock); | |
192 } | |
193 } | |
194 rh_mutex_del(ct->transaction->lock); | |
195 tmp_trans = ct->transaction->parent; | |
196 free_trans(ct->transaction); | |
197 ct->transaction = tmp_trans; | |
198 return 1; | |
199 } | |
200 | |
201 void prep_retry(context * ct) | |
202 { | |
203 transaction * current; | |
204 int32_t idx,got_global_lock=0; | |
205 if (ct->transaction->parent) | |
206 { | |
207 rh_lock(ct->transaction->parent->lock); | |
208 current = ct->transaction; | |
209 while(current) | |
210 { | |
211 for (idx = 0; idx < current->num_cells; ++idx) | |
212 { | |
213 release_ref(current->cells[idx].local_data); | |
214 current->cells[idx].local_version = 0; | |
215 if (!current->cells[idx].parent) | |
216 current->cells[idx].parent = find_obj_cell(ct->transaction->parent, current->cells[idx].obj); | |
217 if (current->cells[idx].parent) | |
218 { | |
219 current->cells[idx].local_data = current->cells[idx].parent->local_data; | |
220 current->cells[idx].orig_version = current->cells[idx].parent->local_version; | |
221 } else { | |
222 if (!got_global_lock) | |
223 { | |
224 rh_lock(trans_lock); | |
225 got_global_lock = 1; | |
226 } | |
227 current->cells[idx].local_data = current->cells[idx].obj->data; | |
228 current->cells[idx].orig_version = current->cells[idx].obj->version; | |
229 } | |
230 } | |
231 current = current->chain; | |
232 } | |
233 if (got_global_lock) | |
234 { | |
235 rh_unlock(trans_lock); | |
236 } | |
237 rh_unlock(ct->transaction->parent->lock); | |
238 } else { | |
239 rh_lock(trans_lock); | |
240 current = ct->transaction; | |
241 while(current) | |
242 { | |
243 for (idx = 0; idx < current->num_cells; ++idx) | |
244 { | |
245 release_ref(current->cells[idx].local_data); | |
246 current->cells[idx].local_version = 0; | |
247 current->cells[idx].local_data = current->cells[idx].obj->data; | |
248 current->cells[idx].orig_version = current->cells[idx].obj->version; | |
249 } | |
250 current = current->chain; | |
251 } | |
252 rh_unlock(trans_lock); | |
253 } | |
254 } | |
255 |