00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 #include <string.h>
00015 #endif
00016
00017 #include "db_int.h"
00018 #include "dbinc/db_page.h"
00019 #include "dbinc/db_shash.h"
00020 #include "dbinc/lock.h"
00021 #include "dbinc/mp.h"
00022 #include "dbinc/txn.h"
00023 #include "dbinc/db_am.h"
00024
00025 typedef struct __txn_event TXN_EVENT;
00026 struct __txn_event {
00027 TXN_EVENT_T op;
00028 TAILQ_ENTRY(__txn_event) links;
00029 union {
00030 struct {
00031
00032 DB *dbp;
00033 } c;
00034 struct {
00035
00036 char *name;
00037 u_int8_t *fileid;
00038 int inmem;
00039 } r;
00040 struct {
00041
00042 DB_LOCK lock;
00043 u_int32_t locker;
00044 DB *dbp;
00045 } t;
00046 } u;
00047 };
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 int
00058 __txn_closeevent(dbenv, txn, dbp)
00059 DB_ENV *dbenv;
00060 DB_TXN *txn;
00061 DB *dbp;
00062 {
00063 int ret;
00064 TXN_EVENT *e;
00065
00066 e = NULL;
00067 if ((ret = __os_calloc(dbenv, 1, sizeof(TXN_EVENT), &e)) != 0)
00068 return (ret);
00069
00070 e->u.c.dbp = dbp;
00071 e->op = TXN_CLOSE;
00072 TAILQ_INSERT_TAIL(&txn->events, e, links);
00073
00074 return (0);
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 int
00086 __txn_remevent(dbenv, txn, name, fileid, inmem)
00087 DB_ENV *dbenv;
00088 DB_TXN *txn;
00089 const char *name;
00090 u_int8_t *fileid;
00091 int inmem;
00092 {
00093 int ret;
00094 TXN_EVENT *e;
00095
00096 e = NULL;
00097 if ((ret = __os_calloc(dbenv, 1, sizeof(TXN_EVENT), &e)) != 0)
00098 return (ret);
00099
00100 if ((ret = __os_strdup(dbenv, name, &e->u.r.name)) != 0)
00101 goto err;
00102
00103 if (fileid != NULL) {
00104 if ((ret = __os_calloc(dbenv,
00105 1, DB_FILE_ID_LEN, &e->u.r.fileid)) != 0)
00106 return (ret);
00107 memcpy(e->u.r.fileid, fileid, DB_FILE_ID_LEN);
00108 }
00109
00110 e->u.r.inmem = inmem;
00111 e->op = TXN_REMOVE;
00112 TAILQ_INSERT_TAIL(&txn->events, e, links);
00113
00114 return (0);
00115
00116 err: if (e != NULL)
00117 __os_free(dbenv, e);
00118
00119 return (ret);
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129 void
00130 __txn_remrem(dbenv, txn, name)
00131 DB_ENV *dbenv;
00132 DB_TXN *txn;
00133 const char *name;
00134 {
00135 TXN_EVENT *e, *next_e;
00136
00137 for (e = TAILQ_FIRST(&txn->events); e != NULL; e = next_e) {
00138 next_e = TAILQ_NEXT(e, links);
00139 if (e->op != TXN_REMOVE || strcmp(name, e->u.r.name) != 0)
00140 continue;
00141 TAILQ_REMOVE(&txn->events, e, links);
00142 __os_free(dbenv, e->u.r.name);
00143 if (e->u.r.fileid != NULL)
00144 __os_free(dbenv, e->u.r.fileid);
00145 __os_free(dbenv, e);
00146 }
00147
00148 return;
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 int
00161 __txn_lockevent(dbenv, txn, dbp, lock, locker)
00162 DB_ENV *dbenv;
00163 DB_TXN *txn;
00164 DB *dbp;
00165 DB_LOCK *lock;
00166 u_int32_t locker;
00167 {
00168 int ret;
00169 TXN_EVENT *e;
00170
00171 if (!LOCKING_ON(dbenv))
00172 return (0);
00173
00174 e = NULL;
00175 if ((ret = __os_calloc(dbenv, 1, sizeof(TXN_EVENT), &e)) != 0)
00176 return (ret);
00177
00178 e->u.t.locker = locker;
00179 e->u.t.lock = *lock;
00180 e->u.t.dbp = dbp;
00181 e->op = TXN_TRADE;
00182 TAILQ_INSERT_TAIL(&txn->events, e, links);
00183
00184 return (0);
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194 void
00195 __txn_remlock(dbenv, txn, lock, locker)
00196 DB_ENV *dbenv;
00197 DB_TXN *txn;
00198 DB_LOCK *lock;
00199 u_int32_t locker;
00200 {
00201 TXN_EVENT *e, *next_e;
00202
00203 for (e = TAILQ_FIRST(&txn->events); e != NULL; e = next_e) {
00204 next_e = TAILQ_NEXT(e, links);
00205 if ((e->op != TXN_TRADE && e->op != TXN_TRADED) ||
00206 (e->u.t.lock.off != lock->off && e->u.t.locker != locker))
00207 continue;
00208 TAILQ_REMOVE(&txn->events, e, links);
00209 __os_free(dbenv, e);
00210 }
00211
00212 return;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222 #define DO_TRADE do { \
00223 memset(&req, 0, sizeof(req)); \
00224 req.lock = e->u.t.lock; \
00225 req.op = DB_LOCK_TRADE; \
00226 t_ret = __lock_vec(dbenv, e->u.t.locker, 0, &req, 1, NULL); \
00227 if (t_ret == 0) \
00228 e->u.t.dbp->cur_lid = e->u.t.locker; \
00229 else if (t_ret == DB_NOTFOUND) \
00230 t_ret = 0; \
00231 if (t_ret != 0 && ret == 0) \
00232 ret = t_ret; \
00233 e->op = TXN_TRADED; \
00234 } while (0)
00235
00236 int
00237 __txn_doevents(dbenv, txn, opcode, preprocess)
00238 DB_ENV *dbenv;
00239 DB_TXN *txn;
00240 int opcode, preprocess;
00241 {
00242 DB_LOCKREQ req;
00243 TXN_EVENT *e;
00244 int ret, t_ret;
00245
00246 ret = 0;
00247
00248
00249
00250
00251
00252
00253
00254
00255 if (preprocess) {
00256 for (e = TAILQ_FIRST(&txn->events);
00257 e != NULL; e = TAILQ_NEXT(e, links)) {
00258 if (e->op != TXN_TRADE)
00259 continue;
00260 DO_TRADE;
00261 }
00262 return (ret);
00263 }
00264
00265
00266
00267
00268
00269 DB_ASSERT(opcode != TXN_PREPARE);
00270 while ((e = TAILQ_FIRST(&txn->events)) != NULL) {
00271 TAILQ_REMOVE(&txn->events, e, links);
00272
00273
00274
00275
00276
00277
00278
00279 if (opcode == TXN_ABORT && e->op != TXN_CLOSE)
00280 goto dofree;
00281 switch (e->op) {
00282 case TXN_CLOSE:
00283
00284 DB_ASSERT(opcode == TXN_ABORT);
00285 if ((t_ret = __db_close(e->u.c.dbp,
00286 NULL, DB_NOSYNC)) != 0 && ret == 0)
00287 ret = t_ret;
00288 break;
00289 case TXN_REMOVE:
00290 if (e->u.r.fileid != NULL) {
00291 if ((t_ret = __memp_nameop(dbenv,
00292 e->u.r.fileid, NULL, e->u.r.name,
00293 NULL, e->u.r.inmem)) != 0 && ret == 0)
00294 ret = t_ret;
00295 } else if ((t_ret =
00296 __os_unlink(dbenv, e->u.r.name)) != 0 && ret == 0)
00297 ret = t_ret;
00298 break;
00299 case TXN_TRADE:
00300 DO_TRADE;
00301
00302 case TXN_TRADED:
00303
00304 if ((t_ret = __lock_downgrade(dbenv,
00305 &e->u.t.lock, DB_LOCK_READ, 0)) != 0 && ret == 0)
00306 ret = t_ret;
00307 break;
00308 default:
00309
00310 DB_ASSERT(0);
00311 }
00312 dofree:
00313
00314 switch (e->op) {
00315 case TXN_REMOVE:
00316 if (e->u.r.fileid != NULL)
00317 __os_free(dbenv, e->u.r.fileid);
00318 __os_free(dbenv, e->u.r.name);
00319 break;
00320 case TXN_CLOSE:
00321 case TXN_TRADE:
00322 case TXN_TRADED:
00323 default:
00324 break;
00325 }
00326 __os_free(dbenv, e);
00327 }
00328
00329 return (ret);
00330 }