📄 db.c
字号:
(void)__dbreg_revoke_id(dbp, 0); else (void)__dbreg_close_id(dbp, txn); /* Discard the log FNAME. */ (void)__dbreg_teardown(dbp); } /* Clear out fields that normally get set during open. */ memset(dbp->fileid, 0, sizeof(dbp->fileid)); dbp->adj_fileid = 0; dbp->meta_pgno = 0; dbp->cur_lid = DB_LOCK_INVALIDID; dbp->associate_lid = DB_LOCK_INVALIDID; dbp->cl_id = 0; /* * If we are being refreshed with a txn specified, then we need * to make sure that we clear out the lock handle field, because * releasing all the locks for this transaction will release this * lock and we don't want close to stumble upon this handle and * try to close it. */ if (txn != NULL) LOCK_INIT(dbp->handle_lock); F_CLR(dbp, DB_AM_DBM_ERROR); F_CLR(dbp, DB_AM_DISCARD); F_CLR(dbp, DB_AM_INMEM); F_CLR(dbp, DB_AM_RECOVER); F_CLR(dbp, DB_AM_OPEN_CALLED); F_CLR(dbp, DB_AM_RDONLY); F_CLR(dbp, DB_AM_SWAP); return (ret);}/* * __db_log_page * Log a meta-data or root page during a subdatabase create operation. * * PUBLIC: int __db_log_page __P((DB *, DB_TXN *, DB_LSN *, db_pgno_t, PAGE *)); */int__db_log_page(dbp, txn, lsn, pgno, page) DB *dbp; DB_TXN *txn; DB_LSN *lsn; db_pgno_t pgno; PAGE *page;{ DBT page_dbt; DB_LSN new_lsn; int ret; if (!LOGGING_ON(dbp->dbenv) || txn == NULL) return (0); memset(&page_dbt, 0, sizeof(page_dbt)); page_dbt.size = dbp->pgsize; page_dbt.data = page; ret = __crdel_metasub_log(dbp, txn, &new_lsn, 0, pgno, &page_dbt, lsn); if (ret == 0) page->lsn = new_lsn; return (ret);}/* * __db_backup_name * Create the backup file name for a given file. * * PUBLIC: int __db_backup_name __P((DB_ENV *, * PUBLIC: const char *, DB_TXN *, char **)); */#undef BACKUP_PREFIX#define BACKUP_PREFIX "__db."#undef MAX_LSN_TO_TEXT#define MAX_LSN_TO_TEXT 17int__db_backup_name(dbenv, name, txn, backup) DB_ENV *dbenv; const char *name; DB_TXN *txn; char **backup;{ DB_LSN lsn; size_t len; int plen, ret; char *p, *retp; /* * Create the name. Backup file names are in one of two forms: * * In a transactional env: __db.LSN(8).LSN(8) * and * in a non-transactional env: __db.FILENAME. * * If the transaction doesn't have a current LSN, we write * a dummy log record to force it, so that we ensure that * all tmp names are unique. * * In addition, the name passed may contain an env-relative path. * In that case, put the __db. in the right place (in the last * component of the pathname). */ if (txn != NULL) { if (IS_ZERO_LSN(txn->last_lsn)) { /* * Write dummy log record. The two choices for * dummy log records are __db_noop_log and * __db_debug_log; unfortunately __db_noop_log requires * a valid dbp, and we aren't guaranteed to be able * to pass one in here. */ if ((ret = __db_debug_log(dbenv, txn, &lsn, 0, NULL, 0, NULL, NULL, 0)) != 0) return (ret); } else lsn = txn->last_lsn; } /* * Part of the name may be a full path, so we need to make sure that * we allocate enough space for it, even in the case where we don't * use the entire filename for the backup name. */ len = strlen(name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT; if ((ret = __os_malloc(dbenv, len, &retp)) != 0) return (ret); /* * There are four cases here: * 1. simple path w/out transaction * 2. simple path + transaction * 3. multi-component path w/out transaction * 4. multi-component path + transaction */ if ((p = __db_rpath(name)) == NULL) { if (txn == NULL) /* case 1 */ snprintf(retp, len, "%s%s.", BACKUP_PREFIX, name); else /* case 2 */ snprintf(retp, len, "%s%x.%x", BACKUP_PREFIX, lsn.file, lsn.offset); } else { plen = (int)(p - name) + 1; p++; if (txn == NULL) /* case 3 */ snprintf(retp, len, "%.*s%s%s.", plen, name, BACKUP_PREFIX, p); else /* case 4 */ snprintf(retp, len, "%.*s%x.%x.", plen, name, lsn.file, lsn.offset); } *backup = retp; return (0);}/* * __dblist_get -- * Get the first element of dbenv->dblist with * dbp->adj_fileid matching adjid. * * PUBLIC: DB *__dblist_get __P((DB_ENV *, u_int32_t)); */DB *__dblist_get(dbenv, adjid) DB_ENV *dbenv; u_int32_t adjid;{ DB *dbp; for (dbp = LIST_FIRST(&dbenv->dblist); dbp != NULL && dbp->adj_fileid != adjid; dbp = LIST_NEXT(dbp, dblistlinks)) ; return (dbp);}/* * __db_disassociate -- * Destroy the association between a given secondary and its primary. */static int__db_disassociate(sdbp) DB *sdbp;{ DBC *dbc; int ret, t_ret; ret = 0; sdbp->s_callback = NULL; sdbp->s_primary = NULL; sdbp->get = sdbp->stored_get; sdbp->close = sdbp->stored_close; /* * Complain, but proceed, if we have any active cursors. (We're in * the middle of a close, so there's really no turning back.) */ if (sdbp->s_refcnt != 1 || TAILQ_FIRST(&sdbp->active_queue) != NULL || TAILQ_FIRST(&sdbp->join_queue) != NULL) { __db_err(sdbp->dbenv, "Closing a primary DB while a secondary DB has active cursors is unsafe"); ret = EINVAL; } sdbp->s_refcnt = 0; while ((dbc = TAILQ_FIRST(&sdbp->free_queue)) != NULL) if ((t_ret = __db_c_destroy(dbc)) != 0 && ret == 0) ret = t_ret; F_CLR(sdbp, DB_AM_SECONDARY); return (ret);}#if CONFIG_TEST/* * __db_testcopy * Create a copy of all backup files and our "main" DB. * * PUBLIC: #if CONFIG_TEST * PUBLIC: int __db_testcopy __P((DB_ENV *, DB *, const char *)); * PUBLIC: #endif */int__db_testcopy(dbenv, dbp, name) DB_ENV *dbenv; DB *dbp; const char *name;{ DB_MPOOLFILE *mpf; DB_ASSERT(dbp != NULL || name != NULL); if (name == NULL) { mpf = dbp->mpf; name = R_ADDR(mpf->dbmp->reginfo, mpf->mfp->path_off); } if (dbp != NULL && dbp->type == DB_QUEUE) return (__qam_testdocopy(dbp, name)); else return (__db_testdocopy(dbenv, name));}static int__qam_testdocopy(dbp, name) DB *dbp; const char *name;{ QUEUE_FILELIST *filelist, *fp; char buf[256], *dir; int ret; filelist = NULL; if ((ret = __db_testdocopy(dbp->dbenv, name)) != 0) return (ret); if (dbp->mpf != NULL && (ret = __qam_gen_filelist(dbp, &filelist)) != 0) return (ret); if (filelist == NULL) return (0); dir = ((QUEUE *)dbp->q_internal)->dir; for (fp = filelist; fp->mpf != NULL; fp++) { snprintf(buf, sizeof(buf), QUEUE_EXTENT, dir, PATH_SEPARATOR[0], name, fp->id); if ((ret = __db_testdocopy(dbp->dbenv, buf)) != 0) return (ret); } __os_free(dbp->dbenv, filelist); return (0);}/* * __db_testdocopy * Create a copy of all backup files and our "main" DB. * */static int__db_testdocopy(dbenv, name) DB_ENV *dbenv; const char *name;{ size_t len; int dircnt, i, ret; char **namesp, *backup, *copy, *dir, *p, *real_name; real_name = NULL; /* Get the real backing file name. */ if ((ret = __db_appname(dbenv, DB_APP_DATA, name, 0, NULL, &real_name)) != 0) return (ret); copy = backup = NULL; namesp = NULL; /* * Maximum size of file, including adding a ".afterop". */ len = strlen(real_name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT + 9; if ((ret = __os_malloc(dbenv, len, ©)) != 0) goto out; if ((ret = __os_malloc(dbenv, len, &backup)) != 0) goto out; /* * First copy the file itself. */ snprintf(copy, len, "%s.afterop", real_name); __db_makecopy(real_name, copy); if ((ret = __os_strdup(dbenv, real_name, &dir)) != 0) goto out; __os_free(dbenv, real_name); real_name = NULL; /* * Create the name. Backup file names are of the form: * * __db.name.0x[lsn-file].0x[lsn-offset] * * which guarantees uniqueness. We want to look for the * backup name, followed by a '.0x' (so that if they have * files named, say, 'a' and 'abc' we won't match 'abc' when * looking for 'a'. */ snprintf(backup, len, "%s%s.0x", BACKUP_PREFIX, name); /* * We need the directory path to do the __os_dirlist. */ p = __db_rpath(dir); if (p != NULL) *p = '\0'; ret = __os_dirlist(dbenv, dir, &namesp, &dircnt);#if DIAGNOSTIC /* * XXX * To get the memory guard code to work because it uses strlen and we * just moved the end of the string somewhere sooner. This causes the * guard code to fail because it looks at one byte past the end of the * string. */ *p = '/';#endif __os_free(dbenv, dir); if (ret != 0) goto out; for (i = 0; i < dircnt; i++) { /* * Need to check if it is a backup file for this. * No idea what namesp[i] may be or how long, so * must use strncmp and not memcmp. We don't want * to use strcmp either because we are only matching * the first part of the real file's name. We don't * know its LSN's. */ if (strncmp(namesp[i], backup, strlen(backup)) == 0) { if ((ret = __db_appname(dbenv, DB_APP_DATA, namesp[i], 0, NULL, &real_name)) != 0) goto out; /* * This should not happen. Check that old * .afterop files aren't around. * If so, just move on. */ if (strstr(real_name, ".afterop") != NULL) { __os_free(dbenv, real_name); real_name = NULL; continue; } snprintf(copy, len, "%s.afterop", real_name); __db_makecopy(real_name, copy); __os_free(dbenv, real_name); real_name = NULL; } }out: if (backup != NULL) __os_free(dbenv, backup); if (copy != NULL) __os_free(dbenv, copy); if (namesp != NULL) __os_dirfree(dbenv, namesp, dircnt); if (real_name != NULL) __os_free(dbenv, real_name); return (ret);}static void__db_makecopy(src, dest) const char *src, *dest;{ DB_FH rfh, wfh; size_t rcnt, wcnt; char *buf; memset(&rfh, 0, sizeof(rfh)); memset(&wfh, 0, sizeof(wfh)); if (__os_malloc(NULL, 1024, &buf) != 0) return; if (__os_open(NULL, src, DB_OSO_RDONLY, __db_omode("rw----"), &rfh) != 0) goto err; if (__os_open(NULL, dest, DB_OSO_CREATE | DB_OSO_TRUNC, __db_omode("rw----"), &wfh) != 0) goto err; for (;;) if (__os_read(NULL, &rfh, buf, 1024, &rcnt) < 0 || rcnt == 0 || __os_write(NULL, &wfh, buf, rcnt, &wcnt) < 0) break;err: __os_free(NULL, buf); if (F_ISSET(&rfh, DB_FH_VALID)) __os_closehandle(NULL, &rfh); if (F_ISSET(&wfh, DB_FH_VALID)) __os_closehandle(NULL, &wfh);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -