mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-04 17:24:12 +08:00
mdbx: dynamic mapsize/geometry and API (mostly done).
Change-Id: Ifb768ff3207cae1755c53c211a3ae552c6455e12
This commit is contained in:
parent
45defdc170
commit
9a2fff91f3
26
mdbx.h
26
mdbx.h
@ -72,6 +72,7 @@ typedef unsigned mode_t;
|
|||||||
typedef HANDLE mdbx_filehandle_t;
|
typedef HANDLE mdbx_filehandle_t;
|
||||||
typedef DWORD mdbx_pid_t;
|
typedef DWORD mdbx_pid_t;
|
||||||
typedef DWORD mdbx_tid_t;
|
typedef DWORD mdbx_tid_t;
|
||||||
|
typedef SSIZE_T ssize_t;
|
||||||
#define MDBX_ENODATA ERROR_HANDLE_EOF
|
#define MDBX_ENODATA ERROR_HANDLE_EOF
|
||||||
#define MDBX_EINVAL ERROR_INVALID_PARAMETER
|
#define MDBX_EINVAL ERROR_INVALID_PARAMETER
|
||||||
#define MDBX_EACCESS ERROR_ACCESS_DENIED
|
#define MDBX_EACCESS ERROR_ACCESS_DENIED
|
||||||
@ -437,16 +438,24 @@ typedef struct MDBX_stat {
|
|||||||
|
|
||||||
/* Information about the environment */
|
/* Information about the environment */
|
||||||
typedef struct MDBX_envinfo {
|
typedef struct MDBX_envinfo {
|
||||||
void *me_mapaddr; /* Address of map, if fixed */
|
struct {
|
||||||
uint64_t me_mapsize; /* Size of the data memory map */
|
uint64_t lower; /* lower limit for datafile size */
|
||||||
uint64_t me_recent_pgno; /* ID of the last used page */
|
uint64_t upper; /* upper limit for datafile size */
|
||||||
uint64_t me_recent_txnid; /* ID of the last committed transaction */
|
uint64_t current; /* current datafile size */
|
||||||
uint32_t me_maxreaders; /* max reader slots in the environment */
|
uint64_t shrink; /* shrink theshold for datafile */
|
||||||
uint32_t me_numreaders; /* max reader slots used in the environment */
|
uint64_t grow; /* growth step for datafile */
|
||||||
|
} me_geo;
|
||||||
|
uint64_t me_mapsize; /* Size of the data memory map */
|
||||||
|
uint64_t me_last_pgno; /* ID of the last used page */
|
||||||
|
uint64_t me_recent_txnid; /* ID of the last committed transaction */
|
||||||
uint64_t me_latter_reader_txnid; /* ID of the last reader transaction */
|
uint64_t me_latter_reader_txnid; /* ID of the last reader transaction */
|
||||||
uint64_t me_meta0_txnid, me_meta0_sign;
|
uint64_t me_meta0_txnid, me_meta0_sign;
|
||||||
uint64_t me_meta1_txnid, me_meta1_sign;
|
uint64_t me_meta1_txnid, me_meta1_sign;
|
||||||
uint64_t me_meta2_txnid, me_meta2_sign;
|
uint64_t me_meta2_txnid, me_meta2_sign;
|
||||||
|
uint32_t me_maxreaders; /* max reader slots in the environment */
|
||||||
|
uint32_t me_numreaders; /* max reader slots used in the environment */
|
||||||
|
uint32_t me_dxb_pagesize; /* database pagesize */
|
||||||
|
uint32_t me_sys_pagesize; /* system pagesize */
|
||||||
} MDBX_envinfo;
|
} MDBX_envinfo;
|
||||||
|
|
||||||
/* Return a string describing a given error code.
|
/* Return a string describing a given error code.
|
||||||
@ -800,6 +809,11 @@ LIBMDBX_API int mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *fd);
|
|||||||
* - MDBX_EINVAL - an invalid parameter was specified,
|
* - MDBX_EINVAL - an invalid parameter was specified,
|
||||||
* or the environment has an active write transaction. */
|
* or the environment has an active write transaction. */
|
||||||
LIBMDBX_API int mdbx_env_set_mapsize(MDBX_env *env, size_t size);
|
LIBMDBX_API int mdbx_env_set_mapsize(MDBX_env *env, size_t size);
|
||||||
|
LIBMDBX_API int mdbx_env_set_geometry(MDBX_env *env, ssize_t size_lower,
|
||||||
|
ssize_t size_now, ssize_t size_upper,
|
||||||
|
ssize_t growth_step,
|
||||||
|
ssize_t shrink_threshold,
|
||||||
|
ssize_t pagesize);
|
||||||
|
|
||||||
/* Set the maximum number of threads/reader slots for the environment.
|
/* Set the maximum number of threads/reader slots for the environment.
|
||||||
*
|
*
|
||||||
|
59
src/bits.h
59
src/bits.h
@ -125,7 +125,7 @@
|
|||||||
typedef uint32_t pgno_t;
|
typedef uint32_t pgno_t;
|
||||||
#define PRIaPGNO PRIu32
|
#define PRIaPGNO PRIu32
|
||||||
#define MAX_PAGENO ((pgno_t)UINT64_C(0xffffFFFFffff))
|
#define MAX_PAGENO ((pgno_t)UINT64_C(0xffffFFFFffff))
|
||||||
#define MIN_PAGENO (NUM_METAS - 1)
|
#define MIN_PAGENO NUM_METAS
|
||||||
|
|
||||||
/* A transaction ID. */
|
/* A transaction ID. */
|
||||||
typedef uint64_t txnid_t;
|
typedef uint64_t txnid_t;
|
||||||
@ -247,12 +247,17 @@ typedef struct MDBX_meta {
|
|||||||
* zero (nothing) for now */
|
* zero (nothing) for now */
|
||||||
uint8_t mm_extra_pagehdr; /* extra bytes in the page header,
|
uint8_t mm_extra_pagehdr; /* extra bytes in the page header,
|
||||||
* zero (nothing) for now */
|
* zero (nothing) for now */
|
||||||
/* Last used page in the datafile.
|
|
||||||
* Actually the file may be shorter if the freeDB lists the final pages. */
|
|
||||||
pgno_t mm_last_pg;
|
|
||||||
|
|
||||||
uint64_t mm_dbsize_min; /* minimal size of db */
|
struct {
|
||||||
uint64_t mm_dbsize_max; /* maximal size of db */
|
uint16_t grow; /* datafile growth step in pages */
|
||||||
|
uint16_t shrink; /* datafile shrink threshold in pages */
|
||||||
|
pgno_t lower; /* minimal size of datafile in pages */
|
||||||
|
pgno_t upper; /* maximal size of datafile in pages */
|
||||||
|
pgno_t now; /* current size of datafile in pages */
|
||||||
|
pgno_t next; /* first unused page in the datafile,
|
||||||
|
* but actually the file may be shorter. */
|
||||||
|
} mm_geo;
|
||||||
|
|
||||||
MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */
|
MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */
|
||||||
/* The size of pages used in this DB */
|
/* The size of pages used in this DB */
|
||||||
#define mm_psize mm_dbs[FREE_DBI].md_xsize
|
#define mm_psize mm_dbs[FREE_DBI].md_xsize
|
||||||
@ -268,9 +273,6 @@ typedef struct MDBX_meta {
|
|||||||
#define META_IS_STEADY(meta) SIGN_IS_STEADY((meta)->mm_datasync_sign)
|
#define META_IS_STEADY(meta) SIGN_IS_STEADY((meta)->mm_datasync_sign)
|
||||||
volatile uint64_t mm_datasync_sign;
|
volatile uint64_t mm_datasync_sign;
|
||||||
|
|
||||||
/* to be removed */
|
|
||||||
uint64_t mm_mapsize; /* current size of mmap region */
|
|
||||||
|
|
||||||
/* txnid that committed this page, the second of a two-phase-update pair */
|
/* txnid that committed this page, the second of a two-phase-update pair */
|
||||||
volatile txnid_t mm_txnid_b;
|
volatile txnid_t mm_txnid_b;
|
||||||
} MDBX_meta;
|
} MDBX_meta;
|
||||||
@ -481,6 +483,7 @@ struct MDBX_txn {
|
|||||||
/* Nested txn under this txn, set together with flag MDBX_TXN_HAS_CHILD */
|
/* Nested txn under this txn, set together with flag MDBX_TXN_HAS_CHILD */
|
||||||
MDBX_txn *mt_child;
|
MDBX_txn *mt_child;
|
||||||
pgno_t mt_next_pgno; /* next unallocated page */
|
pgno_t mt_next_pgno; /* next unallocated page */
|
||||||
|
pgno_t mt_end_pgno; /* corresponding to the current size of datafile */
|
||||||
/* The ID of this transaction. IDs are integers incrementing from 1.
|
/* The ID of this transaction. IDs are integers incrementing from 1.
|
||||||
* Only committed write transactions increment the ID. If a transaction
|
* Only committed write transactions increment the ID. If a transaction
|
||||||
* aborts, the ID may be re-used by the next writer. */
|
* aborts, the ID may be re-used by the next writer. */
|
||||||
@ -636,8 +639,9 @@ typedef struct MDBX_xcursor {
|
|||||||
|
|
||||||
/* State of FreeDB old pages, stored in the MDBX_env */
|
/* State of FreeDB old pages, stored in the MDBX_env */
|
||||||
typedef struct MDBX_pgstate {
|
typedef struct MDBX_pgstate {
|
||||||
pgno_t *mf_pghead; /* Reclaimed freeDB pages, or NULL before use */
|
pgno_t *mf_reclaimed_pglist; /* Reclaimed freeDB pages, or NULL before use */
|
||||||
txnid_t mf_pglast; /* ID of last used record, or 0 if !mf_pghead */
|
txnid_t mf_last_reclaimed; /* ID of last used record, or 0 if
|
||||||
|
!mf_reclaimed_pglist */
|
||||||
} MDBX_pgstate;
|
} MDBX_pgstate;
|
||||||
|
|
||||||
/* The database environment. */
|
/* The database environment. */
|
||||||
@ -646,6 +650,10 @@ struct MDBX_env {
|
|||||||
uint32_t me_signature;
|
uint32_t me_signature;
|
||||||
mdbx_filehandle_t me_fd; /* The main data file */
|
mdbx_filehandle_t me_fd; /* The main data file */
|
||||||
mdbx_filehandle_t me_lfd; /* The lock file */
|
mdbx_filehandle_t me_lfd; /* The lock file */
|
||||||
|
#ifdef MDBX_OSAL_SECTION
|
||||||
|
MDBX_OSAL_SECTION me_dxb_section;
|
||||||
|
MDBX_OSAL_SECTION me_lck_section;
|
||||||
|
#endif
|
||||||
/* Failed to update the meta page. Probably an I/O error. */
|
/* Failed to update the meta page. Probably an I/O error. */
|
||||||
#define MDBX_FATAL_ERROR UINT32_C(0x80000000)
|
#define MDBX_FATAL_ERROR UINT32_C(0x80000000)
|
||||||
/* Some fields are initialized. */
|
/* Some fields are initialized. */
|
||||||
@ -670,15 +678,14 @@ struct MDBX_env {
|
|||||||
MDBX_txn *me_txn; /* current write transaction */
|
MDBX_txn *me_txn; /* current write transaction */
|
||||||
MDBX_txn *me_txn0; /* prealloc'd write transaction */
|
MDBX_txn *me_txn0; /* prealloc'd write transaction */
|
||||||
size_t me_mapsize; /* size of the data memory map */
|
size_t me_mapsize; /* size of the data memory map */
|
||||||
pgno_t me_maxpg; /* me_mapsize / me_psize */
|
|
||||||
MDBX_dbx *me_dbxs; /* array of static DB info */
|
MDBX_dbx *me_dbxs; /* array of static DB info */
|
||||||
uint16_t *me_dbflags; /* array of flags from MDBX_db.md_flags */
|
uint16_t *me_dbflags; /* array of flags from MDBX_db.md_flags */
|
||||||
unsigned *me_dbiseqs; /* array of dbi sequence numbers */
|
unsigned *me_dbiseqs; /* array of dbi sequence numbers */
|
||||||
mdbx_thread_key_t me_txkey; /* thread-key for readers */
|
mdbx_thread_key_t me_txkey; /* thread-key for readers */
|
||||||
volatile txnid_t *me_oldest; /* ID of oldest reader last time we looked */
|
volatile txnid_t *me_oldest; /* ID of oldest reader last time we looked */
|
||||||
MDBX_pgstate me_pgstate; /* state of old pages from freeDB */
|
MDBX_pgstate me_pgstate; /* state of old pages from freeDB */
|
||||||
#define me_pglast me_pgstate.mf_pglast
|
#define me_last_reclaimed me_pgstate.mf_last_reclaimed
|
||||||
#define me_pghead me_pgstate.mf_pghead
|
#define me_reclaimed_pglist me_pgstate.mf_reclaimed_pglist
|
||||||
MDBX_page *me_dpages; /* list of malloc'd blocks for re-use */
|
MDBX_page *me_dpages; /* list of malloc'd blocks for re-use */
|
||||||
/* IDL of pages that became unused in a write txn */
|
/* IDL of pages that became unused in a write txn */
|
||||||
MDBX_IDL me_free_pgs;
|
MDBX_IDL me_free_pgs;
|
||||||
@ -702,6 +709,13 @@ struct MDBX_env {
|
|||||||
#ifdef USE_VALGRIND
|
#ifdef USE_VALGRIND
|
||||||
int me_valgrind_handle;
|
int me_valgrind_handle;
|
||||||
#endif
|
#endif
|
||||||
|
struct {
|
||||||
|
size_t lower; /* minimal size of datafile */
|
||||||
|
size_t upper; /* maximal size of datafile */
|
||||||
|
size_t now; /* current size of datafile */
|
||||||
|
size_t grow; /* step to grow datafile */
|
||||||
|
size_t shrink; /* threshold to shrink datafile */
|
||||||
|
} me_dbgeo; /* */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Nested transaction */
|
/* Nested transaction */
|
||||||
@ -869,13 +883,24 @@ int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin,
|
|||||||
void mdbx_rthc_remove(mdbx_thread_key_t key);
|
void mdbx_rthc_remove(mdbx_thread_key_t key);
|
||||||
void mdbx_rthc_cleanup(void);
|
void mdbx_rthc_cleanup(void);
|
||||||
|
|
||||||
static __inline bool is_power2(size_t x) { return (x & (x - 1)) == 0; }
|
static __inline bool mdbx_is_power2(size_t x) { return (x & (x - 1)) == 0; }
|
||||||
|
|
||||||
static __inline size_t roundup2(size_t value, size_t granularity) {
|
static __inline size_t mdbx_roundup2(size_t value, size_t granularity) {
|
||||||
assert(is_power2(granularity));
|
assert(mdbx_is_power2(granularity));
|
||||||
return (value + granularity - 1) & ~(granularity - 1);
|
return (value + granularity - 1) & ~(granularity - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __inline unsigned mdbx_log2(size_t value) {
|
||||||
|
assert(mdbx_is_power2(value));
|
||||||
|
|
||||||
|
unsigned log = 0;
|
||||||
|
while (value > 1) {
|
||||||
|
log += 1;
|
||||||
|
value >>= 1;
|
||||||
|
}
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
#define MDBX_IS_ERROR(rc) \
|
#define MDBX_IS_ERROR(rc) \
|
||||||
((rc) != MDBX_RESULT_TRUE && (rc) != MDBX_RESULT_FALSE)
|
((rc) != MDBX_RESULT_TRUE && (rc) != MDBX_RESULT_FALSE)
|
||||||
|
|
||||||
|
1191
src/mdbx.c
1191
src/mdbx.c
File diff suppressed because it is too large
Load Diff
210
src/osal.c
210
src/osal.c
@ -49,21 +49,57 @@ static int ntstatus2errcode(NTSTATUS status) {
|
|||||||
* conflict with the regular user-level headers, so we explicitly
|
* conflict with the regular user-level headers, so we explicitly
|
||||||
* declare them here. Using these APIs also means we must link to
|
* declare them here. Using these APIs also means we must link to
|
||||||
* ntdll.dll, which is not linked by default in user code. */
|
* ntdll.dll, which is not linked by default in user code. */
|
||||||
NTSTATUS WINAPI NtCreateSection(OUT PHANDLE sh, IN ACCESS_MASK acc,
|
|
||||||
IN void *oa OPTIONAL,
|
#ifndef NT_SUCCESS
|
||||||
IN PLARGE_INTEGER ms OPTIONAL, IN ULONG pp,
|
#define NT_SUCCESS(x) ((x) >= 0)
|
||||||
IN ULONG aa, IN HANDLE fh OPTIONAL);
|
#define STATUS_SUCCESS ((NTSTATUS)0)
|
||||||
|
#endif
|
||||||
|
typedef struct _UNICODE_STRING {
|
||||||
|
USHORT Length;
|
||||||
|
USHORT MaximumLength;
|
||||||
|
PWSTR Buffer;
|
||||||
|
} UNICODE_STRING, *PUNICODE_STRING;
|
||||||
|
|
||||||
|
typedef struct _OBJECT_ATTRIBUTES {
|
||||||
|
ULONG Length;
|
||||||
|
HANDLE RootDirectory;
|
||||||
|
PUNICODE_STRING ObjectName;
|
||||||
|
ULONG Attributes;
|
||||||
|
PVOID SecurityDescriptor;
|
||||||
|
PVOID SecurityQualityOfService;
|
||||||
|
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
|
||||||
|
|
||||||
|
extern NTSTATUS NTAPI NtCreateSection(
|
||||||
|
OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess,
|
||||||
|
IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
|
IN OPTIONAL PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection,
|
||||||
|
IN ULONG AllocationAttributes, IN OPTIONAL HANDLE FileHandle);
|
||||||
|
|
||||||
|
extern NTSTATUS NTAPI NtExtendSection(IN HANDLE SectionHandle,
|
||||||
|
IN PLARGE_INTEGER NewSectionSize);
|
||||||
|
|
||||||
typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT;
|
typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT;
|
||||||
|
|
||||||
NTSTATUS WINAPI NtMapViewOfSection(IN PHANDLE sh, IN HANDLE ph,
|
extern NTSTATUS NTAPI NtMapViewOfSection(
|
||||||
IN OUT PVOID *addr, IN ULONG_PTR zbits,
|
IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress,
|
||||||
IN SIZE_T cs,
|
IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize,
|
||||||
IN OUT PLARGE_INTEGER off OPTIONAL,
|
IN OUT OPTIONAL PLARGE_INTEGER SectionOffset, IN OUT PSIZE_T ViewSize,
|
||||||
IN OUT PSIZE_T vs, IN SECTION_INHERIT ih,
|
IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType,
|
||||||
IN ULONG at, IN ULONG pp);
|
IN ULONG Win32Protect);
|
||||||
|
|
||||||
NTSTATUS WINAPI NtClose(HANDLE h);
|
extern NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle,
|
||||||
|
IN OPTIONAL PVOID BaseAddress);
|
||||||
|
|
||||||
|
extern NTSTATUS NTAPI NtClose(HANDLE Handle);
|
||||||
|
|
||||||
|
extern NTSTATUS NTAPI NtAllocateVirtualMemory(
|
||||||
|
IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG ZeroBits,
|
||||||
|
IN OUT PULONG RegionSize, IN ULONG AllocationType, IN ULONG Protect);
|
||||||
|
|
||||||
|
extern NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
|
IN PVOID *BaseAddress,
|
||||||
|
IN OUT PULONG RegionSize,
|
||||||
|
IN ULONG FreeType);
|
||||||
|
|
||||||
#endif /* _WIN32 || _WIN64 */
|
#endif /* _WIN32 || _WIN64 */
|
||||||
|
|
||||||
@ -558,6 +594,16 @@ int mdbx_filesync(mdbx_filehandle_t fd, bool fullsync) {
|
|||||||
#elif __GLIBC_PREREQ(2, 16) || _BSD_SOURCE || _XOPEN_SOURCE || \
|
#elif __GLIBC_PREREQ(2, 16) || _BSD_SOURCE || _XOPEN_SOURCE || \
|
||||||
(__GLIBC_PREREQ(2, 8) && _POSIX_C_SOURCE >= 200112L)
|
(__GLIBC_PREREQ(2, 8) && _POSIX_C_SOURCE >= 200112L)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
/* LY: It is no reason to use fdatasync() here, even in case
|
||||||
|
* no such bug in a kernel. Because "no-bug" mean that a kernel
|
||||||
|
* internally do nearly the same, e.g. fdatasync() == fsync()
|
||||||
|
* when no-kernel-bug and file size was changed.
|
||||||
|
*
|
||||||
|
* So, this code is always safe and without appreciable
|
||||||
|
* performance degradation.
|
||||||
|
*
|
||||||
|
* For more info about of a corresponding fdatasync() bug
|
||||||
|
* see http://www.spinics.net/lists/linux-ext4/msg33714.html */
|
||||||
#if _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE >= 500 || \
|
#if _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE >= 500 || \
|
||||||
defined(_POSIX_SYNCHRONIZED_IO)
|
defined(_POSIX_SYNCHRONIZED_IO)
|
||||||
if (!fullsync && fdatasync(fd) == 0)
|
if (!fullsync && fdatasync(fd) == 0)
|
||||||
@ -576,6 +622,22 @@ int mdbx_filesync(mdbx_filehandle_t fd, bool fullsync) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mdbx_filesize_sync(mdbx_filehandle_t fd) {
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
(void)fd;
|
||||||
|
/* Nothing on Windows (i.e. newer 100% steady) */
|
||||||
|
return MDBX_SUCCESS;
|
||||||
|
#else
|
||||||
|
for (;;) {
|
||||||
|
if (fsync(fd) == 0)
|
||||||
|
return MDBX_SUCCESS;
|
||||||
|
int rc = errno;
|
||||||
|
if (rc != EINTR)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length) {
|
int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
BY_HANDLE_FILE_INFORMATION info;
|
BY_HANDLE_FILE_INFORMATION info;
|
||||||
@ -678,51 +740,113 @@ int mdbx_msync(void *addr, size_t length, int async) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_mremap_size(void **address, size_t old_size, size_t new_size) {
|
int mdbx_mmap(int flags, mdbx_mmap_param_t *map, size_t length, size_t limit) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
*address = MAP_FAILED;
|
NTSTATUS rc = NtCreateSection(
|
||||||
(void)old_size;
|
&map->section,
|
||||||
(void)new_size;
|
/* DesiredAccess */ SECTION_MAP_READ | SECTION_EXTEND_SIZE |
|
||||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
((flags & MDBX_WRITEMAP) ? SECTION_MAP_WRITE : 0),
|
||||||
|
/* ObjectAttributes */ NULL, /* MaximumSize */ NULL,
|
||||||
|
/* SectionPageProtection */ (flags & MDBX_RDONLY) ? PAGE_READONLY
|
||||||
|
: PAGE_READWRITE,
|
||||||
|
/* AllocationAttributes */ SEC_RESERVE, map->fd);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(rc)) {
|
||||||
|
map->section = 0;
|
||||||
|
map->address = MAP_FAILED;
|
||||||
|
return ntstatus2errcode(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
map->address = NULL;
|
||||||
|
size_t ViewSize = limit;
|
||||||
|
rc = NtMapViewOfSection(
|
||||||
|
map->section, GetCurrentProcess(), &map->address,
|
||||||
|
/* ZeroBits */ 0,
|
||||||
|
/* CommitSize */ length,
|
||||||
|
/* SectionOffset */ NULL, &ViewSize,
|
||||||
|
/* InheritDisposition */ ViewUnmap,
|
||||||
|
/* AllocationType */ (flags & MDBX_RDONLY) ? 0 : MEM_RESERVE,
|
||||||
|
/* Win32Protect */ (flags & MDBX_WRITEMAP) ? PAGE_READWRITE
|
||||||
|
: PAGE_READONLY);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(rc)) {
|
||||||
|
NtClose(map->section);
|
||||||
|
map->section = 0;
|
||||||
|
map->address = MAP_FAILED;
|
||||||
|
return ntstatus2errcode(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(map->address != MAP_FAILED);
|
||||||
|
return MDBX_SUCCESS;
|
||||||
#else
|
#else
|
||||||
*address = mremap(*address, old_size, new_size, 0, address);
|
(void)length;
|
||||||
return (*address != MAP_FAILED) ? MDBX_SUCCESS : errno;
|
map->address = mmap(
|
||||||
|
NULL, limit, (flags & MDBX_WRITEMAP) ? PROT_READ | PROT_WRITE : PROT_READ,
|
||||||
|
MAP_SHARED, map->fd, 0);
|
||||||
|
return (map->address != MAP_FAILED) ? MDBX_SUCCESS : errno;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_mmap(void **address, size_t length, int rw, mdbx_filehandle_t fd) {
|
int mdbx_munmap(mdbx_mmap_param_t *map, size_t length) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
HANDLE h = CreateFileMapping(fd, NULL, rw ? PAGE_READWRITE : PAGE_READONLY,
|
|
||||||
HIGH_DWORD(length), (DWORD)length, NULL);
|
|
||||||
if (!h)
|
|
||||||
return mdbx_get_errno_checked();
|
|
||||||
*address = MapViewOfFileEx(h, rw ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0,
|
|
||||||
length, *address);
|
|
||||||
int rc = (*address != MAP_FAILED) ? MDBX_SUCCESS : mdbx_get_errno_checked();
|
|
||||||
CloseHandle(h);
|
|
||||||
return rc;
|
|
||||||
#else
|
|
||||||
*address = mmap(NULL, length, rw ? PROT_READ | PROT_WRITE : PROT_READ,
|
|
||||||
MAP_SHARED, fd, 0);
|
|
||||||
return (*address != MAP_FAILED) ? MDBX_SUCCESS : errno;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdbx_munmap(void *address, size_t length) {
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
(void)length;
|
(void)length;
|
||||||
return UnmapViewOfFile(address) ? MDBX_SUCCESS : mdbx_get_errno_checked();
|
if (map->section)
|
||||||
|
NtClose(map->section);
|
||||||
|
NTSTATUS rc = NtUnmapViewOfSection(GetCurrentProcess(), map->address);
|
||||||
|
return NT_SUCCESS(rc) ? MDBX_SUCCESS : ntstatus2errcode(rc);
|
||||||
#else
|
#else
|
||||||
return (munmap(address, length) == 0) ? MDBX_SUCCESS : errno;
|
return (munmap(map->address, length) == 0) ? MDBX_SUCCESS : errno;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdbx_mlock(const void *address, size_t length) {
|
int mdbx_mlock(mdbx_mmap_param_t *map, size_t length) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
return VirtualLock((void *)address, length) ? MDBX_SUCCESS
|
return VirtualLock(map->address, length) ? MDBX_SUCCESS : GetLastError();
|
||||||
: mdbx_get_errno_checked();
|
|
||||||
#else
|
#else
|
||||||
return (mlock(address, length) == 0) ? MDBX_SUCCESS : errno;
|
return (mlock(map->address, length) == 0) ? MDBX_SUCCESS : errno;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int mdbx_mresize(int flags, mdbx_mmap_param_t *map, size_t current,
|
||||||
|
size_t wanna) {
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
if (wanna > current) {
|
||||||
|
/* growth */
|
||||||
|
uint8_t *ptr = (uint8_t *)map->address + current;
|
||||||
|
return (ptr == VirtualAlloc(ptr, wanna - current, MEM_COMMIT,
|
||||||
|
(flags & MDBX_WRITEMAP) ? PAGE_READWRITE
|
||||||
|
: PAGE_READONLY))
|
||||||
|
? MDBX_SUCCESS
|
||||||
|
: GetLastError();
|
||||||
|
}
|
||||||
|
/* Windows is unable shrinking a mapped file */
|
||||||
|
return MDBX_RESULT_TRUE;
|
||||||
|
#else
|
||||||
|
(void)flags;
|
||||||
|
(void)current;
|
||||||
|
return mdbx_ftruncate(map->fd, wanna);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int mdbx_mremap(int flags, mdbx_mmap_param_t *map, size_t old_limit,
|
||||||
|
size_t new_limit) {
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
(void)flags;
|
||||||
|
if (old_limit > new_limit) {
|
||||||
|
/* Windows is unable shrinking a mapped section */
|
||||||
|
return ERROR_USER_MAPPED_FILE;
|
||||||
|
}
|
||||||
|
LARGE_INTEGER new_size;
|
||||||
|
new_size.QuadPart = new_limit;
|
||||||
|
NTSTATUS rc = NtExtendSection(map->section, &new_size);
|
||||||
|
return NT_SUCCESS(rc) ? MDBX_SUCCESS : ntstatus2errcode(rc);
|
||||||
|
#else
|
||||||
|
(void)flags;
|
||||||
|
void *ptr = mremap(map->address, old_limit, new_limit, 0);
|
||||||
|
if (ptr == MAP_FAILED)
|
||||||
|
return errno;
|
||||||
|
map->address = ptr;
|
||||||
|
return MDBX_SUCCESS;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
src/osal.h
21
src/osal.h
@ -69,7 +69,7 @@
|
|||||||
#define HAVE_SYS_TYPES_H
|
#define HAVE_SYS_TYPES_H
|
||||||
typedef HANDLE mdbx_thread_t;
|
typedef HANDLE mdbx_thread_t;
|
||||||
typedef unsigned mdbx_thread_key_t;
|
typedef unsigned mdbx_thread_key_t;
|
||||||
typedef SSIZE_T ssize_t;
|
#define MDBX_OSAL_SECTION HANDLE
|
||||||
#define MAP_FAILED NULL
|
#define MAP_FAILED NULL
|
||||||
#define HIGH_DWORD(v) ((DWORD)((sizeof(v) > 4) ? ((uint64_t)(v) >> 32) : 0))
|
#define HIGH_DWORD(v) ((DWORD)((sizeof(v) > 4) ? ((uint64_t)(v) >> 32) : 0))
|
||||||
#define THREAD_CALL WINAPI
|
#define THREAD_CALL WINAPI
|
||||||
@ -430,16 +430,27 @@ void *mdbx_thread_rthc_get(mdbx_thread_key_t key);
|
|||||||
void mdbx_thread_rthc_set(mdbx_thread_key_t key, const void *value);
|
void mdbx_thread_rthc_set(mdbx_thread_key_t key, const void *value);
|
||||||
|
|
||||||
int mdbx_filesync(mdbx_filehandle_t fd, bool fullsync);
|
int mdbx_filesync(mdbx_filehandle_t fd, bool fullsync);
|
||||||
|
int mdbx_filesize_sync(mdbx_filehandle_t fd);
|
||||||
int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length);
|
int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length);
|
||||||
int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length);
|
int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length);
|
||||||
int mdbx_openfile(const char *pathname, int flags, mode_t mode,
|
int mdbx_openfile(const char *pathname, int flags, mode_t mode,
|
||||||
mdbx_filehandle_t *fd);
|
mdbx_filehandle_t *fd);
|
||||||
int mdbx_closefile(mdbx_filehandle_t fd);
|
int mdbx_closefile(mdbx_filehandle_t fd);
|
||||||
|
|
||||||
int mdbx_mremap_size(void **address, size_t old_size, size_t new_size);
|
typedef struct mdbx_mmap_param {
|
||||||
int mdbx_mmap(void **address, size_t length, int rw, mdbx_filehandle_t fd);
|
void *address;
|
||||||
int mdbx_munmap(void *address, size_t length);
|
#ifdef MDBX_OSAL_SECTION
|
||||||
int mdbx_mlock(const void *address, size_t length);
|
MDBX_OSAL_SECTION section;
|
||||||
|
#endif
|
||||||
|
mdbx_filehandle_t fd;
|
||||||
|
} mdbx_mmap_param_t;
|
||||||
|
int mdbx_mmap(int flags, mdbx_mmap_param_t *map, size_t length, size_t limit);
|
||||||
|
int mdbx_munmap(mdbx_mmap_param_t *map, size_t length);
|
||||||
|
int mdbx_mlock(mdbx_mmap_param_t *map, size_t length);
|
||||||
|
int mdbx_mresize(int flags, mdbx_mmap_param_t *map, size_t current,
|
||||||
|
size_t wanna);
|
||||||
|
int mdbx_mremap(int flags, mdbx_mmap_param_t *map, size_t old_limit,
|
||||||
|
size_t new_limit);
|
||||||
|
|
||||||
static __inline mdbx_pid_t mdbx_getpid(void) {
|
static __inline mdbx_pid_t mdbx_getpid(void) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
@ -345,10 +345,10 @@ static int handle_freedb(const uint64_t record_number, const MDBX_val *key,
|
|||||||
reclaimable_pages += number;
|
reclaimable_pages += number;
|
||||||
for (i = number, prev = 1; --i >= 0;) {
|
for (i = number, prev = 1; --i >= 0;) {
|
||||||
pg = iptr[i];
|
pg = iptr[i];
|
||||||
if (pg < NUM_METAS || pg > envinfo.me_recent_pgno)
|
if (pg < NUM_METAS || pg > envinfo.me_last_pgno)
|
||||||
problem_add("entry", record_number, "wrong idl entry",
|
problem_add("entry", record_number, "wrong idl entry",
|
||||||
"%u < %" PRIiPTR " < %" PRIiPTR "", NUM_METAS, pg,
|
"%u < %" PRIiPTR " < %" PRIiPTR "", NUM_METAS, pg,
|
||||||
envinfo.me_recent_pgno);
|
envinfo.me_last_pgno);
|
||||||
else if (pg <= prev) {
|
else if (pg <= prev) {
|
||||||
bad = " [bad sequence]";
|
bad = " [bad sequence]";
|
||||||
problem_add("entry", record_number, "bad sequence",
|
problem_add("entry", record_number, "bad sequence",
|
||||||
@ -727,6 +727,17 @@ static int check_meta_head(bool steady) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print_size(const char *prefix, const uint64_t value,
|
||||||
|
const char *suffix) {
|
||||||
|
const char sf[] =
|
||||||
|
"KMGTPEZY"; /* LY: Kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta! */
|
||||||
|
double k = 1024.0;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; sf[i + 1] && value / k > 1000.0; ++i)
|
||||||
|
k *= 1024;
|
||||||
|
print("%s%" PRIu64 " (%.2f %cb)%s", prefix, value, value / k, sf[i], suffix);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int i, rc;
|
int i, rc;
|
||||||
char *prog = argv[0];
|
char *prog = argv[0];
|
||||||
@ -858,21 +869,26 @@ int main(int argc, char *argv[]) {
|
|||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastpgno = envinfo.me_recent_pgno + 1;
|
lastpgno = envinfo.me_last_pgno + 1;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
double k = 1024.0;
|
print(" - pagesize %u (%u system), max keysize %" PRIuPTR
|
||||||
const char sf[] =
|
", max readers %u\n",
|
||||||
"KMGTPEZY"; /* LY: Kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta! */
|
envinfo.me_dxb_pagesize, envinfo.me_sys_pagesize, maxkeysize,
|
||||||
for (i = 0; sf[i + 1] && envinfo.me_mapsize / k > 1000.0; ++i)
|
envinfo.me_maxreaders);
|
||||||
k *= 1024;
|
print_size(" - mapsize ", envinfo.me_mapsize, "\n");
|
||||||
print(" - map size %" PRIu64 " (%.2f %cb)\n", envinfo.me_mapsize,
|
if (envinfo.me_geo.lower == envinfo.me_geo.upper)
|
||||||
envinfo.me_mapsize / k, sf[i]);
|
print_size(" - fixed datafile: ", envinfo.me_geo.current, "");
|
||||||
if (envinfo.me_mapaddr)
|
else {
|
||||||
print(" - mapaddr %p\n", envinfo.me_mapaddr);
|
print_size(" - dynamic datafile: ", envinfo.me_geo.lower, "");
|
||||||
print(" - pagesize %u, max keysize %" PRIuPTR ", max readers %u\n",
|
print_size(" .. ", envinfo.me_geo.upper, ", ");
|
||||||
envstat.ms_psize, maxkeysize, envinfo.me_maxreaders);
|
print_size("+", envinfo.me_geo.grow, ", ");
|
||||||
|
print_size("-", envinfo.me_geo.shrink, "\n");
|
||||||
|
print_size(" - current datafile: ", envinfo.me_geo.current, "");
|
||||||
|
}
|
||||||
|
printf(", %" PRIu64 " pages\n",
|
||||||
|
envinfo.me_geo.current / envinfo.me_dxb_pagesize);
|
||||||
print(" - transactions: recent %" PRIu64 ", latter reader %" PRIu64
|
print(" - transactions: recent %" PRIu64 ", latter reader %" PRIu64
|
||||||
", lag %" PRIi64 "\n",
|
", lag %" PRIi64 "\n",
|
||||||
envinfo.me_recent_txnid, envinfo.me_latter_reader_txnid,
|
envinfo.me_recent_txnid, envinfo.me_latter_reader_txnid,
|
||||||
@ -884,7 +900,7 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
print(" - performs check for meta-pages overlap\n");
|
print(" - performs check for meta-pages clashes\n");
|
||||||
if (meta_eq(envinfo.me_meta0_txnid, envinfo.me_meta0_sign,
|
if (meta_eq(envinfo.me_meta0_txnid, envinfo.me_meta0_sign,
|
||||||
envinfo.me_meta1_txnid, envinfo.me_meta1_sign)) {
|
envinfo.me_meta1_txnid, envinfo.me_meta1_sign)) {
|
||||||
print(" - meta-%d and meta-%d are clashed\n", 0, 1);
|
print(" - meta-%d and meta-%d are clashed\n", 0, 1);
|
||||||
@ -1008,6 +1024,8 @@ int main(int argc, char *argv[]) {
|
|||||||
uint64_t value = envinfo.me_mapsize / envstat.ms_psize;
|
uint64_t value = envinfo.me_mapsize / envstat.ms_psize;
|
||||||
double percent = value / 100.0;
|
double percent = value / 100.0;
|
||||||
print(" - pages info: %" PRIu64 " total", value);
|
print(" - pages info: %" PRIu64 " total", value);
|
||||||
|
value = envinfo.me_geo.current / envinfo.me_dxb_pagesize;
|
||||||
|
print(", backed %" PRIu64 " (%.1f%%)", value, value / percent);
|
||||||
print(", allocated %" PRIu64 " (%.1f%%)", lastpgno, lastpgno / percent);
|
print(", allocated %" PRIu64 " (%.1f%%)", lastpgno, lastpgno / percent);
|
||||||
|
|
||||||
if (verbose > 1) {
|
if (verbose > 1) {
|
||||||
|
@ -110,8 +110,6 @@ static int dumpit(MDBX_txn *txn, MDBX_dbi dbi, char *name) {
|
|||||||
printf("database=%s\n", name);
|
printf("database=%s\n", name);
|
||||||
printf("type=btree\n");
|
printf("type=btree\n");
|
||||||
printf("mapsize=%" PRIu64 "\n", info.me_mapsize);
|
printf("mapsize=%" PRIu64 "\n", info.me_mapsize);
|
||||||
if (info.me_mapaddr)
|
|
||||||
printf("mapaddr=%p\n", info.me_mapaddr);
|
|
||||||
printf("maxreaders=%u\n", info.me_maxreaders);
|
printf("maxreaders=%u\n", info.me_maxreaders);
|
||||||
|
|
||||||
for (i = 0; dbflags[i].bit; i++)
|
for (i = 0; dbflags[i].bit; i++)
|
||||||
|
@ -107,8 +107,8 @@ static void readhdr(void) {
|
|||||||
ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len);
|
ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len);
|
||||||
if (ptr)
|
if (ptr)
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
i = sscanf((char *)dbuf.iov_base + STRLENOF("mapaddr="), "%p",
|
void *unused;
|
||||||
&envinfo.me_mapaddr);
|
i = sscanf((char *)dbuf.iov_base + STRLENOF("mapaddr="), "%p", &unused);
|
||||||
if (i != 1) {
|
if (i != 1) {
|
||||||
fprintf(stderr, "%s: line %" PRIiPTR ": invalid mapaddr %s\n", prog,
|
fprintf(stderr, "%s: line %" PRIiPTR ": invalid mapaddr %s\n", prog,
|
||||||
lineno, (char *)dbuf.iov_base + STRLENOF("mapaddr="));
|
lineno, (char *)dbuf.iov_base + STRLENOF("mapaddr="));
|
||||||
|
@ -13,15 +13,17 @@
|
|||||||
* top-level directory of the distribution or, alternatively, at
|
* top-level directory of the distribution or, alternatively, at
|
||||||
* <http://www.OpenLDAP.org/license.html>. */
|
* <http://www.OpenLDAP.org/license.html>. */
|
||||||
|
|
||||||
#include "../../mdbx.h"
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "../../mdbx.h"
|
||||||
|
#include "../bits.h"
|
||||||
|
|
||||||
static void prstat(MDBX_stat *ms) {
|
static void prstat(MDBX_stat *ms) {
|
||||||
printf(" Page size: %u\n", ms->ms_psize);
|
printf(" Pagesize: %u\n", ms->ms_psize);
|
||||||
printf(" Tree depth: %u\n", ms->ms_depth);
|
printf(" Tree depth: %u\n", ms->ms_depth);
|
||||||
printf(" Branch pages: %" PRIu64 "\n", ms->ms_branch_pages);
|
printf(" Branch pages: %" PRIu64 "\n", ms->ms_branch_pages);
|
||||||
printf(" Leaf pages: %" PRIu64 "\n", ms->ms_leaf_pages);
|
printf(" Leaf pages: %" PRIu64 "\n", ms->ms_leaf_pages);
|
||||||
@ -121,11 +123,24 @@ int main(int argc, char *argv[]) {
|
|||||||
(void)mdbx_env_stat(env, &mst, sizeof(mst));
|
(void)mdbx_env_stat(env, &mst, sizeof(mst));
|
||||||
(void)mdbx_env_info(env, &mei, sizeof(mei));
|
(void)mdbx_env_info(env, &mei, sizeof(mei));
|
||||||
printf("Environment Info\n");
|
printf("Environment Info\n");
|
||||||
printf(" Map address: %p\n", mei.me_mapaddr);
|
printf(" Pagesize: %u\n", mst.ms_psize);
|
||||||
printf(" Map size: %" PRIu64 "\n", mei.me_mapsize);
|
if (mei.me_geo.lower != mei.me_geo.upper) {
|
||||||
printf(" Page size: %u\n", mst.ms_psize);
|
printf(" Dynamic datafile: %" PRIu64 "..%" PRIu64 " bytes (+%" PRIu64
|
||||||
printf(" Max pages: %" PRIu64 "\n", mei.me_mapsize / mst.ms_psize);
|
"/-%" PRIu64 "), %" PRIu64 "..%" PRIu64 " pages (+%" PRIu64
|
||||||
printf(" Number of pages used: %" PRIu64 "\n", mei.me_recent_pgno + 1);
|
"/-%" PRIu64 ")\n",
|
||||||
|
mei.me_geo.lower, mei.me_geo.upper, mei.me_geo.grow,
|
||||||
|
mei.me_geo.shrink, mei.me_geo.lower / mst.ms_psize,
|
||||||
|
mei.me_geo.upper / mst.ms_psize, mei.me_geo.grow / mst.ms_psize,
|
||||||
|
mei.me_geo.shrink / mst.ms_psize);
|
||||||
|
printf(" Current datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n",
|
||||||
|
mei.me_geo.current, mei.me_geo.current / mst.ms_psize);
|
||||||
|
} else {
|
||||||
|
printf(" Fixed datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n",
|
||||||
|
mei.me_geo.current, mei.me_geo.current / mst.ms_psize);
|
||||||
|
}
|
||||||
|
printf(" Current mapsize: %" PRIu64 " bytes, %" PRIu64 " pages \n",
|
||||||
|
mei.me_mapsize, mei.me_mapsize / mst.ms_psize);
|
||||||
|
printf(" Number of pages used: %" PRIu64 "\n", mei.me_last_pgno + 1);
|
||||||
printf(" Last transaction ID: %" PRIu64 "\n", mei.me_recent_txnid);
|
printf(" Last transaction ID: %" PRIu64 "\n", mei.me_recent_txnid);
|
||||||
printf(" Tail transaction ID: %" PRIu64 " (%" PRIi64 ")\n",
|
printf(" Tail transaction ID: %" PRIu64 " (%" PRIi64 ")\n",
|
||||||
mei.me_latter_reader_txnid,
|
mei.me_latter_reader_txnid,
|
||||||
@ -161,8 +176,8 @@ int main(int argc, char *argv[]) {
|
|||||||
if (freinfo) {
|
if (freinfo) {
|
||||||
MDBX_cursor *cursor;
|
MDBX_cursor *cursor;
|
||||||
MDBX_val key, data;
|
MDBX_val key, data;
|
||||||
size_t pages = 0, *iptr;
|
pgno_t pages = 0, *iptr;
|
||||||
size_t reclaimable = 0;
|
pgno_t reclaimable = 0;
|
||||||
|
|
||||||
printf("Freelist Status\n");
|
printf("Freelist Status\n");
|
||||||
dbi = 0;
|
dbi = 0;
|
||||||
@ -186,7 +201,7 @@ int main(int argc, char *argv[]) {
|
|||||||
reclaimable += *iptr;
|
reclaimable += *iptr;
|
||||||
if (freinfo > 1) {
|
if (freinfo > 1) {
|
||||||
char *bad = "";
|
char *bad = "";
|
||||||
size_t pg, prev;
|
pgno_t pg, prev;
|
||||||
ssize_t i, j, span = 0;
|
ssize_t i, j, span = 0;
|
||||||
j = *iptr++;
|
j = *iptr++;
|
||||||
for (i = j, prev = 1; --i >= 0;) {
|
for (i = j, prev = 1; --i >= 0;) {
|
||||||
@ -198,53 +213,52 @@ int main(int argc, char *argv[]) {
|
|||||||
for (; i >= span && iptr[i - span] == pg; span++, pg++)
|
for (; i >= span && iptr[i - span] == pg; span++, pg++)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
printf(" Transaction %" PRIuPTR ", %" PRIiPTR
|
printf(" Transaction %" PRIaTXN ", %" PRIiPTR
|
||||||
" pages, maxspan %" PRIiPTR "%s\n",
|
" pages, maxspan %" PRIiPTR "%s\n",
|
||||||
*(size_t *)key.iov_base, j, span, bad);
|
*(txnid_t *)key.iov_base, j, span, bad);
|
||||||
if (freinfo > 2) {
|
if (freinfo > 2) {
|
||||||
for (--j; j >= 0;) {
|
for (--j; j >= 0;) {
|
||||||
pg = iptr[j];
|
pg = iptr[j];
|
||||||
for (span = 1; --j >= 0 && iptr[j] == pg + span; span++)
|
for (span = 1; --j >= 0 && iptr[j] == pg + span; span++)
|
||||||
;
|
;
|
||||||
if (span > 1)
|
if (span > 1)
|
||||||
printf(" %9zu[%" PRIiPTR "]\n", pg, span);
|
printf(" %9" PRIaPGNO "[%" PRIiPTR "]\n", pg, span);
|
||||||
else
|
else
|
||||||
printf(" %9zu\n", pg);
|
printf(" %9" PRIaPGNO "\n", pg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mdbx_cursor_close(cursor);
|
mdbx_cursor_close(cursor);
|
||||||
if (envinfo) {
|
if (envinfo) {
|
||||||
size_t value = mei.me_mapsize / mst.ms_psize;
|
uint64_t value = mei.me_mapsize / mst.ms_psize;
|
||||||
double percent = value / 100.0;
|
double percent = value / 100.0;
|
||||||
printf("Page Allocation Info\n");
|
printf("Page Allocation Info\n");
|
||||||
printf(" Max pages: %9zu 100%%\n", value);
|
printf(" Max pages: %" PRIu64 " 100%%\n", value);
|
||||||
|
|
||||||
value = mei.me_recent_pgno + 1;
|
value = mei.me_last_pgno + 1;
|
||||||
printf(" Number of pages used: %" PRIuPTR " %.1f%%\n", value,
|
printf(" Pages used: %" PRIu64 " %.1f%%\n", value, value / percent);
|
||||||
value / percent);
|
|
||||||
|
|
||||||
value = mei.me_mapsize / mst.ms_psize - (mei.me_recent_pgno + 1);
|
value = mei.me_mapsize / mst.ms_psize - (mei.me_last_pgno + 1);
|
||||||
printf(" Remained: %" PRIuPTR " %.1f%%\n", value, value / percent);
|
printf(" Remained: %" PRIu64 " %.1f%%\n", value, value / percent);
|
||||||
|
|
||||||
value = mei.me_recent_pgno + 1 - pages;
|
value = mei.me_last_pgno + 1 - pages;
|
||||||
printf(" Used now: %" PRIuPTR " %.1f%%\n", value, value / percent);
|
printf(" Used now: %" PRIu64 " %.1f%%\n", value, value / percent);
|
||||||
|
|
||||||
value = pages;
|
value = pages;
|
||||||
printf(" Unallocated: %" PRIuPTR " %.1f%%\n", value, value / percent);
|
printf(" Unallocated: %" PRIu64 " %.1f%%\n", value, value / percent);
|
||||||
|
|
||||||
value = pages - reclaimable;
|
value = pages - reclaimable;
|
||||||
printf(" Detained: %" PRIuPTR " %.1f%%\n", value, value / percent);
|
printf(" Detained: %" PRIu64 " %.1f%%\n", value, value / percent);
|
||||||
|
|
||||||
value = reclaimable;
|
value = reclaimable;
|
||||||
printf(" Reclaimable: %" PRIuPTR " %.1f%%\n", value, value / percent);
|
printf(" Reclaimable: %" PRIu64 " %.1f%%\n", value, value / percent);
|
||||||
|
|
||||||
value = mei.me_mapsize / mst.ms_psize - (mei.me_recent_pgno + 1) +
|
value =
|
||||||
reclaimable;
|
mei.me_mapsize / mst.ms_psize - (mei.me_last_pgno + 1) + reclaimable;
|
||||||
printf(" Available: %" PRIuPTR " %.1f%%\n", value, value / percent);
|
printf(" Available: %" PRIu64 " %.1f%%\n", value, value / percent);
|
||||||
} else
|
} else
|
||||||
printf(" Free pages: %" PRIuPTR "\n", pages);
|
printf(" Free pages: %" PRIaPGNO "\n", pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = mdbx_dbi_open(txn, subname, 0, &dbi);
|
rc = mdbx_dbi_open(txn, subname, 0, &dbi);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user