📄 env_region.c
字号:
} __os_dirfree(dbenv, names, fcnt); /* * !!! * Backward compatibility -- remove region files from releases * before 2.8.XX. */ for (names = (char **)old_region_names; *names != NULL; ++names) if (__db_appname(dbenv, DB_APP_NONE, *names, 0, NULL, &path) == 0) { (void)__os_unlink(dbenv, path); __os_free(dbenv, path); } return (0);}/* * __db_e_stat * Statistics for the environment. * * PUBLIC: int __db_e_stat __P((DB_ENV *, * PUBLIC: REGENV *, REGION *, int *, u_int32_t)); */int__db_e_stat(dbenv, arg_renv, arg_regions, arg_regions_cnt, flags) DB_ENV *dbenv; REGENV *arg_renv; REGION *arg_regions; int *arg_regions_cnt; u_int32_t flags;{ REGENV *renv; REGINFO *infop; REGION *rp; int n, ret; infop = dbenv->reginfo; renv = infop->primary; rp = infop->rp; if ((ret = __db_fchk(dbenv, "DB_ENV->stat", flags, DB_STAT_CLEAR)) != 0) return (ret); /* Lock the environment. */ MUTEX_LOCK(dbenv, &rp->mutex); *arg_renv = *renv; if (LF_ISSET(DB_STAT_CLEAR)) { renv->mutex.mutex_set_nowait = 0; renv->mutex.mutex_set_wait = 0; } for (n = 0, rp = SH_LIST_FIRST(&renv->regionq, __db_region); n < *arg_regions_cnt && rp != NULL; ++n, rp = SH_LIST_NEXT(rp, q, __db_region)) { arg_regions[n] = *rp; if (LF_ISSET(DB_STAT_CLEAR)) { rp->mutex.mutex_set_nowait = 0; rp->mutex.mutex_set_wait = 0; } } /* Release the lock. */ rp = infop->rp; MUTEX_UNLOCK(dbenv, &rp->mutex); *arg_regions_cnt = n == 0 ? n : n - 1; return (0);}/* * __db_r_attach * Join/create a region. * * PUBLIC: int __db_r_attach __P((DB_ENV *, REGINFO *, size_t)); */int__db_r_attach(dbenv, infop, size) DB_ENV *dbenv; REGINFO *infop; size_t size;{ REGENV *renv; REGION *rp; int ret; char buf[sizeof(DB_REGION_FMT) + 20]; renv = ((REGINFO *)dbenv->reginfo)->primary; /* Lock the environment. */ MUTEX_LOCK(dbenv, &renv->mutex); /* * Find or create a REGION structure for this region. If we create * it, the REGION_CREATE flag will be set in the infop structure. */ F_CLR(infop, REGION_CREATE); if ((ret = __db_des_get(dbenv, dbenv->reginfo, infop, &rp)) != 0) { MUTEX_UNLOCK(dbenv, &renv->mutex); return (ret); } infop->rp = rp; infop->type = rp->type; infop->id = rp->id; /* If we're creating the region, set the desired size. */ if (F_ISSET(infop, REGION_CREATE)) rp->size = (roff_t)size; /* Join/create the underlying region. */ (void)snprintf(buf, sizeof(buf), DB_REGION_FMT, infop->id); if ((ret = __db_appname(dbenv, DB_APP_NONE, buf, 0, NULL, &infop->name)) != 0) goto err; if ((ret = __os_r_attach(dbenv, infop, rp)) != 0) goto err; /* * Fault the pages into memory. Note, do this BEFORE we initialize * anything because we're writing pages in created regions, not just * reading them. */ (void)__db_faultmem(dbenv, infop->addr, rp->size, F_ISSET(infop, REGION_CREATE)); /* * !!! * The underlying layer may have just decided that we are going * to create the region. There are various system issues that * can result in a useless region that requires re-initialization. * * If we created the region, initialize it for allocation. */ if (F_ISSET(infop, REGION_CREATE)) { ((REGION *)(infop->addr))->magic = DB_REGION_MAGIC; (void)__db_shalloc_init(infop->addr, rp->size); } /* * If the underlying REGION isn't the environment, acquire a lock * for it and release our lock on the environment. */ if (infop->type != REGION_TYPE_ENV) { MUTEX_LOCK(dbenv, &rp->mutex); MUTEX_UNLOCK(dbenv, &renv->mutex); } return (0); /* Discard the underlying region. */err: if (infop->addr != NULL) (void)__os_r_detach(dbenv, infop, F_ISSET(infop, REGION_CREATE)); infop->rp = NULL; infop->id = INVALID_REGION_ID; /* Discard the REGION structure if we created it. */ if (F_ISSET(infop, REGION_CREATE)) { (void)__db_des_destroy(dbenv, rp); F_CLR(infop, REGION_CREATE); } /* Release the environment lock. */ MUTEX_UNLOCK(dbenv, &renv->mutex); return (ret);}/* * __db_r_detach -- * Detach from a region. * * PUBLIC: int __db_r_detach __P((DB_ENV *, REGINFO *, int)); */int__db_r_detach(dbenv, infop, destroy) DB_ENV *dbenv; REGINFO *infop; int destroy;{ REGENV *renv; REGION *rp; int ret, t_ret; renv = ((REGINFO *)dbenv->reginfo)->primary; rp = infop->rp; if (F_ISSET(dbenv, DB_ENV_PRIVATE)) destroy = 1; /* Lock the environment. */ MUTEX_LOCK(dbenv, &renv->mutex); /* Acquire the lock for the REGION. */ MUTEX_LOCK(dbenv, &rp->mutex); /* * We need to call destroy on per-subsystem info before * we free the memory associated with the region. */ if (destroy) __db_region_destroy(dbenv, infop); /* Detach from the underlying OS region. */ ret = __os_r_detach(dbenv, infop, destroy); /* Release the REGION lock. */ MUTEX_UNLOCK(dbenv, &rp->mutex); /* If we destroyed the region, discard the REGION structure. */ if (destroy && ((t_ret = __db_des_destroy(dbenv, rp)) != 0) && ret == 0) ret = t_ret; /* Release the environment lock. */ MUTEX_UNLOCK(dbenv, &renv->mutex); /* Destroy the structure. */ if (infop->name != NULL) __os_free(dbenv, infop->name); return (ret);}/* * __db_des_get -- * Return a reference to the shared information for a REGION, * optionally creating a new entry. */static int__db_des_get(dbenv, env_infop, infop, rpp) DB_ENV *dbenv; REGINFO *env_infop, *infop; REGION **rpp;{ REGENV *renv; REGION *rp, *first_type; u_int32_t maxid; int ret; /* * !!! * Called with the environment already locked. */ *rpp = NULL; renv = env_infop->primary; /* * If the caller wants to join a region, walk through the existing * regions looking for a matching ID (if ID specified) or matching * type (if type specified). If we return based on a matching type * return the "primary" region, that is, the first region that was * created of this type. * * Track the maximum region ID so we can allocate a new region, * note that we have to start at 1 because the primary environment * uses ID == 1. */ maxid = REGION_ID_ENV; for (first_type = NULL, rp = SH_LIST_FIRST(&renv->regionq, __db_region); rp != NULL; rp = SH_LIST_NEXT(rp, q, __db_region)) { if (infop->id != INVALID_REGION_ID) { if (infop->id == rp->id) break; continue; } if (infop->type == rp->type && F_ISSET(infop, REGION_JOIN_OK) && (first_type == NULL || first_type->id > rp->id)) first_type = rp; if (rp->id > maxid) maxid = rp->id; } if (rp == NULL) rp = first_type; /* * If we didn't find a region and we can't create the region, fail. * The caller generates any error message. */ if (rp == NULL && !F_ISSET(infop, REGION_CREATE_OK)) return (ENOENT); /* * If we didn't find a region, create and initialize a REGION structure * for the caller. If id was set, use that value, otherwise we use the * next available ID. */ if (rp == NULL) { if ((ret = __db_shalloc(env_infop->addr, sizeof(REGION), MUTEX_ALIGN, &rp)) != 0) return (ret); /* Initialize the region. */ memset(rp, 0, sizeof(*rp)); if ((ret = __db_mutex_setup(dbenv, env_infop, &rp->mutex, MUTEX_NO_RECORD | MUTEX_NO_RLOCK)) != 0) { __db_shalloc_free(env_infop->addr, rp); return (ret); } rp->segid = INVALID_REGION_SEGID; /* * Set the type and ID; if no region ID was specified, * allocate one. */ rp->type = infop->type; rp->id = infop->id == INVALID_REGION_ID ? maxid + 1 : infop->id; SH_LIST_INSERT_HEAD(&renv->regionq, rp, q, __db_region); F_SET(infop, REGION_CREATE); } *rpp = rp; return (0);}/* * __db_des_destroy -- * Destroy a reference to a REGION. */static int__db_des_destroy(dbenv, rp) DB_ENV *dbenv; REGION *rp;{ REGINFO *infop; /* * !!! * Called with the environment already locked. */ infop = dbenv->reginfo; SH_LIST_REMOVE(rp, q, __db_region); __db_mutex_destroy(&rp->mutex); __db_shalloc_free(infop->addr, rp); return (0);}/* * __db_faultmem -- * Fault the region into memory. */static int__db_faultmem(dbenv, addr, size, created) DB_ENV *dbenv; void *addr; size_t size; int created;{ int ret; u_int8_t *p, *t; /* * It's sometimes significantly faster to page-fault in all of the * region's pages before we run the application, as we see nasty * side-effects when we page-fault while holding various locks, i.e., * the lock takes a long time to acquire because of the underlying * page fault, and the other threads convoy behind the lock holder. * * If we created the region, we write a non-zero value so that the * system can't cheat. If we're just joining the region, we can * only read the value and try to confuse the compiler sufficiently * that it doesn't figure out that we're never really using it. */ ret = 0; if (F_ISSET(dbenv, DB_ENV_REGION_INIT)) { if (created) for (p = addr, t = (u_int8_t *)addr + size; p < t; p += OS_VMPAGESIZE) p[0] = 0xdb; else for (p = addr, t = (u_int8_t *)addr + size; p < t; p += OS_VMPAGESIZE) ret |= p[0]; } return (ret);}/* * __db_region_destroy -- * Destroy per-subsystem region information. * Called with the region already locked. */static void__db_region_destroy(dbenv, infop) DB_ENV *dbenv; REGINFO *infop;{ switch (infop->type) { case REGION_TYPE_LOCK: __lock_region_destroy(dbenv, infop); break; case REGION_TYPE_LOG: __log_region_destroy(dbenv, infop); break; case REGION_TYPE_MPOOL: __mpool_region_destroy(dbenv, infop); break; case REGION_TYPE_TXN: __txn_region_destroy(dbenv, infop); break; case REGION_TYPE_ENV: case REGION_TYPE_MUTEX: break; default: DB_ASSERT(0); break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -