diff --git a/libraries/liblmdb/.gitignore b/libraries/liblmdb/.gitignore index d5102a87c0..80b6d81144 100644 --- a/libraries/liblmdb/.gitignore +++ b/libraries/liblmdb/.gitignore @@ -5,6 +5,7 @@ mdb_copy mdb_stat mdb_dump mdb_load +mdb_drop *.lo *.[ao] *.so diff --git a/libraries/liblmdb/COPYRIGHT b/libraries/liblmdb/COPYRIGHT index f076556eb5..14eb1493d6 100644 --- a/libraries/liblmdb/COPYRIGHT +++ b/libraries/liblmdb/COPYRIGHT @@ -1,4 +1,4 @@ -Copyright 2011-2019 Howard Chu, Symas Corp. +Copyright 2011-2021 Howard Chu, Symas Corp. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/intro.doc b/libraries/liblmdb/intro.doc index 64dfcaad84..b5bb06716a 100644 --- a/libraries/liblmdb/intro.doc +++ b/libraries/liblmdb/intro.doc @@ -1,5 +1,5 @@ /* - * Copyright 2015-2018 Howard Chu, Symas Corp. + * Copyright 2015-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/lmdb.h b/libraries/liblmdb/lmdb.h index 1f4736ce2b..28cfc36f53 100644 --- a/libraries/liblmdb/lmdb.h +++ b/libraries/liblmdb/lmdb.h @@ -136,7 +136,7 @@ * * @author Howard Chu, Symas Corporation. * - * @copyright Copyright 2011-2019 Howard Chu, Symas Corp. All rights reserved. + * @copyright Copyright 2011-2021 Howard Chu, Symas Corp. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP @@ -610,7 +610,7 @@ int mdb_env_create(MDB_env **env); *
  • #MDB_NOTLS * Don't use Thread-Local Storage. Tie reader locktable slots to * #MDB_txn objects instead of to threads. I.e. #mdb_txn_reset() keeps - * the slot reseved for the #MDB_txn object. A thread may use parallel + * the slot reserved for the #MDB_txn object. A thread may use parallel * read-only transactions. A read-only transaction may span threads if * the user synchronizes its use. Applications that multiplex many * user threads over individual OS threads need this option. Such an @@ -968,7 +968,7 @@ void *mdb_env_get_userctx(MDB_env *env); typedef void MDB_assert_func(MDB_env *env, const char *msg); /** Set or reset the assert() callback of the environment. - * Disabled if liblmdb is buillt with NDEBUG. + * Disabled if liblmdb is built with NDEBUG. * @note This hack should become obsolete as lmdb's error handling matures. * @param[in] env An environment handle returned by #mdb_env_create(). * @param[in] func An #MDB_assert_func function, or 0. diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index f68542124e..40728e716b 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -5,7 +5,7 @@ * BerkeleyDB API, but much simplified. */ /* - * Copyright 2011-2019 Howard Chu, Symas Corp. + * Copyright 2011-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -96,6 +96,7 @@ static NtCloseFunc *NtClose; # define SSIZE_MAX INT_MAX # endif #endif +#define MDB_OFF_T int64_t #else #include #include @@ -108,6 +109,7 @@ static NtCloseFunc *NtClose; #include #endif #include +#define MDB_OFF_T off_t #endif #if defined(__mips) && defined(__linux) @@ -159,7 +161,10 @@ typedef SSIZE_T ssize_t; #include /* defines BYTE_ORDER on HPUX and Solaris */ #endif -#if defined(__APPLE__) || defined (BSD) || defined(__FreeBSD_kernel__) +#if defined(__FreeBSD__) && defined(__FreeBSD_version) && __FreeBSD_version >= 1100110 +# define MDB_USE_POSIX_MUTEX 1 +# define MDB_USE_ROBUST 1 +#elif defined(__APPLE__) || defined (BSD) || defined(__FreeBSD_kernel__) # if !(defined(MDB_USE_POSIX_MUTEX) || defined(MDB_USE_POSIX_SEM)) # define MDB_USE_SYSV_SEM 1 # endif @@ -585,7 +590,7 @@ static txnid_t mdb_debug_start; * The string is printed literally, with no format processing. */ #define DPUTS(arg) DPRINTF(("%s", arg)) - /** Debuging output value of a cursor DBI: Negative in a sub-cursor. */ + /** Debugging output value of a cursor DBI: Negative in a sub-cursor. */ #define DDBI(mc) \ (((mc)->mc_flags & C_SUB) ? -(int)(mc)->mc_dbi : (int)(mc)->mc_dbi) /** @} */ @@ -1462,9 +1467,12 @@ struct MDB_env { HANDLE me_fd; /**< The main data file */ HANDLE me_lfd; /**< The lock file */ HANDLE me_mfd; /**< For writing and syncing the meta pages */ -#if defined(MDB_VL32) && defined(_WIN32) +#ifdef _WIN32 +#ifdef MDB_VL32 HANDLE me_fmh; /**< File Mapping handle */ -#endif +#endif /* MDB_VL32 */ + HANDLE me_ovfd; /**< Overlapped/async with write-through file handle */ +#endif /* _WIN32 */ /** Failed to update the meta page. Probably an I/O error. */ #define MDB_FATAL_ERROR 0x80000000U /** Some fields are initialized. */ @@ -1490,7 +1498,7 @@ struct MDB_env { MDB_txn *me_txn; /**< current write transaction */ MDB_txn *me_txn0; /**< prealloc'd write transaction */ mdb_size_t me_mapsize; /**< size of the data memory map */ - off_t me_size; /**< current file size */ + MDB_OFF_T me_size; /**< current file size */ pgno_t me_maxpg; /**< me_mapsize / me_psize */ MDB_dbx *me_dbxs; /**< array of static DB info */ uint16_t *me_dbflags; /**< array of flags from MDB_db.md_flags */ @@ -1515,6 +1523,8 @@ struct MDB_env { int me_live_reader; /**< have liveness lock in reader table */ #ifdef _WIN32 int me_pidquery; /**< Used in OpenProcess */ + OVERLAPPED *ov; /**< Used for for overlapping I/O requests */ + int ovs; /**< Count of OVERLAPPEDs */ #endif #ifdef MDB_USE_POSIX_MUTEX /* Posix mutexes reside in shared mem */ # define me_rmutex me_txns->mti_rmutex /**< Shared reader lock */ @@ -1597,7 +1607,7 @@ static int mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, static int mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta); static MDB_meta *mdb_env_pick_meta(const MDB_env *env); static int mdb_env_write_meta(MDB_txn *txn); -#ifdef MDB_USE_POSIX_MUTEX /* Drop unused excl arg */ +#if defined(MDB_USE_POSIX_MUTEX) && !defined(MDB_ROBUST_SUPPORTED) /* Drop unused excl arg */ # define mdb_env_close0(env, excl) mdb_env_close1(env) #endif static void mdb_env_close0(MDB_env *env, int excl); @@ -2386,12 +2396,16 @@ mdb_page_dirty(MDB_txn *txn, MDB_page *mp) { MDB_ID2 mid; int rc, (*insert)(MDB_ID2L, MDB_ID2 *); - - if (txn->mt_flags & MDB_TXN_WRITEMAP) { +#ifdef _WIN32 /* With Windows we always write dirty pages with WriteFile, + * so we always want them ordered */ + insert = mdb_mid2l_insert; +#else /* but otherwise with writemaps, we just use msync, we + * don't need the ordering and just append */ + if (txn->mt_flags & MDB_TXN_WRITEMAP) insert = mdb_mid2l_append; - } else { + else insert = mdb_mid2l_insert; - } +#endif mid.mid = mp->mp_pgno; mid.mptr = mp; rc = insert(txn->mt_u.dirty_list, &mid); @@ -2804,7 +2818,11 @@ mdb_env_sync0(MDB_env *env, int force, pgno_t numpgs) int rc = 0; if (env->me_flags & MDB_RDONLY) return EACCES; - if (force || !F_ISSET(env->me_flags, MDB_NOSYNC)) { + if (force +#ifndef _WIN32 /* Sync is normally achieved in Windows by doing WRITE_THROUGH writes */ + || !(env->me_flags & MDB_NOSYNC) +#endif + ) { if (env->me_flags & MDB_WRITEMAP) { int flags = ((env->me_flags & MDB_MAPASYNC) && !force) ? MS_ASYNC : MS_SYNC; @@ -3350,9 +3368,9 @@ mdb_txn_end(MDB_txn *txn, unsigned mode) txn->mt_parent->mt_flags &= ~MDB_TXN_HAS_CHILD; env->me_pgstate = ((MDB_ntxn *)txn)->mnt_pgstate; mdb_midl_free(txn->mt_free_pgs); - mdb_midl_free(txn->mt_spill_pgs); free(txn->mt_u.dirty_list); } + mdb_midl_free(txn->mt_spill_pgs); mdb_midl_free(pghead); } @@ -3649,21 +3667,30 @@ mdb_page_flush(MDB_txn *txn, int keep) unsigned psize = env->me_psize, j; int i, pagecount = dl[0].mid, rc; size_t size = 0; - off_t pos = 0; + MDB_OFF_T pos = 0; pgno_t pgno = 0; MDB_page *dp = NULL; #ifdef _WIN32 - OVERLAPPED ov; + OVERLAPPED *ov = env->ov; + MDB_page *wdp; + int async_i = 0; + HANDLE fd = (env->me_flags & MDB_NOSYNC) ? env->me_fd : env->me_ovfd; #else struct iovec iov[MDB_COMMIT_PAGES]; + HANDLE fd = env->me_fd; +#endif ssize_t wsize = 0, wres; - off_t wpos = 0, next_pos = 1; /* impossible pos, so pos != next_pos */ + MDB_OFF_T wpos = 0, next_pos = 1; /* impossible pos, so pos != next_pos */ int n = 0; -#endif j = i = keep; - - if (env->me_flags & MDB_WRITEMAP) { + if (env->me_flags & MDB_WRITEMAP +#ifdef _WIN32 + /* In windows, we still do writes to the file (with write-through enabled in sync mode), + * as this is faster than FlushViewOfFile/FlushFileBuffers */ + && (env->me_flags & MDB_NOSYNC) +#endif + ) { /* Clear dirty flags */ while (++i <= pagecount) { dp = dl[i].mptr; @@ -3678,6 +3705,27 @@ mdb_page_flush(MDB_txn *txn, int keep) goto done; } +#ifdef _WIN32 + if (pagecount - keep >= env->ovs) { + /* ran out of room in ov array, and re-malloc, copy handles and free previous */ + int ovs = (pagecount - keep) * 1.5; /* provide extra padding to reduce number of re-allocations */ + int new_size = ovs * sizeof(OVERLAPPED); + ov = malloc(new_size); + if (ov == NULL) + return ENOMEM; + int previous_size = env->ovs * sizeof(OVERLAPPED); + memcpy(ov, env->ov, previous_size); /* Copy previous OVERLAPPED data to retain event handles */ + /* And clear rest of memory */ + memset(&ov[env->ovs], 0, new_size - previous_size); + if (env->ovs > 0) { + free(env->ov); /* release previous allocation */ + } + + env->ov = ov; + env->ovs = ovs; + } +#endif + /* Write the pages */ for (;;) { if (++i <= pagecount) { @@ -3695,46 +3743,65 @@ mdb_page_flush(MDB_txn *txn, int keep) size = psize; if (IS_OVERFLOW(dp)) size *= dp->mp_pages; } -#ifdef _WIN32 - else break; - - /* Windows actually supports scatter/gather I/O, but only on - * unbuffered file handles. Since we're relying on the OS page - * cache for all our data, that's self-defeating. So we just - * write pages one at a time. We use the ov structure to set - * the write offset, to at least save the overhead of a Seek - * system call. - */ - DPRINTF(("committing page %"Yu, pgno)); - memset(&ov, 0, sizeof(ov)); - ov.Offset = pos & 0xffffffff; - ov.OffsetHigh = pos >> 16 >> 16; - if (!WriteFile(env->me_fd, dp, size, NULL, &ov)) { - rc = ErrCode(); - DPRINTF(("WriteFile: %d", rc)); - return rc; - } -#else /* Write up to MDB_COMMIT_PAGES dirty pages at a time. */ - if (pos!=next_pos || n==MDB_COMMIT_PAGES || wsize+size>MAX_WRITE) { + if (pos!=next_pos || n==MDB_COMMIT_PAGES || wsize+size>MAX_WRITE +#ifdef _WIN32 + /* If writemap is enabled, consecutive page positions infer + * contiguous (mapped) memory. + * Otherwise force write pages one at a time. + * Windows actually supports scatter/gather I/O, but only on + * unbuffered file handles. Since we're relying on the OS page + * cache for all our data, that's self-defeating. So we just + * write pages one at a time. We use the ov structure to set + * the write offset, to at least save the overhead of a Seek + * system call. + */ + || !(env->me_flags & MDB_WRITEMAP) +#endif + ) { if (n) { retry_write: /* Write previous page(s) */ + DPRINTF(("committing page %"Z"u", pgno)); +#ifdef _WIN32 + OVERLAPPED *this_ov = &ov[async_i]; + /* Clear status, and keep hEvent, we reuse that */ + this_ov->Internal = 0; + this_ov->Offset = wpos & 0xffffffff; + this_ov->OffsetHigh = wpos >> 16 >> 16; + if (!F_ISSET(env->me_flags, MDB_NOSYNC) && !this_ov->hEvent) { + HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!event) { + rc = ErrCode(); + DPRINTF(("CreateEvent: %s", strerror(rc))); + return rc; + } + this_ov->hEvent = event; + } + if (!WriteFile(fd, wdp, wsize, NULL, this_ov)) { + rc = ErrCode(); + if (rc != ERROR_IO_PENDING) { + DPRINTF(("WriteFile: %d", rc)); + return rc; + } + } + async_i++; +#else #ifdef MDB_USE_PWRITEV - wres = pwritev(env->me_fd, iov, n, wpos); + wres = pwritev(fd, iov, n, wpos); #else if (n == 1) { - wres = pwrite(env->me_fd, iov[0].iov_base, wsize, wpos); + wres = pwrite(fd, iov[0].iov_base, wsize, wpos); } else { retry_seek: - if (lseek(env->me_fd, wpos, SEEK_SET) == -1) { + if (lseek(fd, wpos, SEEK_SET) == -1) { rc = ErrCode(); if (rc == EINTR) goto retry_seek; DPRINTF(("lseek: %s", strerror(rc))); return rc; } - wres = writev(env->me_fd, iov, n); + wres = writev(fd, iov, n); } #endif if (wres != wsize) { @@ -3749,41 +3816,69 @@ mdb_page_flush(MDB_txn *txn, int keep) } return rc; } +#endif /* _WIN32 */ n = 0; } if (i > pagecount) break; wpos = pos; wsize = 0; +#ifdef _WIN32 + wdp = dp; + } +#else } - DPRINTF(("committing page %"Yu, pgno)); - next_pos = pos + size; iov[n].iov_len = size; iov[n].iov_base = (char *)dp; +#endif /* _WIN32 */ + DPRINTF(("committing page %"Yu, pgno)); + next_pos = pos + size; wsize += size; n++; -#endif /* _WIN32 */ } #ifdef MDB_VL32 if (pgno > txn->mt_last_pgno) txn->mt_last_pgno = pgno; #endif - /* MIPS has cache coherency issues, this is a no-op everywhere else - * Note: for any size >= on-chip cache size, entire on-chip cache is - * flushed. - */ - CACHEFLUSH(env->me_map, txn->mt_next_pgno * env->me_psize, DCACHE); +#ifdef _WIN32 + if (!F_ISSET(env->me_flags, MDB_NOSYNC)) { + /* Now wait for all the asynchronous/overlapped sync/write-through writes to complete. + * We start with the last one so that all the others should already be complete and + * we reduce thread suspend/resuming (in practice, typically about 99.5% of writes are + * done after the last write is done) */ + rc = 0; + while (--async_i >= 0) { + if (ov[async_i].hEvent) { + if (!GetOverlappedResult(fd, &ov[async_i], &wres, TRUE)) { + rc = ErrCode(); /* Continue on so that all the event signals are reset */ + } + } + } + if (rc) { /* any error on GetOverlappedResult, exit now */ + return rc; + } + } +#endif /* _WIN32 */ - for (i = keep; ++i <= pagecount; ) { - dp = dl[i].mptr; - /* This is a page we skipped above */ - if (!dl[i].mid) { - dl[++j] = dl[i]; - dl[j].mid = dp->mp_pgno; - continue; + if (!(env->me_flags & MDB_WRITEMAP)) { + /* Don't free pages when using writemap (can only get here in NOSYNC mode in Windows) + * MIPS has cache coherency issues, this is a no-op everywhere else + * Note: for any size >= on-chip cache size, entire on-chip cache is + * flushed. + */ + CACHEFLUSH(env->me_map, txn->mt_next_pgno * env->me_psize, DCACHE); + + for (i = keep; ++i <= pagecount; ) { + dp = dl[i].mptr; + /* This is a page we skipped above */ + if (!dl[i].mid) { + dl[++j] = dl[i]; + dl[j].mid = dp->mp_pgno; + continue; + } + mdb_dpage_free(env, dp); } - mdb_dpage_free(env, dp); } done: @@ -4141,7 +4236,6 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta) if (len == -1 && ErrCode() == EINTR) continue; \ rc = (len >= 0); break; } while(1) #endif - DPUTS("writing new meta page"); psize = env->me_psize; @@ -4180,7 +4274,7 @@ mdb_env_write_meta(MDB_txn *txn) MDB_meta meta, metab, *mp; unsigned flags; mdb_size_t mapsize; - off_t off; + MDB_OFF_T off; int rc, len, toggle; char *ptr; HANDLE mfd; @@ -4202,6 +4296,7 @@ mdb_env_write_meta(MDB_txn *txn) if (mapsize < env->me_mapsize) mapsize = env->me_mapsize; +#ifndef _WIN32 /* We don't want to ever use MSYNC/FlushViewOfFile in Windows */ if (flags & MDB_WRITEMAP) { mp->mm_mapsize = mapsize; mp->mm_dbs[FREE_DBI] = txn->mt_dbs[FREE_DBI]; @@ -4217,11 +4312,10 @@ mdb_env_write_meta(MDB_txn *txn) unsigned meta_size = env->me_psize; rc = (env->me_flags & MDB_MAPASYNC) ? MS_ASYNC : MS_SYNC; ptr = (char *)mp - PAGEHDRSZ; -#ifndef _WIN32 /* POSIX msync() requires ptr = start of OS page */ + /* POSIX msync() requires ptr = start of OS page */ r2 = (ptr - env->me_map) & (env->me_os_psize - 1); ptr -= r2; meta_size += r2; -#endif if (MDB_MSYNC(ptr, meta_size, rc)) { rc = ErrCode(); goto fail; @@ -4229,6 +4323,7 @@ mdb_env_write_meta(MDB_txn *txn) } goto done; } +#endif metab.mm_txnid = mp->mm_txnid; metab.mm_last_pg = mp->mm_last_pg; @@ -4379,7 +4474,19 @@ mdb_env_map(MDB_env *env, void *addr) alloctype = MEM_RESERVE; } + /** Some users are afraid of seeing their disk space getting used + * all at once, so the default is now to do incremental file growth. + * But that has a large performance impact, so give the option of + * allocating the file up front. + */ +#ifdef MDB_FIXEDSIZE + LARGE_INTEGER fsize; + fsize.LowPart = msize & 0xffffffff; + fsize.HighPart = msize >> 16 >> 16; + rc = NtCreateSection(&mh, access, NULL, &fsize, secprot, SEC_RESERVE, env->me_fd); +#else rc = NtCreateSection(&mh, access, NULL, NULL, secprot, SEC_RESERVE, env->me_fd); +#endif if (rc) return mdb_nt2win32(rc); map = addr; @@ -4396,22 +4503,27 @@ mdb_env_map(MDB_env *env, void *addr) return mdb_nt2win32(rc); env->me_map = map; #else + int mmap_flags = MAP_SHARED; + int prot = PROT_READ; +#ifdef MAP_NOSYNC /* Used on FreeBSD */ + if (flags & MDB_NOSYNC) + mmap_flags |= MAP_NOSYNC; +#endif #ifdef MDB_VL32 (void) flags; - env->me_map = mmap(addr, NUM_METAS * env->me_psize, PROT_READ, MAP_SHARED, + env->me_map = mmap(addr, NUM_METAS * env->me_psize, prot, mmap_flags, env->me_fd, 0); if (env->me_map == MAP_FAILED) { env->me_map = NULL; return ErrCode(); } #else - int prot = PROT_READ; if (flags & MDB_WRITEMAP) { prot |= PROT_WRITE; if (ftruncate(env->me_fd, env->me_mapsize) < 0) return ErrCode(); } - env->me_map = mmap(addr, env->me_mapsize, prot, MAP_SHARED, + env->me_map = mmap(addr, env->me_mapsize, prot, mmap_flags, env->me_fd, 0); if (env->me_map == MAP_FAILED) { env->me_map = NULL; @@ -4604,7 +4716,7 @@ mdb_fname_init(const char *path, unsigned envflags, MDB_name *fname) /** File type, access mode etc. for #mdb_fopen() */ enum mdb_fopen_type { #ifdef _WIN32 - MDB_O_RDONLY, MDB_O_RDWR, MDB_O_META, MDB_O_COPY, MDB_O_LOCKS + MDB_O_RDONLY, MDB_O_RDWR, MDB_O_OVERLAPPED, MDB_O_META, MDB_O_COPY, MDB_O_LOCKS #else /* A comment in mdb_fopen() explains some O_* flag choices. */ MDB_O_RDONLY= O_RDONLY, /**< for RDONLY me_fd */ @@ -4665,6 +4777,11 @@ mdb_fopen(const MDB_env *env, MDB_name *fname, disp = OPEN_ALWAYS; attrs = FILE_ATTRIBUTE_NORMAL; switch (which) { + case MDB_O_OVERLAPPED: /* for unbuffered asynchronous writes (write-through mode)*/ + acc = GENERIC_WRITE; + disp = OPEN_EXISTING; + attrs = FILE_FLAG_OVERLAPPED|FILE_FLAG_WRITE_THROUGH; + break; case MDB_O_RDONLY: /* read-only datafile */ acc = GENERIC_READ; disp = OPEN_EXISTING; @@ -4754,6 +4871,7 @@ mdb_env_open2(MDB_env *env, int prev) if (!NtCreateSection) return MDB_PROBLEM; } + env->ovs = 0; #endif /* _WIN32 */ #ifdef BROKEN_FDATASYNC @@ -4880,9 +4998,6 @@ mdb_env_open2(MDB_env *env, int prev) #endif env->me_maxpg = env->me_mapsize / env->me_psize; - if (env->me_txns) - env->me_txns->mti_txnid = meta.mm_txnid; - #if MDB_DEBUG { MDB_meta *meta = mdb_env_pick_meta(env); @@ -4982,6 +5097,9 @@ static int ESECT mdb_env_share_locks(MDB_env *env, int *excl) { int rc = 0; + MDB_meta *meta = mdb_env_pick_meta(env); + + env->me_txns->mti_txnid = meta->mm_txnid; #ifdef _WIN32 { @@ -5169,7 +5287,7 @@ mdb_env_setup_locks(MDB_env *env, MDB_name *fname, int mode, int *excl) union semun semu; #endif int rc; - off_t size, rsize; + MDB_OFF_T size, rsize; rc = mdb_fopen(env, fname, MDB_O_LOCKS, mode, &env->me_lfd); if (rc) { @@ -5500,6 +5618,11 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode mode, &env->me_fd); if (rc) goto leave; +#ifdef _WIN32 + rc = mdb_fopen(env, &fname, MDB_O_OVERLAPPED, mode, &env->me_ovfd); + if (rc) + goto leave; +#endif if ((flags & (MDB_RDONLY|MDB_NOLOCK)) == MDB_RDONLY) { rc = mdb_env_setup_locks(env, &fname, mode, &excl); @@ -5508,10 +5631,10 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode } if ((rc = mdb_env_open2(env, flags & MDB_PREVSNAPSHOT)) == MDB_SUCCESS) { + /* Synchronous fd for meta writes. Needed even with + * MDB_NOSYNC/MDB_NOMETASYNC, in case these get reset. + */ if (!(flags & (MDB_RDONLY|MDB_WRITEMAP))) { - /* Synchronous fd for meta writes. Needed even with - * MDB_NOSYNC/MDB_NOMETASYNC, in case these get reset. - */ rc = mdb_fopen(env, &fname, MDB_O_META, mode, &env->me_mfd); if (rc) goto leave; @@ -5618,6 +5741,16 @@ mdb_env_close0(MDB_env *env, int excl) } if (env->me_mfd != INVALID_HANDLE_VALUE) (void) close(env->me_mfd); +#ifdef _WIN32 + if (env->ovs > 0) { + for (i = 0; i < env->ovs; i++) { + CloseHandle(env->ov[i].hEvent); + } + free(env->ov); + } + if (env->me_ovfd != INVALID_HANDLE_VALUE) + (void) close(env->me_ovfd); +#endif if (env->me_fd != INVALID_HANDLE_VALUE) (void) close(env->me_fd); if (env->me_txns) { @@ -5665,6 +5798,17 @@ mdb_env_close0(MDB_env *env, int excl) if (excl > 0) semctl(env->me_rmutex->semid, 0, IPC_RMID); } +#elif defined(MDB_ROBUST_SUPPORTED) + /* If we have the filelock: If we are the + * only remaining user, clean up robust + * mutexes. + */ + if (excl == 0) + mdb_env_excl_lock(env, &excl); + if (excl > 0) { + pthread_mutex_destroy(env->me_txns->mti_rmutex); + pthread_mutex_destroy(env->me_txns->mti_wmutex); + } #endif munmap((void *)env->me_txns, (env->me_maxreaders-1)*sizeof(MDB_reader)+sizeof(MDB_txninfo)); } @@ -6804,16 +6948,12 @@ mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { mdb_xcursor_init1(mc, leaf); - } - if (data) { + rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); + if (rc != MDB_SUCCESS) + return rc; + } else if (data) { if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS) return rc; - - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); - if (rc != MDB_SUCCESS) - return rc; - } } MDB_GET_KEY(leaf, key); @@ -6837,7 +6977,8 @@ mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) mp = mc->mc_pg[mc->mc_top]; - if (mc->mc_db->md_flags & MDB_DUPSORT) { + if ((mc->mc_db->md_flags & MDB_DUPSORT) && + mc->mc_ki[mc->mc_top] < NUMKEYS(mp)) { leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { if (op == MDB_PREV || op == MDB_PREV_DUP) { @@ -6879,27 +7020,25 @@ mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) DPRINTF(("==> cursor points to page %"Yu" with %u keys, key index %u", mdb_dbg_pgno(mp), NUMKEYS(mp), mc->mc_ki[mc->mc_top])); + if (!IS_LEAF(mp)) + return MDB_CORRUPTED; + if (IS_LEAF2(mp)) { key->mv_size = mc->mc_db->md_pad; key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size); return MDB_SUCCESS; } - mdb_cassert(mc, IS_LEAF(mp)); leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { mdb_xcursor_init1(mc, leaf); - } - if (data) { + rc = mdb_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); + if (rc != MDB_SUCCESS) + return rc; + } else if (data) { if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS) return rc; - - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - rc = mdb_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); - if (rc != MDB_SUCCESS) - return rc; - } } MDB_GET_KEY(leaf, key); @@ -7057,24 +7196,22 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { mdb_xcursor_init1(mc, leaf); - } - if (data) { - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - if (op == MDB_SET || op == MDB_SET_KEY || op == MDB_SET_RANGE) { - rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); + if (op == MDB_SET || op == MDB_SET_KEY || op == MDB_SET_RANGE) { + rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); + } else { + int ex2, *ex2p; + if (op == MDB_GET_BOTH) { + ex2p = &ex2; + ex2 = 0; } else { - int ex2, *ex2p; - if (op == MDB_GET_BOTH) { - ex2p = &ex2; - ex2 = 0; - } else { - ex2p = NULL; - } - rc = mdb_cursor_set(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_SET_RANGE, ex2p); - if (rc != MDB_SUCCESS) - return rc; + ex2p = NULL; } - } else if (op == MDB_GET_BOTH || op == MDB_GET_BOTH_RANGE) { + rc = mdb_cursor_set(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_SET_RANGE, ex2p); + if (rc != MDB_SUCCESS) + return rc; + } + } else if (data) { + if (op == MDB_GET_BOTH || op == MDB_GET_BOTH_RANGE) { MDB_val olddata; MDB_cmp_func *dcmp; if ((rc = mdb_node_read(mc, leaf, &olddata)) != MDB_SUCCESS) @@ -7132,22 +7269,23 @@ mdb_cursor_first(MDB_cursor *mc, MDB_val *key, MDB_val *data) mc->mc_ki[mc->mc_top] = 0; if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { - key->mv_size = mc->mc_db->md_pad; - key->mv_data = LEAF2KEY(mc->mc_pg[mc->mc_top], 0, key->mv_size); + if ( key ) { + key->mv_size = mc->mc_db->md_pad; + key->mv_data = LEAF2KEY(mc->mc_pg[mc->mc_top], 0, key->mv_size); + } return MDB_SUCCESS; } - if (data) { - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - mdb_xcursor_init1(mc, leaf); - rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); - if (rc) - return rc; - } else { - if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS) - return rc; - } + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + mdb_xcursor_init1(mc, leaf); + rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); + if (rc) + return rc; + } else if (data) { + if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS) + return rc; } + MDB_GET_KEY(leaf, key); return MDB_SUCCESS; } @@ -7176,21 +7314,21 @@ mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data) leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { - key->mv_size = mc->mc_db->md_pad; - key->mv_data = LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], key->mv_size); + if (key) { + key->mv_size = mc->mc_db->md_pad; + key->mv_data = LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], key->mv_size); + } return MDB_SUCCESS; } - if (data) { - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - mdb_xcursor_init1(mc, leaf); - rc = mdb_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); - if (rc) - return rc; - } else { - if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS) - return rc; - } + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + mdb_xcursor_init1(mc, leaf); + rc = mdb_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); + if (rc) + return rc; + } else if (data) { + if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS) + return rc; } MDB_GET_KEY(leaf, key); @@ -7352,6 +7490,7 @@ mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data, rc = MDB_NOTFOUND; break; } + mc->mc_flags &= ~C_EOF; { MDB_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) { @@ -7666,7 +7805,7 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, offset *= 4; /* space for 4 more */ break; } - /* FALLTHRU: Big enough MDB_DUPFIXED sub-page */ + /* FALLTHRU */ /* Big enough MDB_DUPFIXED sub-page */ case MDB_CURRENT: fp->mp_flags |= P_DIRTY; COPY_PGNO(fp->mp_pgno, mp->mp_pgno); @@ -7865,7 +8004,7 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, xdata.mv_size = 0; xdata.mv_data = ""; leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (flags == MDB_CURRENT) { + if ((flags & (MDB_CURRENT|MDB_APPENDDUP)) == MDB_CURRENT) { xflags = MDB_CURRENT|MDB_NOSPILL; } else { mdb_xcursor_init1(mc, leaf); @@ -7969,6 +8108,8 @@ mdb_cursor_del(MDB_cursor *mc, unsigned int flags) return rc; mp = mc->mc_pg[mc->mc_top]; + if (!IS_LEAF(mp)) + return MDB_CORRUPTED; if (IS_LEAF2(mp)) goto del_key; leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); @@ -9347,60 +9488,68 @@ mdb_cursor_del0(MDB_cursor *mc) } } rc = mdb_rebalance(mc); + if (rc) + goto fail; - if (rc == MDB_SUCCESS) { - /* DB is totally empty now, just bail out. - * Other cursors adjustments were already done - * by mdb_rebalance and aren't needed here. - */ - if (!mc->mc_snum) - return rc; + /* DB is totally empty now, just bail out. + * Other cursors adjustments were already done + * by mdb_rebalance and aren't needed here. + */ + if (!mc->mc_snum) { + mc->mc_flags |= C_EOF; + return rc; + } - mp = mc->mc_pg[mc->mc_top]; - nkeys = NUMKEYS(mp); + mp = mc->mc_pg[mc->mc_top]; + nkeys = NUMKEYS(mp); - /* Adjust other cursors pointing to mp */ - for (m2 = mc->mc_txn->mt_cursors[dbi]; !rc && m2; m2=m2->mc_next) { - m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (! (m2->mc_flags & m3->mc_flags & C_INITIALIZED)) - continue; - if (m3->mc_snum < mc->mc_snum) - continue; - if (m3->mc_pg[mc->mc_top] == mp) { - /* if m3 points past last node in page, find next sibling */ - if (m3->mc_ki[mc->mc_top] >= mc->mc_ki[mc->mc_top]) { - if (m3->mc_ki[mc->mc_top] >= nkeys) { - rc = mdb_cursor_sibling(m3, 1); - if (rc == MDB_NOTFOUND) { - m3->mc_flags |= C_EOF; - rc = MDB_SUCCESS; - continue; - } + /* Adjust other cursors pointing to mp */ + for (m2 = mc->mc_txn->mt_cursors[dbi]; !rc && m2; m2=m2->mc_next) { + m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; + if (!(m2->mc_flags & m3->mc_flags & C_INITIALIZED)) + continue; + if (m3->mc_snum < mc->mc_snum) + continue; + if (m3->mc_pg[mc->mc_top] == mp) { + if (m3->mc_ki[mc->mc_top] >= mc->mc_ki[mc->mc_top]) { + /* if m3 points past last node in page, find next sibling */ + if (m3->mc_ki[mc->mc_top] >= nkeys) { + rc = mdb_cursor_sibling(m3, 1); + if (rc == MDB_NOTFOUND) { + m3->mc_flags |= C_EOF; + rc = MDB_SUCCESS; + continue; } - if (mc->mc_db->md_flags & MDB_DUPSORT) { - MDB_node *node = NODEPTR(m3->mc_pg[m3->mc_top], m3->mc_ki[m3->mc_top]); - /* If this node has dupdata, it may need to be reinited - * because its data has moved. - * If the xcursor was not initd it must be reinited. - * Else if node points to a subDB, nothing is needed. - * Else (xcursor was initd, not a subDB) needs mc_pg[0] reset. - */ - if (node->mn_flags & F_DUPDATA) { - if (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { - if (!(node->mn_flags & F_SUBDATA)) - m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node); - } else { - mdb_xcursor_init1(m3, node); - m3->mc_xcursor->mx_cursor.mc_flags |= C_DEL; - } + if (rc) + goto fail; + } + if (m3->mc_xcursor && !(m3->mc_flags & C_EOF)) { + MDB_node *node = NODEPTR(m3->mc_pg[m3->mc_top], m3->mc_ki[m3->mc_top]); + /* If this node has dupdata, it may need to be reinited + * because its data has moved. + * If the xcursor was not initd it must be reinited. + * Else if node points to a subDB, nothing is needed. + * Else (xcursor was initd, not a subDB) needs mc_pg[0] reset. + */ + if (node->mn_flags & F_DUPDATA) { + if (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { + if (!(node->mn_flags & F_SUBDATA)) + m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node); + } else { + mdb_xcursor_init1(m3, node); + rc = mdb_cursor_first(&m3->mc_xcursor->mx_cursor, NULL, NULL); + if (rc) + goto fail; } } + m3->mc_xcursor->mx_cursor.mc_flags |= C_DEL; } } } - mc->mc_flags |= C_DEL; } + mc->mc_flags |= C_DEL; +fail: if (rc) mc->mc_txn->mt_flags |= MDB_TXN_ERROR; return rc; diff --git a/libraries/liblmdb/mdb_copy.1 b/libraries/liblmdb/mdb_copy.1 index 30e4754f13..c61a102424 100644 --- a/libraries/liblmdb/mdb_copy.1 +++ b/libraries/liblmdb/mdb_copy.1 @@ -1,5 +1,5 @@ .TH MDB_COPY 1 "2017/07/31" "LMDB 0.9.70" -.\" Copyright 2012-2019 Howard Chu, Symas Corp. All Rights Reserved. +.\" Copyright 2012-2021 Howard Chu, Symas Corp. All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME mdb_copy \- LMDB environment copy tool diff --git a/libraries/liblmdb/mdb_copy.c b/libraries/liblmdb/mdb_copy.c index 23be815062..ecc9beeff0 100644 --- a/libraries/liblmdb/mdb_copy.c +++ b/libraries/liblmdb/mdb_copy.c @@ -1,6 +1,6 @@ /* mdb_copy.c - memory-mapped database backup tool */ /* - * Copyright 2012-2018 Howard Chu, Symas Corp. + * Copyright 2012-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/mdb_drop.1 b/libraries/liblmdb/mdb_drop.1 index 10666e5204..959a8e96b7 100644 --- a/libraries/liblmdb/mdb_drop.1 +++ b/libraries/liblmdb/mdb_drop.1 @@ -1,5 +1,5 @@ .TH MDB_DROP 1 "2017/11/19" "LMDB 0.9.70" -.\" Copyright 2014-2018 Howard Chu, Symas Corp. All Rights Reserved. +.\" Copyright 2014-2021 Howard Chu, Symas Corp. All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME mdb_drop \- LMDB database delete tool diff --git a/libraries/liblmdb/mdb_drop.c b/libraries/liblmdb/mdb_drop.c index 7d2af4b62e..c6b82dd269 100644 --- a/libraries/liblmdb/mdb_drop.c +++ b/libraries/liblmdb/mdb_drop.c @@ -1,6 +1,6 @@ /* mdb_drop.c - memory-mapped database delete tool */ /* - * Copyright 2016-2018 Howard Chu, Symas Corp. + * Copyright 2016-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/mdb_dump.1 b/libraries/liblmdb/mdb_dump.1 index 424ad9321c..ad733c9e57 100644 --- a/libraries/liblmdb/mdb_dump.1 +++ b/libraries/liblmdb/mdb_dump.1 @@ -1,5 +1,5 @@ .TH MDB_DUMP 1 "2017/07/31" "LMDB 0.9.70" -.\" Copyright 2014-2017 Howard Chu, Symas Corp. All Rights Reserved. +.\" Copyright 2014-2021 Howard Chu, Symas Corp. All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME mdb_dump \- LMDB environment export tool diff --git a/libraries/liblmdb/mdb_dump.c b/libraries/liblmdb/mdb_dump.c index b7737f12de..29ee02e031 100644 --- a/libraries/liblmdb/mdb_dump.c +++ b/libraries/liblmdb/mdb_dump.c @@ -1,6 +1,6 @@ /* mdb_dump.c - memory-mapped database dump tool */ /* - * Copyright 2011-2018 Howard Chu, Symas Corp. + * Copyright 2011-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,6 +64,8 @@ static void text(MDB_val *v) end = c + v->mv_size; while (c < end) { if (isprint(*c)) { + if (*c == '\\') + putchar('\\'); putchar(*c); } else { putchar('\\'); @@ -179,7 +181,7 @@ int main(int argc, char *argv[]) * -V: print version and exit * (default) dump only the main DB */ - while ((i = getopt(argc, argv, "af:lnps:V")) != EOF) { + while ((i = getopt(argc, argv, "af:lnps:vV")) != EOF) { switch(i) { case 'V': printf("%s\n", MDB_VERSION_STRING); diff --git a/libraries/liblmdb/mdb_load.1 b/libraries/liblmdb/mdb_load.1 index a2f8373c57..78439a14da 100644 --- a/libraries/liblmdb/mdb_load.1 +++ b/libraries/liblmdb/mdb_load.1 @@ -1,5 +1,5 @@ .TH MDB_LOAD 1 "2015/09/30" "LMDB 0.9.17" -.\" Copyright 2014-2018 Howard Chu, Symas Corp. All Rights Reserved. +.\" Copyright 2014-2021 Howard Chu, Symas Corp. All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME mdb_load \- LMDB environment import tool diff --git a/libraries/liblmdb/mdb_load.c b/libraries/liblmdb/mdb_load.c index ad911c088c..6f6dddc9e6 100644 --- a/libraries/liblmdb/mdb_load.c +++ b/libraries/liblmdb/mdb_load.c @@ -1,6 +1,6 @@ /* mdb_load.c - memory-mapped database load tool */ /* - * Copyright 2011-2018 Howard Chu, Symas Corp. + * Copyright 2011-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -236,7 +236,7 @@ static int readline(MDB_val *out, MDB_val *buf) while (c2 < end) { if (*c2 == '\\') { if (c2[1] == '\\') { - c1++; c2 += 2; + *c1++ = *c2; } else { if (c2+3 > end || !isxdigit(c2[1]) || !isxdigit(c2[2])) { Eof = 1; @@ -244,8 +244,8 @@ static int readline(MDB_val *out, MDB_val *buf) return EOF; } *c1++ = unhex(++c2); - c2 += 2; } + c2 += 2; } else { /* copies are redundant when no escapes were used */ *c1++ = *c2++; diff --git a/libraries/liblmdb/mdb_stat.1 b/libraries/liblmdb/mdb_stat.1 index 83988a0fa0..e1e37550ad 100644 --- a/libraries/liblmdb/mdb_stat.1 +++ b/libraries/liblmdb/mdb_stat.1 @@ -1,5 +1,5 @@ .TH MDB_STAT 1 "2017/07/31" "LMDB 0.9.70" -.\" Copyright 2012-2019 Howard Chu, Symas Corp. All Rights Reserved. +.\" Copyright 2012-2021 Howard Chu, Symas Corp. All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME mdb_stat \- LMDB environment status tool diff --git a/libraries/liblmdb/mdb_stat.c b/libraries/liblmdb/mdb_stat.c index 08f30befd6..088f620a19 100644 --- a/libraries/liblmdb/mdb_stat.c +++ b/libraries/liblmdb/mdb_stat.c @@ -1,6 +1,6 @@ /* mdb_stat.c - memory-mapped database status tool */ /* - * Copyright 2011-2018 Howard Chu, Symas Corp. + * Copyright 2011-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) * -V: print version and exit * (default) print stat of only the main DB */ - while ((i = getopt(argc, argv, "Vaefnrs:")) != EOF) { + while ((i = getopt(argc, argv, "Vaefnrs:v")) != EOF) { switch(i) { case 'V': printf("%s\n", MDB_VERSION_STRING); diff --git a/libraries/liblmdb/midl.c b/libraries/liblmdb/midl.c index ee89822e39..568daba1e8 100644 --- a/libraries/liblmdb/midl.c +++ b/libraries/liblmdb/midl.c @@ -3,8 +3,8 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2000-2019 The OpenLDAP Foundation. - * Portions Copyright 2001-2018 Howard Chu, Symas Corp. + * Copyright 2000-2021 The OpenLDAP Foundation. + * Portions Copyright 2001-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/midl.h b/libraries/liblmdb/midl.h index 0f826771a1..1035c01e14 100644 --- a/libraries/liblmdb/midl.h +++ b/libraries/liblmdb/midl.h @@ -11,8 +11,8 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2000-2019 The OpenLDAP Foundation. - * Portions Copyright 2001-2019 Howard Chu, Symas Corp. + * Copyright 2000-2021 The OpenLDAP Foundation. + * Portions Copyright 2001-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/mtest.c b/libraries/liblmdb/mtest.c index 6fc5840c3f..c03daa1081 100644 --- a/libraries/liblmdb/mtest.c +++ b/libraries/liblmdb/mtest.c @@ -1,6 +1,6 @@ /* mtest.c - memory-mapped database tester/toy */ /* - * Copyright 2011-2018 Howard Chu, Symas Corp. + * Copyright 2011-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/mtest2.c b/libraries/liblmdb/mtest2.c index 64b742aa46..1ce4c9442d 100644 --- a/libraries/liblmdb/mtest2.c +++ b/libraries/liblmdb/mtest2.c @@ -1,6 +1,6 @@ /* mtest2.c - memory-mapped database tester/toy */ /* - * Copyright 2011-2018 Howard Chu, Symas Corp. + * Copyright 2011-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/mtest3.c b/libraries/liblmdb/mtest3.c index 81e4bbf9b0..f8da0d331c 100644 --- a/libraries/liblmdb/mtest3.c +++ b/libraries/liblmdb/mtest3.c @@ -1,6 +1,6 @@ /* mtest3.c - memory-mapped database tester/toy */ /* - * Copyright 2011-2018 Howard Chu, Symas Corp. + * Copyright 2011-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/mtest4.c b/libraries/liblmdb/mtest4.c index c355cf105a..3d7476c455 100644 --- a/libraries/liblmdb/mtest4.c +++ b/libraries/liblmdb/mtest4.c @@ -1,6 +1,6 @@ /* mtest4.c - memory-mapped database tester/toy */ /* - * Copyright 2011-2018 Howard Chu, Symas Corp. + * Copyright 2011-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/mtest5.c b/libraries/liblmdb/mtest5.c index 95793ec1fb..d7a7307e29 100644 --- a/libraries/liblmdb/mtest5.c +++ b/libraries/liblmdb/mtest5.c @@ -1,6 +1,6 @@ /* mtest5.c - memory-mapped database tester/toy */ /* - * Copyright 2011-2018 Howard Chu, Symas Corp. + * Copyright 2011-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/mtest6.c b/libraries/liblmdb/mtest6.c index cb0d4d73c9..cf8ba961d0 100644 --- a/libraries/liblmdb/mtest6.c +++ b/libraries/liblmdb/mtest6.c @@ -1,6 +1,6 @@ /* mtest6.c - memory-mapped database tester/toy */ /* - * Copyright 2011-2018 Howard Chu, Symas Corp. + * Copyright 2011-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/sample-bdb.txt b/libraries/liblmdb/sample-bdb.txt index 97220f0ed2..8ca927c6cf 100644 --- a/libraries/liblmdb/sample-bdb.txt +++ b/libraries/liblmdb/sample-bdb.txt @@ -3,7 +3,7 @@ * Do a line-by-line comparison of this and sample-mdb.txt */ /* - * Copyright 2012-2018 Howard Chu, Symas Corp. + * Copyright 2012-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/libraries/liblmdb/sample-mdb.txt b/libraries/liblmdb/sample-mdb.txt index 1d20ed3d02..2e1731631d 100644 --- a/libraries/liblmdb/sample-mdb.txt +++ b/libraries/liblmdb/sample-mdb.txt @@ -3,7 +3,7 @@ * Do a line-by-line comparison of this and sample-bdb.txt */ /* - * Copyright 2012-2018 Howard Chu, Symas Corp. + * Copyright 2012-2021 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without