1*7c478bd9Sstevel@tonic-gate /*- 2*7c478bd9Sstevel@tonic-gate * See the file LICENSE for redistribution information. 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * Copyright (c) 1996, 1997, 1998 5*7c478bd9Sstevel@tonic-gate * Sleepycat Software. All rights reserved. 6*7c478bd9Sstevel@tonic-gate */ 7*7c478bd9Sstevel@tonic-gate /* 8*7c478bd9Sstevel@tonic-gate * Copyright (c) 1995, 1996 9*7c478bd9Sstevel@tonic-gate * The President and Fellows of Harvard University. All rights reserved. 10*7c478bd9Sstevel@tonic-gate * 11*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 12*7c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 13*7c478bd9Sstevel@tonic-gate * are met: 14*7c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 15*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 16*7c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 17*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 18*7c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 19*7c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 20*7c478bd9Sstevel@tonic-gate * must display the following acknowledgement: 21*7c478bd9Sstevel@tonic-gate * This product includes software developed by the University of 22*7c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors. 23*7c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 24*7c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 25*7c478bd9Sstevel@tonic-gate * without specific prior written permission. 26*7c478bd9Sstevel@tonic-gate * 27*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28*7c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30*7c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31*7c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32*7c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33*7c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34*7c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35*7c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36*7c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37*7c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #include "config.h" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #ifndef lint 43*7c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)log_rec.c 10.26 (Sleepycat) 10/21/98"; 44*7c478bd9Sstevel@tonic-gate #endif /* not lint */ 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #ifndef NO_SYSTEM_INCLUDES 47*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #include <errno.h> 50*7c478bd9Sstevel@tonic-gate #include <string.h> 51*7c478bd9Sstevel@tonic-gate #endif 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #include "db_int.h" 54*7c478bd9Sstevel@tonic-gate #include "shqueue.h" 55*7c478bd9Sstevel@tonic-gate #include "log.h" 56*7c478bd9Sstevel@tonic-gate #include "db_dispatch.h" 57*7c478bd9Sstevel@tonic-gate #include "common_ext.h" 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate static int __log_do_open __P((DB_LOG *, 60*7c478bd9Sstevel@tonic-gate u_int8_t *, char *, DBTYPE, u_int32_t)); 61*7c478bd9Sstevel@tonic-gate static int __log_lid_to_fname __P((DB_LOG *, u_int32_t, FNAME **)); 62*7c478bd9Sstevel@tonic-gate static int __log_open_file __P((DB_LOG *, __log_register_args *)); 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* 65*7c478bd9Sstevel@tonic-gate * PUBLIC: int __log_register_recover 66*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 67*7c478bd9Sstevel@tonic-gate */ 68*7c478bd9Sstevel@tonic-gate int 69*7c478bd9Sstevel@tonic-gate __log_register_recover(logp, dbtp, lsnp, redo, info) 70*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 71*7c478bd9Sstevel@tonic-gate DBT *dbtp; 72*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 73*7c478bd9Sstevel@tonic-gate int redo; 74*7c478bd9Sstevel@tonic-gate void *info; 75*7c478bd9Sstevel@tonic-gate { 76*7c478bd9Sstevel@tonic-gate DB_ENTRY *dbe; 77*7c478bd9Sstevel@tonic-gate __log_register_args *argp; 78*7c478bd9Sstevel@tonic-gate int ret; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate #ifdef DEBUG_RECOVER 81*7c478bd9Sstevel@tonic-gate __log_register_print(logp, dbtp, lsnp, redo, info); 82*7c478bd9Sstevel@tonic-gate #endif 83*7c478bd9Sstevel@tonic-gate COMPQUIET(info, NULL); 84*7c478bd9Sstevel@tonic-gate COMPQUIET(lsnp, NULL); 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate F_SET(logp, DBC_RECOVER); 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate if ((ret = __log_register_read(dbtp->data, &argp)) != 0) 89*7c478bd9Sstevel@tonic-gate goto out; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate if ((argp->opcode == LOG_CHECKPOINT && redo == TXN_OPENFILES) || 92*7c478bd9Sstevel@tonic-gate (argp->opcode == LOG_OPEN && 93*7c478bd9Sstevel@tonic-gate (redo == TXN_REDO || redo == TXN_OPENFILES || 94*7c478bd9Sstevel@tonic-gate redo == TXN_FORWARD_ROLL)) || 95*7c478bd9Sstevel@tonic-gate (argp->opcode == LOG_CLOSE && 96*7c478bd9Sstevel@tonic-gate (redo == TXN_UNDO || redo == TXN_BACKWARD_ROLL))) { 97*7c478bd9Sstevel@tonic-gate /* 98*7c478bd9Sstevel@tonic-gate * If we are redoing an open or undoing a close, then we need 99*7c478bd9Sstevel@tonic-gate * to open a file. 100*7c478bd9Sstevel@tonic-gate */ 101*7c478bd9Sstevel@tonic-gate ret = __log_open_file(logp, argp); 102*7c478bd9Sstevel@tonic-gate if (ret == ENOENT) { 103*7c478bd9Sstevel@tonic-gate if (redo == TXN_OPENFILES) 104*7c478bd9Sstevel@tonic-gate __db_err(logp->dbenv, "warning: %s: %s", 105*7c478bd9Sstevel@tonic-gate argp->name.data, strerror(ENOENT)); 106*7c478bd9Sstevel@tonic-gate ret = 0; 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate } else if (argp->opcode != LOG_CHECKPOINT && 109*7c478bd9Sstevel@tonic-gate argp->opcode != LOG_CLOSE) { 110*7c478bd9Sstevel@tonic-gate /* 111*7c478bd9Sstevel@tonic-gate * If we are undoing an open, then we need to close the file. 112*7c478bd9Sstevel@tonic-gate * Note that we do *not* close the file if we are redoing a 113*7c478bd9Sstevel@tonic-gate * close, because we do not log the reference counts on log 114*7c478bd9Sstevel@tonic-gate * files and we may have had the file open multiple times, 115*7c478bd9Sstevel@tonic-gate * and therefore, this close should just dec a reference 116*7c478bd9Sstevel@tonic-gate * count. However, since we only do one open during a 117*7c478bd9Sstevel@tonic-gate * checkpoint, this will inadvertently close the file. 118*7c478bd9Sstevel@tonic-gate * 119*7c478bd9Sstevel@tonic-gate * If the file is deleted, then we can just ignore this close. 120*7c478bd9Sstevel@tonic-gate * Otherwise, we should usually have a valid dbp we should 121*7c478bd9Sstevel@tonic-gate * close or whose reference count should be decremented. 122*7c478bd9Sstevel@tonic-gate * However, if we shut down without closing a file, we 123*7c478bd9Sstevel@tonic-gate * may, in fact, not have the file open, and that's OK. 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate LOCK_LOGTHREAD(logp); 126*7c478bd9Sstevel@tonic-gate if (argp->id < logp->dbentry_cnt) { 127*7c478bd9Sstevel@tonic-gate dbe = &logp->dbentry[argp->id]; 128*7c478bd9Sstevel@tonic-gate if (dbe->dbp != NULL && --dbe->refcount == 0) { 129*7c478bd9Sstevel@tonic-gate ret = dbe->dbp->close(dbe->dbp, 0); 130*7c478bd9Sstevel@tonic-gate if (dbe->name != NULL) { 131*7c478bd9Sstevel@tonic-gate __os_freestr(dbe->name); 132*7c478bd9Sstevel@tonic-gate dbe->name = NULL; 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate (void)__log_rem_logid(logp, argp->id); 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate UNLOCK_LOGTHREAD(logp); 138*7c478bd9Sstevel@tonic-gate } else if (argp->opcode == LOG_CHECKPOINT && redo == TXN_UNDO && 139*7c478bd9Sstevel@tonic-gate (argp->id >= logp->dbentry_cnt || 140*7c478bd9Sstevel@tonic-gate (!logp->dbentry[argp->id].deleted && 141*7c478bd9Sstevel@tonic-gate logp->dbentry[argp->id].dbp == NULL))) { 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * It's a checkpoint and we are rolling backward. It 144*7c478bd9Sstevel@tonic-gate * is possible that the system was shut down and thus 145*7c478bd9Sstevel@tonic-gate * ended with a stable checkpoint; this file was never 146*7c478bd9Sstevel@tonic-gate * closed and has therefore not been reopened yet. If 147*7c478bd9Sstevel@tonic-gate * so, we need to try to open it. 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate ret = __log_open_file(logp, argp); 150*7c478bd9Sstevel@tonic-gate if (ret == ENOENT) { 151*7c478bd9Sstevel@tonic-gate __db_err(logp->dbenv, "warning: %s: %s", 152*7c478bd9Sstevel@tonic-gate argp->name.data, strerror(ENOENT)); 153*7c478bd9Sstevel@tonic-gate ret = 0; 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate out: F_CLR(logp, DBC_RECOVER); 158*7c478bd9Sstevel@tonic-gate if (argp != NULL) 159*7c478bd9Sstevel@tonic-gate __os_free(argp, 0); 160*7c478bd9Sstevel@tonic-gate return (ret); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* Hand coded routines. */ 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * Called during log_register recovery. Make sure that we have an 167*7c478bd9Sstevel@tonic-gate * entry in the dbentry table for this ndx. 168*7c478bd9Sstevel@tonic-gate * Returns 0 on success, non-zero on error. 169*7c478bd9Sstevel@tonic-gate */ 170*7c478bd9Sstevel@tonic-gate static int 171*7c478bd9Sstevel@tonic-gate __log_open_file(lp, argp) 172*7c478bd9Sstevel@tonic-gate DB_LOG *lp; 173*7c478bd9Sstevel@tonic-gate __log_register_args *argp; 174*7c478bd9Sstevel@tonic-gate { 175*7c478bd9Sstevel@tonic-gate DB_ENTRY *dbe; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate if (argp->name.size == 0) 178*7c478bd9Sstevel@tonic-gate return(0); 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* 181*7c478bd9Sstevel@tonic-gate * Because of reference counting, we cannot automatically close files 182*7c478bd9Sstevel@tonic-gate * during recovery, so when we're opening, we have to check that the 183*7c478bd9Sstevel@tonic-gate * name we are opening is what we expect. If it's not, then we close 184*7c478bd9Sstevel@tonic-gate * the old file and open the new one. 185*7c478bd9Sstevel@tonic-gate */ 186*7c478bd9Sstevel@tonic-gate LOCK_LOGTHREAD(lp); 187*7c478bd9Sstevel@tonic-gate if (argp->id < lp->dbentry_cnt) 188*7c478bd9Sstevel@tonic-gate dbe = &lp->dbentry[argp->id]; 189*7c478bd9Sstevel@tonic-gate else 190*7c478bd9Sstevel@tonic-gate dbe = NULL; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate if (dbe != NULL && (dbe->deleted == 1 || dbe->dbp != NULL) && 193*7c478bd9Sstevel@tonic-gate dbe->name != NULL && argp->name.data != NULL && 194*7c478bd9Sstevel@tonic-gate strncmp(argp->name.data, dbe->name, argp->name.size) == 0) { 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate dbe->refcount++; 197*7c478bd9Sstevel@tonic-gate UNLOCK_LOGTHREAD(lp); 198*7c478bd9Sstevel@tonic-gate return (0); 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate UNLOCK_LOGTHREAD(lp); 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate if (dbe != NULL && dbe->dbp != NULL) { 203*7c478bd9Sstevel@tonic-gate (void)dbe->dbp->close(dbe->dbp, 0); 204*7c478bd9Sstevel@tonic-gate if (dbe->name != NULL) 205*7c478bd9Sstevel@tonic-gate __os_freestr(dbe->name); 206*7c478bd9Sstevel@tonic-gate dbe->name = NULL; 207*7c478bd9Sstevel@tonic-gate (void)__log_rem_logid(lp, argp->id); 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate return (__log_do_open(lp, 212*7c478bd9Sstevel@tonic-gate argp->uid.data, argp->name.data, argp->ftype, argp->id)); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate /* 216*7c478bd9Sstevel@tonic-gate * __log_do_open -- 217*7c478bd9Sstevel@tonic-gate * Open files referenced in the log. This is the part of the open that 218*7c478bd9Sstevel@tonic-gate * is not protected by the thread mutex. 219*7c478bd9Sstevel@tonic-gate */ 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate static int 222*7c478bd9Sstevel@tonic-gate __log_do_open(lp, uid, name, ftype, ndx) 223*7c478bd9Sstevel@tonic-gate DB_LOG *lp; 224*7c478bd9Sstevel@tonic-gate u_int8_t *uid; 225*7c478bd9Sstevel@tonic-gate char *name; 226*7c478bd9Sstevel@tonic-gate DBTYPE ftype; 227*7c478bd9Sstevel@tonic-gate u_int32_t ndx; 228*7c478bd9Sstevel@tonic-gate { 229*7c478bd9Sstevel@tonic-gate DB *dbp; 230*7c478bd9Sstevel@tonic-gate int ret; 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate dbp = NULL; 233*7c478bd9Sstevel@tonic-gate if ((ret = db_open(name, ftype, 0, 0, lp->dbenv, NULL, &dbp)) == 0) { 234*7c478bd9Sstevel@tonic-gate /* 235*7c478bd9Sstevel@tonic-gate * Verify that we are opening the same file that we were 236*7c478bd9Sstevel@tonic-gate * referring to when we wrote this log record. 237*7c478bd9Sstevel@tonic-gate */ 238*7c478bd9Sstevel@tonic-gate if (memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0) { 239*7c478bd9Sstevel@tonic-gate (void)dbp->close(dbp, 0); 240*7c478bd9Sstevel@tonic-gate dbp = NULL; 241*7c478bd9Sstevel@tonic-gate ret = ENOENT; 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate if (ret == 0 || ret == ENOENT) 246*7c478bd9Sstevel@tonic-gate (void)__log_add_logid(lp, dbp, name, ndx); 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate return (ret); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* 252*7c478bd9Sstevel@tonic-gate * __log_add_logid -- 253*7c478bd9Sstevel@tonic-gate * Adds a DB entry to the log's DB entry table. 254*7c478bd9Sstevel@tonic-gate * 255*7c478bd9Sstevel@tonic-gate * PUBLIC: int __log_add_logid __P((DB_LOG *, DB *, const char *, u_int32_t)); 256*7c478bd9Sstevel@tonic-gate */ 257*7c478bd9Sstevel@tonic-gate int 258*7c478bd9Sstevel@tonic-gate __log_add_logid(logp, dbp, name, ndx) 259*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 260*7c478bd9Sstevel@tonic-gate DB *dbp; 261*7c478bd9Sstevel@tonic-gate const char *name; 262*7c478bd9Sstevel@tonic-gate u_int32_t ndx; 263*7c478bd9Sstevel@tonic-gate { 264*7c478bd9Sstevel@tonic-gate u_int32_t i; 265*7c478bd9Sstevel@tonic-gate int ret; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate ret = 0; 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate LOCK_LOGTHREAD(logp); 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * Check if we need to grow the table. Note, ndx is 0-based (the 273*7c478bd9Sstevel@tonic-gate * index into the DB entry table) an dbentry_cnt is 1-based, the 274*7c478bd9Sstevel@tonic-gate * number of available slots. 275*7c478bd9Sstevel@tonic-gate */ 276*7c478bd9Sstevel@tonic-gate if (logp->dbentry_cnt <= ndx) { 277*7c478bd9Sstevel@tonic-gate if ((ret = __os_realloc(&logp->dbentry, 278*7c478bd9Sstevel@tonic-gate (ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY))) != 0) 279*7c478bd9Sstevel@tonic-gate goto err; 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* Initialize the new entries. */ 282*7c478bd9Sstevel@tonic-gate for (i = logp->dbentry_cnt; i < ndx + DB_GROW_SIZE; i++) { 283*7c478bd9Sstevel@tonic-gate logp->dbentry[i].dbp = NULL; 284*7c478bd9Sstevel@tonic-gate logp->dbentry[i].deleted = 0; 285*7c478bd9Sstevel@tonic-gate logp->dbentry[i].name = NULL; 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate logp->dbentry_cnt = i; 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate /* Make space for the name and copy it in. */ 292*7c478bd9Sstevel@tonic-gate if (name != NULL) { 293*7c478bd9Sstevel@tonic-gate if ((ret = __os_malloc(strlen(name) + 1, 294*7c478bd9Sstevel@tonic-gate NULL, &logp->dbentry[ndx].name)) != 0) 295*7c478bd9Sstevel@tonic-gate goto err; 296*7c478bd9Sstevel@tonic-gate strcpy(logp->dbentry[ndx].name, name); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate if (logp->dbentry[ndx].deleted == 0 && logp->dbentry[ndx].dbp == NULL) { 300*7c478bd9Sstevel@tonic-gate logp->dbentry[ndx].dbp = dbp; 301*7c478bd9Sstevel@tonic-gate logp->dbentry[ndx].refcount = 1; 302*7c478bd9Sstevel@tonic-gate logp->dbentry[ndx].deleted = dbp == NULL; 303*7c478bd9Sstevel@tonic-gate } else 304*7c478bd9Sstevel@tonic-gate logp->dbentry[ndx].refcount++; 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate err: UNLOCK_LOGTHREAD(logp); 308*7c478bd9Sstevel@tonic-gate return (ret); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate /* 313*7c478bd9Sstevel@tonic-gate * __db_fileid_to_db -- 314*7c478bd9Sstevel@tonic-gate * Return the DB corresponding to the specified fileid. 315*7c478bd9Sstevel@tonic-gate * 316*7c478bd9Sstevel@tonic-gate * PUBLIC: int __db_fileid_to_db __P((DB_LOG *, DB **, u_int32_t)); 317*7c478bd9Sstevel@tonic-gate */ 318*7c478bd9Sstevel@tonic-gate int 319*7c478bd9Sstevel@tonic-gate __db_fileid_to_db(logp, dbpp, ndx) 320*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 321*7c478bd9Sstevel@tonic-gate DB **dbpp; 322*7c478bd9Sstevel@tonic-gate u_int32_t ndx; 323*7c478bd9Sstevel@tonic-gate { 324*7c478bd9Sstevel@tonic-gate int ret; 325*7c478bd9Sstevel@tonic-gate char *name; 326*7c478bd9Sstevel@tonic-gate FNAME *fname; 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate ret = 0; 329*7c478bd9Sstevel@tonic-gate LOCK_LOGTHREAD(logp); 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate /* 332*7c478bd9Sstevel@tonic-gate * Under XA, a process different than the one issuing DB 333*7c478bd9Sstevel@tonic-gate * operations may abort a transaction. In this case, 334*7c478bd9Sstevel@tonic-gate * recovery routines are run by a process that does not 335*7c478bd9Sstevel@tonic-gate * necessarily have the file open. In this case, we must 336*7c478bd9Sstevel@tonic-gate * open the file explicitly. 337*7c478bd9Sstevel@tonic-gate */ 338*7c478bd9Sstevel@tonic-gate if (ndx >= logp->dbentry_cnt || 339*7c478bd9Sstevel@tonic-gate (!logp->dbentry[ndx].deleted && logp->dbentry[ndx].dbp == NULL)) { 340*7c478bd9Sstevel@tonic-gate if (__log_lid_to_fname(logp, ndx, &fname) != 0) { 341*7c478bd9Sstevel@tonic-gate /* Couldn't find entry; this is a fatal error. */ 342*7c478bd9Sstevel@tonic-gate ret = EINVAL; 343*7c478bd9Sstevel@tonic-gate goto err; 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate name = R_ADDR(logp, fname->name_off); 346*7c478bd9Sstevel@tonic-gate /* 347*7c478bd9Sstevel@tonic-gate * __log_do_open is called without protection of the 348*7c478bd9Sstevel@tonic-gate * log thread lock. 349*7c478bd9Sstevel@tonic-gate */ 350*7c478bd9Sstevel@tonic-gate UNLOCK_LOGTHREAD(logp); 351*7c478bd9Sstevel@tonic-gate /* 352*7c478bd9Sstevel@tonic-gate * At this point, we are not holding the thread lock, so 353*7c478bd9Sstevel@tonic-gate * exit directly instead of going through the exit code 354*7c478bd9Sstevel@tonic-gate * at the bottom. If the __log_do_open succeeded, then 355*7c478bd9Sstevel@tonic-gate * we don't need to do any of the remaining error checking 356*7c478bd9Sstevel@tonic-gate * at the end of this routine. 357*7c478bd9Sstevel@tonic-gate */ 358*7c478bd9Sstevel@tonic-gate if ((ret = __log_do_open(logp, 359*7c478bd9Sstevel@tonic-gate fname->ufid, name, fname->s_type, ndx)) != 0) 360*7c478bd9Sstevel@tonic-gate return (ret); 361*7c478bd9Sstevel@tonic-gate *dbpp = logp->dbentry[ndx].dbp; 362*7c478bd9Sstevel@tonic-gate return (0); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * Return DB_DELETED if the file has been deleted 367*7c478bd9Sstevel@tonic-gate * (it's not an error). 368*7c478bd9Sstevel@tonic-gate */ 369*7c478bd9Sstevel@tonic-gate if (logp->dbentry[ndx].deleted) { 370*7c478bd9Sstevel@tonic-gate ret = DB_DELETED; 371*7c478bd9Sstevel@tonic-gate goto err; 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate /* 375*7c478bd9Sstevel@tonic-gate * Otherwise return 0, but if we don't have a corresponding DB, 376*7c478bd9Sstevel@tonic-gate * it's an error. 377*7c478bd9Sstevel@tonic-gate */ 378*7c478bd9Sstevel@tonic-gate if ((*dbpp = logp->dbentry[ndx].dbp) == NULL) 379*7c478bd9Sstevel@tonic-gate ret = ENOENT; 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate err: UNLOCK_LOGTHREAD(logp); 382*7c478bd9Sstevel@tonic-gate return (ret); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate /* 386*7c478bd9Sstevel@tonic-gate * Close files that were opened by the recovery daemon. 387*7c478bd9Sstevel@tonic-gate * 388*7c478bd9Sstevel@tonic-gate * PUBLIC: void __log_close_files __P((DB_LOG *)); 389*7c478bd9Sstevel@tonic-gate */ 390*7c478bd9Sstevel@tonic-gate void 391*7c478bd9Sstevel@tonic-gate __log_close_files(logp) 392*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate u_int32_t i; 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate LOCK_LOGTHREAD(logp); 397*7c478bd9Sstevel@tonic-gate for (i = 0; i < logp->dbentry_cnt; i++) 398*7c478bd9Sstevel@tonic-gate if (logp->dbentry[i].dbp) { 399*7c478bd9Sstevel@tonic-gate logp->dbentry[i].dbp->close(logp->dbentry[i].dbp, 0); 400*7c478bd9Sstevel@tonic-gate logp->dbentry[i].dbp = NULL; 401*7c478bd9Sstevel@tonic-gate logp->dbentry[i].deleted = 0; 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate F_CLR(logp, DBC_RECOVER); 404*7c478bd9Sstevel@tonic-gate UNLOCK_LOGTHREAD(logp); 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate /* 408*7c478bd9Sstevel@tonic-gate * PUBLIC: void __log_rem_logid __P((DB_LOG *, u_int32_t)); 409*7c478bd9Sstevel@tonic-gate */ 410*7c478bd9Sstevel@tonic-gate void 411*7c478bd9Sstevel@tonic-gate __log_rem_logid(logp, ndx) 412*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 413*7c478bd9Sstevel@tonic-gate u_int32_t ndx; 414*7c478bd9Sstevel@tonic-gate { 415*7c478bd9Sstevel@tonic-gate LOCK_LOGTHREAD(logp); 416*7c478bd9Sstevel@tonic-gate if (--logp->dbentry[ndx].refcount == 0) { 417*7c478bd9Sstevel@tonic-gate logp->dbentry[ndx].dbp = NULL; 418*7c478bd9Sstevel@tonic-gate logp->dbentry[ndx].deleted = 0; 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate UNLOCK_LOGTHREAD(logp); 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate /* 424*7c478bd9Sstevel@tonic-gate * __log_lid_to_fname -- 425*7c478bd9Sstevel@tonic-gate * Traverse the shared-memory region looking for the entry that 426*7c478bd9Sstevel@tonic-gate * matches the passed log fileid. Returns 0 on success; -1 on error. 427*7c478bd9Sstevel@tonic-gate */ 428*7c478bd9Sstevel@tonic-gate static int 429*7c478bd9Sstevel@tonic-gate __log_lid_to_fname(dblp, lid, fnamep) 430*7c478bd9Sstevel@tonic-gate DB_LOG *dblp; 431*7c478bd9Sstevel@tonic-gate u_int32_t lid; 432*7c478bd9Sstevel@tonic-gate FNAME **fnamep; 433*7c478bd9Sstevel@tonic-gate { 434*7c478bd9Sstevel@tonic-gate FNAME *fnp; 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname); 437*7c478bd9Sstevel@tonic-gate fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) { 438*7c478bd9Sstevel@tonic-gate if (fnp->ref == 0) /* Entry not in use. */ 439*7c478bd9Sstevel@tonic-gate continue; 440*7c478bd9Sstevel@tonic-gate if (fnp->id == lid) { 441*7c478bd9Sstevel@tonic-gate *fnamep = fnp; 442*7c478bd9Sstevel@tonic-gate return (0); 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate return (-1); 446*7c478bd9Sstevel@tonic-gate } 447