Codebase list lmdb / e41dc2e
New upstream version 0.9.11 Ondřej Surý 10 years ago
6 changed file(s) with 450 addition(s) and 280 deletion(s). Raw diff Collapse all Expand all
00 LMDB 0.9 Change Log
1
2 LMDB 0.9.11 Release (2014/01/15)
3 Add mdb_env_set_assert() (ITS#7775)
4 Fix: invalidate txn on page allocation errors (ITS#7377)
5 Fix xcursor tracking in mdb_cursor_del0() (ITS#7771)
6 Fix corruption from deletes (ITS#7756)
7 Fix Windows/MSVC build issues
8 Raise safe limit of max MDB_MAXKEYSIZE
9 Misc code cleanup
10 Documentation
11 Remove spurious note about non-overlapping flags (ITS#7665)
112
213 LMDB 0.9.10 Release (2013/11/12)
314 Add MDB_NOMEMINIT option
1526 Fix mdb_page_merge() cursor fixup (ITS#7722)
1627 Fix mdb_cursor_del() on last delete (ITS#7718)
1728 Fix adding WRITEMAP on existing env (ITS#7715)
18 Fixes for nested txns (ITS#7515)
29 Fix nested txns (ITS#7515)
1930 Fix mdb_env_copy() O_DIRECT bug (ITS#7682)
2031 Fix mdb_cursor_set(SET_RANGE) return code (ITS#7681)
2132 Fix mdb_rebalance() cursor fixup (ITS#7701)
183183 /** Library minor version */
184184 #define MDB_VERSION_MINOR 9
185185 /** Library patch version */
186 #define MDB_VERSION_PATCH 10
186 #define MDB_VERSION_PATCH 11
187187
188188 /** Combine args a,b,c into a single integer for easy version comparisons */
189189 #define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c))
193193 MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
194194
195195 /** The release date of this library version */
196 #define MDB_VERSION_DATE "November 11, 2013"
196 #define MDB_VERSION_DATE "January 15, 2014"
197197
198198 /** A stringifier for the version info */
199199 #define MDB_VERSTR(a,b,c,d) "MDB " #a "." #b "." #c ": (" d ")"
262262 typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *relctx);
263263
264264 /** @defgroup mdb_env Environment Flags
265 *
266 * Values do not overlap Database Flags.
267265 * @{
268266 */
269267 /** mmap at a fixed address (experimental) */
291289 /** @} */
292290
293291 /** @defgroup mdb_dbi_open Database Flags
294 *
295 * Values do not overlap Environment Flags.
296292 * @{
297293 */
298294 /** use reverse string keys */
796792 */
797793 int mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs);
798794
799 /** @brief Get the maximum size of a key for the environment.
800 *
801 * This is the compile-time constant #MDB_MAXKEYSIZE, default 511.
795 /** @brief Get the maximum size of keys and #MDB_DUPSORT data we can write.
796 *
797 * Depends on the compile-time constant #MDB_MAXKEYSIZE. Default 511.
802798 * See @ref MDB_val.
803799 * @param[in] env An environment handle returned by #mdb_env_create()
804 * @return The maximum size of a key
800 * @return The maximum size of a key we can write
805801 */
806802 int mdb_env_get_maxkeysize(MDB_env *env);
803
804 /** @brief Set application information associated with the #MDB_env.
805 *
806 * @param[in] env An environment handle returned by #mdb_env_create()
807 * @param[in] ctx An arbitrary pointer for whatever the application needs.
808 * @return A non-zero error value on failure and 0 on success.
809 */
810 int mdb_env_set_userctx(MDB_env *env, void *ctx);
811
812 /** @brief Get the application information associated with the #MDB_env.
813 *
814 * @param[in] env An environment handle returned by #mdb_env_create()
815 * @return The pointer set by #mdb_env_set_userctx().
816 */
817 void *mdb_env_get_userctx(MDB_env *env);
818
819 /** @brief A callback function for most MDB assert() failures,
820 * called before printing the message and aborting.
821 *
822 * @param[in] env An environment handle returned by #mdb_env_create().
823 * @param[in] msg The assertion message, not including newline.
824 */
825 typedef void MDB_assert_func(MDB_env *env, const char *msg);
826
827 /** Set or reset the assert() callback of the environment.
828 * Disabled if liblmdb is buillt with NDEBUG.
829 * @note This hack should become obsolete as lmdb's error handling matures.
830 * @param[in] env An environment handle returned by #mdb_env_create().
831 * @parem[in] func An #MDB_assert_func function, or 0.
832 * @return A non-zero error value on failure and 0 on success.
833 */
834 int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func);
807835
808836 /** @brief Create a transaction for use with the environment.
809837 *
14081436 *
14091437 * @param[in] msg The string to be printed.
14101438 * @param[in] ctx An arbitrary context pointer for the callback.
1411 * @return < 0 on failure, 0 on success.
1439 * @return < 0 on failure, >= 0 on success.
14121440 */
14131441 typedef int (MDB_msg_func)(const char *msg, void *ctx);
14141442
14171445 * @param[in] env An environment handle returned by #mdb_env_create()
14181446 * @param[in] func A #MDB_msg_func function
14191447 * @param[in] ctx Anything the message function needs
1420 * @return < 0 on failure, 0 on success.
1448 * @return < 0 on failure, >= 0 on success.
14211449 */
14221450 int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx);
14231451
6464 #include <fcntl.h>
6565 #endif
6666
67 #include <assert.h>
6867 #include <errno.h>
6968 #include <limits.h>
7069 #include <stddef.h>
148147 /** @defgroup internal MDB Internals
149148 * @{
150149 */
151 /** @defgroup compat Windows Compatibility Macros
150 /** @defgroup compat Compatibility Macros
152151 * A bunch of macros to minimize the amount of platform-specific ifdefs
153152 * needed throughout the rest of the code. When the features this library
154153 * needs are similar enough to POSIX to be hidden in a one-or-two line
155154 * replacement, this macro approach is used.
156155 * @{
157156 */
157
158 /** Wrapper around __func__, which is a C99 feature */
159 #if __STDC_VERSION__ >= 199901L
160 # define mdb_func_ __func__
161 #elif __GNUC__ >= 2 || _MSC_VER >= 1300
162 # define mdb_func_ __FUNCTION__
163 #else
164 /* If a debug message says <mdb_unknown>(), update the #if statements above */
165 # define mdb_func_ "<mdb_unknown>"
166 #endif
167
158168 #ifdef _WIN32
159169 #define MDB_USE_HASH 1
160170 #define MDB_PIDLOCK 0
326336 */
327337 # define DPRINTF(args) ((void) ((mdb_debug) && DPRINTF0 args))
328338 # define DPRINTF0(fmt, ...) \
329 fprintf(stderr, "%s:%d " fmt "\n", __func__, __LINE__, __VA_ARGS__)
339 fprintf(stderr, "%s:%d " fmt "\n", mdb_func_, __LINE__, __VA_ARGS__)
330340 #else
331341 # define DPRINTF(args) ((void) 0)
332342 #endif
381391 /** The version number for a database's lockfile format. */
382392 #define MDB_LOCK_VERSION 1
383393
384 /** @brief The maximum size of a key in the database.
394 /** @brief The max size of a key we can write, or 0 for dynamic max.
385395 *
386 * The library rejects bigger keys, and cannot deal with records
387 * with bigger keys stored by a library with bigger max keysize.
396 * Define this as 0 to compute the max from the page size. 511
397 * is default for backwards compat: liblmdb <= 0.9.10 can break
398 * when modifying a DB with keys/dupsort data bigger than its max.
388399 *
389 * We require that keys all fit onto a regular page. This limit
390 * could be raised a bit further if needed; to something just
391 * under (page size / #MDB_MINKEYS / 3).
392 *
393 * Note that data items in an #MDB_DUPSORT database are actually keys
394 * of a subDB, so they're also limited to this size.
400 * Data items in an #MDB_DUPSORT database are also limited to
401 * this size, since they're actually keys of a sub-DB. Keys and
402 * #MDB_DUPSORT data items must fit on a node in a regular page.
395403 */
396404 #ifndef MDB_MAXKEYSIZE
397405 #define MDB_MAXKEYSIZE 511
406 #endif
407
408 /** The maximum size of a key we can write to the environment. */
409 #if MDB_MAXKEYSIZE
410 #define ENV_MAXKEY(env) (MDB_MAXKEYSIZE)
411 #else
412 #define ENV_MAXKEY(env) ((env)->me_maxkey)
398413 #endif
399414
400415 /** @brief The maximum size of a data item.
404419 #define MAXDATASIZE 0xffffffffUL
405420
406421 #if MDB_DEBUG
422 /** Key size which fits in a #DKBUF.
423 * @ingroup debug
424 */
425 #define DKBUF_MAXKEYSIZE ((MDB_MAXKEYSIZE) > 0 ? (MDB_MAXKEYSIZE) : 511)
407426 /** A key buffer.
408427 * @ingroup debug
409428 * This is used for printing a hex dump of a key's contents.
410429 */
411 #define DKBUF char kbuf[(MDB_MAXKEYSIZE*2+1)]
430 #define DKBUF char kbuf[DKBUF_MAXKEYSIZE*2+1]
412431 /** Display a key in hex.
413432 * @ingroup debug
414433 * Invoke a function to display a key in hex.
426445
427446 /** Test if the flags \b f are set in a flag word \b w. */
428447 #define F_ISSET(w, f) (((w) & (f)) == (f))
448
449 /** Round \b n up to an even number. */
450 #define EVEN(n) (((n) + 1U) & -2) /* sign-extending -2 to match n+1U */
429451
430452 /** Used for offsets within a single page.
431453 * Since memory pages are typically 4 or 8KB in size, 12-13 bits,
678700 #define OVPAGES(size, psize) ((PAGEHDRSZ-1 + (size)) / (psize) + 1)
679701
680702 /** Header for a single key/data pair within a page.
681 * We guarantee 2-byte alignment for nodes.
703 * Used in pages of type #P_BRANCH and #P_LEAF without #P_LEAF2.
704 * We guarantee 2-byte alignment for 'MDB_node's.
682705 */
683706 typedef struct MDB_node {
684707 /** lo and hi are used for data size on leaf nodes and for
687710 * They are in host byte order in case that lets some
688711 * accesses be optimized into a 32-bit word access.
689712 */
690 #define mn_lo mn_offset[BYTE_ORDER!=LITTLE_ENDIAN]
691 #define mn_hi mn_offset[BYTE_ORDER==LITTLE_ENDIAN] /**< part of dsize or pgno */
692 unsigned short mn_offset[2]; /**< storage for #mn_lo and #mn_hi */
713 #if BYTE_ORDER == LITTLE_ENDIAN
714 unsigned short mn_lo, mn_hi; /**< part of data size or pgno */
715 #else
716 unsigned short mn_hi, mn_lo;
717 #endif
693718 /** @defgroup mdb_node Node Flags
694719 * @ingroup internal
695720 * Flags for node headers.
10421067 int me_maxfree_1pg;
10431068 /** Max size of a node on a page */
10441069 unsigned int me_nodemax;
1070 #if !(MDB_MAXKEYSIZE)
1071 unsigned int me_maxkey; /**< max size of a key */
1072 #endif
10451073 #ifdef _WIN32
10461074 int me_pidquery; /**< Used in OpenProcess */
10471075 HANDLE me_rmutex; /* Windows mutexes don't reside in shared mem */
10501078 sem_t *me_rmutex; /* Shared mutexes are not supported */
10511079 sem_t *me_wmutex;
10521080 #endif
1081 void *me_userctx; /**< User-settable context */
1082 MDB_assert_func *me_assert_func; /**< Callback for assertion failures */
10531083 };
10541084
10551085 /** Nested transaction */
10981128 static MDB_node *mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp);
10991129 static int mdb_node_add(MDB_cursor *mc, indx_t indx,
11001130 MDB_val *key, MDB_val *data, pgno_t pgno, unsigned int flags);
1101 static void mdb_node_del(MDB_page *mp, indx_t indx, int ksize);
1131 static void mdb_node_del(MDB_cursor *mc, int ksize);
11021132 static void mdb_node_shrink(MDB_page *mp, indx_t indx);
11031133 static int mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst);
11041134 static int mdb_node_read(MDB_txn *txn, MDB_node *leaf, MDB_val *data);
11851215 return strerror(err);
11861216 }
11871217
1218 /** assert(3) variant in cursor context */
1219 #define mdb_cassert(mc, expr) mdb_assert0((mc)->mc_txn->mt_env, expr, #expr)
1220 /** assert(3) variant in transaction context */
1221 #define mdb_tassert(mc, expr) mdb_assert0((txn)->mt_env, expr, #expr)
1222 /** assert(3) variant in environment context */
1223 #define mdb_eassert(env, expr) mdb_assert0(env, expr, #expr)
1224
1225 #ifndef NDEBUG
1226 # define mdb_assert0(env, expr, expr_txt) ((expr) ? (void)0 : \
1227 mdb_assert_fail(env, expr_txt, mdb_func_, __FILE__, __LINE__))
1228
1229 static void
1230 mdb_assert_fail(MDB_env *env, const char *expr_txt,
1231 const char *func, const char *file, int line)
1232 {
1233 char buf[400];
1234 sprintf(buf, "%.100s:%d: Assertion '%.200s' failed in %.40s()",
1235 file, line, expr_txt, func);
1236 if (env->me_assert_func)
1237 env->me_assert_func(env, buf);
1238 fprintf(stderr, "%s\n", buf);
1239 abort();
1240 }
1241 #else
1242 # define mdb_assert0(env, expr, expr_txt) ((void) 0)
1243 #endif /* NDEBUG */
1244
11881245 #if MDB_DEBUG
1246 /** Return the page number of \b mp which may be sub-page, for debug output */
1247 static pgno_t
1248 mdb_dbg_pgno(MDB_page *mp)
1249 {
1250 pgno_t ret;
1251 COPY_PGNO(ret, mp->mp_pgno);
1252 return ret;
1253 }
1254
11891255 /** Display a key in hexadecimal and return the address of the result.
11901256 * @param[in] key the key to display
11911257 * @param[in] buf the buffer to write into. Should always be #DKBUF.
12011267 if (!key)
12021268 return "";
12031269
1204 if (key->mv_size > MDB_MAXKEYSIZE)
1270 if (key->mv_size > DKBUF_MAXKEYSIZE)
12051271 return "MDB_MAXKEYSIZE";
12061272 /* may want to make this a dynamic check: if the key is mostly
12071273 * printable characters, print it as-is instead of converting to hex.
12211287 mdb_page_list(MDB_page *mp)
12221288 {
12231289 MDB_node *node;
1224 unsigned int i, nkeys, nsize;
1290 unsigned int i, nkeys, nsize, total = 0;
12251291 MDB_val key;
12261292 DKBUF;
12271293
12281294 nkeys = NUMKEYS(mp);
1229 fprintf(stderr, "Page %"Z"u numkeys %d\n", mp->mp_pgno, nkeys);
1295 fprintf(stderr, "Page %"Z"u numkeys %d\n", mdb_dbg_pgno(mp), nkeys);
12301296 for (i=0; i<nkeys; i++) {
12311297 node = NODEPTR(mp, i);
12321298 key.mv_size = node->mn_ksize;
12331299 key.mv_data = node->mn_data;
1234 nsize = NODESIZE + NODEKSZ(node) + sizeof(indx_t);
1300 nsize = NODESIZE + key.mv_size;
12351301 if (IS_BRANCH(mp)) {
12361302 fprintf(stderr, "key %d: page %"Z"u, %s\n", i, NODEPGNO(node),
12371303 DKEY(&key));
1304 total += nsize;
12381305 } else {
12391306 if (F_ISSET(node->mn_flags, F_BIGDATA))
12401307 nsize += sizeof(pgno_t);
12411308 else
12421309 nsize += NODEDSZ(node);
1310 total += nsize;
1311 nsize += sizeof(indx_t);
12431312 fprintf(stderr, "key %d: nsize %d, %s\n", i, nsize, DKEY(&key));
12441313 }
1245 }
1314 total = EVEN(total);
1315 }
1316 fprintf(stderr, "Total: %d\n", total);
12461317 }
12471318
12481319 void
13561427 off = sz - psize;
13571428 }
13581429 if ((ret = malloc(sz)) != NULL) {
1430 VGMEMP_ALLOC(env, ret, sz);
13591431 if (!(env->me_flags & MDB_NOMEMINIT)) {
13601432 memset((char *)ret + off, 0, psize);
13611433 ret->mp_pad = 0;
13621434 }
1363 VGMEMP_ALLOC(env, ret, sz);
1435 } else {
1436 txn->mt_flags |= MDB_TXN_ERROR;
13641437 }
13651438 return ret;
13661439 }
16261699 mdb_page_dirty(MDB_txn *txn, MDB_page *mp)
16271700 {
16281701 MDB_ID2 mid;
1629 int (*insert)(MDB_ID2L, MDB_ID2 *);
1702 int rc, (*insert)(MDB_ID2L, MDB_ID2 *);
16301703
16311704 if (txn->mt_env->me_flags & MDB_WRITEMAP) {
16321705 insert = mdb_mid2l_append;
16351708 }
16361709 mid.mid = mp->mp_pgno;
16371710 mid.mptr = mp;
1638 insert(txn->mt_u.dirty_list, &mid);
1711 rc = insert(txn->mt_u.dirty_list, &mid);
1712 mdb_tassert(txn, rc == 0);
16391713 txn->mt_dirty_room--;
16401714 }
16411715
16681742 #else
16691743 enum { Paranoid = 0, Max_retries = INT_MAX /*infinite*/ };
16701744 #endif
1671 int rc, n2 = num-1, retry = Max_retries;
1745 int rc, retry = Max_retries;
16721746 MDB_txn *txn = mc->mc_txn;
16731747 MDB_env *env = txn->mt_env;
16741748 pgno_t pgno, *mop = env->me_pghead;
1675 unsigned i, j, k, mop_len = mop ? mop[0] : 0;
1749 unsigned i, j, k, mop_len = mop ? mop[0] : 0, n2 = num-1;
16761750 MDB_page *np;
16771751 txnid_t oldest = 0, last;
16781752 MDB_cursor_op op;
16811755 *mp = NULL;
16821756
16831757 /* If our dirty list is already full, we can't do anything */
1684 if (txn->mt_dirty_room == 0)
1685 return MDB_TXN_FULL;
1758 if (txn->mt_dirty_room == 0) {
1759 rc = MDB_TXN_FULL;
1760 goto fail;
1761 }
16861762
16871763 for (op = MDB_FIRST;; op = MDB_NEXT) {
16881764 MDB_val key, data;
16921768 /* Seek a big enough contiguous page range. Prefer
16931769 * pages at the tail, just truncating the list.
16941770 */
1695 if (mop_len >= (unsigned)num) {
1771 if (mop_len > n2) {
16961772 i = mop_len;
16971773 do {
16981774 pgno = mop[i];
16991775 if (mop[i-n2] == pgno+n2)
17001776 goto search_done;
1701 } while (--i >= (unsigned)num);
1777 } while (--i > n2);
17021778 if (Max_retries < INT_MAX && --retry < 0)
17031779 break;
17041780 }
17271803 if (rc) {
17281804 if (rc == MDB_NOTFOUND)
17291805 break;
1730 return rc;
1806 goto fail;
17311807 }
17321808 last = *(txnid_t*)key.mv_data;
17331809 if (oldest <= last)
17401816 idl = (MDB_ID *) data.mv_data;
17411817 i = idl[0];
17421818 if (!mop) {
1743 if (!(env->me_pghead = mop = mdb_midl_alloc(i)))
1744 return ENOMEM;
1819 if (!(env->me_pghead = mop = mdb_midl_alloc(i))) {
1820 rc = ENOMEM;
1821 goto fail;
1822 }
17451823 } else {
17461824 if ((rc = mdb_midl_need(&env->me_pghead, i)) != 0)
1747 return rc;
1825 goto fail;
17481826 mop = env->me_pghead;
17491827 }
17501828 env->me_pglast = last;
17731851 pgno = txn->mt_next_pgno;
17741852 if (pgno + num >= env->me_maxpg) {
17751853 DPUTS("DB size maxed out");
1776 return MDB_MAP_FULL;
1854 rc = MDB_MAP_FULL;
1855 goto fail;
17771856 }
17781857
17791858 search_done:
17801859 if (env->me_flags & MDB_WRITEMAP) {
17811860 np = (MDB_page *)(env->me_map + env->me_psize * pgno);
17821861 } else {
1783 if (!(np = mdb_page_malloc(txn, num)))
1784 return ENOMEM;
1862 if (!(np = mdb_page_malloc(txn, num))) {
1863 rc = ENOMEM;
1864 goto fail;
1865 }
17851866 }
17861867 if (i) {
17871868 mop[0] = mop_len -= num;
17961877 *mp = np;
17971878
17981879 return MDB_SUCCESS;
1880
1881 fail:
1882 txn->mt_flags |= MDB_TXN_ERROR;
1883 return rc;
17991884 }
18001885
18011886 /** Copy the used portions of a non-overflow page.
18261911 * If a page being referenced was spilled to disk in this txn, bring
18271912 * it back and make it dirty/writable again.
18281913 * @param[in] txn the transaction handle.
1829 * @param[in] mp the page being referenced.
1914 * @param[in] mp the page being referenced. It must not be dirty.
18301915 * @param[out] ret the writable page, if any. ret is unchanged if
18311916 * mp wasn't spilled.
18321917 */
19021987 np = NULL;
19031988 rc = mdb_page_unspill(txn, mp, &np);
19041989 if (rc)
1905 return rc;
1990 goto fail;
19061991 if (np)
19071992 goto done;
19081993 }
19091994 if ((rc = mdb_midl_need(&txn->mt_free_pgs, 1)) ||
19101995 (rc = mdb_page_alloc(mc, 1, &np)))
1911 return rc;
1996 goto fail;
19121997 pgno = np->mp_pgno;
19131998 DPRINTF(("touched db %d page %"Z"u -> %"Z"u", DDBI(mc),
19141999 mp->mp_pgno, pgno));
1915 assert(mp->mp_pgno != pgno);
2000 mdb_cassert(mc, mp->mp_pgno != pgno);
19162001 mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno);
19172002 /* Update the parent page, if any, to point to the new page */
19182003 if (mc->mc_top) {
19332018 if (x <= dl[0].mid && dl[x].mid == pgno) {
19342019 if (mp != dl[x].mptr) { /* bad cursor? */
19352020 mc->mc_flags &= ~(C_INITIALIZED|C_EOF);
2021 txn->mt_flags |= MDB_TXN_ERROR;
19362022 return MDB_CORRUPTED;
19372023 }
19382024 return 0;
19392025 }
19402026 }
1941 assert(dl[0].mid < MDB_IDL_UM_MAX);
2027 mdb_cassert(mc, dl[0].mid < MDB_IDL_UM_MAX);
19422028 /* No - copy it */
19432029 np = mdb_page_malloc(txn, 1);
19442030 if (!np)
19452031 return ENOMEM;
19462032 mid.mid = pgno;
19472033 mid.mptr = np;
1948 mdb_mid2l_insert(dl, &mid);
2034 rc = mdb_mid2l_insert(dl, &mid);
2035 mdb_cassert(mc, rc == 0);
19492036 } else {
19502037 return 0;
19512038 }
19812068 }
19822069 }
19832070 return 0;
2071
2072 fail:
2073 txn->mt_flags |= MDB_TXN_ERROR;
2074 return rc;
19842075 }
19852076
19862077 int
21782269
21792270 if (!(env->me_flags & MDB_LIVE_READER)) {
21802271 rc = mdb_reader_pid(env, Pidset, pid);
2181 if (rc) {
2182 UNLOCK_MUTEX_R(env);
2272 if (rc)
21832273 return rc;
2184 }
21852274 env->me_flags |= MDB_LIVE_READER;
21862275 }
21872276
25422631 return rc;
25432632 pglast = head_id = *(txnid_t *)key.mv_data;
25442633 total_room = head_room = 0;
2545 assert(pglast <= env->me_pglast);
2634 mdb_tassert(txn, pglast <= env->me_pglast);
25462635 rc = mdb_cursor_del(&mc, 0);
25472636 if (rc)
25482637 return rc;
26372726 ssize_t len = (ssize_t)(data.mv_size / sizeof(MDB_ID)) - 1;
26382727 MDB_ID save;
26392728
2640 assert(len >= 0 && id <= env->me_pglast);
2729 mdb_tassert(txn, len >= 0 && id <= env->me_pglast);
26412730 key.mv_data = &id;
26422731 if (len > mop_len) {
26432732 len = mop_len;
28032892 unsigned int i;
28042893 MDB_env *env;
28052894
2806 assert(txn != NULL);
2807 assert(txn->mt_env != NULL);
2895 if (txn == NULL || txn->mt_env == NULL)
2896 return EINVAL;
28082897
28092898 if (txn->mt_child) {
28102899 rc = mdb_txn_commit(txn->mt_child);
29123001 if (yp == dst[x].mid)
29133002 free(dst[x--].mptr);
29143003 }
2915 assert(i == x);
3004 mdb_tassert(txn, i == x);
29163005 dst[0].mid = len;
29173006 free(txn->mt_u.dirty_list);
29183007 parent->mt_dirty_room = txn->mt_dirty_room;
31443233 #else
31453234 int r2;
31463235 #endif
3147
3148 assert(txn != NULL);
3149 assert(txn->mt_env != NULL);
31503236
31513237 toggle = txn->mt_txnid & 1;
31523238 DPRINTF(("writing meta page %d for root page %"Z"u",
34693555 env->me_mapsize = minsize;
34703556 }
34713557
3472 rc = mdb_env_map(env, meta.mm_address, newenv);
3558 rc = mdb_env_map(env, meta.mm_address, newenv || env->me_mapsize != meta.mm_mapsize);
34733559 if (rc)
34743560 return rc;
34753561
34813567 return i;
34823568 }
34833569 }
3570
34843571 env->me_maxfree_1pg = (env->me_psize - PAGEHDRSZ) / sizeof(pgno_t) - 1;
3485 env->me_nodemax = (env->me_psize - PAGEHDRSZ) / MDB_MINKEYS;
3486
3572 env->me_nodemax = (((env->me_psize - PAGEHDRSZ) / MDB_MINKEYS) & -2)
3573 - sizeof(indx_t);
3574 #if !(MDB_MAXKEYSIZE)
3575 env->me_maxkey = env->me_nodemax - (NODESIZE + sizeof(MDB_db));
3576 #endif
34873577 env->me_maxpg = env->me_mapsize / env->me_psize;
3578
34883579 #if MDB_DEBUG
34893580 {
34903581 int toggle = mdb_env_pick_meta(env);
39844075 #define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY|MDB_WRITEMAP| \
39854076 MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD)
39864077
4078 #if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE|CHANGELESS)
4079 # error "Persistent DB flags & env flags overlap, but both go in mm_flags"
4080 #endif
4081
39874082 int
39884083 mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode)
39894084 {
44684563
44694564 nkeys = NUMKEYS(mp);
44704565
4471 #if MDB_DEBUG
4472 {
4473 pgno_t pgno;
4474 COPY_PGNO(pgno, mp->mp_pgno);
44754566 DPRINTF(("searching %u keys in %s %spage %"Z"u",
44764567 nkeys, IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "",
4477 pgno));
4478 }
4479 #endif
4480
4481 assert(nkeys > 0);
4568 mdb_dbg_pgno(mp)));
44824569
44834570 low = IS_LEAF(mp) ? 0 : 1;
44844571 high = nkeys - 1;
45424629 node = NODEPTR(mp, i);
45434630 }
45444631 if (exactp)
4545 *exactp = (rc == 0);
4632 *exactp = (rc == 0 && nkeys > 0);
45464633 /* store the key index */
45474634 mc->mc_ki[mc->mc_top] = i;
45484635 if (i >= nkeys)
45924679 DDBI(mc), (void *) mc));
45934680
45944681 if (mc->mc_snum >= CURSOR_STACK) {
4595 assert(mc->mc_snum < CURSOR_STACK);
4682 mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
45964683 return MDB_CURSOR_FULL;
45974684 }
45984685
46524739 p = (MDB_page *)(env->me_map + env->me_psize * pgno);
46534740 } else {
46544741 DPRINTF(("page %"Z"u not found", pgno));
4655 assert(p != NULL);
4742 txn->mt_flags |= MDB_TXN_ERROR;
46564743 return MDB_PAGE_NOTFOUND;
46574744 }
46584745
46784765 indx_t i;
46794766
46804767 DPRINTF(("branch page %"Z"u has %u keys", mp->mp_pgno, NUMKEYS(mp)));
4681 assert(NUMKEYS(mp) > 1);
4768 mdb_cassert(mc, NUMKEYS(mp) > 1);
46824769 DPRINTF(("found index 0 to page %"Z"u", NODEPGNO(NODEPTR(mp, 0))));
46834770
46844771 if (flags & (MDB_PS_FIRST|MDB_PS_LAST)) {
46934780 else {
46944781 i = mc->mc_ki[mc->mc_top];
46954782 if (!exact) {
4696 assert(i > 0);
4783 mdb_cassert(mc, i > 0);
46974784 i--;
46984785 }
46994786 }
47004787 DPRINTF(("following index %u for key [%s]", i, DKEY(key)));
47014788 }
47024789
4703 assert(i < NUMKEYS(mp));
4790 mdb_cassert(mc, i < NUMKEYS(mp));
47044791 node = NODEPTR(mp, i);
47054792
47064793 if ((rc = mdb_page_get(mc->mc_txn, NODEPGNO(node), &mp, NULL)) != 0)
47204807 if (!IS_LEAF(mp)) {
47214808 DPRINTF(("internal error, index points to a %02X page!?",
47224809 mp->mp_flags));
4810 mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
47234811 return MDB_CORRUPTED;
47244812 }
47254813
48144902 }
48154903 }
48164904
4817 assert(root > 1);
4905 mdb_cassert(mc, root > 1);
48184906 if (!mc->mc_pg[0] || mc->mc_pg[0]->mp_pgno != root)
48194907 if ((rc = mdb_page_get(mc->mc_txn, root, &mc->mc_pg[0], NULL)) != 0)
48204908 return rc;
48844972 iy = dl[x];
48854973 dl[x] = ix;
48864974 } else {
4887 assert(x > 1);
4975 mdb_cassert(mc, x > 1);
48884976 j = ++(dl[0].mid);
48894977 dl[j] = ix; /* Unsorted. OK when MDB_TXN_ERROR. */
48904978 txn->mt_flags |= MDB_TXN_ERROR;
49525040 int exact = 0;
49535041 DKBUF;
49545042
4955 assert(key);
4956 assert(data);
5043 if (key == NULL || data == NULL)
5044 return EINVAL;
5045
49575046 DPRINTF(("===> get db %u key [%s]", dbi, DKEY(key)));
49585047
49595048 if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
49615050
49625051 if (txn->mt_flags & MDB_TXN_ERROR)
49635052 return MDB_BAD_TXN;
4964
4965 if (key->mv_size > MDB_MAXKEYSIZE) {
4966 return MDB_BAD_VALSIZE;
4967 }
49685053
49695054 mdb_cursor_init(&mc, txn, dbi, &mx);
49705055 return mdb_cursor_set(&mc, key, data, MDB_SET, &exact);
50115096 DPRINTF(("just moving to %s index key %u",
50125097 move_right ? "right" : "left", mc->mc_ki[mc->mc_top]));
50135098 }
5014 assert(IS_BRANCH(mc->mc_pg[mc->mc_top]));
5099 mdb_cassert(mc, IS_BRANCH(mc->mc_pg[mc->mc_top]));
50155100
50165101 indx = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
50175102 if ((rc = mdb_page_get(mc->mc_txn, NODEPGNO(indx), &mp, NULL)) != 0) {
50395124 return MDB_NOTFOUND;
50405125 }
50415126
5042 assert(mc->mc_flags & C_INITIALIZED);
5127 mdb_cassert(mc, mc->mc_flags & C_INITIALIZED);
50435128
50445129 mp = mc->mc_pg[mc->mc_top];
50455130
50615146 }
50625147 }
50635148
5064 DPRINTF(("cursor_next: top page is %"Z"u in cursor %p", mp->mp_pgno, (void *) mc));
5149 DPRINTF(("cursor_next: top page is %"Z"u in cursor %p",
5150 mdb_dbg_pgno(mp), (void *) mc));
50655151 if (mc->mc_flags & C_DEL)
50665152 goto skip;
50675153
50785164
50795165 skip:
50805166 DPRINTF(("==> cursor points to page %"Z"u with %u keys, key index %u",
5081 mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top]));
5167 mdb_dbg_pgno(mp), NUMKEYS(mp), mc->mc_ki[mc->mc_top]));
50825168
50835169 if (IS_LEAF2(mp)) {
50845170 key->mv_size = mc->mc_db->md_pad;
50865172 return MDB_SUCCESS;
50875173 }
50885174
5089 assert(IS_LEAF(mp));
5175 mdb_cassert(mc, IS_LEAF(mp));
50905176 leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
50915177
50925178 if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
51155201 MDB_node *leaf;
51165202 int rc;
51175203
5118 assert(mc->mc_flags & C_INITIALIZED);
5204 mdb_cassert(mc, mc->mc_flags & C_INITIALIZED);
51195205
51205206 mp = mc->mc_pg[mc->mc_top];
51215207
51375223 }
51385224 }
51395225
5140 DPRINTF(("cursor_prev: top page is %"Z"u in cursor %p", mp->mp_pgno, (void *) mc));
5226 DPRINTF(("cursor_prev: top page is %"Z"u in cursor %p",
5227 mdb_dbg_pgno(mp), (void *) mc));
51415228
51425229 if (mc->mc_ki[mc->mc_top] == 0) {
51435230 DPUTS("=====> move to prev sibling page");
51535240 mc->mc_flags &= ~C_EOF;
51545241
51555242 DPRINTF(("==> cursor points to page %"Z"u with %u keys, key index %u",
5156 mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top]));
5243 mdb_dbg_pgno(mp), NUMKEYS(mp), mc->mc_ki[mc->mc_top]));
51575244
51585245 if (IS_LEAF2(mp)) {
51595246 key->mv_size = mc->mc_db->md_pad;
51615248 return MDB_SUCCESS;
51625249 }
51635250
5164 assert(IS_LEAF(mp));
5251 mdb_cassert(mc, IS_LEAF(mp));
51655252 leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
51665253
51675254 if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
51925279 MDB_node *leaf = NULL;
51935280 DKBUF;
51945281
5195 assert(mc);
5196 assert(key);
51975282 if (key->mv_size == 0)
51985283 return MDB_BAD_VALSIZE;
51995284
52965381 return rc;
52975382
52985383 mp = mc->mc_pg[mc->mc_top];
5299 assert(IS_LEAF(mp));
5384 mdb_cassert(mc, IS_LEAF(mp));
53005385
53015386 set2:
53025387 leaf = mdb_node_search(mc, key, exactp);
53105395 if ((rc = mdb_cursor_sibling(mc, 1)) != MDB_SUCCESS)
53115396 return rc; /* no entries matched */
53125397 mp = mc->mc_pg[mc->mc_top];
5313 assert(IS_LEAF(mp));
5398 mdb_cassert(mc, IS_LEAF(mp));
53145399 leaf = NODEPTR(mp, 0);
53155400 }
53165401
53525437 if (op == MDB_GET_BOTH || rc > 0)
53535438 return MDB_NOTFOUND;
53545439 rc = 0;
5440 *data = d2;
53555441 }
53565442
53575443 } else {
53855471 if (rc != MDB_SUCCESS)
53865472 return rc;
53875473 }
5388 assert(IS_LEAF(mc->mc_pg[mc->mc_top]));
5474 mdb_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]));
53895475
53905476 leaf = NODEPTR(mc->mc_pg[mc->mc_top], 0);
53915477 mc->mc_flags |= C_INITIALIZED;
54315517 if (rc != MDB_SUCCESS)
54325518 return rc;
54335519 }
5434 assert(IS_LEAF(mc->mc_pg[mc->mc_top]));
5520 mdb_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]));
54355521
54365522 }
54375523 mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]) - 1;
54685554 int exact = 0;
54695555 int (*mfunc)(MDB_cursor *mc, MDB_val *key, MDB_val *data);
54705556
5471 assert(mc);
5557 if (mc == NULL)
5558 return EINVAL;
54725559
54735560 if (mc->mc_txn->mt_flags & MDB_TXN_ERROR)
54745561 return MDB_BAD_TXN;
55205607 case MDB_SET_RANGE:
55215608 if (key == NULL) {
55225609 rc = EINVAL;
5523 } else if (key->mv_size > MDB_MAXKEYSIZE) {
5524 rc = MDB_BAD_VALSIZE;
5525 } else if (op == MDB_SET_RANGE)
5526 rc = mdb_cursor_set(mc, key, data, op, NULL);
5527 else
5528 rc = mdb_cursor_set(mc, key, data, op, &exact);
5610 } else {
5611 rc = mdb_cursor_set(mc, key, data, op,
5612 op == MDB_SET_RANGE ? NULL : &exact);
5613 }
55295614 break;
55305615 case MDB_GET_MULTIPLE:
55315616 if (data == NULL || !(mc->mc_flags & C_INITIALIZED)) {
56625747 unsigned int flags)
56635748 {
56645749 enum { MDB_NO_ROOT = MDB_LAST_ERRCODE+10 }; /* internal code */
5665 MDB_env *env = mc->mc_txn->mt_env;
5750 MDB_env *env;
56665751 MDB_node *leaf = NULL;
5667 MDB_val xdata, *rdata, dkey;
5752 MDB_page *fp, *mp;
5753 uint16_t fp_flags;
5754 MDB_val xdata, *rdata, dkey, olddata;
56685755 MDB_db dummy;
5669 int do_sub = 0, insert = 0;
5756 int do_sub = 0, insert;
56705757 unsigned int mcount = 0, dcount = 0, nospill;
56715758 size_t nsize;
56725759 int rc, rc2;
5673 char dbuf[MDB_MAXKEYSIZE+1];
56745760 unsigned int nflags;
56755761 DKBUF;
5762
5763 if (mc == NULL || key == NULL)
5764 return EINVAL;
5765
5766 env = mc->mc_txn->mt_env;
56765767
56775768 /* Check this first so counter will always be zero on any
56785769 * early failures.
56905781 if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR))
56915782 return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
56925783
5693 if (flags != MDB_CURRENT && (key->mv_size == 0 || key->mv_size > MDB_MAXKEYSIZE))
5784 if (flags != MDB_CURRENT && key->mv_size-1 >= ENV_MAXKEY(env))
56945785 return MDB_BAD_VALSIZE;
56955786
5696 if (F_ISSET(mc->mc_db->md_flags, MDB_DUPSORT) && data->mv_size > MDB_MAXKEYSIZE)
5787 #if SIZE_MAX > MAXDATASIZE
5788 if (data->mv_size > ((mc->mc_db->md_flags & MDB_DUPSORT) ? ENV_MAXKEY(env) : MAXDATASIZE))
56975789 return MDB_BAD_VALSIZE;
5698
5699 #if SIZE_MAX > MAXDATASIZE
5700 if (data->mv_size > MAXDATASIZE)
5790 #else
5791 if ((mc->mc_db->md_flags & MDB_DUPSORT) && data->mv_size > ENV_MAXKEY(env))
57015792 return MDB_BAD_VALSIZE;
57025793 #endif
57035794
57815872 return rc2;
57825873 }
57835874
5784 /* The key already exists */
5785 if (rc == MDB_SUCCESS) {
5786 MDB_page *fp, *mp;
5787 MDB_val olddata;
5788
5875 insert = rc;
5876 if (insert) {
5877 /* The key does not exist */
5878 DPRINTF(("inserting key at index %i", mc->mc_ki[mc->mc_top]));
5879 if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
5880 LEAFSIZE(key, data) > env->me_nodemax)
5881 {
5882 /* Too big for a node, insert in sub-DB */
5883 fp_flags = P_LEAF|P_DIRTY;
5884 fp = env->me_pbuf;
5885 fp->mp_pad = data->mv_size; /* used if MDB_DUPFIXED */
5886 fp->mp_lower = fp->mp_upper = olddata.mv_size = PAGEHDRSZ;
5887 goto prep_subDB;
5888 }
5889 } else {
57895890 /* there's only a key anyway, so this is a no-op */
57905891 if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
57915892 unsigned int ksize = mc->mc_db->md_pad;
58055906
58065907 /* DB has dups? */
58075908 if (F_ISSET(mc->mc_db->md_flags, MDB_DUPSORT)) {
5909 /* Prepare (sub-)page/sub-DB to accept the new item,
5910 * if needed. fp: old sub-page or a header faking
5911 * it. mp: new (sub-)page. offset: growth in page
5912 * size. xdata: node data with new page or DB.
5913 */
5914 unsigned i, offset = 0;
58085915 mp = fp = xdata.mv_data = env->me_pbuf;
58095916 mp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno;
58105917
58145921 if (flags == MDB_CURRENT)
58155922 goto current;
58165923
5817 dkey = olddata;
58185924 #if UINT_MAX < SIZE_MAX
5819 if (mc->mc_dbx->md_dcmp == mdb_cmp_int && dkey.mv_size == sizeof(size_t))
5925 if (mc->mc_dbx->md_dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t))
58205926 #ifdef MISALIGNED_OK
58215927 mc->mc_dbx->md_dcmp = mdb_cmp_long;
58225928 #else
58245930 #endif
58255931 #endif
58265932 /* if data matches, skip it */
5827 if (!mc->mc_dbx->md_dcmp(data, &dkey)) {
5933 if (!mc->mc_dbx->md_dcmp(data, &olddata)) {
58285934 if (flags & MDB_NODUPDATA)
58295935 rc = MDB_KEYEXIST;
58305936 else if (flags & MDB_MULTIPLE)
58345940 return rc;
58355941 }
58365942
5837 /* create a fake page for the dup items */
5838 memcpy(dbuf, dkey.mv_data, dkey.mv_size);
5839 dkey.mv_data = dbuf;
5943 /* Back up original data item */
5944 dkey.mv_size = olddata.mv_size;
5945 dkey.mv_data = memcpy(fp+1, olddata.mv_data, olddata.mv_size);
5946
5947 /* Make sub-page header for the dup items, with dummy body */
58405948 fp->mp_flags = P_LEAF|P_DIRTY|P_SUBP;
58415949 fp->mp_lower = PAGEHDRSZ;
58425950 xdata.mv_size = PAGEHDRSZ + dkey.mv_size + data->mv_size;
58495957 (dkey.mv_size & 1) + (data->mv_size & 1);
58505958 }
58515959 fp->mp_upper = xdata.mv_size;
5960 olddata.mv_size = fp->mp_upper; /* pretend olddata is fp */
58525961 } else if (leaf->mn_flags & F_SUBDATA) {
58535962 /* Data is on sub-DB, just store it */
58545963 flags |= F_DUPDATA|F_SUBDATA;
58555964 goto put_sub;
58565965 } else {
5857 /* See if we need to convert from fake page to subDB */
5858 unsigned int offset;
5859 unsigned int i;
5860 uint16_t fp_flags;
5861
5966 /* Data is on sub-page */
58625967 fp = olddata.mv_data;
58635968 switch (flags) {
58645969 default:
58655970 if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
5866 offset = NODESIZE + sizeof(indx_t) + data->mv_size;
5867 offset += offset & 1;
5971 offset = EVEN(NODESIZE + sizeof(indx_t) +
5972 data->mv_size);
58685973 break;
58695974 }
58705975 offset = fp->mp_pad;
58805985 flags |= F_DUPDATA;
58815986 goto put_sub;
58825987 }
5883 fp_flags = fp->mp_flags;
58845988 xdata.mv_size = olddata.mv_size + offset;
5885 if (NODESIZE + sizeof(indx_t) + NODEKSZ(leaf) + xdata.mv_size
5886 >= env->me_nodemax) {
5887 /* yes, convert it */
5989 }
5990
5991 fp_flags = fp->mp_flags;
5992 if (NODESIZE + NODEKSZ(leaf) + xdata.mv_size > env->me_nodemax) {
5993 /* Too big for a sub-page, convert to sub-DB */
5994 fp_flags &= ~P_SUBP;
5995 prep_subDB:
58885996 if (mc->mc_db->md_flags & MDB_DUPFIXED) {
5997 fp_flags |= P_LEAF2;
58895998 dummy.md_pad = fp->mp_pad;
58905999 dummy.md_flags = MDB_DUPFIXED;
58916000 if (mc->mc_db->md_flags & MDB_INTEGERDUP)
59066015 offset = env->me_psize - olddata.mv_size;
59076016 flags |= F_DUPDATA|F_SUBDATA;
59086017 dummy.md_root = mp->mp_pgno;
5909 fp_flags &= ~P_SUBP;
5910 }
6018 }
6019 if (mp != fp) {
59116020 mp->mp_flags = fp_flags | P_DIRTY;
59126021 mp->mp_pad = fp->mp_pad;
59136022 mp->mp_lower = fp->mp_lower;
59146023 mp->mp_upper = fp->mp_upper + offset;
5915 if (IS_LEAF2(fp)) {
6024 if (fp_flags & P_LEAF2) {
59166025 memcpy(METADATA(mp), METADATA(fp), NUMKEYS(fp) * fp->mp_pad);
59176026 } else {
59186027 memcpy((char *)mp + mp->mp_upper, (char *)fp + fp->mp_upper,
59256034 rdata = &xdata;
59266035 flags |= F_DUPDATA;
59276036 do_sub = 1;
5928 mdb_node_del(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], 0);
6037 if (!insert)
6038 mdb_node_del(mc, 0);
59296039 goto new_sub;
59306040 }
59316041 current:
59656075 return ENOMEM;
59666076 id2.mid = pg;
59676077 id2.mptr = np;
5968 mdb_mid2l_insert(mc->mc_txn->mt_u.dirty_list, &id2);
6078 rc = mdb_mid2l_insert(mc->mc_txn->mt_u.dirty_list, &id2);
6079 mdb_cassert(mc, rc == 0);
59696080 if (!(flags & MDB_RESERVE)) {
59706081 /* Copy end of page, adjusting alignment so
59716082 * compiler may copy words instead of bytes.
60016112 memcpy(NODEKEY(leaf), key->mv_data, key->mv_size);
60026113 goto done;
60036114 }
6004 mdb_node_del(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], 0);
6115 mdb_node_del(mc, 0);
60056116 mc->mc_db->md_entries--;
6006 } else {
6007 DPRINTF(("inserting key at index %i", mc->mc_ki[mc->mc_top]));
6008 insert = 1;
60096117 }
60106118
60116119 rdata = data;
62446352 size_t sz;
62456353
62466354 sz = LEAFSIZE(key, data);
6247 if (sz >= env->me_nodemax) {
6355 if (sz > env->me_nodemax) {
62486356 /* put on overflow page */
62496357 sz -= data->mv_size - sizeof(pgno_t);
62506358 }
6251 sz += sz & 1;
6252
6253 return sz + sizeof(indx_t);
6359
6360 return EVEN(sz + sizeof(indx_t));
62546361 }
62556362
62566363 /** Calculate the size of a branch node.
62696376 size_t sz;
62706377
62716378 sz = INDXSIZE(key);
6272 if (sz >= env->me_nodemax) {
6379 if (sz > env->me_nodemax) {
62736380 /* put on overflow page */
62746381 /* not implemented */
62756382 /* sz -= key->size - sizeof(pgno_t); */
63066413 MDB_page *ofp = NULL; /* overflow page */
63076414 DKBUF;
63086415
6309 assert(mp->mp_upper >= mp->mp_lower);
6416 mdb_cassert(mc, mp->mp_upper >= mp->mp_lower);
63106417
63116418 DPRINTF(("add to %s %spage %"Z"u index %i, data size %"Z"u key size %"Z"u [%s]",
63126419 IS_LEAF(mp) ? "leaf" : "branch",
63136420 IS_SUBP(mp) ? "sub-" : "",
6314 mp->mp_pgno, indx, data ? data->mv_size : 0,
6421 mdb_dbg_pgno(mp), indx, data ? data->mv_size : 0,
63156422 key ? key->mv_size : 0, key ? DKEY(key) : "null"));
63166423
63176424 if (IS_LEAF2(mp)) {
63346441 if (key != NULL)
63356442 node_size += key->mv_size;
63366443 if (IS_LEAF(mp)) {
6337 assert(data);
6444 mdb_cassert(mc, data);
63386445 if (F_ISSET(flags, F_BIGDATA)) {
63396446 /* Data already on overflow page. */
63406447 node_size += sizeof(pgno_t);
6341 } else if (node_size + data->mv_size >= mc->mc_txn->mt_env->me_nodemax) {
6448 } else if (node_size + data->mv_size > mc->mc_txn->mt_env->me_nodemax) {
63426449 int ovpages = OVPAGES(data->mv_size, mc->mc_txn->mt_env->me_psize);
63436450 int rc;
63446451 /* Put data on overflow page. */
63456452 DPRINTF(("data size is %"Z"u, node would be %"Z"u, put data on overflow page",
63466453 data->mv_size, node_size+data->mv_size));
6347 node_size += sizeof(pgno_t) + (node_size & 1);
6454 node_size = EVEN(node_size + sizeof(pgno_t));
63486455 if ((ssize_t)node_size > room)
63496456 goto full;
63506457 if ((rc = mdb_page_new(mc, P_OVERFLOW, ovpages, &ofp)))
63566463 node_size += data->mv_size;
63576464 }
63586465 }
6359 node_size += node_size & 1;
6466 node_size = EVEN(node_size);
63606467 if ((ssize_t)node_size > room)
63616468 goto full;
63626469
63676474
63686475 /* Adjust free space offsets. */
63696476 ofs = mp->mp_upper - node_size;
6370 assert(ofs >= mp->mp_lower + sizeof(indx_t));
6477 mdb_cassert(mc, ofs >= mp->mp_lower + sizeof(indx_t));
63716478 mp->mp_ptrs[indx] = ofs;
63726479 mp->mp_upper = ofs;
63736480 mp->mp_lower += sizeof(indx_t);
63856492 memcpy(NODEKEY(node), key->mv_data, key->mv_size);
63866493
63876494 if (IS_LEAF(mp)) {
6388 assert(key);
6495 mdb_cassert(mc, key);
63896496 if (ofp == NULL) {
63906497 if (F_ISSET(flags, F_BIGDATA))
63916498 memcpy(node->mn_data + key->mv_size, data->mv_data,
64096516
64106517 full:
64116518 DPRINTF(("not enough room in page %"Z"u, got %u ptrs",
6412 mp->mp_pgno, NUMKEYS(mp)));
6519 mdb_dbg_pgno(mp), NUMKEYS(mp)));
64136520 DPRINTF(("upper-lower = %u - %u = %"Z"d", mp->mp_upper,mp->mp_lower,room));
64146521 DPRINTF(("node size = %"Z"u", node_size));
6522 mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
64156523 return MDB_PAGE_FULL;
64166524 }
64176525
64226530 * part of a #MDB_DUPFIXED database.
64236531 */
64246532 static void
6425 mdb_node_del(MDB_page *mp, indx_t indx, int ksize)
6426 {
6533 mdb_node_del(MDB_cursor *mc, int ksize)
6534 {
6535 MDB_page *mp = mc->mc_pg[mc->mc_top];
6536 indx_t indx = mc->mc_ki[mc->mc_top];
64276537 unsigned int sz;
64286538 indx_t i, j, numkeys, ptr;
64296539 MDB_node *node;
64306540 char *base;
64316541
6432 #if MDB_DEBUG
6433 {
6434 pgno_t pgno;
6435 COPY_PGNO(pgno, mp->mp_pgno);
64366542 DPRINTF(("delete node %u on %s page %"Z"u", indx,
6437 IS_LEAF(mp) ? "leaf" : "branch", pgno));
6438 }
6439 #endif
6440 assert(indx < NUMKEYS(mp));
6543 IS_LEAF(mp) ? "leaf" : "branch", mdb_dbg_pgno(mp)));
6544 numkeys = NUMKEYS(mp);
6545 mdb_cassert(mc, indx < numkeys);
64416546
64426547 if (IS_LEAF2(mp)) {
6443 int x = NUMKEYS(mp) - 1 - indx;
6548 int x = numkeys - 1 - indx;
64446549 base = LEAF2KEY(mp, indx, ksize);
64456550 if (x)
64466551 memmove(base, base + ksize, x * ksize);
64576562 else
64586563 sz += NODEDSZ(node);
64596564 }
6460 sz += sz & 1;
6565 sz = EVEN(sz);
64616566
64626567 ptr = mp->mp_ptrs[indx];
6463 numkeys = NUMKEYS(mp);
64646568 for (i = j = 0; i < numkeys; i++) {
64656569 if (i != indx) {
64666570 mp->mp_ptrs[j] = mp->mp_ptrs[i];
64876591 MDB_node *node;
64886592 MDB_page *sp, *xp;
64896593 char *base;
6490 int osize, nsize;
6491 int delta;
6594 int nsize, delta;
64926595 indx_t i, numkeys, ptr;
64936596
64946597 node = NODEPTR(mp, indx);
64956598 sp = (MDB_page *)NODEDATA(node);
6496 osize = NODEDSZ(node);
6497
6498 delta = sp->mp_upper - sp->mp_lower;
6499 SETDSZ(node, osize - delta);
6599 delta = SIZELEFT(sp);
65006600 xp = (MDB_page *)((char *)sp + delta);
65016601
65026602 /* shift subpage upward */
65036603 if (IS_LEAF2(sp)) {
65046604 nsize = NUMKEYS(sp) * sp->mp_pad;
6605 if (nsize & 1)
6606 return; /* do not make the node uneven-sized */
65056607 memmove(METADATA(xp), METADATA(sp), nsize);
65066608 } else {
65076609 int i;
6508 nsize = osize - sp->mp_upper;
65096610 numkeys = NUMKEYS(sp);
65106611 for (i=numkeys-1; i>=0; i--)
65116612 xp->mp_ptrs[i] = sp->mp_ptrs[i] - delta;
65156616 xp->mp_flags = sp->mp_flags;
65166617 xp->mp_pad = sp->mp_pad;
65176618 COPY_PGNO(xp->mp_pgno, mp->mp_pgno);
6619
6620 nsize = NODEDSZ(node) - delta;
6621 SETDSZ(node, nsize);
65186622
65196623 /* shift lower nodes upward */
65206624 ptr = mp->mp_ptrs[indx];
66276731 mc->mc_pg[0] = 0;
66286732 mc->mc_flags = 0;
66296733 if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
6630 assert(mx != NULL);
6734 mdb_tassert(txn, mx != NULL);
66316735 mc->mc_xcursor = mx;
66326736 mdb_xcursor_init0(mc);
66336737 } else {
67356839 MDB_dbi
67366840 mdb_cursor_dbi(MDB_cursor *mc)
67376841 {
6738 assert(mc != NULL);
67396842 return mc->mc_dbi;
67406843 }
67416844
6742 /** Replace the key for a node with a new key.
6845 /** Replace the key for a branch node with a new key.
67436846 * @param[in] mc Cursor pointing to the node to operate on.
67446847 * @param[in] key The new key to use.
67456848 * @return 0 on success, non-zero on failure.
67516854 MDB_node *node;
67526855 char *base;
67536856 size_t len;
6754 int delta, delta0;
6857 int delta, ksize, oksize;
67556858 indx_t ptr, i, numkeys, indx;
67566859 DKBUF;
67576860
67626865 #if MDB_DEBUG
67636866 {
67646867 MDB_val k2;
6765 char kbuf2[(MDB_MAXKEYSIZE*2+1)];
6868 char kbuf2[DKBUF_MAXKEYSIZE*2+1];
67666869 k2.mv_data = NODEKEY(node);
67676870 k2.mv_size = node->mn_ksize;
67686871 DPRINTF(("update key %u (ofs %u) [%s] to [%s] on page %"Z"u",
67736876 }
67746877 #endif
67756878
6776 delta0 = delta = key->mv_size - node->mn_ksize;
6777
6778 /* Must be 2-byte aligned. If new key is
6779 * shorter by 1, the shift will be skipped.
6780 */
6781 delta += (delta & 1);
6879 /* Sizes must be 2-byte aligned. */
6880 ksize = EVEN(key->mv_size);
6881 oksize = EVEN(node->mn_ksize);
6882 delta = ksize - oksize;
6883
6884 /* Shift node contents if EVEN(key length) changed. */
67826885 if (delta) {
67836886 if (delta > 0 && SIZELEFT(mp) < delta) {
67846887 pgno_t pgno;
67856888 /* not enough space left, do a delete and split */
67866889 DPRINTF(("Not enough room, delta = %d, splitting...", delta));
67876890 pgno = NODEPGNO(node);
6788 mdb_node_del(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], 0);
6891 mdb_node_del(mc, 0);
67896892 return mdb_page_split(mc, key, NULL, pgno, MDB_SPLIT_REPLACE);
67906893 }
67916894
68046907 }
68056908
68066909 /* But even if no shift was needed, update ksize */
6807 if (delta0)
6910 if (node->mn_ksize != key->mv_size)
68086911 node->mn_ksize = key->mv_size;
68096912
68106913 if (key->mv_size)
68366939 return rc;
68376940
68386941 if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
6839 srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], 0); /* fake */
68406942 key.mv_size = csrc->mc_db->md_pad;
68416943 key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top], key.mv_size);
68426944 data.mv_size = 0;
68456947 flags = 0;
68466948 } else {
68476949 srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top]);
6848 assert(!((size_t)srcnode&1));
6950 mdb_cassert(csrc, !((size_t)srcnode & 1));
68496951 srcpg = NODEPGNO(srcnode);
68506952 flags = srcnode->mn_flags;
68516953 if (csrc->mc_ki[csrc->mc_top] == 0 && IS_BRANCH(csrc->mc_pg[csrc->mc_top])) {
69087010
69097011 /* Delete the node from the source page.
69107012 */
6911 mdb_node_del(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top], key.mv_size);
7013 mdb_node_del(csrc, key.mv_size);
69127014
69137015 {
69147016 /* Adjust other cursors pointing to mp */
69567058 csrc->mc_ki[csrc->mc_top] = 0;
69577059 rc = mdb_update_key(csrc, &nullkey);
69587060 csrc->mc_ki[csrc->mc_top] = ix;
6959 assert(rc == MDB_SUCCESS);
7061 mdb_cassert(csrc, rc == MDB_SUCCESS);
69607062 }
69617063 }
69627064
69847086 cdst->mc_ki[cdst->mc_top] = 0;
69857087 rc = mdb_update_key(cdst, &nullkey);
69867088 cdst->mc_ki[cdst->mc_top] = ix;
6987 assert(rc == MDB_SUCCESS);
7089 mdb_cassert(csrc, rc == MDB_SUCCESS);
69887090 }
69897091 }
69907092
70107112 DPRINTF(("merging page %"Z"u into %"Z"u", csrc->mc_pg[csrc->mc_top]->mp_pgno,
70117113 cdst->mc_pg[cdst->mc_top]->mp_pgno));
70127114
7013 assert(csrc->mc_snum > 1); /* can't merge root page */
7014 assert(cdst->mc_snum > 1);
7115 mdb_cassert(csrc, csrc->mc_snum > 1); /* can't merge root page */
7116 mdb_cassert(csrc, cdst->mc_snum > 1);
70157117
70167118 /* Mark dst as dirty. */
70177119 if ((rc = mdb_page_touch(cdst)))
70667168
70677169 /* Unlink the src page from parent and add to free list.
70687170 */
7069 mdb_node_del(csrc->mc_pg[csrc->mc_top-1], csrc->mc_ki[csrc->mc_top-1], 0);
7070 if (csrc->mc_ki[csrc->mc_top-1] == 0) {
7171 csrc->mc_top--;
7172 mdb_node_del(csrc, 0);
7173 if (csrc->mc_ki[csrc->mc_top] == 0) {
70717174 key.mv_size = 0;
7072 csrc->mc_top--;
70737175 rc = mdb_update_key(csrc, &key);
7074 csrc->mc_top++;
7075 if (rc)
7176 if (rc) {
7177 csrc->mc_top++;
70767178 return rc;
7077 }
7179 }
7180 }
7181 csrc->mc_top++;
70787182
70797183 rc = mdb_midl_append(&csrc->mc_txn->mt_free_pgs,
70807184 csrc->mc_pg[csrc->mc_top]->mp_pgno);
71457249 MDB_cursor mn;
71467250
71477251 minkeys = 1 + (IS_BRANCH(mc->mc_pg[mc->mc_top]));
7148 #if MDB_DEBUG
7149 {
7150 pgno_t pgno;
7151 COPY_PGNO(pgno, mc->mc_pg[mc->mc_top]->mp_pgno);
71527252 DPRINTF(("rebalancing %s page %"Z"u (has %u keys, %.1f%% full)",
71537253 IS_LEAF(mc->mc_pg[mc->mc_top]) ? "leaf" : "branch",
7154 pgno, NUMKEYS(mc->mc_pg[mc->mc_top]),
7254 mdb_dbg_pgno(mc->mc_pg[mc->mc_top]), NUMKEYS(mc->mc_pg[mc->mc_top]),
71557255 (float)PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) / 10));
7156 }
7157 #endif
71587256
71597257 if (PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) >= FILL_THRESHOLD &&
71607258 NUMKEYS(mc->mc_pg[mc->mc_top]) >= minkeys) {
7161 #if MDB_DEBUG
7162 pgno_t pgno;
7163 COPY_PGNO(pgno, mc->mc_pg[mc->mc_top]->mp_pgno);
71647259 DPRINTF(("no need to rebalance page %"Z"u, above fill threshold",
7165 pgno));
7166 #endif
7260 mdb_dbg_pgno(mc->mc_pg[mc->mc_top])));
71677261 return MDB_SUCCESS;
71687262 }
71697263
72457339 * otherwise the tree is invalid.
72467340 */
72477341 ptop = mc->mc_top-1;
7248 assert(NUMKEYS(mc->mc_pg[ptop]) > 1);
7342 mdb_cassert(mc, NUMKEYS(mc->mc_pg[ptop]) > 1);
72497343
72507344 /* Leaf page fill factor is below the threshold.
72517345 * Try to move keys from left or right neighbor, or
73277421 (rc = mdb_ovpage_free(mc, omp)))
73287422 return rc;
73297423 }
7330 mdb_node_del(mp, ki, mc->mc_db->md_pad);
7424 mdb_node_del(mc, mc->mc_db->md_pad);
73317425 mc->mc_db->md_entries--;
73327426 rc = mdb_rebalance(mc);
73337427 if (rc != MDB_SUCCESS)
73347428 mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
73357429 else {
7336 MDB_cursor *m2;
7430 MDB_cursor *m2, *m3;
73377431 MDB_dbi dbi = mc->mc_dbi;
73387432
73397433 mp = mc->mc_pg[mc->mc_top];
73457439
73467440 /* Adjust other cursors pointing to mp */
73477441 for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
7348 if (m2 == mc || m2->mc_snum < mc->mc_snum)
7442 m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2;
7443 if (! (m2->mc_flags & m3->mc_flags & C_INITIALIZED))
73497444 continue;
7350 if (!(m2->mc_flags & C_INITIALIZED))
7445 if (m3 == mc || m3->mc_snum < mc->mc_snum)
73517446 continue;
7352 if (m2->mc_pg[mc->mc_top] == mp) {
7353 if (m2->mc_ki[mc->mc_top] >= ki) {
7354 m2->mc_flags |= C_DEL;
7355 if (m2->mc_ki[mc->mc_top] > ki)
7356 m2->mc_ki[mc->mc_top]--;
7447 if (m3->mc_pg[mc->mc_top] == mp) {
7448 if (m3->mc_ki[mc->mc_top] >= ki) {
7449 m3->mc_flags |= C_DEL;
7450 if (m3->mc_ki[mc->mc_top] > ki)
7451 m3->mc_ki[mc->mc_top]--;
73577452 }
7358 if (m2->mc_ki[mc->mc_top] >= nkeys)
7359 mdb_cursor_sibling(m2, 1);
7453 if (m3->mc_ki[mc->mc_top] >= nkeys)
7454 mdb_cursor_sibling(m3, 1);
73607455 }
73617456 }
73627457 mc->mc_flags |= C_DEL;
73767471 int rc, exact;
73777472 DKBUF;
73787473
7379 assert(key != NULL);
7474 if (key == NULL)
7475 return EINVAL;
73807476
73817477 DPRINTF(("====> delete db %u key [%s]", dbi, DKEY(key)));
73827478
73857481
73867482 if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR))
73877483 return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
7388
7389 if (key->mv_size > MDB_MAXKEYSIZE) {
7390 return MDB_BAD_VALSIZE;
7391 }
73927484
73937485 mdb_cursor_init(&mc, txn, dbi, &mx);
73947486
75577649 nsize = mdb_leaf_size(env, newkey, newdata);
75587650 else
75597651 nsize = mdb_branch_size(env, newkey);
7560 nsize += nsize & 1;
7652 nsize = EVEN(nsize);
75617653
75627654 /* grab a page to hold a temporary copy */
75637655 copy = mdb_page_malloc(mc->mc_txn, 1);
76147706 else
76157707 psize += NODEDSZ(node);
76167708 }
7617 psize += psize & 1;
7709 psize = EVEN(psize);
76187710 }
76197711 if (psize > pmax || i == k-j) {
76207712 split_indx = i + (j<0);
78257917 MDB_cursor mc;
78267918 MDB_xcursor mx;
78277919
7828 assert(key != NULL);
7829 assert(data != NULL);
7920 if (key == NULL || data == NULL)
7921 return EINVAL;
78307922
78317923 if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
78327924 return EINVAL;
78577949 return EINVAL;
78587950
78597951 *arg = env->me_flags;
7952 return MDB_SUCCESS;
7953 }
7954
7955 int
7956 mdb_env_set_userctx(MDB_env *env, void *ctx)
7957 {
7958 if (!env)
7959 return EINVAL;
7960 env->me_userctx = ctx;
7961 return MDB_SUCCESS;
7962 }
7963
7964 void *
7965 mdb_env_get_userctx(MDB_env *env)
7966 {
7967 return env ? env->me_userctx : NULL;
7968 }
7969
7970 int
7971 mdb_env_set_assert(MDB_env *env, MDB_assert_func *func)
7972 {
7973 if (!env)
7974 return EINVAL;
7975 #ifndef NDEBUG
7976 env->me_assert_func = func;
7977 #endif
78607978 return MDB_SUCCESS;
78617979 }
78627980
81298247 rc = mdb_page_get(txn, pg, &omp, NULL);
81308248 if (rc != 0)
81318249 return rc;
8132 assert(IS_OVERFLOW(omp));
8250 mdb_cassert(mc, IS_OVERFLOW(omp));
81338251 rc = mdb_midl_append_range(&txn->mt_free_pgs,
81348252 pg, omp->mp_pages);
81358253 if (rc)
82608378
82618379 int mdb_env_get_maxkeysize(MDB_env *env)
82628380 {
8263 return MDB_MAXKEYSIZE;
8381 return ENV_MAXKEY(env);
82648382 }
82658383
82668384 int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx)
82688386 unsigned int i, rdrs;
82698387 MDB_reader *mr;
82708388 char buf[64];
8271 int first = 1;
8389 int rc = 0, first = 1;
82728390
82738391 if (!env || !func)
82748392 return -1;
82798397 mr = env->me_txns->mti_readers;
82808398 for (i=0; i<rdrs; i++) {
82818399 if (mr[i].mr_pid) {
8282 size_t tid;
8283 int rc;
8284 tid = mr[i].mr_tid;
8285 if (mr[i].mr_txnid == (txnid_t)-1) {
8286 sprintf(buf, "%10d %"Z"x -\n", mr[i].mr_pid, tid);
8287 } else {
8288 sprintf(buf, "%10d %"Z"x %"Z"u\n", mr[i].mr_pid, tid, mr[i].mr_txnid);
8289 }
8400 txnid_t txnid = mr[i].mr_txnid;
8401 sprintf(buf, txnid == (txnid_t)-1 ?
8402 "%10d %"Z"x -\n" : "%10d %"Z"x %"Z"u\n",
8403 (int)mr[i].mr_pid, (size_t)mr[i].mr_tid, txnid);
82908404 if (first) {
82918405 first = 0;
8292 func(" pid thread txnid\n", ctx);
8406 rc = func(" pid thread txnid\n", ctx);
8407 if (rc < 0)
8408 break;
82938409 }
82948410 rc = func(buf, ctx);
82958411 if (rc < 0)
8296 return rc;
8412 break;
82978413 }
82988414 }
82998415 if (first) {
8300 func("(no active readers)\n", ctx);
8301 }
8302 return 0;
8416 rc = func("(no active readers)\n", ctx);
8417 }
8418 return rc;
83038419 }
83048420
83058421 /** Insert pid into list if not already present.
83608476 return ENOMEM;
83618477 pids[0] = 0;
83628478 mr = env->me_txns->mti_readers;
8363 j = 0;
83648479 for (i=0; i<rdrs; i++) {
83658480 if (mr[i].mr_pid && mr[i].mr_pid != env->me_pid) {
83668481 pid = mr[i].mr_pid;
44 mdb_copy \- LMDB environment copy tool
55 .SH SYNOPSIS
66 .B mdb_copy
7 .I srcpath\ [dstpath]
7 [\c
8 .BR \-n ]
9 .B srcpath
10 [\c
11 .BR dstpath ]
812 .SH DESCRIPTION
913 The
1014 .B mdb_copy
1822 for storing the backup. Otherwise, the backup will be
1923 written to stdout.
2024
25 .SH OPTIONS
26 .BR \-n
27 Open LDMB environment(s) which do not use subdirectories.
28
2129 .SH DIAGNOSTICS
2230 Exit status is zero if no errors occur.
2331 Errors result in a non-zero exit status and
3030 {
3131 int rc;
3232 MDB_env *env;
33 char *envname = argv[1];
33 const char *progname = argv[0], *act;
34 unsigned flags = MDB_RDONLY;
35
36 for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) {
37 if (argv[1][1] == 'n' && argv[1][2] == '\0')
38 flags |= MDB_NOSUBDIR;
39 else
40 argc = 0;
41 }
3442
3543 if (argc<2 || argc>3) {
36 fprintf(stderr, "usage: %s srcpath [dstpath]\n", argv[0]);
44 fprintf(stderr, "usage: %s [-n] srcpath [dstpath]\n", progname);
3745 exit(EXIT_FAILURE);
3846 }
3947
4654 signal(SIGINT, sighandle);
4755 signal(SIGTERM, sighandle);
4856
57 act = "opening environment";
4958 rc = mdb_env_create(&env);
50
51 rc = mdb_env_open(env, envname, MDB_RDONLY, 0);
52 if (rc) {
53 printf("mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
54 } else {
59 if (rc == MDB_SUCCESS) {
60 rc = mdb_env_open(env, argv[1], flags, 0);
61 }
62 if (rc == MDB_SUCCESS) {
63 act = "copying";
5564 if (argc == 2)
5665 rc = mdb_env_copyfd(env, MDB_STDOUT);
5766 else
5867 rc = mdb_env_copy(env, argv[2]);
59 if (rc)
60 printf("mdb_env_copy failed, error %d %s\n", rc, mdb_strerror(rc));
6168 }
69 if (rc)
70 fprintf(stderr, "%s: %s failed, error %d (%s)\n",
71 progname, act, rc, mdb_strerror(rc));
6272 mdb_env_close(env);
6373
6474 return rc ? EXIT_FAILURE : EXIT_SUCCESS;
1919 #include <stdlib.h>
2020 #include <errno.h>
2121 #include <sys/types.h>
22 #include <assert.h>
2322 #include "midl.h"
2423
2524 /** @defgroup internal MDB Internals
149148 num = (num + num/4 + (256 + 2)) & -256;
150149 if (!(ids = realloc(ids-1, num * sizeof(MDB_ID))))
151150 return ENOMEM;
152 *ids++ = num -= 2;
151 *ids++ = num - 2;
153152 *idp = ids;
154153 }
155154 return 0;
305304 unsigned x, i;
306305
307306 x = mdb_mid2l_search( ids, id->mid );
308 assert( x > 0 );
309307
310308 if( x < 1 ) {
311309 /* internal error */