cacheflush(
char*
addr,
intnbytes,
intcache);
82 #define CACHEFLUSH(addr, bytes, cache) cacheflush(addr, bytes, cache) 84 #define CACHEFLUSH(addr, bytes, cache) 87 #if defined(__linux) && !defined(MDB_FDATASYNC_WORKS) 93 #define BROKEN_FDATASYNC 112 #if defined(__sun) || defined(ANDROID) 114 #define HAVE_MEMALIGN 1 118 # define _POSIX_PTHREAD_SEMANTICS 1 122 #if !(defined(BYTE_ORDER) || defined(__BYTE_ORDER)) 123 #include <netinet/in.h> 127 #if defined(__APPLE__) || defined (BSD) || defined(__FreeBSD_kernel__) 128 # define MDB_USE_POSIX_SEM 1 129 # define MDB_FDATASYNC fsync 130 #elif defined(ANDROID) 131 # define MDB_FDATASYNC fsync 137 #ifdef MDB_USE_POSIX_SEM 138 # define MDB_USE_HASH 1 139 #include <semaphore.h> 141 #define MDB_USE_POSIX_MUTEX 1 145 #if defined(_WIN32) + defined(MDB_USE_POSIX_SEM) \ 146 + defined(MDB_USE_POSIX_MUTEX) != 1 147 # error "Ambiguous shared-lock implementation" 151 #include <valgrind/memcheck.h> 152 #define VGMEMP_CREATE(h,r,z) VALGRIND_CREATE_MEMPOOL(h,r,z) 153 #define VGMEMP_ALLOC(h,a,s) VALGRIND_MEMPOOL_ALLOC(h,a,s) 154 #define VGMEMP_FREE(h,a) VALGRIND_MEMPOOL_FREE(h,a) 155 #define VGMEMP_DESTROY(h) VALGRIND_DESTROY_MEMPOOL(h) 156 #define VGMEMP_DEFINED(a,s) VALGRIND_MAKE_MEM_DEFINED(a,s) 158 #define VGMEMP_CREATE(h,r,z) 159 #define VGMEMP_ALLOC(h,a,s) 160 #define VGMEMP_FREE(h,a) 161 #define VGMEMP_DESTROY(h) 162 #define VGMEMP_DEFINED(a,s) 166 # if (defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)) 168 # define LITTLE_ENDIAN 1234 169 # define BIG_ENDIAN 4321 170 # ifdef _LITTLE_ENDIAN 171 # define BYTE_ORDER LITTLE_ENDIAN 173 # define BYTE_ORDER BIG_ENDIAN 176 # define BYTE_ORDER __BYTE_ORDER 180 #ifndef LITTLE_ENDIAN 181 #define LITTLE_ENDIAN __LITTLE_ENDIAN 184 #define BIG_ENDIAN __BIG_ENDIAN 187 #if defined(__i386) || defined(__x86_64) || defined(_M_IX86) 188 #define MISALIGNED_OK 1 194 #if (BYTE_ORDER == LITTLE_ENDIAN) == (BYTE_ORDER == BIG_ENDIAN) 195 # error "Unknown or unsupported endianness (BYTE_ORDER)" 196 #elif (-6 & 5) || CHAR_BIT != 8 || UINT_MAX < 0xffffffff || ULONG_MAX % 0xFFFF 197 # error "Two's complement, reasonably sized integer types, please" 203 # define ESECT __attribute__ ((section("__TEXT,text_env")))
205 # define ESECT __attribute__ ((section("text_env")))
212 #define CALL_CONV WINAPI 234 #if __STDC_VERSION__ >= 199901L 235 # define mdb_func_ __func__ 236 #elif __GNUC__ >= 2 || _MSC_VER >= 1300 237 # define mdb_func_ __FUNCTION__ 240 # define mdb_func_ "<mdb_unknown>" 244 #define MDB_NO_ROOT (MDB_LAST_ERRCODE + 10) 246 #define MDB_OWNERDEAD ((int) WAIT_ABANDONED) 247 #elif defined(MDB_USE_POSIX_MUTEX) && defined(EOWNERDEAD) 248 #define MDB_OWNERDEAD EOWNERDEAD 252 #define GLIBC_VER ((__GLIBC__ << 16 )| __GLIBC_MINOR__) 261 #ifndef MDB_USE_ROBUST 263 # define MDB_USE_ROBUST 0 267 #ifndef MDB_USE_ROBUST 269 # if defined(MDB_USE_POSIX_MUTEX) && (defined(ANDROID) || \ 270 (defined(__GLIBC__) && GLIBC_VER < 0x020004)) 271 # define MDB_USE_ROBUST 0 273 # define MDB_USE_ROBUST 1 277 #if defined(MDB_USE_POSIX_MUTEX) && (MDB_USE_ROBUST) 279 # if (defined(__GLIBC__) && GLIBC_VER < 0x02000c) || \ 280 (defined(PTHREAD_MUTEX_ROBUST_NP) && !defined(PTHREAD_MUTEX_ROBUST)) 281 # define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP 282 # define pthread_mutexattr_setrobust(attr, flag) pthread_mutexattr_setrobust_np(attr, flag) 283 # define pthread_mutex_consistent(mutex) pthread_mutex_consistent_np(mutex) 287 #if defined(MDB_OWNERDEAD) && (MDB_USE_ROBUST) 288 #define MDB_ROBUST_SUPPORTED 1 292 #define MDB_USE_HASH 1 293 #define MDB_PIDLOCK 0 294 #define THREAD_RET DWORD 295 #define pthread_t HANDLE 296 #define pthread_mutex_t HANDLE 297 #define pthread_cond_t HANDLE 299 #define pthread_key_t DWORD 300 #define pthread_self() GetCurrentThreadId() 301 #define pthread_key_create(x,y) \ 302 ((*(x) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? ErrCode() : 0) 303 #define pthread_key_delete(x) TlsFree(x) 304 #define pthread_getspecific(x) TlsGetValue(x) 305 #define pthread_setspecific(x,y) (TlsSetValue(x,y) ? 0 : ErrCode()) 306 #define pthread_mutex_unlock(x) ReleaseMutex(*x) 307 #define pthread_mutex_lock(x) WaitForSingleObject(*x, INFINITE) 308 #define pthread_cond_signal(x) SetEvent(*x) 309 #define pthread_cond_wait(cond,mutex) do{SignalObjectAndWait(*mutex, *cond, INFINITE, FALSE); WaitForSingleObject(*mutex, INFINITE);}while(0) 310 #define THREAD_CREATE(thr,start,arg) \ 311 (((thr) = CreateThread(NULL, 0, start, arg, 0, NULL)) ? 0 : ErrCode()) 312 #define THREAD_FINISH(thr) \ 313 (WaitForSingleObject(thr, INFINITE) ? ErrCode() : 0) 314 #define LOCK_MUTEX0(mutex) WaitForSingleObject(mutex, INFINITE) 315 #define UNLOCK_MUTEX(mutex) ReleaseMutex(mutex) 316 #define mdb_mutex_consistent(mutex) 0 317 #define getpid() GetCurrentProcessId() 318 #define MDB_FDATASYNC(fd) (!FlushFileBuffers(fd)) 319 #define MDB_MSYNC(addr,len,flags) (!FlushViewOfFile(addr,len)) 320 #define ErrCode() GetLastError() 321 #define GET_PAGESIZE(x) {SYSTEM_INFO si; GetSystemInfo(&si); (x) = si.dwPageSize;} 322 #define close(fd) (CloseHandle(fd) ? 0 : -1) 323 #define munmap(ptr,len) UnmapViewOfFile(ptr) 324 #ifdef PROCESS_QUERY_LIMITED_INFORMATION 325 #define MDB_PROCESS_QUERY_LIMITED_INFORMATION PROCESS_QUERY_LIMITED_INFORMATION 327 #define MDB_PROCESS_QUERY_LIMITED_INFORMATION 0x1000 331 #define THREAD_RET void * 332 #define THREAD_CREATE(thr,start,arg) pthread_create(&thr,NULL,start,arg) 333 #define THREAD_FINISH(thr) pthread_join(thr,NULL) 337 #define MDB_PIDLOCK 1 339 #ifdef MDB_USE_POSIX_SEM 342 #define LOCK_MUTEX0(mutex) mdb_sem_wait(mutex) 343 #define UNLOCK_MUTEX(mutex) sem_post(mutex) 346mdb_sem_wait(sem_t *sem)
349 while((rc = sem_wait(sem)) && (rc = errno) == EINTR) ;
366 #define LOCK_MUTEX0(mutex) pthread_mutex_lock(mutex) 369 #define UNLOCK_MUTEX(mutex) pthread_mutex_unlock(mutex) 372 #define mdb_mutex_consistent(mutex) pthread_mutex_consistent(mutex) 377 #define ErrCode() errno 389 #define INVALID_HANDLE_VALUE (-1) 395 #define GET_PAGESIZE(x) ((x) = sysconf(_SC_PAGE_SIZE)) 398 #if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) 401 #define MNAME_LEN (sizeof(pthread_mutex_t)) 406 #ifdef MDB_ROBUST_SUPPORTED 410 #define LOCK_MUTEX(rc, env, mutex) \ 411 (((rc) = LOCK_MUTEX0(mutex)) && \ 412 ((rc) = mdb_mutex_failed(env, mutex, rc))) 415 #define LOCK_MUTEX(rc, env, mutex) ((rc) = LOCK_MUTEX0(mutex)) 416 #define mdb_mutex_failed(env, mutex, rc) (rc) 430 # define MDB_DSYNC O_DSYNC 432 # define MDB_DSYNC O_SYNC 440 #ifndef MDB_FDATASYNC 441 # define MDB_FDATASYNC fdatasync 445 # define MDB_MSYNC(addr,len,flags) msync(addr,len,flags) 483 static intmdb_debug;
484 static txnid_tmdb_debug_start;
489 # define DPRINTF(args) ((void) ((mdb_debug) && DPRINTF0 args)) 490 # define DPRINTF0(fmt, ...) \ 491 fprintf(stderr, "%s:%d "fmt "\n", mdb_func_, __LINE__, __VA_ARGS__)
493 # define DPRINTF(args) ((void) 0) 498 #define DPUTS(arg) DPRINTF(("%s", arg))
501 (((mc)->mc_flags & C_SUB) ? -(int)(mc)->mc_dbi : (int)(mc)->mc_dbi) 520 #define MAX_PAGESIZE (PAGEBASE ? 0x10000 : 0x8000) 534 #define MDB_MINKEYS 2 540 #define MDB_MAGIC 0xBEEFC0DE 543 #define MDB_DATA_VERSION ((MDB_DEVEL) ? 999 : 1) 545 #define MDB_LOCK_VERSION 1 563 #ifndef MDB_MAXKEYSIZE 564 #define MDB_MAXKEYSIZE ((MDB_DEVEL) ? 0 : 511) 569 #define ENV_MAXKEY(env) (MDB_MAXKEYSIZE) 571 #define ENV_MAXKEY(env) ((env)->me_maxkey) 578 #define MAXDATASIZE 0xffffffffUL 584 #define DKBUF_MAXKEYSIZE ((MDB_MAXKEYSIZE) > 0 ? (MDB_MAXKEYSIZE) : 511) 589 #define DKBUF char kbuf[DKBUF_MAXKEYSIZE*2+1] 594 #define DKEY(x) mdb_dkey(x, kbuf) 603 #define P_INVALID (~(pgno_t)0) 606 #define F_ISSET(w, f) (((w) & (f)) == (f)) 609 #define EVEN(n) (((n) + 1U) & -2) 621 #define DEFAULT_MAPSIZE 1048576 667 #define DEFAULT_READERS 126 706 #define mr_txnid mru.mrx.mrb_txnid 707 #define mr_pid mru.mrx.mrb_pid 708 #define mr_tid mru.mrx.mrb_tid 734 #if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) 758 #define mti_magic mt1.mtb.mtb_magic 759 #define mti_format mt1.mtb.mtb_format 760 #define mti_rmutex mt1.mtb.mtb_rmutex 761 #define mti_rmname mt1.mtb.mtb_rmname 762 #define mti_txnid mt1.mtb.mtb_txnid 763 #define mti_numreaders mt1.mtb.mtb_numreaders 767 #if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) 769 #define mti_wmname mt2.mt2_wmname 772 #define mti_wmutex mt2.mt2_wmutex 780 #define MDB_LOCK_FORMAT \ 782 ((MDB_LOCK_VERSION) \ 784 + (((MDB_PIDLOCK) != 0) << 16))) 806 #define mp_pgno mp_p.p_pgno 807 #define mp_next mp_p.p_next 818 #define P_BRANCH 0x01 820 #define P_OVERFLOW 0x04 825 #define P_LOOSE 0x4000 826 #define P_KEEP 0x8000 829 #define mp_lower mp_pb.pb.pb_lower 830 #define mp_upper mp_pb.pb.pb_upper 831 #define mp_pages mp_pb.pb_pages 843 #define PAGEHDRSZ ((unsigned) offsetof(MDB_page, mp_ptrs)) 846 #define METADATA(p) ((void *)((char *)(p) + PAGEHDRSZ)) 849 #define PAGEBASE ((MDB_DEVEL) ? PAGEHDRSZ : 0) 852 #define NUMKEYS(p) (((p)->mp_lower - (PAGEHDRSZ-PAGEBASE)) >> 1) 855 #define SIZELEFT(p) (indx_t)((p)->mp_upper - (p)->mp_lower) 858 #define PAGEFILL(env, p) (1000L * ((env)->me_psize - PAGEHDRSZ - SIZELEFT(p)) / \ 859 ((env)->me_psize - PAGEHDRSZ)) 863 #define FILL_THRESHOLD 250 866 #define IS_LEAF(p) F_ISSET((p)->mp_flags, P_LEAF) 868 #define IS_LEAF2(p) F_ISSET((p)->mp_flags, P_LEAF2) 870 #define IS_BRANCH(p) F_ISSET((p)->mp_flags, P_BRANCH) 872 #define IS_OVERFLOW(p) F_ISSET((p)->mp_flags, P_OVERFLOW) 874 #define IS_SUBP(p) F_ISSET((p)->mp_flags, P_SUBP) 877 #define OVPAGES(size, psize) ((PAGEHDRSZ-1 + (size)) / (psize) + 1) 882 #define NEXT_LOOSE_PAGE(p) (*(MDB_page **)((p) + 2)) 901 #if BYTE_ORDER == LITTLE_ENDIAN 912 #define F_BIGDATA 0x01 913 #define F_SUBDATA 0x02 914 #define F_DUPDATA 0x04 917 #define NODE_ADD_FLAGS (F_DUPDATA|F_SUBDATA|MDB_RESERVE|MDB_APPEND) 926 #define NODESIZE offsetof(MDB_node, mn_data) 929 #define PGNO_TOPWORD ((pgno_t)-1 > 0xffffffffu ? 32 : 0) 934 #define INDXSIZE(k) (NODESIZE + ((k) == NULL ? 0 : (k)->mv_size)) 939 #define LEAFSIZE(k, d) (NODESIZE + (k)->mv_size + (d)->mv_size) 942 #define NODEPTR(p, i) ((MDB_node *)((char *)(p) + (p)->mp_ptrs[i] + PAGEBASE)) 945 #define NODEKEY(node) (void *)((node)->mn_data) 948 #define NODEDATA(node) (void *)((char *)(node)->mn_data + (node)->mn_ksize) 951 #define NODEPGNO(node) \ 952 ((node)->mn_lo | ((pgno_t) (node)->mn_hi << 16) | \ 953 (PGNO_TOPWORD ? ((pgno_t) (node)->mn_flags << PGNO_TOPWORD) : 0)) 955 #define SETPGNO(node,pgno) do { \ 956 (node)->mn_lo = (pgno) & 0xffff; (node)->mn_hi = (pgno) >> 16; \ 957 if (PGNO_TOPWORD) (node)->mn_flags = (pgno) >> PGNO_TOPWORD; } while(0) 960 #define NODEDSZ(node) ((node)->mn_lo | ((unsigned)(node)->mn_hi << 16)) 962 #define SETDSZ(node,size) do { \ 963 (node)->mn_lo = (size) & 0xffff; (node)->mn_hi = (size) >> 16;} while(0) 965 #define NODEKSZ(node) ((node)->mn_ksize) 969 #define COPY_PGNO(dst,src) dst = src 971 #if SIZE_MAX > 4294967295UL 972 #define COPY_PGNO(dst,src) do { \ 973 unsigned short *s, *d; \ 974 s = (unsigned short *)&(src); \ 975 d = (unsigned short *)&(dst); \ 982 #define COPY_PGNO(dst,src) do { \ 983 unsigned short *s, *d; \ 984 s = (unsigned short *)&(src); \ 985 d = (unsigned short *)&(dst); \ 995 #define LEAF2KEY(p, i, ks) ((char *)(p) + PAGEHDRSZ + ((i)*(ks))) 998 #define MDB_GET_KEY(node, keyptr) { if ((keyptr) != NULL) { \ 999 (keyptr)->mv_size = NODEKSZ(node); (keyptr)->mv_data = NODEKEY(node); } } 1002 #define MDB_GET_KEY2(node, key) { key.mv_size = NODEKSZ(node); key.mv_data = NODEKEY(node); } 1016 #define MDB_VALID 0x8000 1017 #define PERSISTENT_FLAGS (0xffff & ~(MDB_VALID)) 1019 #define VALID_FLAGS (MDB_REVERSEKEY|MDB_DUPSORT|MDB_INTEGERKEY|MDB_DUPFIXED|\ 1020 MDB_INTEGERDUP|MDB_REVERSEDUP|MDB_CREATE) 1046 #define mm_psize mm_dbs[FREE_DBI].md_pad 1048 #define mm_flags mm_dbs[FREE_DBI].md_flags 1125 #define DB_DIRTY 0x01 1126 #define DB_STALE 0x02 1128 #define DB_VALID 0x08 1129 #define DB_USRVALID 0x10 1130 #define DB_DUPDATA 0x20 1147 #define MDB_TXN_BEGIN_FLAGS MDB_RDONLY 1148 #define MDB_TXN_RDONLY MDB_RDONLY 1150 #define MDB_TXN_WRITEMAP MDB_WRITEMAP 1151 #define MDB_TXN_FINISHED 0x01 1152 #define MDB_TXN_ERROR 0x02 1153 #define MDB_TXN_DIRTY 0x04 1154 #define MDB_TXN_SPILLS 0x08 1155 #define MDB_TXN_HAS_CHILD 0x10 1157 #define MDB_TXN_BLOCKED (MDB_TXN_FINISHED|MDB_TXN_ERROR|MDB_TXN_HAS_CHILD) 1172 #define CURSOR_STACK 32 1208 #define C_INITIALIZED 0x01 1212 #define C_UNTRACK 0x40 1236 #define XCURSOR_INITED(mc) \ 1237 ((mc)->mc_xcursor && ((mc)->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) 1243 #define XCURSOR_REFRESH(mc, top, mp) do { \ 1244 MDB_page *xr_pg = (mp); \ 1245 MDB_node *xr_node; \ 1246 if (!XCURSOR_INITED(mc) || (mc)->mc_ki[top] >= NUMKEYS(xr_pg)) break; \ 1247 xr_node = NODEPTR(xr_pg, (mc)->mc_ki[top]); \ 1248 if ((xr_node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) \ 1249 (mc)->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(xr_node); \ 1264 #define MDB_FATAL_ERROR 0x80000000U 1266 #define MDB_ENV_ACTIVE 0x20000000U 1268 #define MDB_ENV_TXKEY 0x10000000U 1270 #define MDB_FSYNCONLY 0x08000000U 1296 # define me_pglast me_pgstate.mf_pglast 1297 # define me_pghead me_pgstate.mf_pghead 1307 #if !(MDB_MAXKEYSIZE) 1308 unsigned intme_maxkey;
1314 #ifdef MDB_USE_POSIX_MUTEX 1315 # define me_rmutex me_txns->mti_rmutex 1316 # define me_wmutex me_txns->mti_wmutex 1332 #define MDB_COMMIT_PAGES 64 1333 #if defined(IOV_MAX) && IOV_MAX < MDB_COMMIT_PAGES 1334 #undef MDB_COMMIT_PAGES 1335 #define MDB_COMMIT_PAGES IOV_MAX 1339 #define MAX_WRITE (0x40000000U >> (sizeof(ssize_t) == 4)) 1342 #define TXN_DBI_EXIST(txn, dbi, validity) \ 1343 ((txn) && (dbi)<(txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & (validity))) 1346 #define TXN_DBI_CHANGED(txn, dbi) \ 1347 ((txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi]) 1353 #define MDB_END_NAMES {"committed", "empty-commit", "abort", "reset", \
1354"reset-tmp", "fail-begin", "fail-beginchild"}
1360 #define MDB_END_OPMASK 0x0F 1361 #define MDB_END_UPDATE 0x10 1362 #define MDB_END_FREE 0x20 1363 #define MDB_END_SLOT MDB_NOTLS 1369 #define MDB_PS_MODIFY 1 1370 #define MDB_PS_ROOTONLY 2 1371 #define MDB_PS_FIRST 4 1372 #define MDB_PS_LAST 8 1377 #define MDB_SPLIT_REPLACE MDB_APPENDDUP 1379 pgno_tnewpgno,
unsigned intnflags);
1384 #ifdef MDB_USE_POSIX_MUTEX 1385 # define mdb_env_close0(env, excl) mdb_env_close1(env) 1429 #ifdef MISALIGNED_OK 1430 # define mdb_cmp_clong mdb_cmp_long 1432 # define mdb_cmp_clong mdb_cmp_cint 1436 staticSECURITY_DESCRIPTOR mdb_null_sd;
1437 staticSECURITY_ATTRIBUTES mdb_all_sa;
1438 static intmdb_sec_inited;
1441 static intutf8_to_utf16(
const char*src,
struct MDB_name*dst,
intxtra);
1456 "MDB_KEYEXIST: Key/data pair already exists",
1457 "MDB_NOTFOUND: No matching key/data pair found",
1458 "MDB_PAGE_NOTFOUND: Requested page not found",
1459 "MDB_CORRUPTED: Located page was wrong type",
1460 "MDB_PANIC: Update of meta page failed or environment had fatal error",
1461 "MDB_VERSION_MISMATCH: Database environment version mismatch",
1462 "MDB_INVALID: File is not an LMDB file",
1463 "MDB_MAP_FULL: Environment mapsize limit reached",
1464 "MDB_DBS_FULL: Environment maxdbs limit reached",
1465 "MDB_READERS_FULL: Environment maxreaders limit reached",
1466 "MDB_TLS_FULL: Thread-local storage keys full - too many environments open",
1467 "MDB_TXN_FULL: Transaction has too many dirty pages - transaction too big",
1468 "MDB_CURSOR_FULL: Internal error - cursor stack limit reached",
1469 "MDB_PAGE_FULL: Internal error - page has no more space",
1470 "MDB_MAP_RESIZED: Database contents grew beyond environment mapsize",
1471 "MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed",
1472 "MDB_BAD_RSLOT: Invalid reuse of reader locktable slot",
1473 "MDB_BAD_TXN: Transaction must abort, has a child, or is invalid",
1474 "MDB_BAD_VALSIZE: Unsupported size of key/DB name/data, or wrong DUPFIXED size",
1475 "MDB_BAD_DBI: The specified DBI handle was closed/changed unexpectedly",
1486 #define MSGSIZE 1024 1487 #define PADSIZE 4096 1488 char buf[MSGSIZE+PADSIZE], *ptr =
buf;
1492 return(
"Successful return: 0");
1518FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
1519FORMAT_MESSAGE_IGNORE_INSERTS,
1520 NULL, err, 0, ptr, MSGSIZE, (va_list *)
buf+MSGSIZE);
1528 #define mdb_cassert(mc, expr) mdb_assert0((mc)->mc_txn->mt_env, expr, #expr) 1530 #define mdb_tassert(txn, expr) mdb_assert0((txn)->mt_env, expr, #expr) 1532 #define mdb_eassert(env, expr) mdb_assert0(env, expr, #expr) 1535 # define mdb_assert0(env, expr, expr_txt) ((expr) ? (void)0 : \ 1536 mdb_assert_fail(env, expr_txt, mdb_func_, __FILE__, __LINE__)) 1540 const char*func,
const char*
file,
intline)
1543sprintf(
buf,
"%.100s:%d: Assertion '%.200s' failed in %.40s()",
1544 file, line, expr_txt, func);
1545 if(
env->me_assert_func)
1547fprintf(stderr,
"%s\n",
buf);
1551 # define mdb_assert0(env, expr, expr_txt) ((void) 0) 1573 unsigned char*c =
key->mv_data;
1579 if(
key->mv_size > DKBUF_MAXKEYSIZE)
1580 return "MDB_MAXKEYSIZE";
1586 for(
i=0;
i<
key->mv_size;
i++)
1587ptr += sprintf(ptr,
"%02x", *c++);
1589sprintf(
buf,
"%.*s",
key->mv_size,
key->mv_data);
1597 static char*
consttp[2][2] = {{
"",
": DB"}, {
": sub-page",
": sub-DB"}};
1606 pgno_tpgno = mdb_dbg_pgno(mp);
1609 unsigned int i, nkeys, nsize, total = 0;
1620fprintf(stderr,
"Overflow page %"Z"u pages %u%s\n",
1621pgno, mp->mp_pages,
state);
1624fprintf(stderr,
"Meta-page %"Z"u txnid %"Z"u\n",
1628fprintf(stderr,
"Bad page %"Z"u flags 0x%X\n", pgno, mp->
mp_flags);
1633fprintf(stderr,
"%s %"Z"u numkeys %d%s\n",
type, pgno, nkeys,
state);
1635 for(
i=0;
i<nkeys;
i++) {
1640fprintf(stderr,
"key %d: nsize %d, %s\n",
i, nsize,
DKEY(&
key));
1648fprintf(stderr,
"key %d: page %"Z"u, %s\n",
i,
NODEPGNO(node),
1653nsize +=
sizeof(
pgno_t);
1657nsize +=
sizeof(
indx_t);
1658fprintf(stderr,
"key %d: nsize %d, %s%s\n",
1659 i, nsize,
DKEY(&
key), mdb_leafnode_type(node));
1661total =
EVEN(total);
1663fprintf(stderr,
"Total: header %d + contents %d + unused %d\n",
1679printf(
"oops!\n");
1687printf(
"blah!\n");
1699 static voidmdb_audit(
MDB_txn*txn)
1730 for(j=0; j<
NUMKEYS(mp); j++) {
1744fprintf(stderr,
"audit: %"Z"u freecount: %"Z"u count: %"Z"u total: %"Z"u next_pgno: %"Z"u\n",
1761 #if UINT_MAX < SIZE_MAX 1762 if(dcmp ==
mdb_cmp_int&&
a->mv_size ==
sizeof(
size_t))
1765 returndcmp(
a,
b);
1777 size_tpsize =
env->me_psize, sz = psize, off;
1787 env->me_dpages = ret->mp_next;
1798memset((
char*)ret + off, 0, psize);
1813mp->mp_next =
env->me_dpages;
1815 env->me_dpages = mp;
1837 unsigned i,
n= dl[0].
mid;
1839 for(
i= 1;
i<=
n;
i++) {
1859 pgno_tpgno = mp->mp_pgno;
1870 if(x <= dl[0].mid && dl[x].mid == pgno) {
1871 if(mp != dl[x].mptr) {
1924 for(; mc; mc=mc->
mc_next) {
1929 for(j=0; j<m3->
mc_snum; j++) {
1930mp = m3->
mc_pg[j];
1931 if((mp->
mp_flags& Mask) == pflags)
1958 if((dp->
mp_flags& Mask) == pflags && level <= 1)
2007 unsigned int i, j, need;
2034 unsigned intnum = sl[0];
2036 for(
i=1;
i<=num;
i++) {
2059 for(
i=dl[0].mid;
i&& need;
i--) {
2061dp = dl[
i].
mptr;
2072 if(j <= tx2->mt_spill_pgs[0] && tx2->
mt_spill_pgs[j] == pn) {
2109mr =
r[
i].mr_txnid;
2130mid.
mid= mp->mp_pgno;
2162 enum{ Paranoid = 1, Max_retries = 500 };
2164 enum{ Paranoid = 0, Max_retries = INT_MAX
};
2166 intrc, retry = num * 60;
2170 unsigned i, j, mop_len = mop ? mop[0] : 0, n2 = num-1;
2208 if(mop[
i-n2] == pgno+n2)
2210}
while(--
i> n2);
2218oldest =
env->me_pgoldest;
2223 key.mv_size =
sizeof(
last);
2228 if(Paranoid && retry < 0 && mop_len)
2233 if(oldest <=
last) {
2236 env->me_pgoldest = oldest;
2239 if(oldest <=
last)
2252 env->me_pgoldest = oldest;
2255 if(oldest <=
last)
2273mop =
env->me_pghead;
2277 DPRINTF((
"IDL read txn %"Z"u root %"Z"u num %u",
2279 for(j =
i; j; j--)
2290 if(pgno + num >=
env->me_maxpg) {
2291 DPUTS(
"DB size maxed out");
2306mop[0] = mop_len -= num;
2308 for(j =
i-num; j < mop_len; )
2309mop[++j] = mop[++
i];
2332 enum{ Align =
sizeof(
pgno_t) };
2333 indx_tupper = src->mp_upper, lower = src->mp_lower,
unused= upper-lower;
2339upper = (upper +
PAGEBASE) & -Align;
2340memcpy(dst, src, (lower +
PAGEBASE+ (Align-1)) & -Align);
2341memcpy((
pgno_t*)((
char*)dst+upper), (
pgno_t*)((
char*)src+upper),
2344memcpy(dst, src, psize -
unused);
2362 pgno_tpgno = mp->mp_pgno, pn = pgno << 1;
2364 for(tx2 = txn; tx2; tx2=tx2->
mt_parent) {
2368 if(x <= tx2->mt_spill_pgs[0] && tx2->
mt_spill_pgs[x] == pn) {
2384memcpy(np, mp, num *
env->me_psize);
2438mp->mp_pgno, pgno));
2457 if(x <= dl[0].mid && dl[x].mid == pgno) {
2458 if(mp != dl[x].mptr) {
2488 for(; m2; m2=m2->
mc_next) {
2495 for(; m2; m2=m2->
mc_next) {
2497 if(m2 == mc)
continue;
2529 #ifdef BROKEN_FDATASYNC 2531 if(fsync(
env->me_fd))
2556 for(; mc; mc =
bk->mc_next) {
2594 for(mc = cursors[
i]; mc; mc =
next) {
2617cursors[
i] =
NULL;
2646h = OpenProcess(
env->me_pidquery,
FALSE, pid);
2649 return ErrCode() != ERROR_INVALID_PARAMETER;
2651ret = WaitForSingleObject(h, 0) != 0;
2658 structflock lock_info;
2659memset(&lock_info, 0,
sizeof(lock_info));
2660lock_info.l_type = F_WRLCK;
2662lock_info.l_start = pid;
2663lock_info.l_len = 1;
2664 if((rc = fcntl(
env->me_lfd, op, &lock_info)) == 0) {
2665 if(op == F_GETLK && lock_info.l_type != F_UNLCK)
2667}
else if((rc =
ErrCode()) == EINTR) {
2687 intrc, new_notls = 0;
2696pthread_getspecific(
env->me_txkey);
2698 if(
r->mr_pid !=
env->me_pid ||
r->mr_txnid != (
txnid_t)-1)
2705 if(!
env->me_live_reader) {
2709 env->me_live_reader = 1;
2714 nr= ti->mti_numreaders;
2715 for(
i=0;
i<
nr;
i++)
2718 if(
i==
env->me_maxreaders) {
2733ti->mti_numreaders = ++
nr;
2734 env->me_close_readers =
nr;
2739 if(!new_notls && (rc=pthread_setspecific(
env->me_txkey,
r))) {
2745 r->mr_txnid = ti->mti_txnid;
2746 while(
r->mr_txnid != ti->mti_txnid);
2765 if(txn->
mt_txnid== mdb_debug_start)
2778memcpy(txn->
mt_dbiseqs,
env->me_dbiseqs,
env->me_maxdbs *
sizeof(
unsigned int));
2792x =
env->me_dbflags[
i];
2800 DPUTS(
"environment had fatal error, must shutdown!");
2821 DPRINTF((
"renew txn %"Z"u%c %p on mdbenv %p, root page %"Z"u",
2823(
void*)txn, (
void*)txn->
mt_env, txn->mt_dbs[
MAIN_DBI].md_root));
2833 intrc,
size, tsize;
2857txn =
env->me_txn0;
2898 if(
env->me_pghead) {
2901 if(
env->me_pghead)
2916 if(txn !=
env->me_txn0)
2921 DPRINTF((
"begin txn %"Z"u%c %p on mdbenv %p, root page %"Z"u",
2923(
void*) txn, (
void*)
env, txn->mt_dbs[
MAIN_DBI].md_root));
2932 if(!txn)
return NULL;
2953 if(tdbflags[
i] &
DB_NEW) {
2957 char*ptr =
env->me_dbxs[
i].md_name.mv_data;
2959 env->me_dbxs[
i].md_name.mv_data =
NULL;
2960 env->me_dbxs[
i].md_name.mv_size = 0;
2961 env->me_dbflags[
i] = 0;
2962 env->me_dbiseqs[
i]++;
2968 if(keep &&
env->me_numdbs <
n)
2969 env->me_numdbs =
n;
2988 DPRINTF((
"%s txn %"Z"u%c %p on mdbenv %p, root page %"Z"u",
3023 env->me_pglast = 0;
3034 env->me_pgstate = ((
MDB_ntxn*)txn)->mnt_pgstate;
3084 intrc, maxfree_1pg =
env->me_maxfree_1pg, more = 1;
3085 txnid_tpglast = 0, head_id = 0;
3086 pgno_tfreecnt = 0, *free_pgs, *mop;
3087 ssize_thead_room = 0, total_room = 0, mop_len, clean_limit;
3091 if(
env->me_pghead) {
3111 for(x=1; x<=dl[0].
mid; x++)
3112 if(dl[x].mid == mp->mp_pgno)
3125 for(y=1; dl[y].
mptr&& y <= dl[0].
mid; y++);
3126 if(y <= dl[0].mid) {
3128 while(!dl[y].mptr && y <= dl[0].mid) y++;
3129 if(y > dl[0].mid)
break;
3144? SSIZE_MAX : maxfree_1pg;
3159pglast = head_id = *(
txnid_t*)
key.mv_data;
3160total_room = head_room = 0;
3168 if(freecnt < txn->mt_free_pgs[0]) {
3180freecnt = free_pgs[0];
3187}
while(freecnt < free_pgs[0]);
3189memcpy(
data.mv_data, free_pgs,
data.mv_size);
3192 unsigned int i= free_pgs[0];
3193 DPRINTF((
"IDL write txn %"Z"u root %"Z"u num %u",
3196 DPRINTF((
"IDL %"Z"u", free_pgs[
i]));
3202mop =
env->me_pghead;
3209 if(total_room >= mop_len) {
3210 if(total_room == mop_len || --more < 0)
3212}
else if(head_room >= maxfree_1pg && head_id > 1) {
3218total_room -= head_room;
3219head_room = mop_len - total_room;
3220 if(head_room > maxfree_1pg && head_id > 1) {
3222head_room /= head_id;
3223head_room += maxfree_1pg - head_room % (maxfree_1pg + 1);
3224}
else if(head_room < 0) {
3228 key.mv_size =
sizeof(head_id);
3229 key.mv_data = &head_id;
3230 data.mv_size = (head_room + 1) *
sizeof(
pgno_t);
3236j = head_room > clean_limit ? head_room : 0;
3240total_room += head_room;
3253mop =
env->me_pghead;
3256loose[ ++
count] = mp->mp_pgno;
3279 if(
len> mop_len) {
3288 if(rc || !(mop_len -=
len))
3305 unsignedpsize =
env->me_psize, j;
3306 int i, pagecount = dl[0].
mid, rc;
3307 size_t size= 0, pos = 0;
3314 ssize_twpos = 0, wsize = 0, wres;
3315 size_tnext_pos = 1;
3323 while(++
i<= pagecount) {
3324dp = dl[
i].
mptr;
3338 if(++
i<= pagecount) {
3339dp = dl[
i].
mptr;
3346pgno = dl[
i].
mid;
3363 DPRINTF((
"committing page %"Z"u", pgno));
3364memset(&ov, 0,
sizeof(ov));
3365ov.Offset = pos & 0xffffffff;
3366ov.OffsetHigh = pos >> 16 >> 16;
3367 if(!WriteFile(
env->me_fd, dp,
size,
NULL, &ov)) {
3369 DPRINTF((
"WriteFile: %d", rc));
3378 #ifdef MDB_USE_PWRITEV 3379wres = pwritev(
env->me_fd, iov,
n, wpos);
3382wres = pwrite(
env->me_fd, iov[0].iov_base, wsize, wpos);
3392wres = writev(
env->me_fd, iov,
n);
3395 if(wres != wsize) {
3403 DPUTS(
"short write, filesystem full?");
3414 DPRINTF((
"committing page %"Z"u", pgno));
3415next_pos = pos +
size;
3416iov[
n].iov_len =
size;
3417iov[
n].iov_base = (
char*)dp;
3429 for(
i= keep; ++
i<= pagecount; ) {
3430dp = dl[
i].
mptr;
3434dl[j].
mid= dp->mp_pgno;
3451 unsigned int i, end_mode;
3473 DPUTS(
"txn has failed/finished, can't commit");
3485 unsignedx, y,
len, ps_len;
3516 if((pspill = parent->
mt_spill_pgs) && (ps_len = pspill[0])) {
3518pspill[0] = (
pgno_t)-1;
3520 for(
i=0,
len=src[0].mid; ++
i<=
len; ) {
3522 while(pn > pspill[x])
3524 if(pn == pspill[x]) {
3530 for(x=y; ++x <= ps_len; )
3531 if(!(pspill[x] & 1))
3532pspill[++y] = pspill[x];
3544 if(y <= dst[0].mid && dst[y].mid == pn) {
3546 while(y < dst[0].mid) {
3561 for(
i= x; y &&
i; y--) {
3563 while(yp < dst[
i].mid)
3565 if(yp == dst[
i].mid) {
3575 for(
i=
len; y; dst[
i--] = src[y--]) {
3577 while(yp < dst[x].mid)
3578dst[
i--] = dst[x--];
3579 if(yp == dst[x].mid)
3580 free(dst[x--].mptr);
3611 if(txn !=
env->me_txn) {
3612 DPUTS(
"attempt to commit unknown transaction");
3623 DPRINTF((
"committing txn %"Z"u %p on mdbenv %p, root page %"Z"u",
3689 enum{ Size =
sizeof(pbuf) };
3695 for(
i=off=0;
i<
NUM_METAS;
i++, off += meta->mm_psize) {
3699memset(&ov, 0,
sizeof(ov));
3701rc = ReadFile(
env->me_fd, &pbuf, Size, &
len, &ov) ? (
int)
len: -1;
3702 if(rc == -1 &&
ErrCode() == ERROR_HANDLE_EOF)
3705rc = pread(
env->me_fd, &pbuf, Size, off);
3708 if(rc == 0 && off == 0)
3718 DPRINTF((
"page %"Z"u not a meta page", p->mp_pgno));
3724 DPUTS(
"meta has invalid magic");
3729 DPRINTF((
"database is version %u, expected version %u",
3747meta->mm_psize =
env->me_psize;
3749meta->mm_flags =
env->me_flags & 0xffff;
3769memset(&ov, 0,
sizeof(ov));
3770 #define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \ 3772 rc = WriteFile(fd, ptr, size, &len, &ov); } while(0) 3775 #define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \ 3776 len = pwrite(fd, ptr, size, pos); \ 3777 if (len == -1 && ErrCode() == EINTR) continue; \ 3778 rc = (len >= 0); break; } while(1) 3781 DPUTS(
"writing new meta page");
3783psize =
env->me_psize;
3793q = (
MDB_page*)((
char*)p + psize);
3821 intrc,
len, toggle;
3831 DPRINTF((
"writing meta page %d for root page %"Z"u",
3836mp =
env->me_metas[toggle];
3837mapsize =
env->me_metas[toggle ^ 1]->mm_mapsize;
3839 if(mapsize < env->me_mapsize)
3840mapsize =
env->me_mapsize;
3847 #if (__GNUC__ * 100 + __GNUC_MINOR__ >= 404) && \ 3848 !(defined(__i386__) || defined(__x86_64__)) 3850__sync_synchronize();
3854 unsignedmeta_size =
env->me_psize;
3858 r2= (ptr -
env->me_map) & (
env->me_os_psize - 1);
3879ptr = (
char*)&meta + off;
3881off += (
char*)mp -
env->me_map;
3890memset(&ov, 0,
sizeof(ov));
3892 if(!WriteFile(mfd, ptr,
len, (
DWORD*)&rc, &ov))
3897rc = pwrite(mfd, ptr,
len, off);
3900rc = rc < 0 ?
ErrCode() : EIO;
3905 DPUTS(
"write failed, disk error?");
3913memset(&ov, 0,
sizeof(ov));
3915WriteFile(
env->me_fd, ptr,
len,
NULL, &ov);
3917 r2= pwrite(
env->me_fd, ptr,
len, off);
3964 #ifdef MDB_USE_POSIX_SEM 3965e->me_rmutex = SEM_FAILED;
3966e->me_wmutex = SEM_FAILED;
3979 unsigned int flags=
env->me_flags;
3983LONG sizelo, sizehi;
3992msize =
env->me_mapsize;
3993sizelo = msize & 0xffffffff;
3994sizehi = msize >> 16 >> 16;
4001|| !SetEndOfFile(
env->me_fd)
4002|| SetFilePointer(
env->me_fd, 0,
NULL, 0) != 0))
4007PAGE_READWRITE : PAGE_READONLY,
4008sizehi, sizelo,
NULL);
4012FILE_MAP_WRITE : FILE_MAP_READ,
40130, 0, msize,
addr);
4019 int prot= PROT_READ;
4022 if(ftruncate(
env->me_fd,
env->me_mapsize) < 0)
4027 if(
env->me_map == MAP_FAILED) {
4035madvise(
env->me_map,
env->me_mapsize, MADV_RANDOM);
4037 #ifdef POSIX_MADV_RANDOM 4038posix_madvise(
env->me_map,
env->me_mapsize, POSIX_MADV_RANDOM);
4054 env->me_metas[1] = (
MDB_meta*)((
char*)
env->me_metas[0] +
env->me_psize);
4065 if(
env->me_map) {
4080munmap(
env->me_map,
env->me_mapsize);
4088 if(
env->me_psize)
4089 env->me_maxpg =
env->me_mapsize /
env->me_psize;
4105 if(
env->me_map || readers < 1)
4107 env->me_maxreaders = readers;
4114 if(!
env|| !readers)
4116*readers =
env->me_maxreaders;
4124LARGE_INTEGER fsize;
4126 if(!GetFileSizeEx(fd, &fsize))
4129*
size= fsize.QuadPart;
4133 if(fstat(fd, &
st))
4144 # define MDB_NAME(str) L##str 4145 # define mdb_name_cpy wcscpy 4149 # define MDB_NAME(str) str 4150 # define mdb_name_cpy strcpy 4166 #define MDB_SUFFLEN 9 4182 returnutf8_to_utf16(path, fname, no_suffix ? 0 :
MDB_SUFFLEN);
4184fname->
mn_len= strlen(path);
4186fname->
mn_val= (
char*) path;
4189strcpy(fname->
mn_val, path);
4198 #define mdb_fname_destroy(fname) \ 4199 do { if ((fname).mn_alloced) free((fname).mn_val); } while (0) 4202 # define MDB_CLOEXEC O_CLOEXEC 4204 # define MDB_CLOEXEC 0 4242 DWORDacc, share, disp, attrs;
4266acc = GENERIC_READ|GENERIC_WRITE;
4267share = FILE_SHARE_READ|FILE_SHARE_WRITE;
4269attrs = FILE_ATTRIBUTE_NORMAL;
4273disp = OPEN_EXISTING;
4276acc = GENERIC_WRITE;
4277disp = OPEN_EXISTING;
4278attrs = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH;
4281acc = GENERIC_WRITE;
4284attrs = FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH;
4288fd = CreateFileW(fname->
mn_val, acc, share,
NULL, disp, attrs,
NULL);
4300(void) fcntl(fd, F_SETFD,
flags| FD_CLOEXEC);
4307(void) fcntl(fd, F_NOCACHE, 1);
4308 # elif defined O_DIRECT 4312 if((
flags= fcntl(fd, F_GETFL)) != -1)
4313(void) fcntl(fd, F_SETFL,
flags| O_DIRECT);
4324 #ifdef BROKEN_FDATASYNC 4325 #include <sys/utsname.h> 4326 #include <sys/vfs.h> 4334 unsigned int flags=
env->me_flags;
4335 int i, newenv = 0, rc;
4341 if((rc & 0xff) > 5)
4342 env->me_pidquery = MDB_PROCESS_QUERY_LIMITED_INFORMATION;
4344 env->me_pidquery = PROCESS_QUERY_INFORMATION;
4347 #ifdef BROKEN_FDATASYNC 4358fstatfs(
env->me_fd, &
st);
4359 while(
st.f_type == 0xEF53) {
4363 if(uts.release[0] <
'3') {
4364 if(!
strncmp(uts.release,
"2.6.32.", 7)) {
4365 i= atoi(uts.release+7);
4368}
else if(!
strncmp(uts.release,
"2.6.34.", 7)) {
4369 i= atoi(uts.release+7);
4373}
else if(uts.release[0] ==
'3') {
4374 i= atoi(uts.release+2);
4378 i= atoi(uts.release+4);
4381}
else if(
i== 2) {
4382 i= atoi(uts.release+4);
4398 DPUTS(
"new mdbenv");
4400 env->me_psize =
env->me_os_psize;
4403memset(&meta, 0,
sizeof(meta));
4407 env->me_psize = meta.mm_psize;
4411 if(!
env->me_mapsize) {
4418 size_tminsize = (meta.
mm_last_pg+ 1) * meta.mm_psize;
4419 if(
env->me_mapsize < minsize)
4420 env->me_mapsize = minsize;
4454 #if !(MDB_MAXKEYSIZE) 4457 env->me_maxpg =
env->me_mapsize /
env->me_psize;
4464 DPRINTF((
"opened database version %u, pagesize %u",
4490 if(reader->mr_pid == getpid())
4502 #ifndef MAX_TLS_KEYS 4503 #define MAX_TLS_KEYS 64 4505 staticpthread_key_t mdb_tls_keys[MAX_TLS_KEYS];
4506 static intmdb_tls_nkeys;
4508 static voidNTAPI mdb_tls_callback(PVOID module,
DWORDreason, PVOID ptr)
4512 caseDLL_PROCESS_ATTACH:
break;
4513 caseDLL_THREAD_ATTACH:
break;
4514 caseDLL_THREAD_DETACH:
4515 for(
i=0;
i<mdb_tls_nkeys;
i++) {
4516 MDB_reader*
r= pthread_getspecific(mdb_tls_keys[
i]);
4522 caseDLL_PROCESS_DETACH:
break;
4527 constPIMAGE_TLS_CALLBACK mdb_tls_cbp __attribute__((section (
".CRT$XLB"))) = mdb_tls_callback;
4529PIMAGE_TLS_CALLBACK mdb_tls_cbp __attribute__((section (
".CRT$XLB"))) = mdb_tls_callback;
4537 #pragma comment(linker, "/INCLUDE:_tls_used")
4538 #pragma comment(linker, "/INCLUDE:mdb_tls_cbp")
4539 #pragma const_seg(".CRT$XLB")
4540 extern constPIMAGE_TLS_CALLBACK mdb_tls_cbp;
4541 constPIMAGE_TLS_CALLBACK mdb_tls_cbp = mdb_tls_callback;
4544 #pragma comment(linker, "/INCLUDE:__tls_used")
4545 #pragma comment(linker, "/INCLUDE:_mdb_tls_cbp")
4546 #pragma data_seg(".CRT$XLB")
4547PIMAGE_TLS_CALLBACK mdb_tls_cbp = mdb_tls_callback;
4568memset(&ov, 0,
sizeof(ov));
4569 if(!LockFileEx(
env->me_lfd, 0, 0, 1, 0, &ov)) {
4572UnlockFile(
env->me_lfd, 0, 0, 1, 0);
4578 structflock lock_info;
4580memset((
void*)&lock_info, 0,
sizeof(lock_info));
4581lock_info.l_type = F_RDLCK;
4583lock_info.l_start = 0;
4584lock_info.l_len = 1;
4585 while((rc = fcntl(
env->me_lfd, F_SETLK, &lock_info)) &&
4587*excl = rc ? -1 : 0;
4602 if(LockFile(
env->me_lfd, 0, 0, 1, 0)) {
4606memset(&ov, 0,
sizeof(ov));
4607 if(LockFileEx(
env->me_lfd, 0, 0, 1, 0, &ov)) {
4614 structflock lock_info;
4615memset((
void*)&lock_info, 0,
sizeof(lock_info));
4616lock_info.l_type = F_WRLCK;
4618lock_info.l_start = 0;
4619lock_info.l_len = 1;
4620 while((rc = fcntl(
env->me_lfd, F_SETLK, &lock_info)) &&
4625 # ifndef MDB_USE_POSIX_MUTEX 4629lock_info.l_type = F_RDLCK;
4630 while((rc = fcntl(
env->me_lfd, F_SETLKW, &lock_info)) &&
4668 typedef unsigned long longmdb_hash_t;
4669 #define MDB_HASH_INIT ((mdb_hash_t)0xcbf29ce484222325ULL) 4680mdb_hash_val(
MDB_val*
val, mdb_hash_t hval)
4682 unsigned char*s = (
unsigned char*)
val->mv_data;
4683 unsigned char*end = s +
val->mv_size;
4689hval ^= (mdb_hash_t)*s++;
4692hval += (hval << 1) + (hval << 4) + (hval << 5) +
4693(hval << 7) + (hval << 8) + (hval << 40);
4707 static const charmdb_a85[]=
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
4710mdb_pack85(
unsigned long l,
char*
out)
4714 for(
i=0;
i<5;
i++) {
4715*
out++ = mdb_a85[
l% 85];
4723mdb_hash_t h = mdb_hash_val(
val, MDB_HASH_INIT);
4725mdb_pack85(h, encbuf);
4726mdb_pack85(h>>32, encbuf+5);
4742 # define MDB_ERRCODE_ROFS ERROR_WRITE_PROTECT 4744 # define MDB_ERRCODE_ROFS EROFS 4765 if(mdb_tls_nkeys >= MAX_TLS_KEYS) {
4769mdb_tls_keys[mdb_tls_nkeys++] =
env->me_txkey;
4782 if(
size== -1)
gotofail_errno;
4785 if(size < rsize && *excl > 0) {
4787 if(SetFilePointer(
env->me_lfd, rsize,
NULL, FILE_BEGIN) != (
DWORD)rsize
4788|| !SetEndOfFile(
env->me_lfd))
4791 if(ftruncate(
env->me_lfd, rsize) != 0)
gotofail_errno;
4801mh = CreateFileMapping(
env->me_lfd,
NULL, PAGE_READWRITE,
4803 if(!mh)
gotofail_errno;
4804 env->me_txns = MapViewOfFileEx(mh, FILE_MAP_WRITE, 0, 0, rsize,
NULL);
4806 if(!
env->me_txns)
gotofail_errno;
4808 void*m = mmap(
NULL, rsize, PROT_READ|PROT_WRITE, MAP_SHARED,
4810 if(m == MAP_FAILED)
gotofail_errno;
4816BY_HANDLE_FILE_INFORMATION stbuf;
4825 if(!mdb_sec_inited) {
4826InitializeSecurityDescriptor(&mdb_null_sd,
4827SECURITY_DESCRIPTOR_REVISION);
4828SetSecurityDescriptorDacl(&mdb_null_sd,
TRUE, 0,
FALSE);
4829mdb_all_sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
4830mdb_all_sa.bInheritHandle =
FALSE;
4831mdb_all_sa.lpSecurityDescriptor = &mdb_null_sd;
4834 if(!GetFileInformationByHandle(
env->me_lfd, &stbuf))
gotofail_errno;
4835idbuf.volume = stbuf.dwVolumeSerialNumber;
4836idbuf.nhigh = stbuf.nFileIndexHigh;
4837idbuf.nlow = stbuf.nFileIndexLow;
4838 val.mv_data = &idbuf;
4839 val.mv_size =
sizeof(idbuf);
4840mdb_hash_enc(&
val, encbuf);
4841sprintf(
env->me_txns->mti_rmname,
"Global\\MDBr%s", encbuf);
4842sprintf(
env->me_txns->mti_wmname,
"Global\\MDBw%s", encbuf);
4843 env->me_rmutex = CreateMutexA(&mdb_all_sa,
FALSE,
env->me_txns->mti_rmname);
4844 if(!
env->me_rmutex)
gotofail_errno;
4845 env->me_wmutex = CreateMutexA(&mdb_all_sa,
FALSE,
env->me_txns->mti_wmname);
4846 if(!
env->me_wmutex)
gotofail_errno;
4847 #elif defined(MDB_USE_POSIX_SEM) 4856 #if defined(__NetBSD__) 4857 #define MDB_SHORT_SEMNAMES 1 4859 if(fstat(
env->me_lfd, &stbuf))
gotofail_errno;
4860idbuf.dev = stbuf.st_dev;
4861idbuf.ino = stbuf.st_ino;
4862 val.mv_data = &idbuf;
4863 val.mv_size =
sizeof(idbuf);
4864mdb_hash_enc(&
val, encbuf);
4865 #ifdef MDB_SHORT_SEMNAMES 4868sprintf(
env->me_txns->mti_rmname,
"/MDBr%s", encbuf);
4869sprintf(
env->me_txns->mti_wmname,
"/MDBw%s", encbuf);
4873sem_unlink(
env->me_txns->mti_rmname);
4874sem_unlink(
env->me_txns->mti_wmname);
4875 env->me_rmutex = sem_open(
env->me_txns->mti_rmname,
4876O_CREAT|O_EXCL,
mode, 1);
4877 if(
env->me_rmutex == SEM_FAILED)
gotofail_errno;
4878 env->me_wmutex = sem_open(
env->me_txns->mti_wmname,
4879O_CREAT|O_EXCL,
mode, 1);
4880 if(
env->me_wmutex == SEM_FAILED)
gotofail_errno;
4882pthread_mutexattr_t mattr;
4888memset(
env->me_txns->mti_rmutex, 0,
sizeof(*
env->me_txns->mti_rmutex));
4889memset(
env->me_txns->mti_wmutex, 0,
sizeof(*
env->me_txns->mti_wmutex));
4891 if((rc = pthread_mutexattr_init(&mattr)))
4894rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
4895 #ifdef MDB_ROBUST_SUPPORTED 4896 if(!rc) rc = pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST);
4898 if(!rc) rc = pthread_mutex_init(
env->me_txns->mti_rmutex, &mattr);
4899 if(!rc) rc = pthread_mutex_init(
env->me_txns->mti_wmutex, &mattr);
4900pthread_mutexattr_destroy(&mattr);
4907 env->me_txns->mti_txnid = 0;
4908 env->me_txns->mti_numreaders = 0;
4912 DPUTS(
"lock region has invalid magic");
4917 DPRINTF((
"lock region has format+version 0x%x, expected 0x%x",
4923 if(rc && rc != EACCES && rc != EAGAIN) {
4927 env->me_rmutex = OpenMutexA(SYNCHRONIZE,
FALSE,
env->me_txns->mti_rmname);
4928 if(!
env->me_rmutex)
gotofail_errno;
4929 env->me_wmutex = OpenMutexA(SYNCHRONIZE,
FALSE,
env->me_txns->mti_wmname);
4930 if(!
env->me_wmutex)
gotofail_errno;
4931 #elif defined(MDB_USE_POSIX_SEM) 4932 env->me_rmutex = sem_open(
env->me_txns->mti_rmname, 0);
4933 if(
env->me_rmutex == SEM_FAILED)
gotofail_errno;
4934 env->me_wmutex = sem_open(
env->me_txns->mti_wmname, 0);
4935 if(
env->me_wmutex == SEM_FAILED)
gotofail_errno;
4950 #define CHANGEABLE (MDB_NOSYNC|MDB_NOMETASYNC|MDB_MAPASYNC|MDB_NOMEMINIT) 4951 #define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY| \ 4952 MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD) 4954 #if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE|CHANGELESS) 4955 # error "Persistent DB flags & env flags overlap, but both go in mm_flags" 4988 env->me_dbiseqs =
calloc(
env->me_maxdbs,
sizeof(
unsigned int));
4989 if(!(
env->me_dbxs &&
env->me_path &&
env->me_dbflags &&
env->me_dbiseqs)) {
5023 DPRINTF((
"opened dbenv %p", (
void*)
env));
5043 env->me_txn0 = txn;
5068 if(
env->me_dbxs) {
5070 free(
env->me_dbxs[
i].md_name.mv_data);
5083pthread_key_delete(
env->me_txkey);
5086 for(
i=0;
i<mdb_tls_nkeys;
i++)
5087 if(mdb_tls_keys[
i] ==
env->me_txkey) {
5088mdb_tls_keys[
i] = mdb_tls_keys[mdb_tls_nkeys-1];
5095 if(
env->me_map) {
5096munmap(
env->me_map,
env->me_mapsize);
5102 if(
env->me_txns) {
5111 for(
i=
env->me_close_readers; --
i>= 0; )
5112 if(
env->me_txns->mti_readers[
i].mr_pid == pid)
5113 env->me_txns->mti_readers[
i].mr_pid = 0;
5115 if(
env->me_rmutex) {
5116CloseHandle(
env->me_rmutex);
5117 if(
env->me_wmutex) CloseHandle(
env->me_wmutex);
5122 #elif defined(MDB_USE_POSIX_SEM) 5123 if(
env->me_rmutex != SEM_FAILED) {
5124sem_close(
env->me_rmutex);
5125 if(
env->me_wmutex != SEM_FAILED)
5126sem_close(
env->me_wmutex);
5133sem_unlink(
env->me_txns->mti_rmname);
5134sem_unlink(
env->me_txns->mti_wmname);
5146UnlockFile(
env->me_lfd, 0, 0, 1, 0);
5164 while((dp =
env->me_dpages) !=
NULL) {
5166 env->me_dpages = dp->mp_next;
5178 return(*(
size_t*)
a->mv_data < *(
size_t*)
b->mv_data) ? -1 :
5179*(
size_t*)
a->mv_data > *(
size_t*)
b->mv_data;
5190 return(*(
unsigned int*)
a->mv_data < *(
unsigned int*)
b->mv_data) ? -1 :
5191*(
unsigned int*)
a->mv_data > *(
unsigned int*)
b->mv_data;
5200 #if BYTE_ORDER == LITTLE_ENDIAN 5201 unsigned short*u, *c;
5204u = (
unsigned short*) ((
char*)
a->mv_data +
a->mv_size);
5205c = (
unsigned short*) ((
char*)
b->mv_data +
a->mv_size);
5208}
while(!x && u > (
unsigned short*)
a->mv_data);
5211 unsigned short*u, *c, *end;
5214end = (
unsigned short*) ((
char*)
a->mv_data +
a->mv_size);
5215u = (
unsigned short*)
a->mv_data;
5216c = (
unsigned short*)
b->mv_data;
5219}
while(!x && u < end);
5239diff = memcmp(
a->mv_data,
b->mv_data,
len);
5240 returndiff ? diff : len_diff<0 ? -1 : len_diff;
5247 const unsigned char*p1, *p2, *p1_lim;
5251p1_lim = (
const unsigned char*)
a->mv_data;
5252p1 = (
const unsigned char*)
a->mv_data +
a->mv_size;
5253p2 = (
const unsigned char*)
b->mv_data +
b->mv_size;
5261 while(p1 > p1_lim) {
5262diff = *--p1 - *--p2;
5266 returnlen_diff<0 ? -1 : len_diff;
5279 unsigned int i= 0, nkeys;
5290 DPRINTF((
"searching %u keys in %s %spage %"Z"u",
5291nkeys,
IS_LEAF(mp) ?
"leaf":
"branch",
IS_SUBP(mp) ?
"sub-":
"",
5302 if(
NODEPTR(mp, 1)->mn_ksize ==
sizeof(
size_t))
5311 while(low <= high) {
5312 i= (low + high) >> 1;
5314rc =
cmp(
key, &nodekey);
5315 DPRINTF((
"found leaf index %u [%s], rc = %i",
5316 i,
DKEY(&nodekey), rc));
5325 while(low <= high) {
5326 i= (low + high) >> 1;
5332rc =
cmp(
key, &nodekey);
5335 DPRINTF((
"found leaf index %u [%s], rc = %i",
5336 i,
DKEY(&nodekey), rc));
5338 DPRINTF((
"found branch index %u [%s -> %"Z"u], rc = %i",
5356*exactp = (rc == 0 && nkeys > 0);
5386 DPRINTF((
"popping page %"Z"u off db %d cursor %p",
5404 DPRINTF((
"pushing page %"Z"u on db %d cursor %p", mp->mp_pgno,
5405 DDBI(mc), (
void*) mc));
5449 if(x <= tx2->mt_spill_pgs[0] && tx2->
mt_spill_pgs[x] == pn) {
5456 if(x <= dl[0].mid && dl[x].mid == pgno) {
5465 if(pgno < txn->mt_next_pgno) {
5469 DPRINTF((
"page %"Z"u not found", pgno));
5495 DPRINTF((
"branch page %"Z"u has %u keys", mp->mp_pgno,
NUMKEYS(mp)));
5550 DPRINTF((
"internal error, index points to a %02X page!?",
5556 DPRINTF((
"found leaf page %"Z"u for key [%s]", mp->mp_pgno,
5607 DPUTS(
"transaction may not be used now");
5646 DPUTS(
"tree is empty");
5652 if(!mc->
mc_pg[0] || mc->
mc_pg[0]->mp_pgno != root)
5659 DPRINTF((
"db %d root page %"Z"u has flags 0x%X",
5678 unsignedx = 0, ovpages = mp->mp_pages;
5684 DPRINTF((
"free ov page %"Z"u (%d)", pg, ovpages));
5693 if(
env->me_pghead &&
5715 for(ix = dl[x]; ix.
mptr!= mp; ix = iy) {
5722j = ++(dl[0].
mid);
5733mop =
env->me_pghead;
5734j = mop[0] + ovpages;
5735 for(
i= mop[0];
i&& mop[
i] < pg;
i--)
5736mop[j--] = mop[
i];
5773 DPRINTF((
"read overflow page %"Z"u failed", pgno));
5822 DPRINTF((
"parent page is page %"Z"u, index %u",
5827 DPRINTF((
"no more keys left, moving to %s sibling",
5828move_right ?
"right":
"left"));
5840 DPRINTF((
"just moving to %s index key %u",
5841move_right ?
"right":
"left", mc->
mc_ki[mc->
mc_top]));
5899 DPRINTF((
"cursor_next: top page is %"Z"u in cursor %p",
5900mdb_dbg_pgno(mp), (
void*) mc));
5907 DPUTS(
"=====> move to next sibling page");
5918 DPRINTF((
"==> cursor points to page %"Z"u with %u keys, key index %u",
5985 DPRINTF((
"cursor_prev: top page is %"Z"u in cursor %p",
5986mdb_dbg_pgno(mp), (
void*) mc));
5991 DPUTS(
"=====> move to prev sibling page");
6001 DPRINTF((
"==> cursor points to page %"Z"u with %u keys, key index %u",
6041 if(
key->mv_size == 0)
6075 unsigned intnkeys =
NUMKEYS(mp);
6150 if(exactp !=
NULL&& !*exactp) {
6156 DPUTS(
"===> inexact leaf not found, goto sibling");
6203 #if UINT_MAX < SIZE_MAX 6207rc = dcmp(
data, &olddata);
6339 if(!nkeys || mc->
mc_ki[mc->
mc_top] >= nkeys) {
6494 DPRINTF((
"unhandled/unimplemented cursor operation %u", op));
6537 #define MDB_NOSPILL 0x8000 6541 unsigned int flags)
6547 MDB_valxdata, *rdata, dkey, olddata;
6549 intdo_sub = 0, insert_key, insert_data;
6550 unsigned intmcount = 0, dcount = 0, nospill;
6553 unsigned intnflags;
6565dcount =
data[1].mv_size;
6566 data[1].mv_size = 0;
6580 #if SIZE_MAX > MAXDATASIZE 6588 DPRINTF((
"==> put db %d key [%s], size %"Z"u, data size %"Z"u",
6649 DPUTS(
"allocating new root leaf page");
6668insert_key = insert_data = rc;
6680 fp->mp_pad =
data->mv_size;
6690 if(
key->mv_size != ksize)
6693memcpy(ptr,
key->mv_data, ksize);
6699 unsigned shortdtop = 1;
6740 #if UINT_MAX < SIZE_MAX 6745 if(!dcmp(
data, &olddata)) {
6762 fp->mp_pad =
data->mv_size;
6800fp_flags =
fp->mp_flags;
6813 dummy.md_flags = 0;
6815 dummy.md_depth = 1;
6816 dummy.md_branch_pages = 0;
6817 dummy.md_leaf_pages = 1;
6818 dummy.md_overflow_pages = 0;
6826 dummy.md_root = mp->mp_pgno;
6832mp->mp_lower =
fp->mp_lower;
6833mp->mp_upper =
fp->mp_upper +
offset;
6860 intlevel, ovpages, dpages =
OVPAGES(
data->mv_size,
env->me_psize);
6862memcpy(&pg, olddata.
mv_data,
sizeof(pg));
6865ovpages = omp->mp_pages;
6868 if(ovpages >= dpages) {
6885 size_tsz = (size_t)
env->me_psize * ovpages, off;
6905memcpy((
size_t*)((
char*)np + off),
6906(
size_t*)((
char*)omp + off), sz - off);
6909memcpy(np, omp, sz);
6922}
else if(
data->mv_size == olddata.
mv_size) {
6967 if(m3->
mc_ki[
i] >= mc->
mc_ki[
i] && insert_key) {
6982 intxflags, new_dupdata;
7016 if(m2->
mc_pg[
i] == mp) {
7019}
else if(!insert_key) {
7051 data[1].mv_size = mcount;
7052 if(mcount < dcount) {
7053 data[0].mv_data = (
char*)
data[0].mv_data +
data[0].mv_size;
7054insert_key = insert_data = 0;
7186 DPRINTF((
"allocated new mpage %"Z"u, page size %u",
7222 if(sz >
env->me_nodemax) {
7246 if(sz >
env->me_nodemax) {
7252 returnsz +
sizeof(
indx_t);
7287 DPRINTF((
"add to %s %spage %"Z"u index %i, data size %"Z"u key size %"Z"u [%s]",
7288 IS_LEAF(mp) ?
"leaf":
"branch",
7290mdb_dbg_pgno(mp), indx,
data?
data->mv_size : 0,
7296 char*ptr =
LEAF2KEY(mp, indx, ksize);
7299 memmove(ptr+ksize, ptr, dif*ksize);
7301memcpy(ptr,
key->mv_data, ksize);
7304mp->mp_lower +=
sizeof(
indx_t);
7305mp->mp_upper -= ksize -
sizeof(
indx_t);
7311node_size +=
key->mv_size;
7316node_size +=
sizeof(
pgno_t);
7321 DPRINTF((
"data size is %"Z"u, node would be %"Z"u, put data on overflow page",
7322 data->mv_size, node_size+
data->mv_size));
7323node_size =
EVEN(node_size +
sizeof(
pgno_t));
7324 if((
ssize_t)node_size > room)
7328 DPRINTF((
"allocated overflow page %"Z"u", ofp->mp_pgno));
7332node_size +=
data->mv_size;
7335node_size =
EVEN(node_size);
7336 if((
ssize_t)node_size > room)
7345ofs = mp->mp_upper - node_size;
7349mp->mp_lower +=
sizeof(
indx_t);
7367memcpy(ndata,
data->mv_data,
sizeof(
pgno_t));
7369 data->mv_data = ndata;
7371memcpy(ndata,
data->mv_data,
data->mv_size);
7373memcpy(ndata, &ofp->mp_pgno,
sizeof(
pgno_t));
7376 data->mv_data = ndata;
7378memcpy(ndata,
data->mv_data,
data->mv_size);
7385 DPRINTF((
"not enough room in page %"Z"u, got %u ptrs",
7386mdb_dbg_pgno(mp),
NUMKEYS(mp)));
7387 DPRINTF((
"upper-lower = %u - %u = %"Z"d", mp->mp_upper,mp->mp_lower,room));
7388 DPRINTF((
"node size = %"Z"u", node_size));
7408 DPRINTF((
"delete node %u on %s page %"Z"u", indx,
7409 IS_LEAF(mp) ?
"leaf":
"branch", mdb_dbg_pgno(mp)));
7414 intx = numkeys - 1 - indx;
7417 memmove(base, base + ksize, x * ksize);
7418mp->mp_lower -=
sizeof(
indx_t);
7419mp->mp_upper += ksize -
sizeof(
indx_t);
7434 for(
i= j = 0;
i< numkeys;
i++) {
7443base = (
char*)mp + mp->mp_upper +
PAGEBASE;
7444 memmove(base + sz, base, ptr - mp->mp_upper);
7446mp->mp_lower -=
sizeof(
indx_t);
7479sp->mp_upper = sp->mp_lower;
7484base = (
char*)mp + mp->mp_upper +
PAGEBASE;
7492mp->mp_upper +=
delta;
7567 #if UINT_MAX < SIZE_MAX 7593 #if UINT_MAX < SIZE_MAX 7729 while(*
prev&& *
prev!= mc)
prev= &(*prev)->mc_next;
7740 if(!mc)
return NULL;
7763 int delta, ksize, oksize;
7764 indx_tptr,
i, numkeys, indx;
7774 charkbuf2[DKBUF_MAXKEYSIZE*2+1];
7777 DPRINTF((
"update key %u (ofs %u) [%s] to [%s] on page %"Z"u",
7779mdb_dkey(&k2, kbuf2),
7786ksize =
EVEN(
key->mv_size);
7788 delta= ksize - oksize;
7795 DPRINTF((
"Not enough room, delta = %d, splitting...",
delta));
7802 for(
i= 0;
i< numkeys;
i++) {
7807base = (
char*)mp + mp->mp_upper +
PAGEBASE;
7810mp->mp_upper -=
delta;
7829 #define WITH_CURSOR_TRACKING(mn, act) do { \ 7830 MDB_cursor dummy, *tracked, **tp = &(mn).mc_txn->mt_cursors[mn.mc_dbi]; \ 7831 if ((mn).mc_flags & C_SUB) { \ 7832 dummy.mc_flags = C_INITIALIZED; \ 7833 dummy.mc_xcursor = (MDB_xcursor *)&(mn); \ 7838 tracked->mc_next = *tp; \ 7841 *tp = tracked->mc_next; \ 7854 unsigned short flags;
7874 flags= srcnode->mn_flags;
7876 unsigned intsnum = csrc->
mc_snum;
7901 unsigned intsnum = cdst->
mc_snum;
7919mn.
mc_ki[snum] = 0;
7925 DPRINTF((
"moving %s node %u [%s] on page %"Z"u to node %u on page %"Z"u",
7982 if(m3 == csrc)
continue;
8011 DPRINTF((
"update separator for source page %"Z"u to [%s]",
8042 DPRINTF((
"update separator for destination page %"Z"u to [%s]",
8088 DPRINTF((
"merging page %"Z"u into %"Z"u", psrc->mp_pgno, pdst->mp_pgno));
8106 for(
i= 0;
i<
NUMKEYS(psrc);
i++, j++) {
8110 key.mv_data = (
char*)
key.mv_data +
key.mv_size;
8113 for(
i= 0;
i<
NUMKEYS(psrc);
i++, j++) {
8145 DPRINTF((
"dst page %"Z"u now has %u keys (%.1f%% filled)",
8146pdst->mp_pgno,
NUMKEYS(pdst),
8178 unsigned inttop = csrc->
mc_top;
8185 if(m3 == csrc)
continue;
8187 if(m3->
mc_pg[top] == psrc) {
8188m3->
mc_pg[top] = pdst;
8189m3->
mc_ki[top] += nkeys;
8191}
else if(m3->
mc_pg[top-1] == csrc->
mc_pg[top-1] &&
8193m3->
mc_ki[top-1]--;
8200 unsigned intsnum = cdst->
mc_snum;
8246 unsigned intptop, minkeys, thresh;
8257 DPRINTF((
"rebalancing %s page %"Z"u (has %u keys, %.1f%% full)",
8264 DPRINTF((
"no need to rebalance page %"Z"u, above fill threshold",
8272 DPUTS(
"Can't rebalance a subpage, ignoring");
8276 DPUTS(
"tree is completely empty");
8298 if(m3->
mc_pg[0] == mp) {
8307 DPUTS(
"collapsing root page!");
8332 if(m3 == mc)
continue;
8335 if(m3->
mc_pg[0] == mp) {
8346 DPUTS(
"root page doesn't need rebalancing");
8367 if(mc->
mc_ki[ptop] == 0) {
8370 DPUTS(
"reading right neighbor");
8382 DPUTS(
"reading left neighbor");
8393 DPRINTF((
"found neighbor page %"Z"u (%u keys, %.1f%% full)",
8596 unsigned intnflags)
8598 unsigned int flags;
8599 intrc =
MDB_SUCCESS, new_root = 0, did_split = 0;
8602 int i, j, split_indx, nkeys, pmax;
8605 MDB_valsepkey, rkey, xdata, *rdata = &xdata;
8616 DPRINTF((
"-----> splitting %s page %"Z"u and adding [%s] at index %i/%i",
8617 IS_LEAF(mp) ?
"leaf":
"branch", mp->mp_pgno,
8624 DPRINTF((
"new right sibling: page %"Z"u", rp->mp_pgno));
8639mc->
mc_pg[0] = pp;
8642 DPRINTF((
"root split! new root = %"Z"u", pp->mp_pgno));
8659 DPRINTF((
"parent branch page is %"Z"u", mc->
mc_pg[ptop]->mp_pgno));
8670split_indx = newindx;
8674split_indx = (nkeys+1) / 2;
8677 char*
split, *ins;
8679 unsigned intlsize, rsize, ksize;
8684rsize = (nkeys - split_indx) * ksize;
8685lsize = (nkeys - split_indx) *
sizeof(
indx_t);
8686mp->mp_lower -= lsize;
8687rp->mp_lower += lsize;
8688mp->mp_upper += rsize - lsize;
8689rp->mp_upper -= rsize - lsize;
8691 if(newindx == split_indx) {
8701memcpy(ins, newkey->
mv_data, ksize);
8702mp->mp_lower +=
sizeof(
indx_t);
8703mp->mp_upper -= ksize -
sizeof(
indx_t);
8708memcpy(ins, newkey->
mv_data, ksize);
8709memcpy(ins+ksize,
split+ x * ksize, rsize - x * ksize);
8710rp->mp_lower +=
sizeof(
indx_t);
8711rp->mp_upper -= ksize -
sizeof(
indx_t);
8715 intpsize, nsize, k;
8722nsize =
EVEN(nsize);
8730 copy->mp_pgno = mp->mp_pgno;
8736 for(
i=0, j=0;
i<nkeys;
i++) {
8737 if(
i== newindx) {
8738 copy->mp_ptrs[j++] = 0;
8758 if(nkeys < 32 || nsize > pmax/16 || newindx >= nkeys) {
8761 if(newindx <= split_indx || newindx >= nkeys) {
8763k = newindx >= nkeys ? nkeys : split_indx+1+
IS_LEAF(mp);
8768 for(;
i!=k;
i+=j) {
8769 if(
i== newindx) {
8777psize +=
sizeof(
pgno_t);
8781psize =
EVEN(psize);
8783 if(psize > pmax ||
i== k-j) {
8784split_indx =
i+ (j<0);
8789 if(split_indx == newindx) {
8800 DPRINTF((
"separator is %d [%s]", split_indx,
DKEY(&sepkey)));
8824 for(
i=0;
i<ptop;
i++) {
8829 if(mn.
mc_ki[ptop]) {
8848rc =
mdb_node_add(mc, 0, newkey, newdata, newpgno, nflags);
8859 if(
i== newindx) {
8882 if(!
IS_LEAF(mp) && j == 0) {
8898}
while(
i!= split_indx);
8901 for(
i=0;
i<nkeys;
i++)
8903mp->mp_lower =
copy->mp_lower;
8904mp->mp_upper =
copy->mp_upper;
8909 if(newindx < split_indx) {
8913mc->
mc_ki[ptop]++;
8918 for(
i=0;
i<=ptop;
i++) {
8930 if(newindx >= split_indx) {
8932mc->
mc_ki[ptop]++;
8937 for(
i=0;
i<=ptop;
i++) {
8963 if(m3->
mc_pg[0] != mp)
8966 for(k=new_root; k>=0; k--) {
8970 if(m3->
mc_ki[0] >= nkeys) {
8990}
else if(!did_split && m3->
mc_top>= ptop && m3->
mc_pg[ptop] == mc->
mc_pg[ptop] &&
8992m3->
mc_ki[ptop]++;
9034 #define MDB_WBUF (1024*1024) 9036 #define MDB_EOF 0x10 9064 inttoggle = 0, wsize, rc;
9067 #define DO_WRITE(rc, fd, ptr, w2, len) rc = WriteFile(fd, ptr, w2, &len, NULL) 9070 #define DO_WRITE(rc, fd, ptr, w2, len) len = write(fd, ptr, w2); rc = (len >= 0) 9073sigemptyset(&
set);
9074sigaddset(&
set, SIGPIPE);
9075 if((rc = pthread_sigmask(SIG_BLOCK, &
set,
NULL)) != 0)
9080pthread_mutex_lock(&my->
mc_mutex);
9086wsize = my->
mc_wlen[toggle];
9090 while(wsize > 0 && !my->
mc_error) {
9094 #if defined(SIGPIPE) && !defined(_WIN32) 9104}
else if(
len> 0) {
9119wsize = my->
mc_olen[toggle];
9128pthread_cond_signal(&my->
mc_cond);
9130pthread_mutex_unlock(&my->
mc_mutex);
9143pthread_mutex_lock(&my->
mc_mutex);
9145pthread_cond_signal(&my->
mc_cond);
9148pthread_mutex_unlock(&my->
mc_mutex);
9207 for(
i=0;
i<
n;
i++) {
9221memcpy(&pg,
NODEDATA(ni),
sizeof(pg));
9237 if(omp->mp_pages > 1) {
9256memcpy(&db,
NODEDATA(ni),
sizeof(db));
9262memcpy(
NODEDATA(ni), &db,
sizeof(db));
9337rc = ERROR_NOT_ENOUGH_MEMORY;
9341 if((rc = pthread_mutex_init(&my.
mc_mutex,
NULL)) != 0)
9343 if((rc = pthread_cond_init(&my.
mc_cond,
NULL)) != 0)
9345 #ifdef HAVE_MEMALIGN 9354 if((rc = posix_memalign(&p,
env->me_os_psize,
MDB_WBUF*2)) != 0)
9440pthread_cond_destroy(&my.
mc_cond);
9442pthread_mutex_destroy(&my.
mc_mutex);
9458 #define DO_WRITE(rc, fd, ptr, w2, len) rc = WriteFile(fd, ptr, w2, &len, NULL) 9462 #define DO_WRITE(rc, fd, ptr, w2, len) len = write(fd, ptr, w2); rc = (len >= 0) 9472 if(
env->me_txns) {
9477wmutex =
env->me_wmutex;
9496}
else if(
len> 0) {
9531}
else if(
len> 0) {
9594 env->me_flags |= flag;
9596 env->me_flags &= ~flag;
9631 env->me_assert_func = func;
9642*arg =
env->me_path;
9736 intrc, dbflag, exact;
9737 unsigned int unused= 0, seq;
9792 key.mv_data = (
void*)name;
9870 if(dbi < CORE_DBS || dbi >=
env->me_maxdbs)
9872ptr =
env->me_dbxs[dbi].md_name.mv_data;
9875 env->me_dbxs[dbi].md_name.mv_data =
NULL;
9876 env->me_dbxs[dbi].md_name.mv_size = 0;
9877 env->me_dbflags[dbi] = 0;
9878 env->me_dbiseqs[dbi]++;
9923 for(
i=0;
i<
n;
i++) {
9928memcpy(&pg,
NODEDATA(ni),
sizeof(pg));
9952 for(
i=0;
i<
n;
i++) {
10087 unsigned int i, rdrs;
10090 intrc = 0,
first= 1;
10092 if(!
env|| !func)
10094 if(!
env->me_txns) {
10095 returnfunc(
"(no reader locks)\n",
ctx);
10097rdrs =
env->me_txns->mti_numreaders;
10098mr =
env->me_txns->mti_readers;
10099 for(
i=0;
i<rdrs;
i++) {
10103 "%10d %"Z"x -\n":
"%10d %"Z"x %"Z"u\n",
10107rc = func(
" pid thread txnid\n",
ctx);
10117rc = func(
"(no active readers)\n",
ctx);
10130 unsignedcursor = 1;
10132 unsigned n= ids[0];
10135 unsignedpivot =
n>> 1;
10136cursor = base + pivot + 1;
10137 val= pid - ids[cursor];
10142}
else if(
val> 0 ) {
10156 for(
n= ids[0];
n> cursor;
n--)
10157ids[
n] = ids[
n-1];
10177 unsigned int i, j, rdrs;
10182rdrs =
env->me_txns->mti_numreaders;
10187mr =
env->me_txns->mti_readers;
10188 for(
i=0;
i<rdrs;
i++) {
10189pid = mr[
i].mr_pid;
10190 if(pid && pid !=
env->me_pid) {
10206 for(; j<rdrs; j++)
10207 if(mr[j].
mr_pid== pid) {
10208 DPRINTF((
"clear stale reader pid %u txn %"Z"d",
10209(
unsigned) pid, mr[j].
mr_txnid));
10225 #ifdef MDB_ROBUST_SUPPORTED 10239 if(rc == MDB_OWNERDEAD) {
10242rlocked = (mutex ==
env->me_rmutex);
10250 if(
env->me_txn) {
10256 DPRINTF((
"%cmutex owner died, %s", (rlocked ?
'r':
'w'),
10257(rc ?
"this process' env is hosed":
"recovering")));
10261 if(rc || (rc = rc2)) {
10276 #if defined(_WIN32) 10279utf8_to_utf16(
const char*src,
MDB_name*dst,
intxtra)
10284need = MultiByteToWideChar(CP_UTF8, 0, src, -1,
result, need);
10291 result=
malloc(
sizeof(
wchar_t) * (need + xtra));
10297dst->
mn_len= need - 1;
static unsigned char depth[2 *(256+1+29)+1]
std::ofstream out("events_result.xml")
main entry point for tests
static const struct name_t names[]
static DLIST_TYPE *DLIST_NAME() first(DLIST_LIST_TYPE *list)
static DLIST_TYPE *DLIST_NAME() last(DLIST_LIST_TYPE *list)
static DLIST_TYPE *DLIST_NAME() prev(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
static DLIST_TYPE *DLIST_NAME() next(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
#define MDB_VERSION_STRING
The full library version as a C string.
#define MDB_VERSION_MINOR
Library minor version.
#define MDB_VERSION_MAJOR
Library major version.
#define MDB_VERSION_PATCH
Library patch version.
#define ErrCode()
Get the error code for the last failed system function.
#define THREAD_CREATE(thr, start, arg)
pthread_mutex_t * mdb_mutexref_t
Reference to an mdb_mutex_t.
#define Z
printf format modifier for size_t
#define INVALID_HANDLE_VALUE
A value for an invalid file handle.
#define UNLOCK_MUTEX(mutex)
Unlock the reader or writer mutex.
#define THREAD_FINISH(thr)
#define GET_PAGESIZE(x)
Get the size of a memory page for the system.
pthread_mutex_t mdb_mutex_t[1]
Shared mutex/semaphore as the original is stored.
#define mdb_mutex_consistent(mutex)
Mark mutex-protected data as repaired, after death of previous owner.
#define HANDLE
An abstraction for a file handle.
#define LOCK_MUTEX0(mutex)
Lock the reader or writer mutex.
#define DPUTS(arg)
Print a debug string.
#define DDBI(mc)
Debuging output value of a cursor DBI: Negative in a sub-cursor.
#define MDB_PAGE_FULL
Page has not enough space - internal error.
#define MDB_KEYEXIST
key/data pair already exists
#define MDB_MAP_FULL
Environment mapsize reached.
#define MDB_BAD_RSLOT
Invalid reuse of reader locktable slot.
#define MDB_LAST_ERRCODE
The last defined error code.
#define MDB_BAD_VALSIZE
Unsupported size of key/DB name/data, or wrong DUPFIXED size.
#define MDB_DBS_FULL
Environment maxdbs reached.
#define MDB_MAP_RESIZED
Database contents grew beyond environment mapsize.
#define MDB_PAGE_NOTFOUND
Requested page not found - this usually indicates corruption.
#define MDB_VERSION_MISMATCH
Environment version mismatch.
#define MDB_INVALID
File is not a valid LMDB file.
#define MDB_INCOMPATIBLE
Operation and DB incompatible, or DB type changed.
#define MDB_BAD_DBI
The specified DBI was changed unexpectedly.
#define MDB_TLS_FULL
Too many TLS keys in use - Windows only.
#define MDB_NOTFOUND
key/data pair not found (EOF)
#define MDB_TXN_FULL
Txn has too many dirty pages.
#define MDB_SUCCESS
Successful result.
#define MDB_BAD_TXN
Transaction must abort, has a child, or is invalid.
#define MDB_READERS_FULL
Environment maxreaders reached.
#define MDB_CURSOR_FULL
Cursor stack too deep - internal error.
#define MDB_PANIC
Update of meta page failed or environment had fatal error.
#define MDB_CORRUPTED
Located page was wrong type.
void mdb_midl_free(MDB_IDL ids)
Free an IDL.
int mdb_midl_append_list(MDB_IDL *idp, MDB_IDL app)
Append an IDL onto an IDL.
MDB_ID * MDB_IDL
An IDL is an ID List, a sorted array of IDs.
int mdb_midl_need(MDB_IDL *idp, unsigned num)
Make room for num additional elements in an IDL.
#define MDB_IDL_SIZEOF(ids)
void mdb_midl_xmerge(MDB_IDL idl, MDB_IDL merge)
Merge an IDL onto an IDL.
#define MDB_IDL_ALLOCLEN(ids)
Current max length of an mdb_midl_alloc()ed IDL.
unsigned mdb_mid2l_search(MDB_ID2L ids, MDB_ID id)
Search for an ID in an ID2L.
int mdb_mid2l_append(MDB_ID2L ids, MDB_ID2 *id)
Append an ID2 into a ID2L.
int mdb_mid2l_insert(MDB_ID2L ids, MDB_ID2 *id)
Insert an ID2 into a ID2L.
void mdb_midl_shrink(MDB_IDL *idp)
Shrink an IDL.
unsigned mdb_midl_search(MDB_IDL ids, MDB_ID id)
Search for an ID in an IDL.
MDB_IDL mdb_midl_alloc(int num)
Allocate an IDL.
void mdb_midl_sort(MDB_IDL ids)
Sort an IDL.
int mdb_midl_append_range(MDB_IDL *idp, MDB_ID id, unsigned n)
Append an ID range onto an IDL.
size_t MDB_ID
A generic unsigned ID number.
int mdb_midl_append(MDB_IDL *idp, MDB_ID id)
Append an ID onto an IDL.
#define mdb_midl_xappend(idl, id)
Append ID to IDL.
MDB_ID2 * MDB_ID2L
An ID2L is an ID2 List, a sorted array of ID2s.
struct MDB_meta MDB_meta
Meta page content.
static int mdb_cmp_long(const MDB_val *a, const MDB_val *b)
Compare two items pointing at aligned size_t's.
static void mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi)
Set the default comparison functions for a database.
static void mdb_node_shrink(MDB_page *mp, indx_t indx)
Compact the main page after deleting a node on a subpage.
void mdb_txn_reset(MDB_txn *txn)
Reset a read-only transaction.
static int mdb_freelist_save(MDB_txn *txn)
Save the freelist as of this transaction to the freeDB.
#define mdb_name_cpy
Copy name (mdb_nchar_t string)
static int mdb_page_spill(MDB_cursor *m0, MDB_val *key, MDB_val *data)
Spill pages from the dirty list back to disk.
static size_t mdb_leaf_size(MDB_env *env, MDB_val *key, MDB_val *data)
Calculate the size of a leaf node.
static int mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
Move the cursor to the previous data item.
#define NODEKEY(node)
Address of the key for the node.
char * mdb_version(int *major, int *minor, int *patch)
Return the library version info.
int mdb_env_set_flags(MDB_env *env, unsigned int flag, int onoff)
Set environment flags.
static int mdb_cursor_shadow(MDB_txn *src, MDB_txn *dst)
Back up parent txn's cursors, then grab the originals for tracking.
static int mdb_env_excl_lock(MDB_env *env, int *excl)
Try to get exclusive lock, otherwise shared.
#define MAXDATASIZE
The maximum size of a data item.
static int mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
Move the cursor to the next data item.
static int mdb_rebalance(MDB_cursor *mc)
Rebalance the tree after a delete operation.
static int mdb_env_write_meta(MDB_txn *txn)
Update the environment info to commit a transaction.
#define TXN_DBI_CHANGED(txn, dbi)
Check for misused dbi handles.
static int mdb_cursor_first(MDB_cursor *mc, MDB_val *key, MDB_val *data)
Move the cursor to the first item in the database.
static int mdb_env_copyfd0(MDB_env *env, int fd)
Copy environment as-is.
static int mdb_env_setup_locks(MDB_env *env, MDB_name *fname, int mode, int *excl)
Open and/or initialize the lock region for the environment.
#define MDB_EOF
mdb_env_copyfd1() is done reading
#define SETPGNO(node, pgno)
Set the page number in a branch node.
#define MDB_NOSPILL
Do not spill pages to disk if txn is getting full, may fail instead.
static MDB_page * mdb_page_malloc(MDB_txn *txn, unsigned num)
Allocate memory for a page.
static void mdb_dpage_free(MDB_env *env, MDB_page *dp)
Free a dirty page.
static int mdb_node_add(MDB_cursor *mc, indx_t indx, MDB_val *key, MDB_val *data, pgno_t pgno, unsigned int flags)
Add a node to the page pointed to by the cursor.
int mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *arg)
Return the filedescriptor for the given environment.
#define MDB_END_UPDATE
update env state (DBIs)
static void mdb_page_copy(MDB_page *dst, MDB_page *src, unsigned int psize)
Copy the used portions of a non-overflow page.
static size_t mdb_branch_size(MDB_env *env, MDB_val *key)
Calculate the size of a branch node.
static int mdb_cmp_cint(const MDB_val *a, const MDB_val *b)
Compare two items pointing at unsigned ints of unknown alignment.
#define mdb_cassert(mc, expr)
assert(3) variant in cursor context
int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode)
Open an environment handle.
static void mdb_page_free(MDB_env *env, MDB_page *mp)
Free a single page.
static int mdb_page_search_root(MDB_cursor *mc, MDB_val *key, int modify)
Finish mdb_page_search() / mdb_page_search_lowest().
#define METADATA(p)
Address of first usable data byte in a page, after the header.
int mdb_reader_check(MDB_env *env, int *dead)
Check for stale entries in the reader lock table.
static int mdb_cursor_touch(MDB_cursor *mc)
Touch all the pages in the cursor stack.
#define XCURSOR_REFRESH(mc, top, mp)
Update the xcursor's sub-page pointer, if any, in mc.
mdb_fopen_type
File type, access mode etc.
#define XCURSOR_INITED(mc)
Check if there is an inited xcursor.
static int mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op, int *exactp)
Set the cursor on a specific data item.
static int mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp)
#define FREE_DBI
Handle for the DB used to track free pages.
int mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags)
Copy an LMDB environment to the specified path, with options.
static int mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags)
Search for the page a given key should be in.
static char *const mdb_errstr[]
Table of descriptions for LMDB Return Codes.
#define PAGEBASE
ITS#7713, change PAGEBASE to handle 65536 byte pages.
#define MDB_END_OPMASK
mask for mdb_txn_end() operation number
void mdb_env_close(MDB_env *env)
Close the environment and release the memory map.
#define MDB_SPLIT_REPLACE
newkey is not new
static void mdb_xcursor_init2(MDB_cursor *mc, MDB_xcursor *src_mx, int force)
Fixup a sorted-dups cursor due to underlying update.
static int mdb_page_loose(MDB_cursor *mc, MDB_page *mp)
Loosen or free a single page.
void * mdb_env_get_userctx(MDB_env *env)
Get the application information associated with the MDB_env.
#define WITH_CURSOR_TRACKING(mn, act)
Perform act while tracking temporary cursor mn.
int mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *arg)
Retrieve statistics for a database.
void mdb_cursor_close(MDB_cursor *mc)
Close a cursor handle.
#define mdb_cmp_clong
Compare two items pointing at size_t's of unknown alignment.
#define IS_OVERFLOW(p)
Test if a page is an overflow page.
static int mdb_fopen(const MDB_env *env, MDB_name *fname, enum mdb_fopen_type which, mdb_mode_t mode, int *res)
Open an LMDB file.
static int mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp)
Allocate and initialize new pages for a database.
#define IS_SUBP(p)
Test if a page is a sub page.
#define MDB_MAGIC
A stamp that identifies a file as an LMDB file.
struct MDB_page MDB_page
Common header for all page types.
int mdb_put(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned int flags)
Store items into a database.
#define DEFAULT_MAPSIZE
Default size of memory map.
static void mdb_node_del(MDB_cursor *mc, int ksize)
Delete the specified node from a page.
void mdb_dbi_close(MDB_env *env, MDB_dbi dbi)
Close a database handle.
#define MDB_END_FREE
free txn unless it is MDB_env.
static int mdb_cmp_memnr(const MDB_val *a, const MDB_val *b)
Compare two items in reverse byte order.
struct MDB_node MDB_node
Header for a single key/data pair within a page.
static void mdb_cursor_copy(const MDB_cursor *csrc, MDB_cursor *cdst)
Copy the contents of a cursor.
char * mdb_strerror(int err)
Return a string describing a given error code.
#define TXN_DBI_EXIST(txn, dbi, validity)
Check txn and dbi arguments to a function.
static int mdb_txn_renew0(MDB_txn *txn)
Common code for mdb_txn_begin() and mdb_txn_renew().
#define PAGEFILL(env, p)
The percentage of space used in the page, in tenths of a percent.
#define MDB_DATA_VERSION
The version number for a database's datafile format.
int mdb_env_copy(MDB_env *env, const char *path)
Copy an LMDB environment to the specified path.
static int mdb_env_cthr_toggle(mdb_copy *my, int adjust)
Give buffer and/or MDB_EOF to writer thread, await unused buffer.
static int mdb_node_read(MDB_cursor *mc, MDB_node *leaf, MDB_val *data)
Return the data associated with a given node.
static const mdb_nchar_t *const mdb_suffixes[2][2]
Filename suffixes [datafile,lockfile][without,with MDB_NOSUBDIR].
#define FILL_THRESHOLD
The minimum page fill factor, in tenths of a percent.
int mdb_cursor_renew(MDB_txn *txn, MDB_cursor *mc)
Renew a cursor handle.
static int mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data)
Move the cursor to the last item in the database.
static int mdb_pid_insert(pid_t *ids, pid_t pid)
Insert pid into list if not already present.
int mdb_env_info(MDB_env *env, MDB_envinfo *arg)
Return information about the LMDB environment.
static void mdb_page_dirty(MDB_txn *txn, MDB_page *mp)
Add a page to the txn's dirty list.
#define MAX_PAGESIZE
The maximum size of a database page.
int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
Set a custom key comparison function for a database.
int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel)
Set a relocation function for a MDB_FIXEDMAP database.
static int mdb_env_map(MDB_env *env, void *addr)
static int mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
Merge one page into another.
int mdb_txn_renew(MDB_txn *txn)
Renew a read-only transaction.
static int mdb_cmp_memn(const MDB_val *a, const MDB_val *b)
Compare two items lexically.
#define MAX_WRITE
max bytes to write in one call
int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func)
Set or reset the assert() callback of the environment.
static void mdb_dlist_free(MDB_txn *txn)
Return all dirty pages to dpage list.
int mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **ret)
Create a cursor handle.
static void mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
Initialize a cursor for a given transaction and database.
int mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers)
Get the maximum number of threads/reader slots for the environment.
uint16_t indx_t
Used for offsets within a single page.
#define SETDSZ(node, size)
Set the size of the data for a leaf node.
void mdb_txn_abort(MDB_txn *txn)
Abandon all the operations of the transaction instead of saving them.
#define CHANGEABLE
Only a subset of the Environment Flags flags can be changed at runtime.
#define MDB_SUFFLEN
Max string length in mdb_suffixes[].
static int mdb_env_read_header(MDB_env *env, MDB_meta *meta)
Read the environment parameters of a DB environment before mapping it into memory.
static int mdb_pages_xkeep(MDB_cursor *mc, unsigned pflags, int all)
Set or clear P_KEEP in dirty, non-overflow, non-sub pages watched by txn.
#define LEAF2KEY(p, i, ks)
The address of a key in a LEAF2 page.
int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx)
Set a context pointer for a MDB_FIXEDMAP database's relocation function.
#define NUMKEYS(p)
Number of nodes on a page.
#define NODESIZE
Size of the node header, excluding dynamic data at the end.
#define mdb_tassert(txn, expr)
assert(3) variant in transaction context
#define ENV_MAXKEY(env)
The maximum size of a key we can write to the environment.
#define MDB_MINKEYS
The minimum number of keys required in a database page.
int mdb_txn_commit(MDB_txn *txn)
Commit all the operations of a transaction into the database.
struct mdb_copy mdb_copy
State needed for a double-buffering compacting copy.
int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx)
Dump the entries in the reader lock table.
static MDB_node * mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp)
Search for key within a page, using binary search.
int mdb_env_sync(MDB_env *env, int force)
Flush the data buffers to disk.
struct MDB_name MDB_name
Filename - string of mdb_nchar_t[].
static void mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node)
Final setup of a sorted-dups cursor.
union MDB_metabuf MDB_metabuf
Buffer for a stack-allocated meta page.
#define MDB_GET_KEY(node, keyptr)
Set the node's key into keyptr, if requested.
#define LOCK_MUTEX(rc, env, mutex)
int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)
Get items from a database.
int mdb_env_copyfd2(MDB_env *env, int fd, unsigned int flags)
Copy an LMDB environment to the specified file descriptor, with options.
#define MDB_MSYNC(addr, len, flags)
static int mdb_cmp_int(const MDB_val *a, const MDB_val *b)
Compare two items pointing at aligned unsigned int's.
struct MDB_pgstate MDB_pgstate
State of FreeDB old pages, stored in the MDB_env.
static int mdb_reader_pid(MDB_env *env, enum Pidlock_op op, pid_t pid)
Set or check a pid lock.
#define NODEDSZ(node)
Get the size of the data in a leaf node.
static int mdb_page_flush(MDB_txn *txn, int keep)
Flush (some) dirty pages to the map, after clearing their dirty flag.
#define mdb_env_close0(env, excl)
static int mdb_stat0(MDB_env *env, MDB_db *db, MDB_stat *arg)
Common code for mdb_stat() and mdb_env_stat().
int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags)
Retrieve the DB flags for a database handle.
static int mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
Allocate page numbers and memory for writing.
#define VALID_FLAGS
mdb_dbi_open() flags
int mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
Retrieve by cursor.
static txnid_t mdb_find_oldest(MDB_txn *txn)
Find oldest txnid still referenced.
#define NEXT_LOOSE_PAGE(p)
Link in MDB_txn.
#define CORE_DBS
Number of DBs in metapage (free and main) - also hardcoded elsewhere.
static void mdb_txn_end(MDB_txn *txn, unsigned mode)
End a transaction, except successful commit of a nested transaction.
static int mdb_fsize(int fd, size_t *size)
int mdb_env_set_mapsize(MDB_env *env, size_t size)
Set the size of the memory map to use for this environment.
#define COPY_PGNO(dst, src)
Copy a page number from src to dst.
int mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs)
Set the maximum number of named databases for the environment.
#define MDB_FDATASYNC
Function for flushing the data of a file.
#define F_ISSET(w, f)
Test if the flags f are set in a flag word w.
static MDB_meta * mdb_env_pick_meta(const MDB_env *env)
Check both meta pages to see which one is newer.
#define NODEKSZ(node)
The size of a key in a node.
#define EVEN(n)
Round n up to an even number.
#define NODEDATA(node)
Address of the data for a node.
static int mdb_update_key(MDB_cursor *mc, MDB_val *key)
Replace the key for a branch node with a new key.
#define IS_LEAF2(p)
Test if a page is a LEAF2 page.
#define mdb_mutex_failed(env, mutex, rc)
int mdb_env_create(MDB_env **env)
Create an LMDB environment handle.
int mdb_env_get_maxkeysize(MDB_env *env)
Get the maximum size of keys and MDB_DUPSORT data we can write.
static int mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno, unsigned int nflags)
Split a page and insert a new node.
static void mdb_dbis_update(MDB_txn *txn, int keep)
Export or close DBI handles opened in this txn.
#define MDB_END_SLOT
release any reader slot if MDB_NOTLS
int mdb_del(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)
Delete items from a database.
#define P_INVALID
An invalid page number.
int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
Empty or delete+close a database.
static void mdb_assert_fail(MDB_env *env, const char *expr_txt, const char *func, const char *file, int line)
int mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)
Compare two data items according to a particular database.
MDB_ID txnid_t
A transaction ID.
#define NODEPGNO(node)
Get the page number pointed to by a branch node.
MDB_txn * mdb_cursor_txn(MDB_cursor *mc)
Return the cursor's transaction handle.
#define IS_LEAF(p)
Test if a page is a leaf page.
int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)
Open a database in the environment.
static int mdb_cursor_push(MDB_cursor *mc, MDB_page *mp)
Push a page onto the top of the cursor's stack.
int mdb_env_get_flags(MDB_env *env, unsigned int *arg)
Get environment flags.
static int mdb_fname_init(const char *path, unsigned envflags, MDB_name *fname)
Set up filename + scratch area for filename suffix, for opening files.
#define IS_BRANCH(p)
Test if a page is a branch page.
static int mdb_page_search_lowest(MDB_cursor *mc)
Search for the lowest key under the current branch page.
int mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)
Compare two data items according to a particular database.
#define mdb_fname_destroy(fname)
Destroy fname from mdb_fname_init()
static void mdb_xcursor_init0(MDB_cursor *mc)
Initial setup of a sorted-dups cursor.
static void mdb_cursor_pop(MDB_cursor *mc)
Pop a page off the top of the cursor's stack.
static void * mdb_env_copythr(void *arg)
Dedicated writer thread for compacting copy.
struct MDB_dbx MDB_dbx
Auxiliary DB info.
int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
Set a custom data comparison function for a MDB_DUPSORT database.
#define LEAFSIZE(k, d)
Size of a node in a leaf page with a given key and data.
static int mdb_page_touch(MDB_cursor *mc)
Touch a page: make it dirty and re-insert into tree with updated pgno.
#define MAIN_DBI
Handle for the default DB.
static int mdb_env_copyfd1(MDB_env *env, int fd)
Copy environment with compaction.
static int mdb_page_get(MDB_cursor *mc, pgno_t pgno, MDB_page **mp, int *lvl)
Find the address of the page corresponding to a given page number.
static int mdb_env_cwalk(mdb_copy *my, pgno_t *pg, int flags)
Depth-first tree traversal for compacting copy.
static int mdb_env_init_meta(MDB_env *env, MDB_meta *meta)
Write the environment parameters of a freshly created DB environment.
#define OVPAGES(size, psize)
The number of overflow pages needed to store the given size.
MDB_ID pgno_t
A page number in the database.
size_t mdb_txn_id(MDB_txn *txn)
Return the transaction's ID.
int mdb_env_stat(MDB_env *env, MDB_stat *arg)
Return statistics about the LMDB environment.
#define NODEPTR(p, i)
Address of node i in page p.
#define MDB_COMMIT_PAGES
max number of pages to commit in one writev() call
static int mdb_reader_check0(MDB_env *env, int rlocked, int *dead)
As mdb_reader_check().
#define SIZELEFT(p)
The amount of space remaining in the page.
static int mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
Move a node from csrc to cdst.
#define NUM_METAS
Number of meta pages - also hardcoded elsewhere.
static int mdb_env_share_locks(MDB_env *env, int *excl)
Downgrade the exclusive lock on the region back to shared.
#define INDXSIZE(k)
Size of a node in a branch page with a given key.
struct MDB_ntxn MDB_ntxn
Nested transaction.
#define PAGEHDRSZ
Size of the page header, excluding dynamic data at the end.
MDB_dbi mdb_cursor_dbi(MDB_cursor *mc)
Return the cursor's database handle.
int mdb_env_set_maxreaders(MDB_env *env, unsigned int readers)
Set the maximum number of threads/reader slots for the environment.
char mdb_nchar_t
Character type for file names: char on Unix, wchar_t on Windows.
static int mdb_cursor_del0(MDB_cursor *mc)
Complete a delete operation started by mdb_cursor_del().
static int mdb_cursor_sibling(MDB_cursor *mc, int move_right)
Find a sibling for a page.
static void mdb_env_reader_dest(void *ptr)
Release a reader thread's slot in the reader lock table.
static int mdb_del0(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned flags)
MDB_env * mdb_txn_env(MDB_txn *txn)
Returns the transaction's MDB_env.
int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
Create a transaction for use with the environment.
int mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
Delete current key/data pair.
static void mdb_cursors_close(MDB_txn *txn, unsigned merge)
Close this write txn's cursors, give parent txn's cursors back to parent.
#define MDB_GET_KEY2(node, key)
Set the node's key into key.
#define CURSOR_STACK
Enough space for 2^32 nodes with minimum of 2 keys per node.
static int mdb_env_open2(MDB_env *env)
Further setup required for opening an LMDB environment.
int mdb_env_get_path(MDB_env *env, const char **arg)
Return the path that was used in mdb_env_open().
int mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, unsigned int flags)
Store by cursor.
int mdb_env_set_userctx(MDB_env *env, void *ctx)
Set application information associated with the MDB_env.
struct MDB_xcursor MDB_xcursor
Context for sorted-dup records.
#define MDB_VALID
DB handle is valid, for me_dbflags.
static int mdb_page_unspill(MDB_txn *txn, MDB_page *mp, MDB_page **ret)
Pull a page off the txn's spill list, if present.
static int mdb_drop0(MDB_cursor *mc, int subs)
Add all the DB's pages to the free list.
#define MDB_NAME(str)
mdb_nchar_t[] string literal
struct MDB_db MDB_db
Information about a single database in the environment.
int mdb_cursor_count(MDB_cursor *mc, size_t *countp)
Return count of duplicates for current key.
int mdb_env_copyfd(MDB_env *env, int fd)
Copy an LMDB environment to the specified file descriptor.
static void mdb_env_init_meta0(MDB_env *env, MDB_meta *meta)
Fill in most of the zeroed MDB_meta for an empty database environment.
#define MDB_DSYNC
A flag for opening a file and requesting synchronous data writes.
@ MDB_END_FAIL_BEGINCHILD
@ MDB_O_COPY
for mdb_env_copy()
@ MDB_O_MASK
Bitmask for open() flags in enum mdb_fopen_type.
@ MDB_O_RDONLY
for RDONLY me_fd
int() MDB_msg_func(const char *msg, void *ctx)
A callback function used to print a message from the library.
unsigned int
A callback function used to compare two keys in a database.
void MDB_assert_func(MDB_env *env, const char *msg)
A callback function for most LMDB assert() failures, called before printing the message and aborting.
#define MDB_CP_COMPACT
Compacting copy: Omit free space from copy, and renumber all pages sequentially.
MDB_cursor_op
Cursor Get operations.
@ MDB_NEXT_NODUP
Position at first data item of next key.
@ MDB_PREV_NODUP
Position at last data item of previous key.
@ MDB_FIRST_DUP
Position at first data item of current key.
@ MDB_PREV_MULTIPLE
Position at previous page and return up to a page of duplicate data items.
@ MDB_LAST_DUP
Position at last data item of current key.
@ MDB_SET
Position at specified key.
@ MDB_LAST
Position at last key/data item.
@ MDB_NEXT_DUP
Position at next data item of current key.
@ MDB_GET_BOTH_RANGE
position at key, nearest data.
@ MDB_GET_BOTH
Position at key/data pair.
@ MDB_GET_MULTIPLE
Return up to a page of duplicate data items from current cursor position.
@ MDB_FIRST
Position at first key/data item.
@ MDB_NEXT
Position at next data item.
@ MDB_SET_RANGE
Position at first key greater than or equal to specified key.
@ MDB_NEXT_MULTIPLE
Return up to a page of duplicate data items from next cursor position.
@ MDB_PREV
Position at previous data item.
@ MDB_GET_CURRENT
Return key/data at current cursor position.
@ MDB_SET_KEY
Position at specified key, return key + data.
@ MDB_PREV_DUP
Position at previous data item of current key.
#define C_DEL
last op was a cursor_del
#define C_SUB
Cursor is a sub-cursor.
#define C_INITIALIZED
cursor has been initialized and is valid
#define C_UNTRACK
Un-track cursor when closing.
#define C_EOF
No more data.
#define MDB_INTEGERKEY
numeric keys in native byte order: either unsigned int or size_t.
#define MDB_DUPFIXED
with MDB_DUPSORT, sorted dup items have fixed size
#define MDB_INTEGERDUP
with MDB_DUPSORT, dups are MDB_INTEGERKEY-style integers
#define MDB_DUPSORT
use sorted duplicates
#define MDB_REVERSEKEY
use reverse string keys
#define MDB_REVERSEDUP
with MDB_DUPSORT, use reverse string dups
#define MDB_CREATE
create DB if not already existing
#define MDB_NORDAHEAD
don't do readahead (no effect on Windows)
#define MDB_FIXEDMAP
mmap at a fixed address (experimental)
#define MDB_NOMETASYNC
don't fsync metapage after commit
#define MDB_NOSYNC
don't fsync after commit
#define MDB_NOTLS
tie reader locktable slots to MDB_txn objects instead of to threads
#define MDB_WRITEMAP
use writable mmap
#define MDB_NOLOCK
don't do any locking, caller must manage their own locks
#define MDB_MAPASYNC
use asynchronous msync when MDB_WRITEMAP is used
#define MDB_NOSUBDIR
no environment directory
#define MDB_RDONLY
read only
#define MDB_NOMEMINIT
don't initialize malloc'd memory before writing to datafile
#define F_SUBDATA
data is a sub-database
#define F_DUPDATA
data has duplicates
#define NODE_ADD_FLAGS
valid flags for mdb_node_add()
#define F_BIGDATA
data put on overflow page
#define P_OVERFLOW
overflow page
#define P_KEEP
leave this page alone during spill
#define P_LOOSE
page was dirtied then freed, can be reused
#define P_SUBP
for MDB_DUPSORT sub-pages
#define P_DIRTY
dirty page, also set for P_SUBP pages
#define P_LEAF2
for MDB_DUPFIXED records
#define P_BRANCH
branch page
#define MDB_APPENDDUP
Duplicate data is being appended, don't split full pages.
#define MDB_APPEND
Data is being appended, don't split full pages.
unsigned int me_maxreaders
max reader slots in the environment
#define MDB_NOOVERWRITE
For put: Don't write if the key already exists.
size_t ms_entries
Number of data items.
size_t me_mapsize
Size of the data memory map.
size_t me_last_txnid
ID of the last committed transaction.
#define MDB_MULTIPLE
Store multiple data items in one call.
unsigned int ms_psize
Size of a database page.
#define MDB_NODUPDATA
Only for MDB_DUPSORT For put: don't write if the key and data pair already exist.
void * me_mapaddr
Address of map, if fixed.
#define MDB_CURRENT
For mdb_cursor_put: overwrite the current key/data pair.
size_t mv_size
size of the data item
void * mv_data
address of the data item
unsigned int ms_depth
Depth (height) of the B-tree.
#define MDB_RESERVE
For put: Just reserve space for data, don't copy it.
size_t ms_overflow_pages
Number of overflow pages.
size_t ms_leaf_pages
Number of leaf pages.
size_t ms_branch_pages
Number of internal (non-leaf) pages.
unsigned int me_numreaders
max reader slots used in the environment
size_t me_last_pgno
ID of the last used page.
#define MDB_TXN_WRITEMAP
copy of MDB_env flag in writers
#define MDB_TXN_SPILLS
txn or a parent has spilled pages
#define MDB_TXN_RDONLY
read-only transaction
#define MDB_TXN_FINISHED
txn is finished or never began
#define MDB_TXN_DIRTY
must write, even if dirty list is empty
#define MDB_TXN_BEGIN_FLAGS
mdb_txn_begin() flags
#define MDB_TXN_BLOCKED
most operations on the txn are currently illegal
#define MDB_TXN_ERROR
txn is unusable after an error
#define MDB_TXN_HAS_CHILD
txn has an MDB_txn.
void() MDB_rel_func(MDB_val *item, void *oldptr, void *newptr, void *relctx)
A callback function used to relocate a position-dependent data item in a fixed-address database.
struct MDB_txn MDB_txn
Opaque structure for a transaction handle.
int() MDB_cmp_func(const MDB_val *a, const MDB_val *b)
A callback function used to compare two keys in a database.
unsigned int MDB_dbi
A handle for an individual database in the DB environment.
struct MDB_cursor MDB_cursor
Opaque structure for navigating through a database.
#define DB_DUPDATA
DB is MDB_DUPSORT data.
#define DB_STALE
Named-DB record is older than txnID.
#define DB_DIRTY
DB was written in this txn.
#define DB_NEW
Named-DB handle opened in this txn.
#define DB_VALID
DB handle is valid, see also MDB_VALID.
#define DB_USRVALID
As DB_VALID, but not set for FREE_DBI.
struct MDB_rxbody MDB_rxbody
The information we store in a single slot of the reader table.
struct MDB_txninfo MDB_txninfo
The actual reader table definition.
struct MDB_reader MDB_reader
The actual reader record, with cacheline padding.
#define CACHELINE
The size of a CPU cache line in bytes.
#define MDB_LOCK_FORMAT
Lockfile format signature: version, features and field layout.
#define DEFAULT_READERS
Number of slots in the reader table.
struct MDB_txbody MDB_txbody
The header for the reader table.
where boath are integers</td > n< td ></td > n</tr > n< tr > n< td > tse</td > n< td > optional</td > n< td > String</td > n< td class=\"description\"> TSE option controls what blob is smart and slim</td> n<td> orig</td> n</tr> n<tr> n<td> last_modified</td> n<td> optional</td> n<td> Integer</td> n<td class=\"description\"> The blob last modification If provided then the exact match will be requested with n the Cassandra storage corresponding field value</td> n<td> Positive integer Not provided means that the most recent match will be selected</td> n<td></td> n</tr> n<tr> n<td> use_cache</td> n<td> optional</td> n<td> String</td> n<td class=\"description\"> The option controls if the Cassandra LMDB cache and or database should be used It n affects the seq id resolution step and the blob properties lookup step The following n options are BIOSEQ_INFO and BLOB_PROP at all
while(yy_chk[yy_base[yy_current_state]+yy_c] !=yy_current_state)
if(yy_accept[yy_current_state])
static const CS_INT unused
#define DO_PWRITE(rc, fd, ptr, size, len, pos)
#define VGMEMP_FREE(h, a)
#define MDB_ENV_TXKEY
me_txkey is set
#define DO_WRITE(rc, fd, ptr, w2, len)
#define MDB_FSYNCONLY
fdatasync is unreliable
#define mr_txnid
shorthand for mrb_txnid
#define CACHEFLUSH(addr, bytes, cache)
#define VGMEMP_DESTROY(h)
#define VGMEMP_ALLOC(h, a, s)
#define MDB_ENV_ACTIVE
Some fields are initialized.
#define VGMEMP_CREATE(h, r, z)
#define VGMEMP_DEFINED(a, s)
#define me_rmutex
Shared reader lock.
#define MDB_FATAL_ERROR
Failed to update the meta page.
#define me_wmutex
Shared writer lock.
LMDB ID List header file.
const struct ncbi::grid::netcache::search::fields::SIZE size
const struct ncbi::grid::netcache::search::fields::KEY key
int strncmp(const char *str1, const char *str2, size_t count)
#define TRUE
bool replacment for C indicating true.
#define FALSE
bool replacment for C indicating false.
Int4 delta(size_t dimension_, const Int4 *score_)
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
void copy(Njn::Matrix< S > *matrix_, const Njn::Matrix< T > &matrix0_)
void split(std::vector< std::string > *strVec, const std::string &str_, const std::string &split_)
static SLJIT_INLINE sljit_ins st(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
static SLJIT_INLINE sljit_ins nr(sljit_gpr dst, sljit_gpr src)
static SLJIT_INLINE sljit_ins l(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
static const sljit_gpr r2
int mdb_filehandle_t
An abstraction for a file handle.
mode_t mdb_mode_t
Unix permissions for creating files, or dummy definition for Windows.
An ID2 is an ID/pointer pair.
Cursors are used for all DB operations.
MDB_cursor * mc_backup
Backup of the original cursor if this cursor is a shadow.
MDB_txn * mc_txn
The transaction that owns this cursor.
MDB_cursor * mc_next
Next cursor on this DB in this txn.
MDB_dbi mc_dbi
The database handle this cursor operates on.
unsigned char * mc_dbflag
The Transaction DB Flags for this database.
MDB_db * mc_db
The database record for this cursor.
unsigned short mc_top
index of top page, normally mc_snum-1
unsigned int mc_flags
Cursor Flags
indx_t mc_ki[32]
stack of page indices
unsigned short mc_snum
number of pushed pages
MDB_dbx * mc_dbx
The database auxiliary record for this cursor.
MDB_page * mc_pg[32]
stack of pushed pages
struct MDB_xcursor * mc_xcursor
Context used for databases with MDB_DUPSORT, otherwise NULL.
Information about a single database in the environment.
uint32_t md_pad
also ksize for LEAF2 pages
pgno_t md_overflow_pages
number of overflow pages
pgno_t md_branch_pages
number of internal pages
uint16_t md_flags
Database Flags
uint16_t md_depth
depth of this tree
pgno_t md_root
the root page of this tree
pgno_t md_leaf_pages
number of leaf pages
size_t md_entries
number of data items
MDB_cmp_func * md_cmp
function for comparing keys
void * md_relctx
user-provided context for md_rel
MDB_rel_func * md_rel
user relocate function
MDB_cmp_func * md_dcmp
function for comparing data items
MDB_val md_name
name of the database
The database environment.
int me_mfd
For writing and syncing the meta pages.
MDB_pgstate me_pgstate
state of old pages from freeDB
void * me_pbuf
scratch area for DUPSORT put()
pid_t me_pid
process ID of this env
pthread_key_t me_txkey
thread-key for readers
MDB_dbx * me_dbxs
array of static DB info
MDB_txn * me_txn
current write transaction
MDB_ID2L me_dirty_list
ID2L of pages written during a write txn.
MDB_IDL me_free_pgs
IDL of pages that became unused in a write txn.
int me_fd
The main data file.
char * me_path
path to the DB files
char * me_map
the memory map of the data file
volatile int me_close_readers
Max MDB_txninfo.
MDB_txn * me_txn0
prealloc'd write transaction
unsigned int me_nodemax
Max size of a node on a page.
unsigned int * me_dbiseqs
array of dbi sequence numbers
uint16_t * me_dbflags
array of flags from MDB_db.md_flags
pgno_t me_maxpg
me_mapsize / me_psize
unsigned int me_maxreaders
size of the reader table
MDB_meta * me_metas[2]
pointers to the two meta pages
int me_maxfree_1pg
Max number of freelist items that can fit in a single overflow page.
int me_lfd
The lock file.
uint32_t me_flags
Environment Flags
int me_live_reader
have liveness lock in reader table
MDB_dbi me_numdbs
number of DBs opened
void * me_userctx
User-settable context.
MDB_dbi me_maxdbs
size of the DB table
off_t me_size
current file size
MDB_assert_func * me_assert_func
Callback for assertion failures.
MDB_txninfo * me_txns
the memory map of the lock file or NULL
txnid_t me_pgoldest
ID of oldest reader last time we looked.
unsigned int me_os_psize
OS page size, from GET_PAGESIZE.
MDB_page * me_dpages
list of malloc'd blocks for re-use
size_t me_mapsize
size of the data memory map
unsigned int me_psize
DB page size, inited from me_os_psize.
Information about the environment.
Filename - string of mdb_nchar_t[].
mdb_nchar_t * mn_val
Contents.
int mn_alloced
True if mn_val was malloced.
Header for a single key/data pair within a page.
unsigned short mn_ksize
key size
unsigned short mn_flags
Node Flags
unsigned short mn_lo
part of data size or pgno
char mn_data[1]
key and data are appended here
MDB_pgstate mnt_pgstate
parent transaction's saved freestate
MDB_txn mnt_txn
the transaction
Common header for all page types.
uint16_t mp_pad
key size if this is a LEAF2 page
indx_t pb_upper
upper bound of free space
union MDB_page::@1199 mp_p
union MDB_page::@1200 mp_pb
pgno_t p_pgno
page number
uint16_t mp_flags
Page Flags
uint32_t pb_pages
number of overflow pages
struct MDB_page * p_next
for in-memory list of freed pages
struct MDB_page::@1200::@1201 pb
indx_t pb_lower
lower bound of free space
indx_t mp_ptrs[1]
dynamic size
State of FreeDB old pages, stored in the MDB_env.
txnid_t mf_pglast
ID of last used record, or 0 if !mf_pghead.
pgno_t * mf_pghead
Reclaimed freeDB pages, or NULL before use.
The actual reader record, with cacheline padding.
union MDB_reader::@1196 mru
char pad[(sizeof(MDB_rxbody)+64 -1) &~(64 -1)]
cache line alignment
The information we store in a single slot of the reader table.
volatile pid_t mrb_pid
The process ID of the process owning this reader txn.
volatile pthread_t mrb_tid
The thread ID of the thread owning this txn.
volatile txnid_t mrb_txnid
Current Transaction ID when this transaction began, or (txnid_t)-1.
Statistics for a database in the environment.
The header for the reader table.
volatile unsigned mtb_numreaders
The number of slots that have been used in the reader table.
mdb_mutex_t mtb_rmutex
Mutex protecting access to this table.
uint32_t mtb_format
Format of this lock file.
uint32_t mtb_magic
Stamp identifying this as an LMDB file.
volatile txnid_t mtb_txnid
The ID of the last transaction committed to the database.
MDB_env * mt_env
the DB environment
union MDB_txn::@1203 mt_u
MDB_ID2L dirty_list
For write txns: Modified pages.
MDB_reader * reader
For read txns: This thread/txn's reader table slot, or NULL.
unsigned int * mt_dbiseqs
Array of sequence numbers for each DB handle.
MDB_IDL mt_spill_pgs
The sorted list of dirty pages we temporarily wrote to disk because the dirty list was full.
txnid_t mt_txnid
The ID of this transaction.
int mt_loose_count
Number of loose pages (mt_loose_pgs)
unsigned char * mt_dbflags
Array of flags for each DB.
MDB_db * mt_dbs
Array of MDB_db records for each known DB.
MDB_IDL mt_free_pgs
The list of pages that became unused during this transaction.
MDB_txn * mt_child
Nested txn under this txn, set together with flag MDB_TXN_HAS_CHILD.
unsigned int mt_flags
Transaction Flags
MDB_page * mt_loose_pgs
The list of loose pages that became unused and may be reused in this transaction, linked through NEXT...
pgno_t mt_next_pgno
next unallocated page
MDB_dbx * mt_dbxs
Array of records for each DB known in the environment.
MDB_cursor ** mt_cursors
In write txns, array of cursors for each DB.
unsigned int mt_dirty_room
dirty_list room: Array size - #dirty pages visible to this txn.
MDB_txn * mt_parent
parent of a nested txn
MDB_dbi mt_numdbs
Number of DB records in use, or 0 when the txn is finished.
The actual reader table definition.
MDB_reader mti_readers[1]
union MDB_txninfo::@1198 mt2
union MDB_txninfo::@1197 mt1
char pad[(sizeof(MDB_txbody)+64 -1) &~(64 -1)]
Generic structure used for passing keys and data in and out of the database.
Context for sorted-dup records.
unsigned char mx_dbflag
The Transaction DB Flags for this Dup DB.
MDB_cursor mx_cursor
A sub-cursor for traversing the Dup DB.
MDB_db mx_db
The database record for this Dup DB.
MDB_dbx mx_dbx
The auxiliary DB record for this Dup DB.
State needed for a double-buffering compacting copy.
int mc_toggle
Buffer number in provider.
volatile int mc_error
Error code.
pthread_cond_t mc_cond
Condition variable for mc_new.
int mc_new
(0-2 buffers to write) | (MDB_EOF at end)
CRef< CTestThread > thr[k_NumThreadsMax]
voidp calloc(uInt items, uInt size)
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4