00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "config.h"
00040
00041 #ifndef lint
00042 static const char revid[] = "$Id: db__dispatch_8c-source.html,v 1.1 2008/06/08 10:17:25 sebdiaz Exp $";
00043 #endif
00044
00045 #ifndef NO_SYSTEM_INCLUDES
00046 #include <sys/types.h>
00047
00048 #include <errno.h>
00049 #include <stddef.h>
00050 #include <stdlib.h>
00051 #include <string.h>
00052 #endif
00053
00054 #include "db_int.h"
00055 #include "db_page.h"
00056 #include "db_dispatch.h"
00057 #include "db_am.h"
00058 #include "log_auto.h"
00059 #include "txn.h"
00060 #include "txn_auto.h"
00061 #include "log.h"
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 int
00075 CDB___db_dispatch(dbenv, db, lsnp, redo, info)
00076 DB_ENV *dbenv;
00077 DBT *db;
00078 DB_LSN *lsnp;
00079 db_recops redo;
00080 void *info;
00081 {
00082 u_int32_t rectype, txnid;
00083
00084 memcpy(&rectype, db->data, sizeof(rectype));
00085 memcpy(&txnid, (u_int8_t *)db->data + sizeof(rectype), sizeof(txnid));
00086
00087 switch (redo) {
00088 case DB_TXN_ABORT:
00089 return ((dbenv->dtab[rectype])(dbenv, db, lsnp, redo, info));
00090 case DB_TXN_OPENFILES:
00091 if (rectype == DB_log_register)
00092 return (dbenv->dtab[rectype](dbenv,
00093 db, lsnp, redo, info));
00094 break;
00095 case DB_TXN_BACKWARD_ROLL:
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 if (rectype == DB_log_register || rectype == DB_txn_ckp ||
00107 rectype == DB_db_noop ||
00108 (CDB___db_txnlist_find(info, txnid) == DB_NOTFOUND &&
00109 txnid != 0))
00110 return (dbenv->dtab[rectype](dbenv,
00111 db, lsnp, DB_TXN_BACKWARD_ROLL, info));
00112 break;
00113 case DB_TXN_FORWARD_ROLL:
00114
00115
00116
00117
00118
00119
00120
00121 if (rectype == DB_log_register || rectype == DB_txn_ckp ||
00122 rectype == DB_db_noop ||
00123 CDB___db_txnlist_find(info, txnid) != DB_NOTFOUND)
00124 return (dbenv->dtab[rectype](dbenv,
00125 db, lsnp, DB_TXN_FORWARD_ROLL, info));
00126 break;
00127 default:
00128 return (CDB___db_unknown_flag(dbenv, "CDB___db_dispatch", redo));
00129 }
00130 return (0);
00131 }
00132
00133
00134
00135
00136
00137
00138
00139 int
00140 CDB___db_add_recovery(dbenv, func, ndx)
00141 DB_ENV *dbenv;
00142 int (*func) __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00143 u_int32_t ndx;
00144 {
00145 u_int32_t i, nsize;
00146 int ret;
00147
00148
00149 if (ndx >= dbenv->dtab_size) {
00150 nsize = ndx + 40;
00151 if ((ret = CDB___os_realloc(dbenv,
00152 nsize * sizeof(dbenv->dtab[0]), NULL, &dbenv->dtab)) != 0)
00153 return (ret);
00154 for (i = dbenv->dtab_size; i < nsize; ++i)
00155 dbenv->dtab[i] = NULL;
00156 dbenv->dtab_size = nsize;
00157 }
00158
00159 dbenv->dtab[ndx] = func;
00160 return (0);
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170 int
00171 CDB___deprecated_recover(dbenv, dbtp, lsnp, op, info)
00172 DB_ENV *dbenv;
00173 DBT *dbtp;
00174 DB_LSN *lsnp;
00175 db_recops op;
00176 void *info;
00177 {
00178 COMPQUIET(dbenv, NULL);
00179 COMPQUIET(dbtp, NULL);
00180 COMPQUIET(lsnp, NULL);
00181 COMPQUIET(op, 0);
00182 COMPQUIET(info, NULL);
00183 return (EINVAL);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 int
00193 CDB___db_txnlist_init(dbenv, retp)
00194 DB_ENV *dbenv;
00195 void *retp;
00196 {
00197 DB_TXNHEAD *headp;
00198 int ret;
00199
00200 if ((ret = CDB___os_malloc(dbenv, sizeof(DB_TXNHEAD), NULL, &headp)) != 0)
00201 return (ret);
00202
00203 LIST_INIT(&headp->head);
00204 headp->maxid = 0;
00205 headp->generation = 1;
00206
00207 *(void **)retp = headp;
00208 return (0);
00209 }
00210
00211
00212
00213
00214
00215
00216
00217 int
00218 CDB___db_txnlist_add(dbenv, listp, txnid)
00219 DB_ENV *dbenv;
00220 void *listp;
00221 u_int32_t txnid;
00222 {
00223 DB_TXNHEAD *hp;
00224 DB_TXNLIST *elp;
00225 int ret;
00226
00227 if ((ret = CDB___os_malloc(dbenv, sizeof(DB_TXNLIST), NULL, &elp)) != 0)
00228 return (ret);
00229
00230 hp = (DB_TXNHEAD *)listp;
00231 LIST_INSERT_HEAD(&hp->head, elp, links);
00232
00233 elp->type = TXNLIST_TXNID;
00234 elp->u.t.txnid = txnid;
00235 if (txnid > hp->maxid)
00236 hp->maxid = txnid;
00237 elp->u.t.generation = hp->generation;
00238
00239 return (0);
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 int
00253 CDB___db_txnlist_close(listp, lid, count)
00254 void *listp;
00255 int32_t lid;
00256 u_int32_t count;
00257 {
00258 DB_TXNHEAD *hp;
00259 DB_TXNLIST *p;
00260
00261 hp = (DB_TXNHEAD *)listp;
00262 for (p = LIST_FIRST(&hp->head); p != NULL; p = LIST_NEXT(p, links)) {
00263 if (p->type == TXNLIST_DELETE)
00264 if (lid == p->u.d.fileid &&
00265 !F_ISSET(&p->u.d, TXNLIST_FLAG_CLOSED)) {
00266 p->u.d.count += count;
00267 return (0);
00268 }
00269 }
00270
00271 return (0);
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 int
00286 CDB___db_txnlist_delete(dbenv, listp, name, lid, deleted)
00287 DB_ENV *dbenv;
00288 void *listp;
00289 char *name;
00290 u_int32_t lid;
00291 int deleted;
00292 {
00293 DB_TXNHEAD *hp;
00294 DB_TXNLIST *p;
00295 int ret;
00296
00297 hp = (DB_TXNHEAD *)listp;
00298 for (p = LIST_FIRST(&hp->head); p != NULL; p = LIST_NEXT(p, links)) {
00299 if (p->type == TXNLIST_DELETE)
00300 if (strcmp(name, p->u.d.fname) == 0) {
00301 if (deleted)
00302 F_SET(&p->u.d, TXNLIST_FLAG_DELETED);
00303 else
00304 F_CLR(&p->u.d, TXNLIST_FLAG_CLOSED);
00305 return (0);
00306 }
00307 }
00308
00309
00310 if ((ret = CDB___os_malloc(dbenv, sizeof(DB_TXNLIST), NULL, &p)) != 0)
00311 return (ret);
00312 LIST_INSERT_HEAD(&hp->head, p, links);
00313
00314 p->type = TXNLIST_DELETE;
00315 p->u.d.flags = 0;
00316 if (deleted)
00317 F_SET(&p->u.d, TXNLIST_FLAG_DELETED);
00318 p->u.d.fileid = lid;
00319 p->u.d.count = 0;
00320 ret = CDB___os_strdup(dbenv, name, &p->u.d.fname);
00321
00322 return (ret);
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332 void
00333 CDB___db_txnlist_end(dbenv, listp)
00334 DB_ENV *dbenv;
00335 void *listp;
00336 {
00337 DB_TXNHEAD *hp;
00338 DB_TXNLIST *p;
00339 DB_LOG *lp;
00340
00341 hp = (DB_TXNHEAD *)listp;
00342 lp = (DB_LOG *)dbenv->lg_handle;
00343 while (hp != NULL &&
00344 (p = LIST_FIRST(&hp->head)) != LIST_END(&hp->head)) {
00345 LIST_REMOVE(p, links);
00346 if (p->type == TXNLIST_DELETE) {
00347
00348
00349
00350
00351
00352
00353 if ((!F_ISSET(&p->u.d, TXNLIST_FLAG_DELETED) &&
00354 p->u.d.count != 0) ||
00355 (!F_ISSET(&p->u.d, TXNLIST_FLAG_CLOSED) &&
00356 p->u.d.fileid != (int32_t) TXNLIST_INVALID_ID &&
00357 p->u.d.fileid < lp->dbentry_cnt &&
00358 lp->dbentry[p->u.d.fileid].count != 0))
00359 CDB___db_err(dbenv, "warning: %s: %s",
00360 p->u.d.fname, CDB_db_strerror(ENOENT));
00361 CDB___os_freestr(p->u.d.fname);
00362 }
00363 CDB___os_free(p, sizeof(DB_TXNLIST));
00364 }
00365 CDB___os_free(listp, sizeof(DB_TXNHEAD));
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375 int
00376 CDB___db_txnlist_find(listp, txnid)
00377 void *listp;
00378 u_int32_t txnid;
00379 {
00380 DB_TXNHEAD *hp;
00381 DB_TXNLIST *p;
00382
00383 if (txnid == 0 || (hp = (DB_TXNHEAD *)listp) == NULL)
00384 return (DB_NOTFOUND);
00385
00386 for (p = LIST_FIRST(&hp->head); p != NULL; p = LIST_NEXT(p, links)) {
00387 if (p->type != TXNLIST_TXNID)
00388 continue;
00389 if (p->u.t.txnid == txnid &&
00390 hp->generation == p->u.t.generation) {
00391
00392 if (p != LIST_FIRST(&hp->head)) {
00393 LIST_REMOVE(p, links);
00394 LIST_INSERT_HEAD(&hp->head, p, links);
00395 }
00396 return (0);
00397 }
00398 }
00399
00400 return (DB_NOTFOUND);
00401 }
00402
00403
00404
00405
00406
00407
00408
00409 void
00410 CDB___db_txnlist_gen(listp, incr)
00411 void *listp;
00412 int incr;
00413 {
00414 DB_TXNHEAD *hp;
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 hp = (DB_TXNHEAD *)listp;
00425 hp->generation += incr;
00426 }
00427
00428 #ifdef DEBUG
00429
00430
00431
00432
00433
00434
00435 void
00436 CDB___db_txnlist_print(listp)
00437 void *listp;
00438 {
00439 DB_TXNHEAD *hp;
00440 DB_TXNLIST *p;
00441
00442 hp = (DB_TXNHEAD *)listp;
00443
00444 printf("Maxid: %lu Generation: %lu\n",
00445 (u_long)hp->maxid, (u_long)hp->generation);
00446 for (p = LIST_FIRST(&hp->head); p != NULL; p = LIST_NEXT(p, links)) {
00447 switch (p->type) {
00448 case TXNLIST_TXNID:
00449 printf("TXNID: %lu(%lu)\n",
00450 (u_long)p->u.t.txnid, (u_long)p->u.t.generation);
00451 break;
00452 case TXNLIST_DELETE:
00453 printf("FILE: %s id=%d ops=%d %s %s\n",
00454 p->u.d.fname, p->u.d.fileid, p->u.d.count,
00455 F_ISSET(&p->u.d, TXNLIST_FLAG_DELETED) ?
00456 "(deleted)" : "(missing)",
00457 F_ISSET(&p->u.d, TXNLIST_FLAG_CLOSED) ?
00458 "(closed)" : "(open)");
00459
00460 break;
00461 default:
00462 printf("Unrecognized type: %d\n", p->type);
00463 break;
00464 }
00465 }
00466 }
00467 #endif