crdel_rec.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:16k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996, 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: crdel_rec.c,v 11.43 2000/12/13 08:06:34 krinsky Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <string.h>
  14. #endif
  15. #include "db_int.h"
  16. #include "db_page.h"
  17. #include "log.h"
  18. #include "hash.h"
  19. #include "mp.h"
  20. #include "db_dispatch.h"
  21. /*
  22.  * __crdel_fileopen_recover --
  23.  * Recovery function for fileopen.
  24.  *
  25.  * PUBLIC: int __crdel_fileopen_recover
  26.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  27.  */
  28. int
  29. __crdel_fileopen_recover(dbenv, dbtp, lsnp, op, info)
  30. DB_ENV *dbenv;
  31. DBT *dbtp;
  32. DB_LSN *lsnp;
  33. db_recops op;
  34. void *info;
  35. {
  36. __crdel_fileopen_args *argp;
  37. DBMETA ondisk;
  38. DB_FH fh;
  39. size_t nr;
  40. int do_unlink, ret;
  41. u_int32_t b, mb, io;
  42. char *real_name;
  43. COMPQUIET(info, NULL);
  44. real_name = NULL;
  45. REC_PRINT(__crdel_fileopen_print);
  46. if ((ret = __crdel_fileopen_read(dbenv, dbtp->data, &argp)) != 0)
  47. goto out;
  48. /*
  49.  * If this is an in-memory database, then the name is going to
  50.  * be NULL, which looks like a 0-length name in recovery.
  51.  */
  52. if (argp->name.size == 0)
  53. goto done;
  54. if ((ret = __db_appname(dbenv, DB_APP_DATA,
  55.     NULL, argp->name.data, 0, NULL, &real_name)) != 0)
  56. goto out;
  57. if (DB_REDO(op)) {
  58. /*
  59.  * The create commited, so we need to make sure that the file
  60.  * exists.  A simple open should suffice.
  61.  */
  62. if ((ret = __os_open(dbenv, real_name,
  63.     DB_OSO_CREATE, argp->mode, &fh)) != 0)
  64. goto out;
  65. if ((ret = __os_closehandle(&fh)) != 0)
  66. goto out;
  67. } else if (DB_UNDO(op)) {
  68. /*
  69.  * If the file is 0-length then it was in the process of being
  70.  * created, so we should unlink it.  If it is non-0 length, then
  71.  * either someone else created it and we need to leave it
  72.  * untouched or we were in the process of creating it, allocated
  73.  * the first page on a system that requires you to actually
  74.  * write pages as you allocate them, but never got any data
  75.  * on it.
  76.  * If the file doesn't exist, we never got around to creating
  77.  * it, so that's fine.
  78.  */
  79. if (__os_exists(real_name, NULL) != 0)
  80. goto done;
  81. if ((ret = __os_open(dbenv, real_name, 0, 0, &fh)) != 0)
  82. goto out;
  83. if ((ret = __os_ioinfo(dbenv,
  84.     real_name, &fh, &mb, &b, &io)) != 0)
  85. goto out;
  86. do_unlink = 0;
  87. if (mb != 0 || b != 0) {
  88. /*
  89.  * We need to read the first page
  90.  * to see if its got valid data on it.
  91.  */
  92. if ((ret = __os_read(dbenv, &fh,
  93.     &ondisk, sizeof(ondisk), &nr)) != 0 ||
  94.     nr != sizeof(ondisk))
  95. goto out;
  96. if (ondisk.magic == 0)
  97. do_unlink = 1;
  98. }
  99. if ((ret = __os_closehandle(&fh)) != 0)
  100. goto out;
  101. /* Check for 0-length and if it is, delete it. */
  102. if (do_unlink || (mb == 0 && b == 0))
  103. if ((ret = __os_unlink(dbenv, real_name)) != 0)
  104. goto out;
  105. }
  106. done: *lsnp = argp->prev_lsn;
  107. ret = 0;
  108. out: if (argp != NULL)
  109. __os_free(argp, 0);
  110. if (real_name != NULL)
  111. __os_freestr(real_name);
  112. return (ret);
  113. }
  114. /*
  115.  * __crdel_metasub_recover --
  116.  * Recovery function for metasub.
  117.  *
  118.  * PUBLIC: int __crdel_metasub_recover
  119.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  120.  */
  121. int
  122. __crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
  123. DB_ENV *dbenv;
  124. DBT *dbtp;
  125. DB_LSN *lsnp;
  126. db_recops op;
  127. void *info;
  128. {
  129. __crdel_metasub_args *argp;
  130. DB *file_dbp;
  131. DBC *dbc;
  132. DB_MPOOLFILE *mpf;
  133. PAGE *pagep;
  134. u_int8_t *file_uid, ptype;
  135. int cmp_p, modified, reopen, ret;
  136. COMPQUIET(info, NULL);
  137. REC_PRINT(__crdel_metasub_print);
  138. REC_INTRO(__crdel_metasub_read, 0);
  139. if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
  140. if (DB_REDO(op)) {
  141. if ((ret = memp_fget(mpf,
  142.     &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
  143. goto out;
  144. } else {
  145. *lsnp = argp->prev_lsn;
  146. ret = 0;
  147. goto out;
  148. }
  149. }
  150. modified = 0;
  151. reopen = 0;
  152. cmp_p = log_compare(&LSN(pagep), &argp->lsn);
  153. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
  154. if (cmp_p == 0 && DB_REDO(op)) {
  155. memcpy(pagep, argp->page.data, argp->page.size);
  156. LSN(pagep) = *lsnp;
  157. modified = 1;
  158. /*
  159.  * If this is a meta-data page, then we must reopen;
  160.  * if it was a root page, then we do not.
  161.  */
  162. ptype = ((DBMETA *)argp->page.data)->type;
  163. if (ptype == P_HASHMETA || ptype == P_BTREEMETA ||
  164.     ptype == P_QAMMETA)
  165. reopen = 1;
  166. } else if (DB_UNDO(op)) {
  167. /*
  168.  * We want to undo this page creation.  The page creation
  169.  * happened in two parts.  First, we called __bam_new which
  170.  * was logged separately. Then we wrote the meta-data onto
  171.  * the page.  So long as we restore the LSN, then the recovery
  172.  * for __bam_new will do everything else.
  173.  * Don't bother checking the lsn on the page.  If we
  174.  * are rolling back the next thing is that this page
  175.  * will get freed.  Opening the subdb will have reinitialized
  176.  * the page, but not the lsn.
  177.  */
  178. LSN(pagep) = argp->lsn;
  179. modified = 1;
  180. }
  181. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  182. goto out;
  183. /*
  184.  * If we are redoing a subdatabase create, we must close and reopen the
  185.  * file to be sure that we have the proper meta information in the
  186.  * in-memory structures
  187.  */
  188. if (reopen) {
  189. /* Close cursor if it's open. */
  190.  if (dbc != NULL) {
  191. dbc->c_close(dbc);
  192. dbc = NULL;
  193. }
  194. if ((ret = __os_malloc(dbenv,
  195.     DB_FILE_ID_LEN, NULL, &file_uid)) != 0)
  196. goto out;
  197. memcpy(file_uid, &file_dbp->fileid[0], DB_FILE_ID_LEN);
  198. ret = __log_reopen_file(dbenv,
  199.      NULL, argp->fileid, file_uid, argp->pgno);
  200. (void)__os_free(file_uid, DB_FILE_ID_LEN);
  201. if (ret != 0)
  202. goto out;
  203. }
  204. done: *lsnp = argp->prev_lsn;
  205. ret = 0;
  206. out: REC_CLOSE;
  207. }
  208. /*
  209.  * __crdel_metapage_recover --
  210.  * Recovery function for metapage.
  211.  *
  212.  * PUBLIC: int __crdel_metapage_recover
  213.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  214.  */
  215. int
  216. __crdel_metapage_recover(dbenv, dbtp, lsnp, op, info)
  217. DB_ENV *dbenv;
  218. DBT *dbtp;
  219. DB_LSN *lsnp;
  220. db_recops op;
  221. void *info;
  222. {
  223. __crdel_metapage_args *argp;
  224. DB *dbp;
  225. DBMETA *meta, ondisk;
  226. DB_FH fh;
  227. size_t nr;
  228. u_int32_t b, io, mb, pagesize;
  229. int is_done, ret;
  230. char *real_name;
  231. COMPQUIET(info, NULL);
  232. real_name = NULL;
  233. memset(&fh, 0, sizeof(fh));
  234. REC_PRINT(__crdel_metapage_print);
  235. if ((ret = __crdel_metapage_read(dbenv, dbtp->data, &argp)) != 0)
  236. goto out;
  237. /*
  238.  * If this is an in-memory database, then the name is going to
  239.  * be NULL, which looks like a 0-length name in recovery.
  240.  */
  241. if (argp->name.size == 0)
  242. goto done;
  243. meta = (DBMETA *)argp->page.data;
  244. __ua_memcpy(&pagesize, &meta->pagesize, sizeof(pagesize));
  245. if ((ret = __db_appname(dbenv, DB_APP_DATA,
  246.     NULL, argp->name.data, 0, NULL, &real_name)) != 0)
  247. goto out;
  248. if (DB_REDO(op)) {
  249. if ((ret = __db_fileid_to_db(dbenv,
  250.     &dbp, argp->fileid, 0)) != 0) {
  251. if (ret == DB_DELETED)
  252. goto done;
  253. else
  254. goto out;
  255. }
  256. /*
  257.  * We simply read the first page and if the LSN is 0, we
  258.  * write the meta-data page.
  259.  */
  260. if ((ret = __os_open(dbenv, real_name, 0, 0, &fh)) != 0)
  261. goto out;
  262. if ((ret = __os_seek(dbenv, &fh,
  263.     pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
  264. goto out;
  265. /*
  266.  * If the read succeeds then the page exists, then we need
  267.  * to vrify that the page has actually been written, because
  268.  * on some systems (e.g., Windows) we preallocate pages because
  269.  * files aren't allowed to have holes in them.  If the page
  270.  * looks good then we're done.
  271.  */
  272. if ((ret = __os_read(dbenv, &fh, &ondisk,
  273.     sizeof(ondisk), &nr)) == 0 && nr == sizeof(ondisk)) {
  274. if (ondisk.magic != 0)
  275. goto done;
  276. if ((ret = __os_seek(dbenv, &fh,
  277.     pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
  278. goto out;
  279. }
  280. /*
  281.  * Page didn't exist, update the LSN and write a new one.
  282.  * (seek pointer shouldn't have moved)
  283.  */
  284. __ua_memcpy(&meta->lsn, lsnp, sizeof(DB_LSN));
  285. if ((ret = __os_write(dbp->dbenv, &fh,
  286.     argp->page.data, argp->page.size, &nr)) != 0)
  287. goto out;
  288. if (nr != (size_t)argp->page.size) {
  289. __db_err(dbenv, "Write failed during recovery");
  290. ret = EIO;
  291. goto out;
  292. }
  293. /*
  294.  * We must close and reopen the file to be sure
  295.  * that we have the proper meta information
  296.  * in the in memory structures
  297.  */
  298. if ((ret = __log_reopen_file(dbenv,
  299.      argp->name.data, argp->fileid,
  300.      meta->uid, argp->pgno)) != 0)
  301. goto out;
  302. /* Handle will be closed on exit. */
  303. } else if (DB_UNDO(op)) {
  304. is_done = 0;
  305. /* If file does not exist, there is nothing to undo. */
  306. if (__os_exists(real_name, NULL) != 0)
  307. goto done;
  308. /*
  309.  * Before we can look at anything on disk, we have to check
  310.  * if there is a valid dbp for this, and if there is, we'd
  311.  * better flush it.
  312.  */
  313. dbp = NULL;
  314. if ((ret =
  315.     __db_fileid_to_db(dbenv, &dbp, argp->fileid, 0)) == 0)
  316. (void)dbp->sync(dbp, 0);
  317. /*
  318.  * We need to make sure that we do not remove a file that
  319.  * someone else created.   If the file is 0-length, then we
  320.  * can assume that we created it and remove it.  If it is
  321.  * not 0-length, then we need to check the LSN and make
  322.  * sure that it's the file we created.
  323.  */
  324. if ((ret = __os_open(dbenv, real_name, 0, 0, &fh)) != 0)
  325. goto out;
  326. if ((ret = __os_ioinfo(dbenv,
  327.     real_name, &fh, &mb, &b, &io)) != 0)
  328. goto out;
  329. if (mb != 0 || b != 0) {
  330. /* The file has something in it. */
  331. if ((ret = __os_seek(dbenv, &fh,
  332.     pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
  333. goto out;
  334. if ((ret = __os_read(dbenv, &fh,
  335.     &ondisk, sizeof(ondisk), &nr)) != 0)
  336. goto out;
  337. if (log_compare(&ondisk.lsn, lsnp) != 0)
  338. is_done = 1;
  339. }
  340. /*
  341.  * Must close here, because unlink with the file open fails
  342.  * on some systems.
  343.  */
  344. if ((ret = __os_closehandle(&fh)) != 0)
  345. goto out;
  346. if (!is_done) {
  347. /*
  348.  * On some systems, you cannot unlink an open file so
  349.  * we close the fd in the dbp here and make sure we
  350.  * don't try to close it again.  First, check for a
  351.  * saved_open_fhp, then close down the mpool.
  352.  */
  353. if (dbp != NULL && dbp->saved_open_fhp != NULL &&
  354.     F_ISSET(dbp->saved_open_fhp, DB_FH_VALID) &&
  355.     (ret = __os_closehandle(dbp->saved_open_fhp)) != 0)
  356. goto out;
  357. if (dbp != NULL && dbp->mpf != NULL) {
  358. (void)__memp_fremove(dbp->mpf);
  359. if ((ret = memp_fclose(dbp->mpf)) != 0)
  360. goto out;
  361. F_SET(dbp, DB_AM_DISCARD);
  362. dbp->mpf = NULL;
  363. }
  364. if ((ret = __os_unlink(dbenv, real_name)) != 0)
  365. goto out;
  366. }
  367. }
  368. done: *lsnp = argp->prev_lsn;
  369. ret = 0;
  370. out: if (argp != NULL)
  371. __os_free(argp, 0);
  372. if (real_name != NULL)
  373. __os_freestr(real_name);
  374. if (F_ISSET(&fh, DB_FH_VALID))
  375. (void)__os_closehandle(&fh);
  376. return (ret);
  377. }
  378. /*
  379.  * __crdel_delete_recover --
  380.  * Recovery function for delete.
  381.  *
  382.  * PUBLIC: int __crdel_delete_recover
  383.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  384.  */
  385. int
  386. __crdel_delete_recover(dbenv, dbtp, lsnp, op, info)
  387. DB_ENV *dbenv;
  388. DBT *dbtp;
  389. DB_LSN *lsnp;
  390. db_recops op;
  391. void *info;
  392. {
  393. DB *dbp;
  394. __crdel_delete_args *argp;
  395. int ret;
  396. char *backup, *real_back, *real_name;
  397. REC_PRINT(__crdel_delete_print);
  398. backup = real_back = real_name = NULL;
  399. if ((ret = __crdel_delete_read(dbenv, dbtp->data, &argp)) != 0)
  400. goto out;
  401. if (DB_REDO(op)) {
  402. /*
  403.  * On a recovery, as we recreate what was going on, we
  404.  * recreate the creation of the file.  And so, even though
  405.  * it committed, we need to delete it.  Try to delete it,
  406.  * but it is not an error if that delete fails.
  407.  */
  408. if ((ret = __db_appname(dbenv, DB_APP_DATA,
  409.     NULL, argp->name.data, 0, NULL, &real_name)) != 0)
  410. goto out;
  411. if (__os_exists(real_name, NULL) == 0) {
  412. /*
  413.  * If a file is deleted and then recreated, it's
  414.  * possible for the __os_exists call above to
  415.  * return success and for us to get here, but for
  416.  * the fileid we're looking for to be marked
  417.  * deleted.  In that case, we needn't redo the
  418.  * unlink even though the file exists, and it's
  419.  * not an error.
  420.  */
  421. ret = __db_fileid_to_db(dbenv, &dbp, argp->fileid, 0);
  422. if (ret == 0) {
  423. /*
  424.  * On Windows, the underlying file must be
  425.  * closed to perform a remove.
  426.  */
  427. (void)__memp_fremove(dbp->mpf);
  428. if ((ret = memp_fclose(dbp->mpf)) != 0)
  429. goto out;
  430. dbp->mpf = NULL;
  431. if ((ret = __os_unlink(dbenv, real_name)) != 0)
  432. goto out;
  433. } else if (ret != DB_DELETED)
  434. goto out;
  435. }
  436. /*
  437.  * The transaction committed, so the only thing that might
  438.  * be true is that the backup file is still around.  Try
  439.  * to delete it, but it's not an error if that delete fails.
  440.  */
  441. if ((ret =  __db_backup_name(dbenv, argp->name.data,
  442.     &backup, lsnp)) != 0)
  443. goto out;
  444. if ((ret = __db_appname(dbenv,
  445.     DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
  446. goto out;
  447. if (__os_exists(real_back, NULL) == 0)
  448. if ((ret = __os_unlink(dbenv, real_back)) != 0)
  449. goto out;
  450. if ((ret = __db_txnlist_delete(dbenv, info,
  451.     argp->name.data, TXNLIST_INVALID_ID, 1)) != 0)
  452. goto out;
  453. } else if (DB_UNDO(op)) {
  454. /*
  455.  * Trying to undo.  File may or may not have been deleted.
  456.  * Try to move the backup to the original.  If the backup
  457.  * exists, then this is right.  If it doesn't exist, then
  458.  * nothing will happen and that's OK.
  459.  */
  460. if ((ret =  __db_backup_name(dbenv, argp->name.data,
  461.     &backup, lsnp)) != 0)
  462. goto out;
  463. if ((ret = __db_appname(dbenv,
  464.     DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
  465. goto out;
  466. if ((ret = __db_appname(dbenv, DB_APP_DATA,
  467.     NULL, argp->name.data, 0, NULL, &real_name)) != 0)
  468. goto out;
  469. if (__os_exists(real_back, NULL) == 0)
  470. if ((ret =
  471.      __os_rename(dbenv, real_back, real_name)) != 0)
  472. goto out;
  473. }
  474. *lsnp = argp->prev_lsn;
  475. ret = 0;
  476. out: if (argp != NULL)
  477. __os_free(argp, 0);
  478. if (backup != NULL)
  479. __os_freestr(backup);
  480. if (real_back != NULL)
  481. __os_freestr(real_back);
  482. if (real_name != NULL)
  483. __os_freestr(real_name);
  484. return (ret);
  485. }
  486. /*
  487.  * __crdel_rename_recover --
  488.  * Recovery function for rename.
  489.  *
  490.  * PUBLIC: int __crdel_rename_recover
  491.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  492.  */
  493. int
  494. __crdel_rename_recover(dbenv, dbtp, lsnp, op, info)
  495. DB_ENV *dbenv;
  496. DBT *dbtp;
  497. DB_LSN *lsnp;
  498. db_recops op;
  499. void *info;
  500. {
  501. DB *dbp;
  502. __crdel_rename_args *argp;
  503. char *new_name, *real_name;
  504. int ret, set;
  505. COMPQUIET(info, NULL);
  506. REC_PRINT(__crdel_rename_print);
  507. new_name = real_name = NULL;
  508. if ((ret = __crdel_rename_read(dbenv, dbtp->data, &argp)) != 0)
  509. goto out;
  510. if ((ret = __db_fileid_to_db(dbenv, &dbp, argp->fileid, 0)) != 0)
  511. goto out;
  512. if (DB_REDO(op)) {
  513. /*
  514.  * We don't use the dbp parameter to __log_filelist_update
  515.  * in the rename case, so passing NULL for it is OK.
  516.  */
  517. if ((ret = __log_filelist_update(dbenv, NULL,
  518.     argp->fileid, argp->newname.data, &set)) != 0)
  519. goto out;
  520. if (set != 0) {
  521. if ((ret = __db_appname(dbenv, DB_APP_DATA,
  522.     NULL, argp->name.data, 0, NULL, &real_name)) != 0)
  523. goto out;
  524. if (__os_exists(real_name, NULL) == 0) {
  525. if ((ret = __db_appname(dbenv,
  526.     DB_APP_DATA, NULL, argp->newname.data,
  527.     0, NULL, &new_name)) != 0)
  528. goto out;
  529. /*
  530.  * On Windows, the underlying file
  531.  * must be closed to perform a remove.
  532.  * The db will be closed by a
  533.  * log_register record.  Rename
  534.  * has exclusive access to the db.
  535.  */
  536. (void)__memp_fremove(dbp->mpf);
  537. if ((ret = memp_fclose(dbp->mpf)) != 0)
  538. goto out;
  539. dbp->mpf = NULL;
  540. if ((ret = __os_rename(dbenv,
  541.     real_name, new_name)) != 0)
  542. goto out;
  543. }
  544. }
  545. } else {
  546. /*
  547.  * We don't use the dbp parameter to __log_filelist_update
  548.  * in the rename case, so passing NULL for it is OK.
  549.  */
  550. if ((ret = __log_filelist_update(dbenv, NULL,
  551.     argp->fileid, argp->name.data, &set)) != 0)
  552. goto out;
  553. if (set != 0) {
  554. if ((ret = __db_appname(dbenv, DB_APP_DATA,
  555.     NULL, argp->newname.data, 0, NULL, &new_name)) != 0)
  556. goto out;
  557. if (__os_exists(new_name, NULL) == 0) {
  558. if ((ret = __db_appname(dbenv,
  559.     DB_APP_DATA, NULL, argp->name.data,
  560.     0, NULL, &real_name)) != 0)
  561. goto out;
  562. /*
  563.  * On Windows, the underlying file
  564.  * must be closed to perform a remove.
  565.  * The file may have already been closed
  566.  * if we are aborting the transaction.
  567.  */
  568. if (dbp->mpf != NULL) {
  569. (void)__memp_fremove(dbp->mpf);
  570. if ((ret = memp_fclose(dbp->mpf)) != 0)
  571. goto out;
  572. dbp->mpf = NULL;
  573. }
  574. if ((ret = __os_rename(dbenv,
  575.     new_name, real_name)) != 0)
  576. goto out;
  577. }
  578. }
  579. }
  580. *lsnp = argp->prev_lsn;
  581. ret = 0;
  582. out: if (argp != NULL)
  583. __os_free(argp, 0);
  584. if (new_name != NULL)
  585. __os_free(new_name, 0);
  586. if (real_name != NULL)
  587. __os_free(real_name, 0);
  588. return (ret);
  589. }