📄 db.c
字号:
/* Discard the thread mutex. */ if (dbp->mutexp != NULL) { dbmp = dbenv->mp_handle; __db_mutex_free(dbenv, dbmp->reginfo, dbp->mutexp); dbp->mutexp = NULL; } /* Discard any memory allocated for the file and database names. */ if (dbp->fname != NULL) { __os_free(dbp->dbenv, dbp->fname); dbp->fname = NULL; } if (dbp->dname != NULL) { __os_free(dbp->dbenv, dbp->dname); dbp->dname = NULL; } /* Discard any memory used to store returned data. */ if (dbp->my_rskey.data != NULL) __os_free(dbp->dbenv, dbp->my_rskey.data); if (dbp->my_rkey.data != NULL) __os_free(dbp->dbenv, dbp->my_rkey.data); if (dbp->my_rdata.data != NULL) __os_free(dbp->dbenv, dbp->my_rdata.data); /* For safety's sake; we may refresh twice. */ memset(&dbp->my_rskey, 0, sizeof(DBT)); memset(&dbp->my_rkey, 0, sizeof(DBT)); memset(&dbp->my_rdata, 0, sizeof(DBT)); /* 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; dbp->open_flags = 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); /* Reset flags to whatever the user configured. */ dbp->flags = dbp->orig_flags; 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 ret; char *p, *retp; /* * 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); /* * 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 we ensure 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). * * 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 */ p = __db_rpath(name); if (txn == NULL) if (p == NULL) /* Case 1. */ snprintf(retp, len, "%s%s", BACKUP_PREFIX, name); else /* Case 3. */ snprintf(retp, len, "%.*s%s%s", (int)(p - name) + 1, name, BACKUP_PREFIX, p + 1); else { 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) { __os_free(dbenv, retp); return (ret); } } else lsn = txn->last_lsn; if (p == NULL) /* Case 2. */ snprintf(retp, len, "%s%x.%x", BACKUP_PREFIX, lsn.file, lsn.offset); else /* Case 4. */ snprintf(retp, len, "%.*s%x.%x", (int)(p - name) + 1, 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);}#ifdef CONFIG_TEST/* * __db_testcopy * Create a copy of all backup files and our "main" DB. * * PUBLIC: #ifdef 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_MPOOL *dbmp; DB_MPOOLFILE *mpf; DB_ASSERT(dbp != NULL || name != NULL); if (name == NULL) { dbmp = dbenv->mp_handle; mpf = dbp->mpf; name = R_ADDR(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 *backup, *copy, *dir, **namesp, *p, *real_name; dircnt = 0; copy = backup = NULL; namesp = NULL; /* Get the real backing file name. */ if ((ret = __db_appname(dbenv, DB_APP_DATA, name, 0, NULL, &real_name)) != 0) return (ret); /* * 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 err; if ((ret = __os_malloc(dbenv, len, &backup)) != 0) goto err; /* * First copy the file itself. */ snprintf(copy, len, "%s.afterop", real_name); __db_makecopy(dbenv, real_name, copy); if ((ret = __os_strdup(dbenv, real_name, &dir)) != 0) goto err; __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 err; 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 err; /* * 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(dbenv, real_name, copy); __os_free(dbenv, real_name); real_name = NULL; } }err: 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(dbenv, src, dest) DB_ENV *dbenv; const char *src, *dest;{ DB_FH *rfhp, *wfhp; size_t rcnt, wcnt; char *buf; rfhp = wfhp = NULL; if (__os_malloc(dbenv, 1024, &buf) != 0) return; if (__os_open(dbenv, src, DB_OSO_RDONLY, __db_omode("rw----"), &rfhp) != 0) goto err; if (__os_open(dbenv, dest, DB_OSO_CREATE | DB_OSO_TRUNC, __db_omode("rw----"), &wfhp) != 0) goto err; for (;;) if (__os_read(dbenv, rfhp, buf, 1024, &rcnt) < 0 || rcnt == 0 || __os_write(dbenv, wfhp, buf, rcnt, &wcnt) < 0) break;err: if (buf != NULL) __os_free(dbenv, buf); if (rfhp != NULL) (void)__os_closehandle(dbenv, rfhp); if (wfhp != NULL) (void)__os_closehandle(dbenv, wfhp);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -