From 589370d880fb7272ca6e8ff8fc6efec4cb51d8e2 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 2 Jul 2013 02:19:17 -0700 Subject: [PATCH] Tweaks for MDB_MULTIPLE Terminate loop on intermediate failures, return count of written items, document usage. --- libraries/liblmdb/lmdb.h | 12 +++++++++++- libraries/liblmdb/mdb.c | 30 ++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/libraries/liblmdb/lmdb.h b/libraries/liblmdb/lmdb.h index 2076eb3..9f00a04 100644 --- a/libraries/liblmdb/lmdb.h +++ b/libraries/liblmdb/lmdb.h @@ -309,7 +309,7 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel #define MDB_APPEND 0x20000 /** Duplicate data is being appended, don't split full pages. */ #define MDB_APPENDDUP 0x40000 -/** Store multiple data items in one call. */ +/** Store multiple data items in one call. Only for #MDB_DUPFIXED. */ #define MDB_MULTIPLE 0x80000 /* @} */ @@ -1210,6 +1210,16 @@ int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data, * correct order. Loading unsorted keys with this flag will cause * data corruption. *
  • #MDB_APPENDDUP - as above, but for sorted dup data. + *
  • #MDB_MULTIPLE - store multiple contiguous data elements in a + * single request. This flag may only be specified if the database + * was opened with #MDB_DUPFIXED. The \b data argument must be an + * array of two MDB_vals. The mv_size of the first MDB_val must be + * the size of a single data element. The mv_data of the first MDB_val + * must point to the beginning of the array of contiguous data elements. + * The mv_size of the second MDB_val must be the count of the number + * of data elements to store. On return this field will be set to + * the count of the number of elements actually written. The mv_data + * of the second MDB_val is unused. * * @return A non-zero error value on failure and 0 on success. Some possible * errors are: diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 0badbbb..149a893 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -4969,7 +4969,7 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_page *fp; MDB_db dummy; int do_sub = 0, insert = 0; - unsigned int mcount = 0; + unsigned int mcount = 0, dcount; size_t nsize; int rc, rc2; MDB_pagebuf pbuf; @@ -4977,6 +4977,16 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, unsigned int nflags; DKBUF; + /* Check this first so counter will always be zero on any + * early failures. + */ + if (flags & MDB_MULTIPLE) { + dcount = data[1].mv_size; + data[1].mv_size = 0; + if (!F_ISSET(mc->mc_db->md_flags, MDB_DUPFIXED)) + return EINVAL; + } + if (F_ISSET(mc->mc_txn->mt_flags, MDB_TXN_RDONLY)) return EACCES; @@ -5340,8 +5350,8 @@ put_sub: } } } - /* we've done our job */ - dkey.mv_size = 0; + /* we've done our job */ + dkey.mv_size = 0; } if (flags & MDB_APPENDDUP) xflags |= MDB_APPEND; @@ -5357,12 +5367,16 @@ put_sub: if (!rc && !(flags & MDB_CURRENT)) mc->mc_db->md_entries++; if (flags & MDB_MULTIPLE) { - mcount++; - if (mcount < data[1].mv_size) { - data[0].mv_data = (char *)data[0].mv_data + data[0].mv_size; - leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - goto more; + if (!rc) { + mcount++; + if (mcount < dcount) { + data[0].mv_data = (char *)data[0].mv_data + data[0].mv_size; + leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); + goto more; + } } + /* let caller know how many succeeded, if any */ + data[1].mv_size = mcount; } } done: