2 * The UCW Library -- Transactions
4 * (c) 2008 Martin Mares <mj@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
13 #include "ucw/trans.h"
14 #include "ucw/respool.h"
15 #include "ucw/mempool.h"
22 struct ucwlib_context *c = ucwlib_thread_context();
24 c->trans_pool = mp_new(1024);
26 c->exc_pool = mp_new(1024);
32 struct ucwlib_context *c = ucwlib_thread_context();
35 mp_delete(c->trans_pool);
36 mp_delete(c->exc_pool);
40 c->current_trans = NULL;
44 trans_open_rp(struct respool *rp)
47 struct ucwlib_context *c = ucwlib_thread_context();
48 struct mempool *mp = c->trans_pool;
50 struct mempool_state *mst = mp_push(mp);
51 struct trans *t = mp_alloc(mp, sizeof(*t));
52 t->trans_pool_state = mst;
55 rp = rp_new("trans", mp);
57 t->prev_rpool = rp_switch(rp);
59 t->prev_trans = c->current_trans;
61 DBG("Opened transaction %p", t);
66 trans_get_current(void)
68 return ucwlib_thread_context() -> current_trans;
74 return ucwlib_thread_context() -> trans_pool;
78 trans_get_exc_pool(void)
80 return ucwlib_thread_context() -> exc_pool;
84 trans_pop(struct trans *t, struct ucwlib_context *c)
86 DBG("... popping trans %p", t);
87 rp_switch(t->prev_rpool);
88 c->current_trans = t->prev_trans;
92 trans_drop(struct trans *t, struct ucwlib_context *c)
94 DBG("... dropping trans %p", t);
95 mp_restore(c->trans_pool, t->trans_pool_state);
101 struct ucwlib_context *c = ucwlib_thread_context();
102 struct trans *t = c->current_trans;
103 DBG("Committing transaction %p", t);
105 ASSERT(!c->current_exc);
112 trans_rollback_exc(struct ucwlib_context *c)
114 // In case we were processing an exception, roll back all transactions
115 // through which the exception has propagated.
116 struct exception *x = c->current_exc;
117 struct trans *t = x->trans;
118 while (t != c->current_trans)
120 DBG("Rolling back transaction %p after exception", t);
121 struct trans *tprev = t->prev_trans;
127 c->current_exc = NULL;
128 mp_flush(c->exc_pool);
134 struct ucwlib_context *c = ucwlib_thread_context();
137 trans_rollback_exc(c);
141 struct trans *t = c->current_trans;
143 DBG("Rolling back transaction %p", t);
152 struct ucwlib_context *c = ucwlib_thread_context();
153 struct exception *x = c->current_exc;
154 struct trans *t = c->current_trans;
158 printf("Exception %s (%s) in flight\n", x->id, x->msg);
159 struct trans *tx = x->trans;
162 printf("Recovering transaction %p:\n", tx);
170 puts("No transaction open.");
175 printf("Transaction %p:\n", t);
182 trans_throw_exc(struct exception *x)
184 struct ucwlib_context *c = ucwlib_thread_context();
185 struct trans *t = c->current_trans;
186 DBG("Throwing exception %s (%s) in trans %p", x->id, x->msg, t);
190 // Remember which transaction have the exceptions started to propagate from
192 x->trans = c->current_exc->trans;
196 // Pop the current transaction off the transaction stack, but do not roll it
197 // back, it will be done when the exception stops propagating.
200 // And jump overboard.
206 trans_throw(const char *id, void *object, const char *fmt, ...)
211 struct mempool *mp = trans_get_pool();
212 struct exception *x = mp_alloc(mp, sizeof(*x));
215 x->msg = mp_vprintf(mp, fmt, args);
220 trans_current_exc(void)
222 return ucwlib_thread_context() -> current_exc;
227 static void trc_free(struct resource *r)
229 printf("Freeing object #%d\n", (int)(intptr_t) r->priv);
232 static struct res_class trc = {
241 res_new(&trc, (void *)(intptr_t) 1);
242 res_malloc(64, NULL);
245 res_new(&trc, (void *)(intptr_t) 2);
246 res_malloc(128, NULL);
247 trans_throw("ucw.test", "inn", "Universe failure: %d+%d=%d", 1, 2, 4);
251 printf("Inner catch: %s\n", x->msg);
253 //trans_throw("ucw.test2", "out", "Error: %s", x->msg);
259 printf("Outer catch: %s\n", x->msg);
262 trans_throw("ucw.test3", "glob", "Global error. Reboot globe.");
265 res_malloc(64, NULL);