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 #include "config.h" 00008 00009 #ifndef lint 00010 static const char revid[] = "$Id: log__put_8c-source.html,v 1.1 2008年06月08日 10:20:26 sebdiaz Exp $"; 00011 #endif /* not lint */ 00012 00013 #ifndef NO_SYSTEM_INCLUDES 00014 #include <sys/types.h> 00015 00016 #if TIME_WITH_SYS_TIME 00017 #include <sys/time.h> 00018 #include <time.h> 00019 #else 00020 #if HAVE_SYS_TIME_H 00021 #include <sys/time.h> 00022 #else 00023 #include <time.h> 00024 #endif 00025 #endif 00026 00027 #include <errno.h> 00028 #include <stdio.h> 00029 #include <string.h> 00030 #include <unistd.h> 00031 #endif 00032 00033 #ifdef HAVE_RPC 00034 #include "db_server.h" 00035 #endif 00036 00037 #include "db_int.h" 00038 #include "db_page.h" 00039 #include "log.h" 00040 #include "hash.h" 00041 00042 #ifdef HAVE_RPC 00043 #include "gen_client_ext.h" 00044 #include "rpc_client_ext.h" 00045 #endif 00046 00047 static int __log_fill __P((DB_LOG *, DB_LSN *, void *, u_int32_t)); 00048 static int __log_flush __P((DB_LOG *, const DB_LSN *)); 00049 static int __log_newfh __P((DB_LOG *)); 00050 static int __log_putr __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t)); 00051 static int __log_open_files __P((DB_ENV *)); 00052 static int __log_write __P((DB_LOG *, void *, u_int32_t)); 00053 00054 /* 00055 * CDB_log_put -- 00056 * Write a log record. 00057 */ 00058 int 00059 CDB_log_put(dbenv, lsn, dbt, flags) 00060 DB_ENV *dbenv; 00061 DB_LSN *lsn; 00062 const DBT *dbt; 00063 u_int32_t flags; 00064 { 00065 DB_LOG *dblp; 00066 int ret; 00067 00068 #ifdef HAVE_RPC 00069 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) 00070 return (__dbcl_log_put(dbenv, lsn, dbt, flags)); 00071 #endif 00072 00073 PANIC_CHECK(dbenv); 00074 ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG); 00075 00076 /* Validate arguments. */ 00077 if (flags != 0 && flags != DB_CHECKPOINT && 00078 flags != DB_CURLSN && flags != DB_FLUSH) 00079 return (CDB___db_ferr(dbenv, "CDB_log_put", 0)); 00080 00081 dblp = dbenv->lg_handle; 00082 R_LOCK(dbenv, &dblp->reginfo); 00083 ret = CDB___log_put(dbenv, lsn, dbt, flags); 00084 R_UNLOCK(dbenv, &dblp->reginfo); 00085 return (ret); 00086 } 00087 00088 /* 00089 * CDB___log_put -- 00090 * Write a log record; internal version. 00091 * 00092 * PUBLIC: int CDB___log_put __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t)); 00093 */ 00094 int 00095 CDB___log_put(dbenv, lsn, dbt, flags) 00096 DB_ENV *dbenv; 00097 DB_LSN *lsn; 00098 const DBT *dbt; 00099 u_int32_t flags; 00100 { 00101 DBT t; 00102 DB_LOG *dblp; 00103 LOG *lp; 00104 u_int32_t lastoff; 00105 int ret; 00106 00107 dblp = dbenv->lg_handle; 00108 lp = dblp->reginfo.primary; 00109 00110 /* 00111 * If the application just wants to know where we are, fill in 00112 * the information. Currently used by the transaction manager 00113 * to avoid writing TXN_begin records. 00114 */ 00115 if (flags == DB_CURLSN) { 00116 lsn->file = lp->lsn.file; 00117 lsn->offset = lp->lsn.offset; 00118 return (0); 00119 } 00120 00121 /* If this information won't fit in the file, swap files. */ 00122 if (lp->lsn.offset + sizeof(HDR) + dbt->size > lp->persist.lg_max) { 00123 if (sizeof(HDR) + 00124 sizeof(LOGP) + dbt->size > lp->persist.lg_max) { 00125 CDB___db_err(dbenv, 00126 "CDB_log_put: record larger than maximum file size"); 00127 return (EINVAL); 00128 } 00129 00130 /* Flush the log. */ 00131 if ((ret = __log_flush(dblp, NULL)) != 0) 00132 return (ret); 00133 00134 /* 00135 * Save the last known offset from the previous file, we'll 00136 * need it to initialize the persistent header information. 00137 */ 00138 lastoff = lp->lsn.offset; 00139 00140 /* Point the current LSN to the new file. */ 00141 ++lp->lsn.file; 00142 lp->lsn.offset = 0; 00143 00144 /* Reset the file write offset. */ 00145 lp->w_off = 0; 00146 } else 00147 lastoff = 0; 00148 00149 /* Initialize the LSN information returned to the user. */ 00150 lsn->file = lp->lsn.file; 00151 lsn->offset = lp->lsn.offset; 00152 00153 /* 00154 * Insert persistent information as the first record in every file. 00155 * Note that the previous length is wrong for the very first record 00156 * of the log, but that's okay, we check for it during retrieval. 00157 */ 00158 if (lp->lsn.offset == 0) { 00159 t.data = &lp->persist; 00160 t.size = sizeof(LOGP); 00161 if ((ret = __log_putr(dblp, lsn, 00162 &t, lastoff == 0 ? 0 : lastoff - lp->len)) != 0) 00163 return (ret); 00164 00165 /* Record files open in this log. */ 00166 if ((ret = __log_open_files(dbenv)) != 0) 00167 return (ret); 00168 00169 /* Update the LSN information returned to the user. */ 00170 lsn->file = lp->lsn.file; 00171 lsn->offset = lp->lsn.offset; 00172 } 00173 00174 /* Write the application's log record. */ 00175 if ((ret = __log_putr(dblp, lsn, dbt, lp->lsn.offset - lp->len)) != 0) 00176 return (ret); 00177 00178 /* 00179 * On a checkpoint, we: 00180 * Put out the checkpoint record (above). 00181 * Save the LSN of the checkpoint in the shared region. 00182 * Append the set of file name information into the log. 00183 */ 00184 if (flags == DB_CHECKPOINT) { 00185 lp->chkpt_lsn = *lsn; 00186 if ((ret = __log_open_files(dbenv)) != 0) 00187 return (ret); 00188 } 00189 00190 /* 00191 * On a checkpoint or when flush is requested, we: 00192 * Flush the current buffer contents to disk. 00193 * Sync the log to disk. 00194 */ 00195 if (flags == DB_FLUSH || flags == DB_CHECKPOINT) 00196 if ((ret = __log_flush(dblp, NULL)) != 0) 00197 return (ret); 00198 00199 /* 00200 * On a checkpoint, we: 00201 * Save the time the checkpoint was written. 00202 * Reset the bytes written since the last checkpoint. 00203 */ 00204 if (flags == DB_CHECKPOINT) { 00205 (void)time(&lp->chkpt); 00206 lp->stat.st_wc_bytes = lp->stat.st_wc_mbytes = 0; 00207 } 00208 return (0); 00209 } 00210 00211 /* 00212 * __log_putr -- 00213 * Actually put a record into the log. 00214 */ 00215 static int 00216 __log_putr(dblp, lsn, dbt, prev) 00217 DB_LOG *dblp; 00218 DB_LSN *lsn; 00219 const DBT *dbt; 00220 u_int32_t prev; 00221 { 00222 HDR hdr; 00223 LOG *lp; 00224 int ret; 00225 00226 lp = dblp->reginfo.primary; 00227 00228 /* 00229 * Initialize the header. If we just switched files, lsn.offset will 00230 * be 0, and what we really want is the offset of the previous record 00231 * in the previous file. Fortunately, prev holds the value we want. 00232 */ 00233 hdr.prev = prev; 00234 hdr.len = sizeof(HDR) + dbt->size; 00235 hdr.cksum = CDB___ham_func4(dbt->data, dbt->size); 00236 00237 if ((ret = __log_fill(dblp, lsn, &hdr, sizeof(HDR))) != 0) 00238 return (ret); 00239 lp->len = sizeof(HDR); 00240 lp->lsn.offset += sizeof(HDR); 00241 00242 if ((ret = __log_fill(dblp, lsn, dbt->data, dbt->size)) != 0) 00243 return (ret); 00244 lp->len += dbt->size; 00245 lp->lsn.offset += dbt->size; 00246 return (0); 00247 } 00248 00249 /* 00250 * CDB_log_flush -- 00251 * Write all records less than or equal to the specified LSN. 00252 */ 00253 int 00254 CDB_log_flush(dbenv, lsn) 00255 DB_ENV *dbenv; 00256 const DB_LSN *lsn; 00257 { 00258 DB_LOG *dblp; 00259 int ret; 00260 00261 #ifdef HAVE_RPC 00262 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) 00263 return (__dbcl_log_flush(dbenv, lsn)); 00264 #endif 00265 00266 PANIC_CHECK(dbenv); 00267 ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG); 00268 00269 dblp = dbenv->lg_handle; 00270 R_LOCK(dbenv, &dblp->reginfo); 00271 ret = __log_flush(dblp, lsn); 00272 R_UNLOCK(dbenv, &dblp->reginfo); 00273 return (ret); 00274 } 00275 00276 /* 00277 * __log_flush -- 00278 * Write all records less than or equal to the specified LSN; internal 00279 * version. 00280 */ 00281 static int 00282 __log_flush(dblp, lsn) 00283 DB_LOG *dblp; 00284 const DB_LSN *lsn; 00285 { 00286 DB_LSN t_lsn; 00287 LOG *lp; 00288 int current, ret; 00289 00290 ret = 0; 00291 lp = dblp->reginfo.primary; 00292 00293 /* 00294 * If no LSN specified, flush the entire log by setting the flush LSN 00295 * to the last LSN written in the log. Otherwise, check that the LSN 00296 * isn't a non-existent record for the log. 00297 */ 00298 if (lsn == NULL) { 00299 t_lsn.file = lp->lsn.file; 00300 t_lsn.offset = lp->lsn.offset - lp->len; 00301 lsn = &t_lsn; 00302 } else 00303 if (lsn->file > lp->lsn.file || 00304 (lsn->file == lp->lsn.file && 00305 lsn->offset > lp->lsn.offset - lp->len)) { 00306 CDB___db_err(dblp->dbenv, 00307 "CDB_log_flush: LSN past current end-of-log"); 00308 return (EINVAL); 00309 } 00310 00311 /* 00312 * If the LSN is less than or equal to the last-sync'd LSN, we're 00313 * done. Note, the last-sync LSN saved in s_lsn is the LSN of the 00314 * first byte we absolutely know has been written to disk, so the 00315 * test is <=. 00316 */ 00317 if (lsn->file < lp->s_lsn.file || 00318 (lsn->file == lp->s_lsn.file && lsn->offset <= lp->s_lsn.offset)) 00319 return (0); 00320 00321 /* 00322 * We may need to write the current buffer. We have to write the 00323 * current buffer if the flush LSN is greater than or equal to the 00324 * buffer's starting LSN. 00325 */ 00326 current = 0; 00327 if (lp->b_off != 0 && CDB_log_compare(lsn, &lp->f_lsn) >= 0) { 00328 if ((ret = __log_write(dblp, dblp->bufp, lp->b_off)) != 0) 00329 return (ret); 00330 00331 lp->b_off = 0; 00332 current = 1; 00333 } 00334 00335 /* 00336 * It's possible that this thread may never have written to this log 00337 * file. Acquire a file descriptor if we don't already have one. 00338 * One last check -- if we're not writing anything from the current 00339 * buffer, don't bother. We have nothing to write and nothing to 00340 * sync. 00341 */ 00342 if (dblp->lfname != lp->lsn.file) { 00343 if (!current) 00344 return (0); 00345 if ((ret = __log_newfh(dblp)) != 0) 00346 return (ret); 00347 } 00348 00349 /* Sync all writes to disk. */ 00350 if ((ret = CDB___os_fsync(dblp->dbenv, &dblp->lfh)) != 0) { 00351 CDB___db_panic(dblp->dbenv, ret); 00352 return (ret); 00353 } 00354 ++lp->stat.st_scount; 00355 00356 /* 00357 * Set the last-synced LSN, using the LSN of the current buffer. If 00358 * the current buffer was flushed, we know the LSN of the first byte 00359 * of the buffer is on disk, otherwise, we only know that the LSN of 00360 * the record before the one beginning the current buffer is on disk. 00361 * 00362 * Check to be sure the saved lsn isn't 0 before decrementing it. If 00363 * DB_CHECKPOINT was called before we wrote any log records, you can 00364 * end up here without ever having written anything to a log file, and 00365 * decrementing s_lsn.file or s_lsn.offset will cause much sadness. 00366 */ 00367 lp->s_lsn = lp->f_lsn; 00368 if (!current && lp->s_lsn.file != 0) { 00369 if (lp->s_lsn.offset == 0) { 00370 --lp->s_lsn.file; 00371 lp->s_lsn.offset = lp->persist.lg_max; 00372 } else 00373 --lp->s_lsn.offset; 00374 } 00375 00376 return (0); 00377 } 00378 00379 /* 00380 * __log_fill -- 00381 * Write information into the log. 00382 */ 00383 static int 00384 __log_fill(dblp, lsn, addr, len) 00385 DB_LOG *dblp; 00386 DB_LSN *lsn; 00387 void *addr; 00388 u_int32_t len; 00389 { 00390 LOG *lp; 00391 u_int32_t bsize, nrec; 00392 size_t nw, remain; 00393 int ret; 00394 00395 lp = dblp->reginfo.primary; 00396 bsize = lp->buffer_size; 00397 00398 while (len > 0) { /* Copy out the data. */ 00399 /* 00400 * If we're beginning a new buffer, note the user LSN to which 00401 * the first byte of the buffer belongs. We have to know this 00402 * when flushing the buffer so that we know if the in-memory 00403 * buffer needs to be flushed. 00404 */ 00405 if (lp->b_off == 0) 00406 lp->f_lsn = *lsn; 00407 00408 /* 00409 * If we're on a buffer boundary and the data is big enough, 00410 * copy as many records as we can directly from the data. 00411 */ 00412 if (lp->b_off == 0 && len >= bsize) { 00413 nrec = len / bsize; 00414 if ((ret = __log_write(dblp, addr, nrec * bsize)) != 0) 00415 return (ret); 00416 addr = (u_int8_t *)addr + nrec * bsize; 00417 len -= nrec * bsize; 00418 ++lp->stat.st_wcount_fill; 00419 continue; 00420 } 00421 00422 /* Figure out how many bytes we can copy this time. */ 00423 remain = bsize - lp->b_off; 00424 nw = remain > len ? len : remain; 00425 memcpy(dblp->bufp + lp->b_off, addr, nw); 00426 addr = (u_int8_t *)addr + nw; 00427 len -= nw; 00428 lp->b_off += nw; 00429 00430 /* If we fill the buffer, flush it. */ 00431 if (lp->b_off == bsize) { 00432 if ((ret = __log_write(dblp, dblp->bufp, bsize)) != 0) 00433 return (ret); 00434 lp->b_off = 0; 00435 ++lp->stat.st_wcount_fill; 00436 } 00437 } 00438 return (0); 00439 } 00440 00441 /* 00442 * __log_write -- 00443 * Write the log buffer to disk. 00444 */ 00445 static int 00446 __log_write(dblp, addr, len) 00447 DB_LOG *dblp; 00448 void *addr; 00449 u_int32_t len; 00450 { 00451 LOG *lp; 00452 size_t nw; 00453 int ret; 00454 00455 /* 00456 * If we haven't opened the log file yet or the current one 00457 * has changed, acquire a new log file. 00458 */ 00459 lp = dblp->reginfo.primary; 00460 if (!F_ISSET(&dblp->lfh, DB_FH_VALID) || dblp->lfname != lp->lsn.file) 00461 if ((ret = __log_newfh(dblp)) != 0) 00462 return (ret); 00463 00464 /* 00465 * Seek to the offset in the file (someone may have written it 00466 * since we last did). 00467 */ 00468 if ((ret = 00469 CDB___os_seek(dblp->dbenv, 00470 &dblp->lfh, 0, 0, lp->w_off, 0, DB_OS_SEEK_SET)) != 0 || 00471 (ret = CDB___os_write(dblp->dbenv, &dblp->lfh, addr, len, &nw)) != 0) { 00472 CDB___db_panic(dblp->dbenv, ret); 00473 return (ret); 00474 } 00475 if (nw != len) { 00476 CDB___db_err(dblp->dbenv, "Short write while writing log"); 00477 return (EIO); 00478 } 00479 00480 /* Reset the buffer offset and update the seek offset. */ 00481 lp->w_off += len; 00482 00483 /* Update written statistics. */ 00484 if ((lp->stat.st_w_bytes += len) >= MEGABYTE) { 00485 lp->stat.st_w_bytes -= MEGABYTE; 00486 ++lp->stat.st_w_mbytes; 00487 } 00488 if ((lp->stat.st_wc_bytes += len) >= MEGABYTE) { 00489 lp->stat.st_wc_bytes -= MEGABYTE; 00490 ++lp->stat.st_wc_mbytes; 00491 } 00492 ++lp->stat.st_wcount; 00493 00494 return (0); 00495 } 00496 00497 /* 00498 * CDB_log_file -- 00499 * Map a DB_LSN to a file name. 00500 */ 00501 int 00502 CDB_log_file(dbenv, lsn, namep, len) 00503 DB_ENV *dbenv; 00504 const DB_LSN *lsn; 00505 char *namep; 00506 size_t len; 00507 { 00508 DB_LOG *dblp; 00509 int ret; 00510 char *name; 00511 00512 #ifdef HAVE_RPC 00513 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) 00514 return (__dbcl_log_file(dbenv, lsn, namep, len)); 00515 #endif 00516 00517 PANIC_CHECK(dbenv); 00518 ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, DB_INIT_LOG); 00519 00520 dblp = dbenv->lg_handle; 00521 R_LOCK(dbenv, &dblp->reginfo); 00522 ret = CDB___log_name(dblp, lsn->file, &name, NULL, 0); 00523 R_UNLOCK(dbenv, &dblp->reginfo); 00524 if (ret != 0) 00525 return (ret); 00526 00527 /* Check to make sure there's enough room and copy the name. */ 00528 if (len < strlen(name) + 1) { 00529 *namep = '0円'; 00530 CDB___db_err(dbenv, "CDB_log_file: name buffer is too short"); 00531 return (EINVAL); 00532 } 00533 (void)strcpy(namep, name); 00534 CDB___os_freestr(name); 00535 00536 return (0); 00537 } 00538 00539 /* 00540 * __log_newfh -- 00541 * Acquire a file handle for the current log file. 00542 */ 00543 static int 00544 __log_newfh(dblp) 00545 DB_LOG *dblp; 00546 { 00547 LOG *lp; 00548 int ret; 00549 char *name; 00550 00551 /* Close any previous file descriptor. */ 00552 if (F_ISSET(&dblp->lfh, DB_FH_VALID)) 00553 (void)CDB___os_closehandle(&dblp->lfh); 00554 00555 /* Get the path of the new file and open it. */ 00556 lp = dblp->reginfo.primary; 00557 dblp->lfname = lp->lsn.file; 00558 00559 /* Adding DB_OSO_LOG to the flags may cause additional 00560 * platform-specific optimizations. On WinNT, the logfile 00561 * is preallocated, which may have a time penalty at startup, 00562 * but may lead to overall better throughput. We are not 00563 * certain that this works reliably, so enable at your own risk. 00564 */ 00565 if ((ret = CDB___log_name(dblp, dblp->lfname, 00566 &name, &dblp->lfh, 00567 DB_OSO_CREATE |/* DB_OSO_LOG |*/ DB_OSO_SEQ)) != 0) 00568 CDB___db_err(dblp->dbenv, 00569 "CDB_log_put: %s: %s", name, CDB_db_strerror(ret)); 00570 00571 CDB___os_freestr(name); 00572 return (ret); 00573 } 00574 00575 /* 00576 * CDB___log_name -- 00577 * Return the log name for a particular file, and optionally open it. 00578 * 00579 * PUBLIC: int CDB___log_name __P((DB_LOG *, 00580 * PUBLIC: u_int32_t, char **, DB_FH *, u_int32_t)); 00581 */ 00582 int 00583 CDB___log_name(dblp, filenumber, namep, fhp, flags) 00584 DB_LOG *dblp; 00585 u_int32_t filenumber, flags; 00586 char **namep; 00587 DB_FH *fhp; 00588 { 00589 LOG *lp; 00590 int ret; 00591 char *oname; 00592 char old[sizeof(LFPREFIX) + 5 + 20], new[sizeof(LFPREFIX) + 10 + 20]; 00593 00594 lp = dblp->reginfo.primary; 00595 00596 /* 00597 * !!! 00598 * The semantics of this routine are bizarre. 00599 * 00600 * The reason for all of this is that we need a place where we can 00601 * intercept requests for log files, and, if appropriate, check for 00602 * both the old-style and new-style log file names. The trick is 00603 * that all callers of this routine that are opening the log file 00604 * read-only want to use an old-style file name if they can't find 00605 * a match using a new-style name. The only down-side is that some 00606 * callers may check for the old-style when they really don't need 00607 * to, but that shouldn't mess up anything, and we only check for 00608 * the old-style name when we've already failed to find a new-style 00609 * one. 00610 * 00611 * Create a new-style file name, and if we're not going to open the 00612 * file, return regardless. 00613 */ 00614 (void)snprintf(new, sizeof(new), LFNAME, filenumber); 00615 if ((ret = CDB___db_appname(dblp->dbenv, 00616 DB_APP_LOG, NULL, new, 0, NULL, namep)) != 0 || fhp == NULL) 00617 return (ret); 00618 00619 /* Open the new-style file -- if we succeed, we're done. */ 00620 if ((ret = CDB___os_open(dblp->dbenv, 00621 *namep, flags, lp->persist.mode, fhp)) == 0) 00622 return (0); 00623 00624 /* 00625 * The open failed... if the DB_RDONLY flag isn't set, we're done, 00626 * the caller isn't interested in old-style files. 00627 */ 00628 if (!LF_ISSET(DB_OSO_RDONLY)) { 00629 CDB___db_err(dblp->dbenv, 00630 "%s: log file open failed: %s", *namep, CDB_db_strerror(ret)); 00631 CDB___db_panic(dblp->dbenv, ret); 00632 return (ret); 00633 } 00634 00635 /* Create an old-style file name. */ 00636 (void)snprintf(old, sizeof(old), LFNAME_V1, filenumber); 00637 if ((ret = CDB___db_appname(dblp->dbenv, 00638 DB_APP_LOG, NULL, old, 0, NULL, &oname)) != 0) 00639 goto err; 00640 00641 /* 00642 * Open the old-style file -- if we succeed, we're done. Free the 00643 * space allocated for the new-style name and return the old-style 00644 * name to the caller. 00645 */ 00646 if ((ret = CDB___os_open(dblp->dbenv, 00647 oname, flags, lp->persist.mode, fhp)) == 0) { 00648 CDB___os_freestr(*namep); 00649 *namep = oname; 00650 return (0); 00651 } 00652 00653 /* 00654 * Couldn't find either style of name -- return the new-style name 00655 * for the caller's error message. If it's an old-style name that's 00656 * actually missing we're going to confuse the user with the error 00657 * message, but that implies that not only were we looking for an 00658 * old-style name, but we expected it to exist and we weren't just 00659 * looking for any log file. That's not a likely error. 00660 */ 00661 err: CDB___os_freestr(oname); 00662 return (ret); 00663 } 00664 00665 static int 00666 __log_open_files(dbenv) 00667 DB_ENV *dbenv; 00668 { 00669 DB_LOG *dblp; 00670 DB_LSN r_unused; 00671 DBT fid_dbt, t; 00672 FNAME *fnp; 00673 LOG *lp; 00674 int ret; 00675 00676 dblp = dbenv->lg_handle; 00677 lp = dblp->reginfo.primary; 00678 00679 for (fnp = SH_TAILQ_FIRST(&lp->fq, __fname); 00680 fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) { 00681 if (fnp->ref == 0) /* Entry not in use. */ 00682 continue; 00683 if (fnp->name_off != INVALID_ROFF) { 00684 memset(&t, 0, sizeof(t)); 00685 t.data = R_ADDR(&dblp->reginfo, fnp->name_off); 00686 t.size = strlen(t.data) + 1; 00687 } 00688 memset(&fid_dbt, 0, sizeof(fid_dbt)); 00689 fid_dbt.data = fnp->ufid; 00690 fid_dbt.size = DB_FILE_ID_LEN; 00691 if ((ret = CDB___log_register_log(dbenv, 00692 NULL, &r_unused, 0, LOG_CHECKPOINT, 00693 fnp->name_off == INVALID_ROFF ? NULL : &t, 00694 &fid_dbt, fnp->id, fnp->s_type, fnp->meta_pgno)) != 0) 00695 return (ret); 00696 } 00697 return (0); 00698 }