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

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. /*
  8.  * Copyright (c) 1995, 1996
  9.  * The President and Fellows of Harvard University.  All rights reserved.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without
  12.  * modification, are permitted provided that the following conditions
  13.  * are met:
  14.  * 1. Redistributions of source code must retain the above copyright
  15.  *    notice, this list of conditions and the following disclaimer.
  16.  * 2. Redistributions in binary form must reproduce the above copyright
  17.  *    notice, this list of conditions and the following disclaimer in the
  18.  *    documentation and/or other materials provided with the distribution.
  19.  * 3. Neither the name of the University nor the names of its contributors
  20.  *    may be used to endorse or promote products derived from this software
  21.  *    without specific prior written permission.
  22.  *
  23.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  24.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33.  * SUCH DAMAGE.
  34.  */
  35. #include "db_config.h"
  36. #ifndef lint
  37. static const char revid[] = "$Id: log_rec.c,v 11.48 2001/01/11 18:19:53 bostic Exp $";
  38. #endif /* not lint */
  39. #ifndef NO_SYSTEM_INCLUDES
  40. #include <sys/types.h>
  41. #include <string.h>
  42. #endif
  43. #include "db_int.h"
  44. #include "db_page.h"
  45. #include "db_am.h"
  46. #include "log.h"
  47. static int __log_check_master __P((DB_ENV *, u_int8_t *, char *));
  48. static int __log_do_open __P((DB_ENV *, DB_LOG *,
  49.     u_int8_t *, char *, DBTYPE, int32_t, db_pgno_t));
  50. static int __log_open_file __P((DB_ENV *, DB_LOG *, __log_register_args *));
  51. /*
  52.  * PUBLIC: int __log_register_recover
  53.  * PUBLIC:     __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  54.  */
  55. int
  56. __log_register_recover(dbenv, dbtp, lsnp, op, info)
  57. DB_ENV *dbenv;
  58. DBT *dbtp;
  59. DB_LSN *lsnp;
  60. db_recops op;
  61. void *info;
  62. {
  63. DB_ENTRY *dbe;
  64. DB_LOG *logp;
  65. DB *dbp;
  66. __log_register_args *argp;
  67. int do_rem, ret, t_ret;
  68. logp = dbenv->lg_handle;
  69. dbp = NULL;
  70. #ifdef DEBUG_RECOVER
  71. REC_PRINT(__log_register_print);
  72. #endif
  73. COMPQUIET(lsnp, NULL);
  74. if ((ret = __log_register_read(dbenv, dbtp->data, &argp)) != 0)
  75. goto out;
  76. if ((argp->opcode == LOG_OPEN &&
  77.     (DB_REDO(op) || op == DB_TXN_OPENFILES)) ||
  78.     (argp->opcode == LOG_CLOSE && DB_UNDO(op))) {
  79. /*
  80.  * If we are redoing an open or undoing a close, then we need
  81.  * to open a file.  We must open the file even if
  82.  * the meta page is not yet written as we may be creating it.
  83.  */
  84. if (op == DB_TXN_OPENFILES)
  85. F_SET(logp, DBLOG_FORCE_OPEN);
  86. ret = __log_open_file(dbenv, logp, argp);
  87. F_CLR(logp, DBLOG_FORCE_OPEN);
  88. if (ret == ENOENT || ret == EINVAL) {
  89. if (op == DB_TXN_OPENFILES && argp->name.size != 0 &&
  90.     (ret = __db_txnlist_delete(dbenv, info,
  91. argp->name.data, argp->fileid, 0)) != 0)
  92. goto out;
  93. ret = 0;
  94. }
  95. } else if (argp->opcode != LOG_CHECKPOINT) {
  96. /*
  97.  * If we are undoing an open, then we need to close the file.
  98.  *
  99.  * If the file is deleted, then we can just ignore this close.
  100.  * Otherwise, we should usually have a valid dbp we should
  101.  * close or whose reference count should be decremented.
  102.  * However, if we shut down without closing a file, we may, in
  103.  * fact, not have the file open, and that's OK.
  104.  */
  105. do_rem = 0;
  106. MUTEX_THREAD_LOCK(dbenv, logp->mutexp);
  107. if (argp->fileid < logp->dbentry_cnt) {
  108. dbe = &logp->dbentry[argp->fileid];
  109. DB_ASSERT(dbe->refcount == 1);
  110. ret = __db_txnlist_close(info,
  111.     argp->fileid, dbe->count);
  112. if ((dbp = TAILQ_FIRST(&dbe->dblist)) != NULL)
  113. (void)log_unregister(dbenv, dbp);
  114. do_rem = 1;
  115. }
  116. MUTEX_THREAD_UNLOCK(dbenv, logp->mutexp);
  117. if (do_rem) {
  118. (void)__log_rem_logid(logp, dbp, argp->fileid);
  119. /*
  120.  * If remove or rename has closed the file, don't
  121.  * sync.
  122.  */
  123. if (dbp != NULL &&
  124.     (t_ret = dbp->close(dbp,
  125.     dbp->mpf == NULL ? DB_NOSYNC : 0)) != 0 && ret == 0)
  126. ret = t_ret;
  127. }
  128. } else if (DB_UNDO(op) || op == DB_TXN_OPENFILES) {
  129. /*
  130.  * It's a checkpoint and we are rolling backward.  It
  131.  * is possible that the system was shut down and thus
  132.  * ended with a stable checkpoint; this file was never
  133.  * closed and has therefore not been reopened yet.  If
  134.  * so, we need to try to open it.
  135.  */
  136. ret = __log_open_file(dbenv, logp, argp);
  137. if (ret == ENOENT || ret == EINVAL) {
  138. if (argp->name.size != 0 && (ret =
  139.     __db_txnlist_delete(dbenv, info,
  140. argp->name.data, argp->fileid, 0)) != 0)
  141. goto out;
  142. ret = 0;
  143. }
  144. }
  145. out: if (argp != NULL)
  146. __os_free(argp, 0);
  147. return (ret);
  148. }
  149. /*
  150.  * __log_open_file --
  151.  * Called during log_register recovery.  Make sure that we have an
  152.  * entry in the dbentry table for this ndx.  Returns 0 on success,
  153.  * non-zero on error.
  154.  */
  155. static int
  156. __log_open_file(dbenv, lp, argp)
  157. DB_ENV *dbenv;
  158. DB_LOG *lp;
  159. __log_register_args *argp;
  160. {
  161. DB_ENTRY *dbe;
  162. DB *dbp;
  163. /*
  164.  * We never re-open temporary files.  Temp files are only
  165.  * useful during aborts in which case the dbp was entered
  166.  * when the file was registered.  During recovery, we treat
  167.  * temp files as properly deleted files, allowing the open to
  168.  * fail and not reporting any errors when recovery fails to
  169.  * get a valid dbp from db_fileid_to_db.
  170.  */
  171. if (argp->name.size == 0) {
  172. (void)__log_add_logid(dbenv, lp, NULL, argp->fileid);
  173. return (ENOENT);
  174. }
  175. /*
  176.  * Because of reference counting, we cannot automatically close files
  177.  * during recovery, so when we're opening, we have to check that the
  178.  * name we are opening is what we expect.  If it's not, then we close
  179.  * the old file and open the new one.
  180.  */
  181. MUTEX_THREAD_LOCK(dbenv, lp->mutexp);
  182. if (argp->fileid < lp->dbentry_cnt)
  183. dbe = &lp->dbentry[argp->fileid];
  184. else
  185. dbe = NULL;
  186. if (dbe != NULL) {
  187. dbe->deleted = 0;
  188. if ((dbp = TAILQ_FIRST(&dbe->dblist)) != NULL) {
  189. if (dbp->meta_pgno != argp->meta_pgno ||
  190.     memcmp(dbp->fileid,
  191.     argp->uid.data, DB_FILE_ID_LEN) != 0) {
  192. MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
  193. goto reopen;
  194. }
  195. if (!F_ISSET(lp, DBLOG_RECOVER))
  196. dbe->refcount++;
  197. MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
  198. return (0);
  199. }
  200. }
  201. MUTEX_THREAD_UNLOCK(dbenv, lp->mutexp);
  202. if (0) {
  203. reopen: (void)log_unregister(dbp->dbenv, dbp);
  204. (void)__log_rem_logid(lp, dbp, argp->fileid);
  205. dbp->close(dbp, 0);
  206. }
  207. return (__log_do_open(dbenv, lp,
  208.     argp->uid.data, argp->name.data,
  209.     argp->ftype, argp->fileid, argp->meta_pgno));
  210. }
  211. /*
  212.  * log_reopen_file -- close and reopen a db file.
  213.  * Must be called when a metadata page changes.
  214.  *
  215.  * PUBLIC: int __log_reopen_file __P((DB_ENV *,
  216.  * PUBLIC:     char *, int32_t, u_int8_t *, db_pgno_t));
  217.  *
  218.  */
  219. int
  220. __log_reopen_file(dbenv, name, ndx, fileid, meta_pgno)
  221. DB_ENV *dbenv;
  222. char *name;
  223. int32_t ndx;
  224. u_int8_t *fileid;
  225. db_pgno_t meta_pgno;
  226. {
  227. DB *dbp;
  228. DB_LOG *logp;
  229. DBTYPE ftype;
  230. FNAME *fnp;
  231. LOG *lp;
  232. char *tmp_name;
  233. int ret;
  234. logp = dbenv->lg_handle;
  235. if (name == NULL) {
  236. R_LOCK(dbenv, &logp->reginfo);
  237. lp = logp->reginfo.primary;
  238. for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
  239.     fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
  240. if (fnp->ref == 0)      /* Entry not in use. */
  241. continue;
  242. if (memcmp(fnp->ufid, fileid, DB_FILE_ID_LEN) == 0)
  243. break;
  244. }
  245. if (fnp == 0 || fnp->name_off == INVALID_ROFF) {
  246. __db_err(dbenv,
  247.     "metasub recover: non-existent file id");
  248. return (EINVAL);
  249. }
  250. name = R_ADDR(&logp->reginfo, fnp->name_off);
  251. ret = __os_strdup(dbenv, name, &tmp_name);
  252. R_UNLOCK(dbenv, &logp->reginfo);
  253. if (ret != 0)
  254. goto out;
  255. name = tmp_name;
  256. } else
  257. tmp_name = NULL;
  258. if ((ret = __db_fileid_to_db(dbenv, &dbp, ndx, 0)) != 0)
  259. goto out;
  260. ftype = dbp->type;
  261. (void)log_unregister(dbenv, dbp);
  262. (void)__log_rem_logid(logp, dbp, ndx);
  263. (void)dbp->close(dbp, 0);
  264. ret = __log_do_open(dbenv, logp, fileid, name, ftype, ndx, meta_pgno);
  265. if (tmp_name != NULL)
  266. __os_free(tmp_name, 0);
  267. out: return (ret);
  268. }
  269. /*
  270.  * __log_do_open --
  271.  * Open files referenced in the log.  This is the part of the open that
  272.  * is not protected by the thread mutex.
  273.  */
  274. static int
  275. __log_do_open(dbenv, lp, uid, name, ftype, ndx, meta_pgno)
  276. DB_ENV *dbenv;
  277. DB_LOG *lp;
  278. u_int8_t *uid;
  279. char *name;
  280. DBTYPE ftype;
  281. int32_t ndx;
  282. db_pgno_t meta_pgno;
  283. {
  284. DB *dbp;
  285. int ret;
  286. u_int8_t zeroid[DB_FILE_ID_LEN];
  287. if ((ret = db_create(&dbp, lp->dbenv, 0)) != 0)
  288. return (ret);
  289. dbp->log_fileid = ndx;
  290. /*
  291.  * This is needed to signal to the locking routines called while
  292.  * opening databases that we are potentially undoing a transaction
  293.  * from an XA process.  Since the XA process does not share
  294.  * locks with the aborting transaction this prevents us from
  295.  * deadlocking during the open during rollback.
  296.  * Because this routine is called either during recovery or during an
  297.  * XA_ABORT, we can safely set DB_AM_RECOVER in the dbp since it
  298.  * will not be shared with other threads.
  299.  */
  300. F_SET(dbp, DB_AM_RECOVER);
  301. if (meta_pgno != PGNO_BASE_MD)
  302. memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
  303. dbp->type = ftype;
  304. if ((ret =
  305.     __db_dbopen(dbp, name, 0, __db_omode("rw----"), meta_pgno)) == 0) {
  306. /*
  307.  * Verify that we are opening the same file that we were
  308.  * referring to when we wrote this log record.
  309.  */
  310. if (meta_pgno != PGNO_BASE_MD &&
  311.     __log_check_master(dbenv, uid, name) != 0)
  312. goto not_right;
  313. if (memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0) {
  314. memset(zeroid, 0, DB_FILE_ID_LEN);
  315. if (memcmp(dbp->fileid, zeroid, DB_FILE_ID_LEN) != 0)
  316. goto not_right;
  317. memcpy(dbp->fileid, uid, DB_FILE_ID_LEN);
  318. }
  319. if (IS_RECOVERING(dbenv)) {
  320. (void)log_register(dbp->dbenv, dbp, name);
  321. (void)__log_add_logid(dbenv, lp, dbp, ndx);
  322. }
  323. return (0);
  324. }
  325. not_right:
  326. (void)dbp->close(dbp, 0);
  327. (void)__log_add_logid(dbenv, lp, NULL, ndx);
  328. return (ENOENT);
  329. }
  330. static int
  331. __log_check_master(dbenv, uid, name)
  332. DB_ENV *dbenv;
  333. u_int8_t *uid;
  334. char *name;
  335. {
  336. DB *dbp;
  337. int ret;
  338. ret = 0;
  339. if ((ret = db_create(&dbp, dbenv, 0)) != 0)
  340. return (ret);
  341. dbp->type = DB_BTREE;
  342. ret = __db_dbopen(dbp, name, 0, __db_omode("rw----"), PGNO_BASE_MD);
  343. if (ret == 0 && memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0) 
  344. ret = EINVAL;
  345. (void) dbp->close(dbp, 0);
  346. return (ret);
  347. }
  348. /*
  349.  * __log_add_logid --
  350.  * Adds a DB entry to the log's DB entry table.
  351.  *
  352.  * PUBLIC: int __log_add_logid __P((DB_ENV *, DB_LOG *, DB *, int32_t));
  353.  */
  354. int
  355. __log_add_logid(dbenv, logp, dbp, ndx)
  356. DB_ENV *dbenv;
  357. DB_LOG *logp;
  358. DB *dbp;
  359. int32_t ndx;
  360. {
  361. DB *dbtmp;
  362. int32_t i;
  363. int ret;
  364. ret = 0;
  365. MUTEX_THREAD_LOCK(dbenv, logp->mutexp);
  366. /*
  367.  * Check if we need to grow the table.  Note, ndx is 0-based (the
  368.  * index into the DB entry table) an dbentry_cnt is 1-based, the
  369.  * number of available slots.
  370.  */
  371. if (logp->dbentry_cnt <= ndx) {
  372. if ((ret = __os_realloc(dbenv,
  373.     (ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY),
  374.     NULL, &logp->dbentry)) != 0)
  375. goto err;
  376. /*
  377.  * We have moved the head of the queue.
  378.  * Fix up the queue header of an empty queue or the previous
  379.  * pointer of the first element.
  380.  */
  381. for (i = 0; i < logp->dbentry_cnt; i++) {
  382. if ((dbtmp =
  383.     TAILQ_FIRST(&logp->dbentry[i].dblist)) == NULL)
  384. TAILQ_INIT(&logp->dbentry[i].dblist);
  385. else
  386. TAILQ_REINSERT_HEAD(
  387.     &logp->dbentry[i].dblist, dbp, links);
  388. }
  389. /* Initialize the new entries. */
  390. for (i = logp->dbentry_cnt; i < ndx + DB_GROW_SIZE; i++) {
  391. logp->dbentry[i].count = 0;
  392. TAILQ_INIT(&logp->dbentry[i].dblist);
  393. logp->dbentry[i].deleted = 0;
  394. logp->dbentry[i].refcount = 0;
  395. }
  396. logp->dbentry_cnt = i;
  397. }
  398. if (logp->dbentry[ndx].deleted == 0 &&
  399.     TAILQ_FIRST(&logp->dbentry[ndx].dblist) == NULL) {
  400. logp->dbentry[ndx].count = 0;
  401. if (dbp != NULL)
  402. TAILQ_INSERT_HEAD(&logp->dbentry[ndx].dblist,
  403.     dbp, links);
  404. logp->dbentry[ndx].deleted = dbp == NULL;
  405. logp->dbentry[ndx].refcount = 1;
  406. } else if (!F_ISSET(logp, DBLOG_RECOVER)) {
  407. if (dbp != NULL)
  408. TAILQ_INSERT_HEAD(&logp->dbentry[ndx].dblist,
  409.     dbp, links);
  410. logp->dbentry[ndx].refcount++;
  411. }
  412. err: MUTEX_THREAD_UNLOCK(dbenv, logp->mutexp);
  413. return (ret);
  414. }
  415. /*
  416.  * __db_fileid_to_db --
  417.  * Return the DB corresponding to the specified fileid.
  418.  *
  419.  * PUBLIC: int __db_fileid_to_db __P((DB_ENV *, DB **, int32_t, int));
  420.  */
  421. int
  422. __db_fileid_to_db(dbenv, dbpp, ndx, inc)
  423. DB_ENV *dbenv;
  424. DB **dbpp;
  425. int32_t ndx;
  426. int inc;
  427. {
  428. DB_LOG *logp;
  429. DB *dbp;
  430. FNAME *fname;
  431. int ret;
  432. char *name;
  433. ret = 0;
  434. logp = dbenv->lg_handle;
  435. MUTEX_THREAD_LOCK(dbenv, logp->mutexp);
  436. /*
  437.  * Under XA, a process different than the one issuing DB operations
  438.  * may abort a transaction.  In this case, recovery routines are run
  439.  * by a process that does not necessarily have the file open, so we
  440.  * we must open the file explicitly.
  441.  */
  442. if (ndx >= logp->dbentry_cnt ||
  443.     (!logp->dbentry[ndx].deleted &&
  444.     (dbp = TAILQ_FIRST(&logp->dbentry[ndx].dblist)) == NULL)) {
  445. if (F_ISSET(logp, DBLOG_RECOVER)) {
  446. ret = ENOENT;
  447. goto err;
  448. }
  449. if (__log_lid_to_fname(logp, ndx, &fname) != 0) {
  450. /* Couldn't find entry; this is a fatal error. */
  451. __db_err(dbenv, "Missing log fileid entry");
  452. ret = EINVAL;
  453. goto err;
  454. }
  455. name = R_ADDR(&logp->reginfo, fname->name_off);
  456. /*
  457.  * __log_do_open is called without protection of the
  458.  * log thread lock.
  459.  */
  460. MUTEX_THREAD_UNLOCK(dbenv, logp->mutexp);
  461. /*
  462.  * At this point, we are not holding the thread lock, so exit
  463.  * directly instead of going through the exit code at the
  464.  * bottom.  If the __log_do_open succeeded, then we don't need
  465.  * to do any of the remaining error checking at the end of this
  466.  * routine.
  467.  */
  468. if ((ret = __log_do_open(dbenv, logp,
  469.     fname->ufid, name, fname->s_type,
  470.     ndx, fname->meta_pgno)) != 0)
  471. return (ret);
  472. *dbpp = TAILQ_FIRST(&logp->dbentry[ndx].dblist);
  473. return (0);
  474. }
  475. /*
  476.  * Return DB_DELETED if the file has been deleted (it's not an error).
  477.  */
  478. if (logp->dbentry[ndx].deleted) {
  479. ret = DB_DELETED;
  480. if (inc)
  481. logp->dbentry[ndx].count++;
  482. goto err;
  483. }
  484. /*
  485.  * Otherwise return 0, but if we don't have a corresponding DB, it's
  486.  * an error.
  487.  */
  488. if ((*dbpp = TAILQ_FIRST(&logp->dbentry[ndx].dblist)) == NULL)
  489. ret = ENOENT;
  490. err: MUTEX_THREAD_UNLOCK(dbenv, logp->mutexp);
  491. return (ret);
  492. }
  493. /*
  494.  * __log_close_files --
  495.  * Close files that were opened by the recovery daemon.  We sync the
  496.  * file, unless its mpf pointer has been NULLed by a db_remove or
  497.  * db_rename.  We may not have flushed the log_register record that
  498.  * closes the file.
  499.  *
  500.  * PUBLIC: void __log_close_files __P((DB_ENV *));
  501.  */
  502. void
  503. __log_close_files(dbenv)
  504. DB_ENV *dbenv;
  505. {
  506. DB_ENTRY *dbe;
  507. DB_LOG *logp;
  508. DB *dbp;
  509. int32_t i;
  510. logp = dbenv->lg_handle;
  511. MUTEX_THREAD_LOCK(dbenv, logp->mutexp);
  512. for (i = 0; i < logp->dbentry_cnt; i++) {
  513. dbe = &logp->dbentry[i];
  514. while ((dbp = TAILQ_FIRST(&dbe->dblist)) != NULL) {
  515. (void)log_unregister(dbenv, dbp);
  516. TAILQ_REMOVE(&dbe->dblist, dbp, links);
  517. (void)dbp->close(dbp, dbp->mpf == NULL ? DB_NOSYNC : 0);
  518. }
  519. dbe->deleted = 0;
  520. dbe->refcount = 0;
  521. }
  522. MUTEX_THREAD_UNLOCK(dbenv, logp->mutexp);
  523. }
  524. /*
  525.  * __log_rem_logid
  526.  * Remove an entry from the log table.  Find the appropriate DB and
  527.  * unlink it from the linked list off the table.  If the DB is NULL, treat
  528.  * this as a simple refcount decrement.
  529.  *
  530.  * PUBLIC: void __log_rem_logid __P((DB_LOG *, DB *, int32_t));
  531.  */
  532. void
  533. __log_rem_logid(logp, dbp, ndx)
  534. DB_LOG *logp;
  535. DB *dbp;
  536. int32_t ndx;
  537. {
  538. DB *xdbp;
  539. MUTEX_THREAD_LOCK(logp->dbenv, logp->mutexp);
  540. if (--logp->dbentry[ndx].refcount == 0) {
  541. TAILQ_INIT(&logp->dbentry[ndx].dblist);
  542. logp->dbentry[ndx].deleted = 0;
  543. } else if (dbp != NULL)
  544. for (xdbp = TAILQ_FIRST(&logp->dbentry[ndx].dblist);
  545.     xdbp != NULL;
  546.     xdbp = TAILQ_NEXT(xdbp, links))
  547. if (xdbp == dbp) {
  548. TAILQ_REMOVE(&logp->dbentry[ndx].dblist,
  549.     xdbp, links);
  550. break;
  551. }
  552. MUTEX_THREAD_UNLOCK(logp->dbenv, logp->mutexp);
  553. }
  554. /*
  555.  * __log_lid_to_fname --
  556.  * Traverse the shared-memory region looking for the entry that
  557.  * matches the passed log fileid.  Returns 0 on success; -1 on error.
  558.  * PUBLIC: int __log_lid_to_fname __P((DB_LOG *, int32_t, FNAME **));
  559.  */
  560. int
  561. __log_lid_to_fname(dblp, lid, fnamep)
  562. DB_LOG *dblp;
  563. int32_t lid;
  564. FNAME **fnamep;
  565. {
  566. FNAME *fnp;
  567. LOG *lp;
  568. lp = dblp->reginfo.primary;
  569. for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname);
  570.     fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) {
  571. if (fnp->ref == 0) /* Entry not in use. */
  572. continue;
  573. if (fnp->id == lid) {
  574. *fnamep = fnp;
  575. return (0);
  576. }
  577. }
  578. return (-1);
  579. }