38 #if defined(__WIN64__)
39 #define _FILE_OFFSET_BITS 64
51 #define MDB_THR_T DWORD
52 #include <sys/types.h>
55 # include <sys/param.h>
57 # define LITTLE_ENDIAN 1234
58 # define BIG_ENDIAN 4321
59 # define BYTE_ORDER LITTLE_ENDIAN
61 # define SSIZE_MAX INT_MAX
65 #include <sys/types.h>
67 #define MDB_PID_T pid_t
68 #define MDB_THR_T pthread_t
69 #include <sys/param.h>
72 #ifdef HAVE_SYS_FILE_H
78 #if defined(__mips) && defined(__linux)
80 #include <asm/cachectl.h>
81 extern int cacheflush(
char *
addr,
int nbytes,
int cache);
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)
346 mdb_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 int mdb_debug;
484 static txnid_t mdb_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 int me_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_t newpgno,
unsigned int nflags);
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 static SECURITY_DESCRIPTOR mdb_null_sd;
1437 static SECURITY_ATTRIBUTES mdb_all_sa;
1438 static int mdb_sec_inited;
1441 static int utf8_to_utf16(
const char *src,
struct MDB_name *dst,
int xtra);
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");
1518 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
1519 FORMAT_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,
int line)
1543 sprintf(
buf,
"%.100s:%d: Assertion '%.200s' failed in %.40s()",
1544 file, line, expr_txt, func);
1545 if (
env->me_assert_func)
1547 fprintf(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++)
1587 ptr += sprintf(ptr,
"%02x", *c++);
1589 sprintf(
buf,
"%.*s",
key->mv_size,
key->mv_data);
1597 static char *
const tp[2][2] = {{
"",
": DB"}, {
": sub-page",
": sub-DB"}};
1606 pgno_t pgno = mdb_dbg_pgno(mp);
1609 unsigned int i, nkeys, nsize, total = 0;
1620 fprintf(stderr,
"Overflow page %"Z"u pages %u%s\n",
1621 pgno, mp->mp_pages,
state);
1624 fprintf(stderr,
"Meta-page %"Z"u txnid %"Z"u\n",
1628 fprintf(stderr,
"Bad page %"Z"u flags 0x%X\n", pgno, mp->
mp_flags);
1633 fprintf(stderr,
"%s %"Z"u numkeys %d%s\n",
type, pgno, nkeys,
state);
1635 for (
i=0;
i<nkeys;
i++) {
1640 fprintf(stderr,
"key %d: nsize %d, %s\n",
i, nsize,
DKEY(&
key));
1648 fprintf(stderr,
"key %d: page %"Z"u, %s\n",
i,
NODEPGNO(node),
1658 fprintf(stderr,
"key %d: nsize %d, %s%s\n",
1659 i, nsize,
DKEY(&
key), mdb_leafnode_type(node));
1661 total =
EVEN(total);
1663 fprintf(stderr,
"Total: header %d + contents %d + unused %d\n",
1699 static void mdb_audit(
MDB_txn *txn)
1730 for (j=0; j<
NUMKEYS(mp); j++) {
1744 fprintf(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))
1777 size_t psize =
env->me_psize, sz = psize, off;
1787 env->me_dpages = ret->mp_next;
1798 memset((
char *)ret + off, 0, psize);
1813 mp->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_t pgno = mp->mp_pgno;
1870 if (x <= dl[0].mid && dl[x].mid == pgno) {
1871 if (mp != dl[x].mptr) {
1929 for (j=0; j<m3->
mc_snum; 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 int num = sl[0];
2036 for (
i=1;
i<=num;
i++) {
2059 for (
i=dl[0].mid;
i && need;
i--) {
2072 if (j <= tx2->mt_spill_pgs[0] && tx2->
mt_spill_pgs[j] == pn) {
2130 mid.
mid = mp->mp_pgno;
2162 enum { Paranoid = 1, Max_retries = 500 };
2164 enum { Paranoid = 0, Max_retries = INT_MAX };
2166 int rc, retry = num * 60;
2170 unsigned i, j, mop_len = mop ? mop[0] : 0, n2 = num-1;
2208 if (mop[
i-n2] == pgno+n2)
2218 oldest =
env->me_pgoldest;
2228 if (Paranoid && retry < 0 && mop_len)
2233 if (oldest <=
last) {
2236 env->me_pgoldest = oldest;
2252 env->me_pgoldest = oldest;
2273 mop =
env->me_pghead;
2277 DPRINTF((
"IDL read txn %"Z"u root %"Z"u num %u",
2290 if (pgno + num >=
env->me_maxpg) {
2291 DPUTS(
"DB size maxed out");
2306 mop[0] = mop_len -= num;
2308 for (j =
i-num; j < mop_len; )
2309 mop[++j] = mop[++
i];
2332 enum { Align =
sizeof(
pgno_t) };
2333 indx_t upper = src->mp_upper, lower = src->mp_lower,
unused = upper-lower;
2339 upper = (upper +
PAGEBASE) & -Align;
2340 memcpy(dst, src, (lower +
PAGEBASE + (Align-1)) & -Align);
2341 memcpy((
pgno_t *)((
char *)dst+upper), (
pgno_t *)((
char *)src+upper),
2344 memcpy(dst, src, psize -
unused);
2362 pgno_t pgno = 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) {
2384 memcpy(np, mp, num *
env->me_psize);
2438 mp->mp_pgno, pgno));
2457 if (x <= dl[0].mid && dl[x].mid == pgno) {
2458 if (mp != dl[x].mptr) {
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) {
2646 h = OpenProcess(
env->me_pidquery,
FALSE, pid);
2649 return ErrCode() != ERROR_INVALID_PARAMETER;
2651 ret = WaitForSingleObject(h, 0) != 0;
2658 struct flock lock_info;
2659 memset(&lock_info, 0,
sizeof(lock_info));
2660 lock_info.l_type = F_WRLCK;
2662 lock_info.l_start = pid;
2663 lock_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 int rc, new_notls = 0;
2696 pthread_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) {
2733 ti->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)
2778 memcpy(txn->
mt_dbiseqs,
env->me_dbiseqs,
env->me_maxdbs *
sizeof(
unsigned int));
2792 x =
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 int rc,
size, tsize;
2898 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;
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)
2988 DPRINTF((
"%s txn %"Z"u%c %p on mdbenv %p, root page %"Z"u",
3084 int rc, maxfree_1pg =
env->me_maxfree_1pg, more = 1;
3085 txnid_t pglast = 0, head_id = 0;
3086 pgno_t freecnt = 0, *free_pgs, *mop;
3087 ssize_t head_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;
3160 total_room = head_room = 0;
3168 if (freecnt < txn->mt_free_pgs[0]) {
3180 freecnt = free_pgs[0];
3187 }
while (freecnt < free_pgs[0]);
3189 memcpy(
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",
3202 mop =
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) {
3218 total_room -= head_room;
3219 head_room = mop_len - total_room;
3220 if (head_room > maxfree_1pg && head_id > 1) {
3222 head_room /= head_id;
3223 head_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);
3236 j = head_room > clean_limit ? head_room : 0;
3240 total_room += head_room;
3253 mop =
env->me_pghead;
3256 loose[ ++
count ] = mp->mp_pgno;
3279 if (
len > mop_len) {
3288 if (rc || !(mop_len -=
len))
3305 unsigned psize =
env->me_psize, j;
3306 int i, pagecount = dl[0].
mid, rc;
3307 size_t size = 0, pos = 0;
3314 ssize_t wpos = 0, wsize = 0, wres;
3315 size_t next_pos = 1;
3323 while (++
i <= pagecount) {
3338 if (++
i <= pagecount) {
3363 DPRINTF((
"committing page %"Z"u", pgno));
3364 memset(&ov, 0,
sizeof(ov));
3365 ov.Offset = pos & 0xffffffff;
3366 ov.OffsetHigh = pos >> 16 >> 16;
3367 if (!WriteFile(
env->me_fd, dp,
size,
NULL, &ov)) {
3369 DPRINTF((
"WriteFile: %d", rc));
3378 #ifdef MDB_USE_PWRITEV
3379 wres = pwritev(
env->me_fd, iov,
n, wpos);
3382 wres = pwrite(
env->me_fd, iov[0].iov_base, wsize, wpos);
3392 wres = writev(
env->me_fd, iov,
n);
3395 if (wres != wsize) {
3403 DPUTS(
"short write, filesystem full?");
3414 DPRINTF((
"committing page %"Z"u", pgno));
3415 next_pos = pos +
size;
3416 iov[
n].iov_len =
size;
3417 iov[
n].iov_base = (
char *)dp;
3429 for (
i = keep; ++
i <= pagecount; ) {
3434 dl[j].
mid = dp->mp_pgno;
3451 unsigned int i, end_mode;
3473 DPUTS(
"txn has failed/finished, can't commit");
3485 unsigned x, y,
len, ps_len;
3516 if ((pspill = parent->
mt_spill_pgs) && (ps_len = pspill[0])) {
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))
3532 pspill[++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)
3578 dst[
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) {
3699 memset(&ov, 0,
sizeof(ov));
3701 rc = ReadFile(
env->me_fd, &pbuf, Size, &
len, &ov) ? (
int)
len : -1;
3702 if (rc == -1 &&
ErrCode() == ERROR_HANDLE_EOF)
3705 rc = 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",
3747 meta->mm_psize =
env->me_psize;
3749 meta->mm_flags =
env->me_flags & 0xffff;
3769 memset(&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");
3783 psize =
env->me_psize;
3793 q = (
MDB_page *)((
char *)p + psize);
3821 int rc,
len, toggle;
3831 DPRINTF((
"writing meta page %d for root page %"Z"u",
3836 mp =
env->me_metas[toggle];
3837 mapsize =
env->me_metas[toggle ^ 1]->mm_mapsize;
3839 if (mapsize < env->me_mapsize)
3840 mapsize =
env->me_mapsize;
3847 #if (__GNUC__ * 100 + __GNUC_MINOR__ >= 404) && \
3848 !(defined(__i386__) || defined(__x86_64__))
3850 __sync_synchronize();
3854 unsigned meta_size =
env->me_psize;
3858 r2 = (ptr -
env->me_map) & (
env->me_os_psize - 1);
3879 ptr = (
char *)&meta + off;
3881 off += (
char *)mp -
env->me_map;
3890 memset(&ov, 0,
sizeof(ov));
3892 if (!WriteFile(mfd, ptr,
len, (
DWORD *)&rc, &ov))
3897 rc = pwrite(mfd, ptr,
len, off);
3900 rc = rc < 0 ?
ErrCode() : EIO;
3905 DPUTS(
"write failed, disk error?");
3913 memset(&ov, 0,
sizeof(ov));
3917 r2 = pwrite(
env->me_fd, ptr,
len, off);
3964 #ifdef MDB_USE_POSIX_SEM
3965 e->me_rmutex = SEM_FAILED;
3966 e->me_wmutex = SEM_FAILED;
3979 unsigned int flags =
env->me_flags;
3983 LONG sizelo, sizehi;
3992 msize =
env->me_mapsize;
3993 sizelo = msize & 0xffffffff;
3994 sizehi = msize >> 16 >> 16;
4001 || !SetEndOfFile(
env->me_fd)
4002 || SetFilePointer(
env->me_fd, 0,
NULL, 0) != 0))
4007 PAGE_READWRITE : PAGE_READONLY,
4008 sizehi, sizelo,
NULL);
4012 FILE_MAP_WRITE : FILE_MAP_READ,
4019 int prot = PROT_READ;
4022 if (ftruncate(
env->me_fd,
env->me_mapsize) < 0)
4027 if (
env->me_map == MAP_FAILED) {
4035 madvise(
env->me_map,
env->me_mapsize, MADV_RANDOM);
4037 #ifdef POSIX_MADV_RANDOM
4038 posix_madvise(
env->me_map,
env->me_mapsize, POSIX_MADV_RANDOM);
4080 munmap(
env->me_map,
env->me_mapsize);
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;
4124 LARGE_INTEGER fsize;
4126 if (!GetFileSizeEx(fd, &fsize))
4129 *
size = fsize.QuadPart;
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 return utf8_to_utf16(path, fname, no_suffix ? 0 :
MDB_SUFFLEN);
4184 fname->
mn_len = strlen(path);
4186 fname->
mn_val = (
char *) path;
4189 strcpy(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 DWORD acc, share, disp, attrs;
4266 acc = GENERIC_READ|GENERIC_WRITE;
4267 share = FILE_SHARE_READ|FILE_SHARE_WRITE;
4269 attrs = FILE_ATTRIBUTE_NORMAL;
4273 disp = OPEN_EXISTING;
4276 acc = GENERIC_WRITE;
4277 disp = OPEN_EXISTING;
4278 attrs = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH;
4281 acc = GENERIC_WRITE;
4284 attrs = FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH;
4288 fd = 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
4358 fstatfs(
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;
4403 memset(&meta, 0,
sizeof(meta));
4407 env->me_psize = meta.mm_psize;
4411 if (!
env->me_mapsize) {
4418 size_t minsize = (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 static pthread_key_t mdb_tls_keys[MAX_TLS_KEYS];
4506 static int mdb_tls_nkeys;
4508 static void NTAPI mdb_tls_callback(PVOID module,
DWORD reason, PVOID ptr)
4512 case DLL_PROCESS_ATTACH:
break;
4513 case DLL_THREAD_ATTACH:
break;
4514 case DLL_THREAD_DETACH:
4515 for (
i=0;
i<mdb_tls_nkeys;
i++) {
4522 case DLL_PROCESS_DETACH:
break;
4527 const PIMAGE_TLS_CALLBACK mdb_tls_cbp __attribute__((section (
".CRT$XLB"))) = mdb_tls_callback;
4529 PIMAGE_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 const PIMAGE_TLS_CALLBACK mdb_tls_cbp;
4541 const PIMAGE_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")
4547 PIMAGE_TLS_CALLBACK mdb_tls_cbp = mdb_tls_callback;
4568 memset(&ov, 0,
sizeof(ov));
4569 if (!LockFileEx(
env->me_lfd, 0, 0, 1, 0, &ov)) {
4572 UnlockFile(
env->me_lfd, 0, 0, 1, 0);
4578 struct flock lock_info;
4580 memset((
void *)&lock_info, 0,
sizeof(lock_info));
4581 lock_info.l_type = F_RDLCK;
4583 lock_info.l_start = 0;
4584 lock_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)) {
4606 memset(&ov, 0,
sizeof(ov));
4607 if (LockFileEx(
env->me_lfd, 0, 0, 1, 0, &ov)) {
4614 struct flock lock_info;
4615 memset((
void *)&lock_info, 0,
sizeof(lock_info));
4616 lock_info.l_type = F_WRLCK;
4618 lock_info.l_start = 0;
4619 lock_info.l_len = 1;
4620 while ((rc = fcntl(
env->me_lfd, F_SETLK, &lock_info)) &&
4625 # ifndef MDB_USE_POSIX_MUTEX
4629 lock_info.l_type = F_RDLCK;
4630 while ((rc = fcntl(
env->me_lfd, F_SETLKW, &lock_info)) &&
4668 typedef unsigned long long mdb_hash_t;
4669 #define MDB_HASH_INIT ((mdb_hash_t)0xcbf29ce484222325ULL)
4682 unsigned char *s = (
unsigned char *)
val->mv_data;
4683 unsigned char *end = s +
val->mv_size;
4689 hval ^= (mdb_hash_t)*s++;
4692 hval += (hval << 1) + (hval << 4) + (hval << 5) +
4693 (hval << 7) + (hval << 8) + (hval << 40);
4707 static const char mdb_a85[]=
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
4710 mdb_pack85(
unsigned long l,
char *
out)
4714 for (
i=0;
i<5;
i++) {
4715 *
out++ = mdb_a85[
l % 85];
4723 mdb_hash_t h = mdb_hash_val(
val, MDB_HASH_INIT);
4725 mdb_pack85(h, encbuf);
4726 mdb_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) {
4769 mdb_tls_keys[mdb_tls_nkeys++] =
env->me_txkey;
4782 if (
size == -1)
goto fail_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)
goto fail_errno;
4801 mh = CreateFileMapping(
env->me_lfd,
NULL, PAGE_READWRITE,
4803 if (!mh)
goto fail_errno;
4804 env->me_txns = MapViewOfFileEx(mh, FILE_MAP_WRITE, 0, 0, rsize,
NULL);
4806 if (!
env->me_txns)
goto fail_errno;
4808 void *m = mmap(
NULL, rsize, PROT_READ|PROT_WRITE, MAP_SHARED,
4810 if (m == MAP_FAILED)
goto fail_errno;
4816 BY_HANDLE_FILE_INFORMATION stbuf;
4825 if (!mdb_sec_inited) {
4826 InitializeSecurityDescriptor(&mdb_null_sd,
4827 SECURITY_DESCRIPTOR_REVISION);
4828 SetSecurityDescriptorDacl(&mdb_null_sd,
TRUE, 0,
FALSE);
4829 mdb_all_sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
4830 mdb_all_sa.bInheritHandle =
FALSE;
4831 mdb_all_sa.lpSecurityDescriptor = &mdb_null_sd;
4834 if (!GetFileInformationByHandle(
env->me_lfd, &stbuf))
goto fail_errno;
4835 idbuf.volume = stbuf.dwVolumeSerialNumber;
4836 idbuf.nhigh = stbuf.nFileIndexHigh;
4837 idbuf.nlow = stbuf.nFileIndexLow;
4838 val.mv_data = &idbuf;
4839 val.mv_size =
sizeof(idbuf);
4840 mdb_hash_enc(&
val, encbuf);
4841 sprintf(
env->me_txns->mti_rmname,
"Global\\MDBr%s", encbuf);
4842 sprintf(
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)
goto fail_errno;
4845 env->me_wmutex = CreateMutexA(&mdb_all_sa,
FALSE,
env->me_txns->mti_wmname);
4846 if (!
env->me_wmutex)
goto fail_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))
goto fail_errno;
4860 idbuf.dev = stbuf.st_dev;
4861 idbuf.ino = stbuf.st_ino;
4862 val.mv_data = &idbuf;
4863 val.mv_size =
sizeof(idbuf);
4864 mdb_hash_enc(&
val, encbuf);
4865 #ifdef MDB_SHORT_SEMNAMES
4868 sprintf(
env->me_txns->mti_rmname,
"/MDBr%s", encbuf);
4869 sprintf(
env->me_txns->mti_wmname,
"/MDBw%s", encbuf);
4873 sem_unlink(
env->me_txns->mti_rmname);
4874 sem_unlink(
env->me_txns->mti_wmname);
4875 env->me_rmutex = sem_open(
env->me_txns->mti_rmname,
4876 O_CREAT|O_EXCL,
mode, 1);
4877 if (
env->me_rmutex == SEM_FAILED)
goto fail_errno;
4878 env->me_wmutex = sem_open(
env->me_txns->mti_wmname,
4879 O_CREAT|O_EXCL,
mode, 1);
4880 if (
env->me_wmutex == SEM_FAILED)
goto fail_errno;
4882 pthread_mutexattr_t mattr;
4888 memset(
env->me_txns->mti_rmutex, 0,
sizeof(*
env->me_txns->mti_rmutex));
4889 memset(
env->me_txns->mti_wmutex, 0,
sizeof(*
env->me_txns->mti_wmutex));
4891 if ((rc = pthread_mutexattr_init(&mattr)))
4894 rc = 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);
4900 pthread_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)
goto fail_errno;
4929 env->me_wmutex = OpenMutexA(SYNCHRONIZE,
FALSE,
env->me_txns->mti_wmname);
4930 if (!
env->me_wmutex)
goto fail_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)
goto fail_errno;
4934 env->me_wmutex = sem_open(
env->me_txns->mti_wmname, 0);
4935 if (
env->me_wmutex == SEM_FAILED)
goto fail_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)) {