]> git.sur5r.net Git - openldap/commitdiff
Begin reimplementing basic ops as cursor ops
authorHoward Chu <hyc@symas.com>
Sun, 4 Sep 2011 00:24:39 +0000 (17:24 -0700)
committerHoward Chu <hyc@symas.com>
Mon, 5 Sep 2011 04:33:57 +0000 (21:33 -0700)
libraries/libmdb/mdb.c
libraries/libmdb/mdb.h
libraries/libmdb/midl.h

index 4eff6ff8ed8fe658c7af030fec4352c172ddcca4..9bc59f5118387a5d6b4fd4155d89b608cb31d55a 100644 (file)
 #endif
 #endif
 
-#define ULONG          unsigned long
 typedef ULONG          pgno_t;
 
 #ifndef DEBUG
@@ -517,7 +516,7 @@ static int           mdb_cursor_first(MDB_cursor *cursor,
 static int              mdb_cursor_last(MDB_cursor *cursor,
                            MDB_val *key, MDB_val *data);
 
-static void            mdb_xcursor_init0(MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx);
+static void            mdb_xcursor_init0(MDB_cursor *mc);
 static void            mdb_xcursor_init1(MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx,
                                        MDB_page *mp, MDB_node *node);
 static void            mdb_xcursor_fini(MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx);
@@ -2251,9 +2250,9 @@ int
 mdb_get(MDB_txn *txn, MDB_dbi dbi,
     MDB_val *key, MDB_val *data)
 {
-       int              rc, exact;
-       MDB_node        *leaf;
-       MDB_pageparent mpp;
+       MDB_cursor      mc;
+       MDB_xcursor     mx;
+       int exact;
        DKBUF;
 
        assert(key);
@@ -2267,36 +2266,16 @@ mdb_get(MDB_txn *txn, MDB_dbi dbi,
                return EINVAL;
        }
 
-       if ((rc = mdb_search_page(txn, dbi, key, NULL, 0, &mpp)) != MDB_SUCCESS)
-               return rc;
-
-       leaf = mdb_search_node(txn, dbi, mpp.mp_page, key, &exact, NULL);
-       if (leaf && exact) {
-               /* Return first duplicate data item */
-               if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
-                       MDB_xcursor mx;
-
-                       mdb_xcursor_init0(txn, dbi, &mx);
-                       mdb_xcursor_init1(txn, dbi, &mx, mpp.mp_page, leaf);
-                       rc = mdb_search_page(&mx.mx_txn, mx.mx_cursor.mc_dbi, NULL, NULL, 0, &mpp);
-                       if (rc != MDB_SUCCESS)
-                               return rc;
-                       if (IS_LEAF2(mpp.mp_page)) {
-                               data->mv_size = txn->mt_dbs[dbi].md_pad;
-                               data->mv_data = LEAF2KEY(mpp.mp_page, 0, data->mv_size);
-                       } else {
-                               leaf = NODEPTR(mpp.mp_page, 0);
-                               data->mv_size = NODEKSZ(leaf);
-                               data->mv_data = NODEKEY(leaf);
-                       }
-               } else {
-                       rc = mdb_read_data(txn, leaf, data);
-               }
+       mc.mc_txn = txn;
+       mc.mc_dbi = dbi;
+       mc.mc_initialized = 0;
+       if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
+               mc.mc_xcursor = &mx;
+               mdb_xcursor_init0(&mc);
        } else {
-               rc = MDB_NOTFOUND;
+               mc.mc_xcursor = NULL;
        }
-
-       return rc;
+       return mdb_cursor_set(&mc, key, data, MDB_SET, &exact);
 }
 
 static int
@@ -2813,6 +2792,61 @@ fetchm:
        return rc;
 }
 
+static int
+mdb_cursor_touch(MDB_cursor *cursor)
+{
+       MDB_pageparent mpp;
+       unsigned int i;
+       int rc;
+
+       mpp.mp_parent = NULL;
+       mpp.mp_pi = 0;
+       for(i=0; i<cursor->mc_snum; i++) {
+               mpp.mp_page = cursor->mc_stack[i].mp_page;
+               if (!F_ISSET(mpp.mp_page->mp_flags, P_DIRTY)) {
+                       rc = mdb_touch(cursor->mc_txn, cursor->mc_dbi, &mpp);
+                       if (rc) return rc;
+                       cursor->mc_stack[i].mp_page = mpp.mp_page;
+               }
+               mpp.mp_parent = mpp.mp_page;
+               mpp.mp_pi = cursor->mc_stack[i].mp_ki;
+       }
+       if (cursor->mc_xcursor)
+               return mdb_cursor_touch(&cursor->mc_xcursor->mx_cursor);
+       return MDB_SUCCESS;
+}
+
+int
+mdb_cursor_put(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
+    unsigned int flags)
+{
+       MDB_ppage       *top;
+       MDB_node        *leaf;
+       int rc, exact;
+
+       if (flags == MDB_NODUPDATA) {
+               rc = mdb_cursor_set(cursor, key, data, MDB_GET_BOTH, &exact);
+               if (rc == 0)
+                       return MDB_KEYEXIST;
+               if (rc != MDB_NOTFOUND)
+                       return rc;
+       } else if (flags != MDB_CURRENT) {
+               rc = mdb_cursor_set(cursor, key, NULL, MDB_SET, &exact);
+               if (flags == MDB_NOOVERWRITE && rc == 0)
+                       return MDB_KEYEXIST;
+               if (rc != MDB_NOTFOUND)
+                       return rc;
+       } else if (!cursor->mc_initialized) {
+               return EINVAL;
+       }
+       /* Cursor is positioned, now make sure all pages are writable */
+       rc = mdb_cursor_touch(cursor);
+       if (rc) return rc;
+
+       top = CURSOR_TOP(cursor);
+
+}
+
 /* Allocate a page and initialize it
  */
 static MDB_dpage *
@@ -3027,17 +3061,18 @@ mdb_del_node(MDB_page *mp, indx_t indx, int ksize)
 }
 
 static void
-mdb_xcursor_init0(MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
+mdb_xcursor_init0(MDB_cursor *mc)
 {
+       MDB_xcursor *mx = mc->mc_xcursor;
        MDB_dbi dbn;
 
-       mx->mx_txn = *txn;
+       mx->mx_txn = *mc->mc_txn;
        mx->mx_txn.mt_dbxs = mx->mx_dbxs;
        mx->mx_txn.mt_dbs = mx->mx_dbs;
-       mx->mx_dbxs[0] = txn->mt_dbxs[0];
-       mx->mx_dbxs[1] = txn->mt_dbxs[1];
-       if (dbi > 1) {
-               mx->mx_dbxs[2] = txn->mt_dbxs[dbi];
+       mx->mx_dbxs[0] = mc->mc_txn->mt_dbxs[0];
+       mx->mx_dbxs[1] = mc->mc_txn->mt_dbxs[1];
+       if (mc->mc_dbi > 1) {
+               mx->mx_dbxs[2] = mc->mc_txn->mt_dbxs[mc->mc_dbi];
                dbn = 2;
        } else {
                dbn = 1;
@@ -3111,7 +3146,7 @@ mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **ret)
                if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
                        MDB_xcursor *mx = (MDB_xcursor *)(cursor + 1);
                        cursor->mc_xcursor = mx;
-                       mdb_xcursor_init0(txn, dbi, mx);
+                       mdb_xcursor_init0(cursor);
                }
        } else {
                return ENOMEM;
@@ -3522,10 +3557,15 @@ mdb_del(MDB_txn *txn, MDB_dbi dbi,
        }
 
        if (!IS_LEAF2(mpp.mp_page) && F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+               MDB_cursor mc;
                MDB_xcursor mx;
                MDB_pageparent mp2;
 
-               mdb_xcursor_init0(txn, dbi, &mx);
+               mc.mc_txn = txn;
+               mc.mc_dbi = dbi;
+               mc.mc_initialized = 0;
+               mc.mc_xcursor = &mx;
+               mdb_xcursor_init0(&mc);
                mdb_xcursor_init1(txn, dbi, &mx, mpp.mp_page, leaf);
                if (data) {
                        rc = mdb_del(&mx.mx_txn, mx.mx_cursor.mc_dbi, data, NULL);
@@ -3946,11 +3986,16 @@ new_sub:
                 * DB are all zero size.
                 */
                if (do_sub) {
+                       MDB_cursor mc;
                        MDB_xcursor mx;
 
                        leaf = NODEPTR(mpp.mp_page, ki);
 put_sub:
-                       mdb_xcursor_init0(txn, dbi, &mx);
+                       mc.mc_txn = txn;
+                       mc.mc_dbi = dbi;
+                       mc.mc_initialized = 0;
+                       mc.mc_xcursor = &mx;
+                       mdb_xcursor_init0(&mc);
                        mdb_xcursor_init1(txn, dbi, &mx, mpp.mp_page, leaf);
                        xdata.mv_size = 0;
                        xdata.mv_data = "";
@@ -3978,6 +4023,10 @@ int
 mdb_put(MDB_txn *txn, MDB_dbi dbi,
     MDB_val *key, MDB_val *data, unsigned int flags)
 {
+       MDB_cursor mc;
+       MDB_xcursor mx;
+       int rc;
+
        assert(key != NULL);
        assert(data != NULL);
 
@@ -3995,7 +4044,28 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
        if ((flags & (MDB_NOOVERWRITE|MDB_NODUPDATA)) != flags)
                return EINVAL;
 
-       return mdb_put0(txn, dbi, key, data, flags);
+       mc.mc_txn = txn;
+       mc.mc_dbi = dbi;
+       mc.mc_snum = 0;
+       mc.mc_initialized = 0;
+       mc.mc_eof = 0;
+       if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
+               mc.mc_xcursor = &mx;
+               mdb_xcursor_init0(&mc);
+       } else {
+               mc.mc_xcursor = NULL;
+       }
+       rc = mdb_cursor_put(&mc, key, data, flags);
+       if (mc.mc_xcursor) {
+               MDB_ppage *top;
+               MDB_node *leaf;
+               mdb_xcursor_fini(txn, dbi, &mx);
+               top = CURSOR_TOP(&mc);
+               leaf = NODEPTR(top->mp_page, top->mp_ki);
+               memcpy(NODEDATA(leaf), &mx.mx_txn.mt_dbs[mx.mx_cursor.mc_dbi],
+                       sizeof(MDB_db));
+       }
+       return rc;
 }
 
 int
index 0f564c5d8229da92ff8762e71cd76dfbbd352d89..e35a6a2c2fd29d015a465f0cce6e04c4a117fd89 100644 (file)
@@ -133,7 +133,7 @@ typedef int  (MDB_cmp_func)(const MDB_val *a, const MDB_val *b);
  */
 typedef void (MDB_rel_func)(void *newptr, void *oldptr, size_t size);
 
-/** @defgroup  mdb_env environment flags
+/** @defgroup  mdb_env Environment Flags
  *     @{
  */
        /** mmap at a fixed address */
@@ -144,7 +144,7 @@ typedef void (MDB_rel_func)(void *newptr, void *oldptr, size_t size);
 #define MDB_RDONLY             0x20000
 /** @} */
 
-/**    @defgroup       mdb_open        database flags
+/**    @defgroup       mdb_open        Database Flags
  *     @{
  */
        /** use reverse string keys */
@@ -161,15 +161,18 @@ typedef void (MDB_rel_func)(void *newptr, void *oldptr, size_t size);
 #define MDB_CREATE             0x40000
 /** @} */
 
-/**    @defgroup mdb_put       mdb_put flags
+/**    @defgroup mdb_put       Write Flags
  *     @{
  */
-/** For mdb_put: don't write if the key already exists. */
+/** For put: Don't write if the key already exists. */
 #define MDB_NOOVERWRITE        0x10
-/** For mdb_put: don't write if the key and data pair already exist.
- * Only for #MDB_DUPSORT
+/** Only for #MDB_DUPSORT<br>
+ * For put: don't write if the key and data pair already exist.<br>
+ * For mdb_cursor_del: remove all duplicate data items.
  */
 #define MDB_NODUPDATA  0x20
+/** For mdb_cursor_put: overwrite the current key/data pair */
+#define MDB_CURRENT    0x40
 /*     @} */
 
 /** Cursor operations */
@@ -723,8 +726,6 @@ int  mdb_del(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data);
        /** Create a cursor handle.
         * Cursors are associated with a specific transaction and database and
         * may not span threads.
-        * @todo Cursors only support read operations. Support for cursor_put() and
-        * cursor_del() needs to be added.
         * @param[in] txn A transaction handle returned by #mdb_txn_begin()
         * @param[in] dbi A database handle returned by #mdb_open()
         * @param[out] cursor Address where the new #MDB_cursor handle will be stored
index a08046308c6de8b6d46cd724b043d122852028e6..1e6c3c38437818ac087f017829e0d875eea30bfa 100644 (file)
 /** @defgroup internal MDB Internals
  *     @{
  */
+       /**     ULONG should be the largest integer type supported on a machine.
+        * It should be equal to the size of a pointer.
+        */
+#define ULONG          unsigned long
 /** @defgroup idls     ID List Management
  *     @{
  */
-       /** An ID should be the largest integer type supported on a machine.
+       /** A generic ID number. These were entryIDs in back-bdb.
         */
-#define        ID      unsigned long
+typedef ULONG ID;
 
        /** An IDL is an ID List, a sorted array of IDs. The first
         * element of the array is a counter for how many actual