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;
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;
54 struct respool *rp = rp_new("trans", mp);
56 t->prev_rpool = rp_switch(rp);
58 t->prev_trans = c->current_trans;
60 DBG("Opened transaction %p", t);
65 trans_get_current(void)
67 return ucwlib_thread_context() -> current_trans;
73 return ucwlib_thread_context() -> trans_pool;
77 trans_get_exc_pool(void)
79 return ucwlib_thread_context() -> exc_pool;
83 trans_pop(struct trans *t, struct ucwlib_context *c)
85 DBG("... popping trans %p", t);
86 rp_switch(t->prev_rpool);
87 c->current_trans = t->prev_trans;
91 trans_drop(struct trans *t, struct ucwlib_context *c)
93 DBG("... dropping trans %p", t);
94 mp_restore(c->trans_pool, t->trans_pool_state);
100 struct ucwlib_context *c = ucwlib_thread_context();
101 struct trans *t = c->current_trans;
102 DBG("Committing transaction %p", t);
104 ASSERT(!c->current_exc);
111 trans_rollback_exc(struct ucwlib_context *c)
113 // In case we were processing an exception, roll back all transactions
114 // through which the exception has propagated.
115 struct exception *x = c->current_exc;
116 struct trans *t = x->trans;
117 while (t != c->current_trans)
119 DBG("Rolling back transaction %p after exception", t);
120 struct trans *tprev = t->prev_trans;
126 c->current_exc = NULL;
127 mp_flush(c->exc_pool);
133 struct ucwlib_context *c = ucwlib_thread_context();
136 trans_rollback_exc(c);
140 struct trans *t = c->current_trans;
142 DBG("Rolling back transaction %p", t);
151 struct ucwlib_context *c = ucwlib_thread_context();
152 struct exception *x = c->current_exc;
153 struct trans *t = c->current_trans;
157 printf("Exception %s (%s) in flight\n", x->id, x->msg);
158 struct trans *tx = x->trans;
161 printf("Recovering transaction %p:\n", tx);
169 puts("No transaction open.");
174 printf("Transaction %p:\n", t);
181 trans_throw_exc(struct exception *x)
183 struct ucwlib_context *c = ucwlib_thread_context();
184 struct trans *t = c->current_trans;
185 DBG("Throwing exception %s (%s) in trans %p", x->id, x->msg, t);
189 // Remember which transaction have the exceptions started to propagate from
191 x->trans = c->current_exc->trans;
195 // Pop the current transaction off the transaction stack, but do not roll it
196 // back, it will be done when the exception stops propagating.
199 // And jump overboard.
205 trans_throw(const char *id, void *object, const char *fmt, ...)
209 trans_vthrow(id, object, fmt, args);
213 trans_vthrow(const char *id, void *object, const char *fmt, va_list args)
215 struct mempool *mp = trans_get_pool();
218 struct exception *x = mp_alloc(mp, sizeof(*x));
221 x->msg = mp_vprintf(mp, fmt, args);
226 trans_current_exc(void)
228 return ucwlib_thread_context() -> current_exc;
233 static void trc_free(struct resource *r)
235 printf("Freeing object #%d\n", (int)(intptr_t) r->priv);
238 static struct res_class trc = {
247 res_new(&trc, (void *)(intptr_t) 1);
248 res_malloc(64, NULL);
251 res_new(&trc, (void *)(intptr_t) 2);
252 res_malloc(128, NULL);
253 trans_throw("ucw.test", "inn", "Universe failure: %d+%d=%d", 1, 2, 4);
257 printf("Inner catch: %s\n", x->msg);
259 //trans_throw("ucw.test2", "out", "Error: %s", x->msg);
265 printf("Outer catch: %s\n", x->msg);
268 trans_throw("ucw.test3", "glob", "Global error. Reboot globe.");
271 res_malloc(64, NULL);