db

crdel_rec.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
00005  * Sleepycat Software. All rights reserved.
00006  */
00007 
00008 #include "config.h"
00009 
00010 #ifndef lint
00011 static const char revid[] = "$Id: crdel__rec_8c-source.html,v 1.1 2008年06月08日 10:16:30 sebdiaz Exp $";
00012 #endif /* not lint */
00013 
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016 
00017 #include <errno.h>
00018 #include <string.h>
00019 #endif
00020 
00021 #include "db_int.h"
00022 #include "db_page.h"
00023 #include "log.h"
00024 #include "hash.h"
00025 #include "mp.h"
00026 #include "db_dispatch.h"
00027 
00028 /*
00029  * CDB___crdel_fileopen_recover --
00030  * Recovery function for fileopen.
00031  *
00032  * PUBLIC: int CDB___crdel_fileopen_recover
00033  * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00034  */
00035 int
00036 CDB___crdel_fileopen_recover(dbenv, dbtp, lsnp, op, info)
00037 DB_ENV *dbenv;
00038 DBT *dbtp;
00039 DB_LSN *lsnp;
00040 db_recops op;
00041 void *info;
00042 {
00043 __crdel_fileopen_args *argp;
00044 DBMETA ondisk;
00045 DB_FH fh;
00046 size_t nr;
00047 int do_unlink, ret;
00048 u_int32_t b, mb, io;
00049 char *real_name;
00050 
00051 COMPQUIET(info, NULL);
00052 
00053 real_name = NULL;
00054 REC_PRINT(CDB___crdel_fileopen_print);
00055 
00056 if ((ret = CDB___crdel_fileopen_read(dbenv, dbtp->data, &argp)) != 0)
00057 goto out;
00058 /*
00059  * If this is an in-memory database, then the name is going to
00060  * be NULL, which looks like a 0-length name in recovery.
00061  */
00062 if (argp->name.size == 0)
00063 goto done;
00064 
00065 if ((ret = CDB___db_appname(dbenv, DB_APP_DATA,
00066 NULL, argp->name.data, 0, NULL, &real_name)) != 0)
00067 goto out;
00068 if (DB_REDO(op)) {
00069 /*
00070  * The create commited, so we need to make sure that the file
00071  * exists. A simple open should suffice.
00072  */
00073 if ((ret = CDB___os_open(dbenv, real_name,
00074 DB_OSO_CREATE, argp->mode, &fh)) != 0)
00075 goto out;
00076 if ((ret = CDB___os_closehandle(&fh)) != 0)
00077 goto out;
00078 } else if (DB_UNDO(op)) {
00079 /*
00080  * If the file is 0-length then it was in the process of being
00081  * created, so we should unlink it. If it is non-0 length, then
00082  * either someone else created it and we need to leave it
00083  * untouched or we were in the process of creating it, allocated
00084  * the first page on a system that requires you to actually
00085  * write pages as you allocate them, but never got any data
00086  * on it.
00087  * If the file doesn't exist, we never got around to creating
00088  * it, so that's fine.
00089  */
00090 if (CDB___os_exists(real_name, NULL) != 0)
00091 goto done;
00092 
00093 if ((ret = CDB___os_open(dbenv, real_name, 0, 0, &fh)) != 0)
00094 goto out;
00095 if ((ret = CDB___os_ioinfo(dbenv,
00096 real_name, &fh, &mb, &b, &io)) != 0)
00097 goto out;
00098 do_unlink = 0;
00099 if (mb != 0 || b != 0) {
00100 /*
00101  * We need to read the first page
00102  * to see if its got valid data on it.
00103  */
00104 if ((ret = CDB___os_read(dbenv, &fh,
00105 &ondisk, sizeof(ondisk), &nr)) != 0 ||
00106 nr != sizeof(ondisk))
00107 goto out;
00108 if (ondisk.magic == 0)
00109 do_unlink = 1;
00110 }
00111 if ((ret = CDB___os_closehandle(&fh)) != 0)
00112 goto out;
00113 /* Check for 0-length and if it is, delete it. */
00114 if (do_unlink || (mb == 0 && b == 0))
00115 if ((ret = CDB___os_unlink(dbenv, real_name)) != 0)
00116 goto out;
00117 }
00118 
00119 done: *lsnp = argp->prev_lsn;
00120 ret = 0;
00121 
00122 out: if (argp != NULL)
00123 CDB___os_free(argp, sizeof(*argp));
00124 if (real_name != NULL)
00125 CDB___os_freestr(real_name);
00126 return (ret);
00127 }
00128 
00129 /*
00130  * CDB___crdel_metasub_recover --
00131  * Recovery function for metasub.
00132  *
00133  * PUBLIC: int CDB___crdel_metasub_recover
00134  * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00135  */
00136 int
00137 CDB___crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
00138 DB_ENV *dbenv;
00139 DBT *dbtp;
00140 DB_LSN *lsnp;
00141 db_recops op;
00142 void *info;
00143 {
00144 __crdel_metasub_args *argp;
00145 DB *file_dbp;
00146 DBC *dbc;
00147 DB_MPOOLFILE *mpf;
00148 PAGE *pagep;
00149 int cmp_p, modified, ret;
00150 
00151 COMPQUIET(info, NULL);
00152 REC_PRINT(CDB___crdel_metasub_print);
00153 REC_INTRO(CDB___crdel_metasub_read, 0);
00154 
00155 if ((ret = CDB_memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
00156 if (DB_REDO(op)) {
00157 if ((ret = CDB_memp_fget(mpf,
00158 &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
00159 goto out;
00160 } else {
00161 *lsnp = argp->prev_lsn;
00162 ret = 0;
00163 goto out;
00164 }
00165 }
00166 
00167 modified = 0;
00168 cmp_p = CDB_log_compare(&LSN(pagep), &argp->lsn);
00169 CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
00170 
00171 if (cmp_p == 0 && DB_REDO(op)) {
00172 memcpy(pagep, argp->page.data, argp->page.size);
00173 LSN(pagep) = *lsnp;
00174 modified = 1;
00175 } else if (DB_UNDO(op)) {
00176 /*
00177  * We want to undo this page creation. The page creation
00178  * happened in two parts. First, we called __bam_new which
00179  * was logged separately. Then we wrote the meta-data onto
00180  * the page. So long as we restore the LSN, then the recovery
00181  * for __bam_new will do everything else.
00182  * Don't bother checking the lsn on the page. If we
00183  * are rolling back the next thing is that this page
00184  * will get freed. Opening the subdb will have reinitialized
00185  * the page, but not the lsn.
00186  */
00187 LSN(pagep) = argp->lsn;
00188 modified = 1;
00189 }
00190 if ((ret = CDB_memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
00191 goto out;
00192 
00193 done: *lsnp = argp->prev_lsn;
00194 ret = 0;
00195 
00196 out: REC_CLOSE;
00197 }
00198 
00199 /*
00200  * CDB___crdel_metapage_recover --
00201  * Recovery function for metapage.
00202  *
00203  * PUBLIC: int CDB___crdel_metapage_recover
00204  * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00205  */
00206 int
00207 CDB___crdel_metapage_recover(dbenv, dbtp, lsnp, op, info)
00208 DB_ENV *dbenv;
00209 DBT *dbtp;
00210 DB_LSN *lsnp;
00211 db_recops op;
00212 void *info;
00213 {
00214 __crdel_metapage_args *argp;
00215 DB *dbp;
00216 DBMETA *meta, ondisk;
00217 DB_FH fh;
00218 size_t nr;
00219 u_int32_t b, io, mb, pagesize;
00220 int is_done, ret;
00221 char *real_name;
00222 
00223 COMPQUIET(info, NULL);
00224 
00225 real_name = NULL;
00226 memset(&fh, 0, sizeof(fh));
00227 REC_PRINT(CDB___crdel_metapage_print);
00228 
00229 if ((ret = CDB___crdel_metapage_read(dbenv, dbtp->data, &argp)) != 0)
00230 goto out;
00231 
00232 /*
00233  * If this is an in-memory database, then the name is going to
00234  * be NULL, which looks like a 0-length name in recovery.
00235  */
00236 if (argp->name.size == 0)
00237 goto done;
00238 
00239 meta = (DBMETA *)argp->page.data;
00240 CDB___ua_memcpy(&pagesize, &meta->pagesize, sizeof(pagesize));
00241 
00242 if ((ret = CDB___db_appname(dbenv, DB_APP_DATA,
00243 NULL, argp->name.data, 0, NULL, &real_name)) != 0)
00244 goto out;
00245 if (DB_REDO(op)) {
00246 if ((ret = CDB___db_fileid_to_db(dbenv,
00247 &dbp, argp->fileid, 0)) != 0) {
00248 if (ret == DB_DELETED)
00249 goto done;
00250 else
00251 goto out;
00252 }
00253 
00254 /*
00255  * We simply read the first page and if the LSN is 0, we
00256  * write the meta-data page.
00257  */
00258 if ((ret = CDB___os_open(dbenv, real_name, 0, 0, &fh)) != 0)
00259 goto out;
00260 if ((ret = CDB___os_seek(dbenv, &fh,
00261 pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
00262 goto out;
00263 /*
00264  * If the read succeeds then the page exists, then we need
00265  * to vrify that the page has actually been written, because
00266  * on some systems (e.g., Windows) we preallocate pages because
00267  * files aren't allowed to have holes in them. If the page
00268  * looks good then we're done.
00269  */
00270 if ((ret = CDB___os_read(dbenv, &fh, &ondisk,
00271 sizeof(ondisk), &nr)) == 0 && nr == sizeof(ondisk)) {
00272 if (ondisk.magic != 0)
00273 goto done;
00274 if ((ret = CDB___os_seek(dbenv, &fh,
00275 pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
00276 goto out;
00277 }
00278 
00279 /*
00280  * Page didn't exist, update the LSN and write a new one.
00281  * (seek pointer shouldn't have moved)
00282  */
00283 CDB___ua_memcpy(&meta->lsn, lsnp, sizeof(DB_LSN));
00284 if ((ret = CDB___os_write(dbp->dbenv, &fh,
00285 argp->page.data, argp->page.size, &nr)) != 0)
00286 goto out;
00287 if (nr != (size_t)argp->page.size) {
00288 CDB___db_err(dbenv, "Write failed during recovery");
00289 ret = EIO;
00290 goto out;
00291 }
00292 
00293 /*
00294  * We must close and reopen the file to be sure
00295  * that we have the proper meta information
00296  * in the in memory structures
00297  */
00298 
00299 if ((ret = CDB___log_reopen_file(dbenv,
00300 argp->name.data, argp->fileid,
00301 meta->uid, argp->pgno)) != 0)
00302 goto out;
00303 
00304 /* Handle will be closed on exit. */
00305 } else if (DB_UNDO(op)) {
00306 is_done = 0;
00307 
00308 /* If file does not exist, there is nothing to undo. */
00309 if (CDB___os_exists(real_name, NULL) != 0)
00310 goto done;
00311 
00312 /*
00313  * Before we can look at anything on disk, we have to check
00314  * if there is a valid dbp for this, and if there is, we'd
00315  * better flush it.
00316  */
00317 dbp = NULL;
00318 if ((ret =
00319 CDB___db_fileid_to_db(dbenv, &dbp, argp->fileid, 0)) == 0)
00320 (void)dbp->sync(dbp, 0);
00321 
00322 /*
00323  * We need to make sure that we do not remove a file that
00324  * someone else created. If the file is 0-length, then we
00325  * can assume that we created it and remove it. If it is
00326  * not 0-length, then we need to check the LSN and make
00327  * sure that it's the file we created.
00328  */
00329 if ((ret = CDB___os_open(dbenv, real_name, 0, 0, &fh)) != 0)
00330 goto out;
00331 if ((ret = CDB___os_ioinfo(dbenv,
00332 real_name, &fh, &mb, &b, &io)) != 0)
00333 goto out;
00334 if (mb != 0 || b != 0) {
00335 /* The file has something in it. */
00336 if ((ret = CDB___os_seek(dbenv, &fh,
00337 pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
00338 goto out;
00339 if ((ret = CDB___os_read(dbenv, &fh,
00340 &ondisk, sizeof(ondisk), &nr)) != 0)
00341 goto out;
00342 if (CDB_log_compare(&ondisk.lsn, lsnp) != 0)
00343 is_done = 1;
00344 }
00345 
00346 /*
00347  * Must close here, because unlink with the file open fails
00348  * on some systems.
00349  */
00350 if ((ret = CDB___os_closehandle(&fh)) != 0)
00351 goto out;
00352 
00353 if (!is_done) {
00354 /*
00355  * On some systems, you cannot unlink an open file so
00356  * we close the fd in the dbp here and make sure we
00357  * don't try to close it again. First, check for a
00358  * saved_open_fhp, then close down the mpool.
00359  */
00360 if (dbp != NULL && dbp->saved_open_fhp != NULL &&
00361 F_ISSET(dbp->saved_open_fhp, DB_FH_VALID) &&
00362 (ret = CDB___os_closehandle(dbp->saved_open_fhp)) != 0)
00363 goto out;
00364 if (dbp != NULL && dbp->mpf != NULL) {
00365 (void)CDB___memp_fremove(dbp->mpf);
00366 if ((ret = CDB_memp_fclose(dbp->mpf)) != 0)
00367 goto out;
00368 F_SET(dbp, DB_AM_DISCARD);
00369 dbp->mpf = NULL;
00370 }
00371 if ((ret = CDB___os_unlink(dbenv, real_name)) != 0)
00372 goto out;
00373 }
00374 }
00375 
00376 done: *lsnp = argp->prev_lsn;
00377 ret = 0;
00378 
00379 out: if (argp != NULL)
00380 CDB___os_free(argp, sizeof(*argp));
00381 if (real_name != NULL)
00382 CDB___os_freestr(real_name);
00383 if (F_ISSET(&fh, DB_FH_VALID))
00384 (void)CDB___os_closehandle(&fh);
00385 return (ret);
00386 }
00387 
00388 /*
00389  * CDB___crdel_delete_recover --
00390  * Recovery function for delete.
00391  *
00392  * PUBLIC: int CDB___crdel_delete_recover
00393  * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00394  */
00395 int
00396 CDB___crdel_delete_recover(dbenv, dbtp, lsnp, op, info)
00397 DB_ENV *dbenv;
00398 DBT *dbtp;
00399 DB_LSN *lsnp;
00400 db_recops op;
00401 void *info;
00402 {
00403 DB *dbp;
00404 __crdel_delete_args *argp;
00405 int ret;
00406 char *backup, *real_back, *real_name;
00407 
00408 REC_PRINT(CDB___crdel_delete_print);
00409 
00410 backup = real_back = real_name = NULL;
00411 if ((ret = CDB___crdel_delete_read(dbenv, dbtp->data, &argp)) != 0)
00412 goto out;
00413 
00414 if (DB_REDO(op)) {
00415 /*
00416  * On a recovery, as we recreate what was going on, we
00417  * recreate the creation of the file. And so, even though
00418  * it committed, we need to delete it. Try to delete it,
00419  * but it is not an error if that delete fails.
00420  */
00421 if ((ret = CDB___db_appname(dbenv, DB_APP_DATA,
00422 NULL, argp->name.data, 0, NULL, &real_name)) != 0)
00423 goto out;
00424 if (CDB___os_exists(real_name, NULL) == 0) {
00425 /*
00426  * On Windows, the underlying file must be
00427  * closed to perform a remove.
00428  */
00429 if ((ret = CDB___db_fileid_to_db(
00430 dbenv, &dbp, argp->fileid, 0)) != 0)
00431 goto out;
00432 (void)CDB___memp_fremove(dbp->mpf);
00433 if ((ret = CDB_memp_fclose(dbp->mpf)) != 0)
00434 goto out;
00435 dbp->mpf = NULL;
00436 if ((ret = CDB___os_unlink(dbenv, real_name)) != 0)
00437 goto out;
00438 }
00439 /*
00440  * The transaction committed, so the only thing that might
00441  * be true is that the backup file is still around. Try
00442  * to delete it, but it's not an error if that delete fails.
00443  */
00444 if ((ret = CDB___db_backup_name(dbenv, argp->name.data,
00445 &backup, lsnp)) != 0)
00446 goto out;
00447 if ((ret = CDB___db_appname(dbenv,
00448 DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
00449 goto out;
00450 if (CDB___os_exists(real_back, NULL) == 0)
00451 if ((ret = CDB___os_unlink(dbenv, real_back)) != 0)
00452 goto out;
00453 if ((ret = CDB___db_txnlist_delete(dbenv, info,
00454 argp->name.data, TXNLIST_INVALID_ID, 1)) != 0)
00455 goto out;
00456 } else if (DB_UNDO(op)) {
00457 /*
00458  * Trying to undo. File may or may not have been deleted.
00459  * Try to move the backup to the original. If the backup
00460  * exists, then this is right. If it doesn't exist, then
00461  * nothing will happen and that's OK.
00462  */
00463 if ((ret = CDB___db_backup_name(dbenv, argp->name.data,
00464 &backup, lsnp)) != 0)
00465 goto out;
00466 if ((ret = CDB___db_appname(dbenv,
00467 DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
00468 goto out;
00469 if ((ret = CDB___db_appname(dbenv, DB_APP_DATA,
00470 NULL, argp->name.data, 0, NULL, &real_name)) != 0)
00471 goto out;
00472 if (CDB___os_exists(real_back, NULL) == 0)
00473 if ((ret =
00474 CDB___os_rename(dbenv, real_back, real_name)) != 0)
00475 goto out;
00476 }
00477 
00478 *lsnp = argp->prev_lsn;
00479 ret = 0;
00480 
00481 out: if (argp != NULL)
00482 CDB___os_free(argp, sizeof(*argp));
00483 if (backup != NULL)
00484 CDB___os_freestr(backup);
00485 if (real_back != NULL)
00486 CDB___os_freestr(real_back);
00487 if (real_name != NULL)
00488 CDB___os_freestr(real_name);
00489 return (ret);
00490 }
00491 /*
00492  * CDB___crdel_rename_recover --
00493  * Recovery function for rename.
00494  *
00495  * PUBLIC: int CDB___crdel_rename_recover
00496  * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00497  */
00498 int
00499 CDB___crdel_rename_recover(dbenv, dbtp, lsnp, op, info)
00500 DB_ENV *dbenv;
00501 DBT *dbtp;
00502 DB_LSN *lsnp;
00503 db_recops op;
00504 void *info;
00505 {
00506 DB *dbp;
00507 __crdel_rename_args *argp;
00508 char *new_name, *real_name;
00509 int ret, set;
00510 
00511 COMPQUIET(info, NULL);
00512 
00513 REC_PRINT(CDB___crdel_rename_print);
00514 if ((ret = CDB___crdel_rename_read(dbenv, dbtp->data, &argp)) != 0)
00515 goto out;
00516 
00517 if ((ret = CDB___db_fileid_to_db(dbenv, &dbp, argp->fileid, 0)) != 0)
00518 goto out;
00519 if (DB_REDO(op)) {
00520 /*
00521  * We don't use the dbp parameter to CDB___log_filelist_update
00522  * in the rename case, so passing NULL for it is OK.
00523  */
00524 if ((ret = CDB___log_filelist_update(dbenv, NULL,
00525 argp->fileid, argp->newname.data, &set)) != 0)
00526 goto out;
00527 if (set != 0) {
00528 if ((ret = CDB___db_appname(dbenv, DB_APP_DATA,
00529 NULL, argp->name.data, 0, NULL, &real_name)) != 0)
00530 goto out;
00531 if (CDB___os_exists(real_name, NULL) == 0) {
00532 if ((ret = CDB___db_appname(dbenv,
00533 DB_APP_DATA, NULL, argp->newname.data,
00534 0, NULL, &new_name)) != 0)
00535 goto out;
00536 /*
00537  * On Windows, the underlying file
00538  * must be closed to perform a remove.
00539  * The db will be closed by a
00540  * CDB_log_register record. Rename
00541  * has exclusive access to the db.
00542  */
00543 (void)CDB___memp_fremove(dbp->mpf);
00544 if ((ret = CDB_memp_fclose(dbp->mpf)) != 0)
00545 goto out;
00546 dbp->mpf = NULL;
00547 if ((ret = CDB___os_rename(dbenv,
00548 real_name, new_name)) != 0)
00549 goto out;
00550 }
00551 }
00552 } else {
00553 /*
00554  * We don't use the dbp parameter to CDB___log_filelist_update
00555  * in the rename case, so passing NULL for it is OK.
00556  */
00557 if ((ret = CDB___log_filelist_update(dbenv, NULL,
00558 argp->fileid, argp->name.data, &set)) != 0)
00559 goto out;
00560 if (set != 0) {
00561 if ((ret = CDB___db_appname(dbenv, DB_APP_DATA,
00562 NULL, argp->newname.data, 0, NULL, &new_name)) != 0)
00563 goto out;
00564 if (CDB___os_exists(new_name, NULL) == 0) {
00565 if ((ret = CDB___db_appname(dbenv,
00566 DB_APP_DATA, NULL, argp->name.data,
00567 0, NULL, &real_name)) != 0)
00568 goto out;
00569 /*
00570  * On Windows, the underlying file
00571  * must be closed to perform a remove.
00572  * The file may have already been closed
00573  * if we are aborting the transaction.
00574  */
00575 if (dbp->mpf != NULL) {
00576 (void)CDB___memp_fremove(dbp->mpf);
00577 if ((ret = CDB_memp_fclose(dbp->mpf)) != 0)
00578 goto out;
00579 dbp->mpf = NULL;
00580 }
00581 if ((ret = CDB___os_rename(dbenv,
00582 new_name, real_name)) != 0)
00583 goto out;
00584 }
00585 }
00586 }
00587 
00588 *lsnp = argp->prev_lsn;
00589 ret = 0;
00590 
00591 out: if (argp != NULL)
00592 CDB___os_free(argp, sizeof(*argp));
00593 return (ret);
00594 }

Generated on Sun Jun 8 10:56:35 2008 for GNUmifluz by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /