📄 qam_files.c
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1999-2002 * Sleepycat Software. All rights reserved. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: qam_files.c,v 1.52 2002/08/26 17:52:18 margo Exp $";#endif /* not lint */#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <stdlib.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/qam.h"#include "dbinc/db_am.h"/* * __qam_fprobe -- calculate and open extent * * Calculate which extent the page is in, open and create if necessary. * * PUBLIC: int __qam_fprobe * PUBLIC: __P((DB *, db_pgno_t, void *, qam_probe_mode, u_int32_t)); */int__qam_fprobe(dbp, pgno, addrp, mode, flags) DB *dbp; db_pgno_t pgno; void *addrp; qam_probe_mode mode; u_int32_t flags;{ DB_ENV *dbenv; DB_MPOOLFILE *mpf; MPFARRAY *array; QUEUE *qp; u_int8_t fid[DB_FILE_ID_LEN]; u_int32_t extid, maxext, openflags; char buf[MAXPATHLEN]; int numext, offset, oldext, ret; dbenv = dbp->dbenv; qp = (QUEUE *)dbp->q_internal; ret = 0; if (qp->page_ext == 0) { mpf = dbp->mpf; return (mode == QAM_PROBE_GET ? mpf->get(mpf, &pgno, flags, addrp) : mpf->put(mpf, addrp, flags)); } mpf = NULL; /* * Need to lock long enough to find the mpf or create the file. * The file cannot go away because we must have a record locked * in that file. */ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); extid = (pgno - 1) / qp->page_ext; /* Array1 will always be in use if array2 is in use. */ array = &qp->array1; if (array->n_extent == 0) { /* Start with 4 extents */ oldext = 0; array->n_extent = 4; array->low_extent = extid; offset = 0; numext = 0; goto alloc; } offset = extid - qp->array1.low_extent; if (qp->array2.n_extent != 0 && abs(offset) > abs(extid - qp->array2.low_extent)) { array = &qp->array2; offset = extid - array->low_extent; } /* * Check to see if the requested extent is outside the range of * extents in the array. This is true by default if there are * no extents here yet. */ if (offset < 0 || (unsigned) offset >= array->n_extent) { oldext = array->n_extent; numext = array->hi_extent - array->low_extent + 1; if (offset < 0 && (unsigned) -offset + numext <= array->n_extent) { /* * If we can fit this one into the existing array by * shifting the existing entries then we do not have * to allocate. */ memmove(&array->mpfarray[-offset], array->mpfarray, numext * sizeof(array->mpfarray[0])); memset(array->mpfarray, 0, -offset * sizeof(array->mpfarray[0])); offset = 0; } else if ((u_int32_t)offset == array->n_extent && mode != QAM_PROBE_MPF && array->mpfarray[0].pinref == 0) { /* * If this is at the end of the array and the file at * the begining has a zero pin count we can close * the bottom extent and put this one at the end. */ mpf = array->mpfarray[0].mpf; if (mpf != NULL && (ret = mpf->close(mpf, 0)) != 0) goto err; memmove(&array->mpfarray[0], &array->mpfarray[1], (array->n_extent - 1) * sizeof(array->mpfarray[0])); array->low_extent++; array->hi_extent++; offset--; array->mpfarray[offset].mpf = NULL; array->mpfarray[offset].pinref = 0; } else { /* * See if we have wrapped around the queue. * If it has then allocate the second array. * Otherwise just expand the one we are using. */ maxext = (u_int32_t) UINT32_T_MAX / (qp->page_ext * qp->rec_page); if ((u_int32_t) abs(offset) >= maxext/2) { array = &qp->array2; DB_ASSERT(array->n_extent == 0); oldext = 0; array->n_extent = 4; array->low_extent = extid; offset = 0; numext = 0; } else { /* * Increase the size to at least include * the new one and double it. */ array->n_extent += abs(offset); array->n_extent <<= 2; } alloc: if ((ret = __os_realloc(dbenv, array->n_extent * sizeof(struct __qmpf), &array->mpfarray)) != 0) goto err; if (offset < 0) { /* * Move the array up and put the new one * in the first slot. */ offset = -offset; memmove(&array->mpfarray[offset], array->mpfarray, numext * sizeof(array->mpfarray[0])); memset(array->mpfarray, 0, offset * sizeof(array->mpfarray[0])); memset(&array->mpfarray[numext + offset], 0, (array->n_extent - (numext + offset)) * sizeof(array->mpfarray[0])); offset = 0; } else /* Clear the new part of the array. */ memset(&array->mpfarray[oldext], 0, (array->n_extent - oldext) * sizeof(array->mpfarray[0])); } } /* Update the low and hi range of saved extents. */ if (extid < array->low_extent) array->low_extent = extid; if (extid > array->hi_extent) array->hi_extent = extid; /* If the extent file is not yet open, open it. */ if (array->mpfarray[offset].mpf == NULL) { snprintf(buf, sizeof(buf), QUEUE_EXTENT, qp->dir, PATH_SEPARATOR[0], qp->name, extid); if ((ret = dbenv->memp_fcreate( dbenv, &array->mpfarray[offset].mpf, 0)) != 0) goto err; mpf = array->mpfarray[offset].mpf; (void)mpf->set_lsn_offset(mpf, 0); (void)mpf->set_pgcookie(mpf, &qp->pgcookie); /* Set up the fileid for this extent. */ __qam_exid(dbp, fid, extid); (void)mpf->set_fileid(mpf, fid); openflags = DB_EXTENT; if (LF_ISSET(DB_MPOOL_CREATE)) openflags |= DB_CREATE; if (F_ISSET(dbp, DB_AM_RDONLY)) openflags |= DB_RDONLY; if (F_ISSET(dbenv, DB_ENV_DIRECT_DB)) openflags |= DB_DIRECT; if ((ret = mpf->open( mpf, buf, openflags, qp->mode, dbp->pgsize)) != 0) { array->mpfarray[offset].mpf = NULL; (void)mpf->close(mpf, 0); goto err; } } mpf = array->mpfarray[offset].mpf; if (mode == QAM_PROBE_GET) array->mpfarray[offset].pinref++; if (LF_ISSET(DB_MPOOL_CREATE)) mpf->set_unlink(mpf, 0);err: MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); if (ret == 0) { if (mode == QAM_PROBE_MPF) { *(DB_MPOOLFILE **)addrp = mpf; return (0); } pgno--; pgno %= qp->page_ext; if (mode == QAM_PROBE_GET) return (mpf->get(mpf, &pgno, flags, addrp)); ret = mpf->put(mpf, addrp, flags); MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); array->mpfarray[offset].pinref--; MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); } return (ret);}/* * __qam_fclose -- close an extent. * * Calculate which extent the page is in and close it. * We assume the mpf entry is present. * * PUBLIC: int __qam_fclose __P((DB *, db_pgno_t)); */int__qam_fclose(dbp, pgnoaddr) DB *dbp; db_pgno_t pgnoaddr;{ DB_ENV *dbenv; DB_MPOOLFILE *mpf; MPFARRAY *array; QUEUE *qp; u_int32_t extid; int offset, ret; ret = 0; dbenv = dbp->dbenv; qp = (QUEUE *)dbp->q_internal; MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); extid = (pgnoaddr - 1) / qp->page_ext; array = &qp->array1; if (array->low_extent > extid || array->hi_extent < extid) array = &qp->array2; offset = extid - array->low_extent; DB_ASSERT(offset >= 0 && (unsigned) offset < array->n_extent); /* If other threads are still using this file, leave it. */ if (array->mpfarray[offset].pinref != 0) goto done; mpf = array->mpfarray[offset].mpf; array->mpfarray[offset].mpf = NULL; ret = mpf->close(mpf, 0);done: MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); return (ret);}/* * __qam_fremove -- remove an extent. * * Calculate which extent the page is in and remove it. There is no way * to remove an extent without probing it first and seeing that is is empty * so we assume the mpf entry is present. * * PUBLIC: int __qam_fremove __P((DB *, db_pgno_t)); */int__qam_fremove(dbp, pgnoaddr) DB *dbp; db_pgno_t pgnoaddr;{ DB_ENV *dbenv; DB_MPOOLFILE *mpf; MPFARRAY *array; QUEUE *qp; u_int32_t extid;#if CONFIG_TEST char buf[MAXPATHLEN], *real_name;#endif int offset, ret; qp = (QUEUE *)dbp->q_internal; dbenv = dbp->dbenv; ret = 0; MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); extid = (pgnoaddr - 1) / qp->page_ext; array = &qp->array1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -