]> git.sur5r.net Git - openldap/commitdiff
Tweaks for MDB_MULTIPLE
authorHoward Chu <hyc@symas.com>
Tue, 2 Jul 2013 09:19:17 +0000 (02:19 -0700)
committerHoward Chu <hyc@symas.com>
Tue, 2 Jul 2013 09:19:17 +0000 (02:19 -0700)
Terminate loop on intermediate failures, return count of written items,
document usage.

libraries/liblmdb/lmdb.h
libraries/liblmdb/mdb.c

index 2076eb35faccd0ca6803b24fea331db743dffc1d..9f00a04202eeda9889263f3a57e5b48fcff88ea1 100644 (file)
@@ -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.
         *      <li>#MDB_APPENDDUP - as above, but for sorted dup data.
+        *      <li>#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.
         * </ul>
         * @return A non-zero error value on failure and 0 on success. Some possible
         * errors are:
index 0badbbbf690ba5f53586cce6ea7f32aa65ca6178..149a893208193e6684556a589f4ab3f29c7ac585 100644 (file)
@@ -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: