From: Howard Chu Date: Wed, 3 Aug 2011 22:04:20 +0000 (-0700) Subject: More subdb stuff, add cursor_last() X-Git-Tag: OPENLDAP_REL_ENG_2_4_27~148^2~145 X-Git-Url: https://git.sur5r.net/?p=openldap;a=commitdiff_plain;h=1f3fdc811e3ce6a34bea15d3dd275fe01425a2a6 More subdb stuff, add cursor_last() --- diff --git a/libraries/libmdb/mdb.c b/libraries/libmdb/mdb.c index 87d531964f..d0e28d3215 100644 --- a/libraries/libmdb/mdb.c +++ b/libraries/libmdb/mdb.c @@ -223,13 +223,12 @@ typedef struct MDB_db { } MDB_db; typedef struct MDB_dbx { - char *md_name; + MDB_val md_name; MDB_cmp_func *md_cmp; /* user compare function */ MDB_cmp_func *md_dcmp; /* user dupsort function */ MDB_rel_func *md_rel; /* user relocate function */ MDB_db *md_db; MDB_page *md_page; - unsigned int md_ki; /* cursor index on parent page */ } MDB_dbx; struct MDB_txn { @@ -331,6 +330,8 @@ static int mdb_cursor_set(MDB_cursor *cursor, MDB_val *key, MDB_val *data, int *exactp); static int mdb_cursor_first(MDB_cursor *cursor, MDB_val *key, MDB_val *data); +static int mdb_cursor_last(MDB_cursor *cursor, + MDB_val *key, MDB_val *data); static size_t mdb_leaf_size(MDB_env *env, MDB_val *key, MDB_val *data); @@ -1372,7 +1373,10 @@ mdb_search_page_root(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, if (key == NULL) /* Initialize cursor to first page. */ i = 0; - else { + else if (key->mv_size > MAXKEYSIZE && key->mv_data == NULL) { + /* cursor to last page */ + i = NUMKEYS(mp)-1; + } else { int exact; node = mdb_search_node(txn, dbi, mp, key, &exact, &i); if (node == NULL) @@ -1458,12 +1462,22 @@ mdb_search_page(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, DPRINTF("root page has flags 0x%X", mpp->mp_page->mp_flags); - if (modify && !F_ISSET(mpp->mp_page->mp_flags, P_DIRTY)) { - mpp->mp_parent = NULL; - mpp->mp_pi = 0; - if ((rc = mdb_touch(txn, mpp))) - return rc; - txn->mt_dbxs[dbi].md_db->md_root = mpp->mp_page->mp_pgno; + if (modify) { + /* For sub-databases, update main root first */ + if (dbi && !F_ISSET(txn->mt_dbxs[dbi].md_page->mp_flags, P_DIRTY)) { + MDB_pageparent mp2; + rc = mdb_search_page(txn, 0, &txn->mt_dbxs[dbi].md_name, + NULL, 1, &mp2); + if (rc) + return rc; + } + if (!F_ISSET(mpp->mp_page->mp_flags, P_DIRTY)) { + mpp->mp_parent = NULL; + mpp->mp_pi = 0; + if ((rc = mdb_touch(txn, mpp))) + return rc; + txn->mt_dbxs[dbi].md_db->md_root = mpp->mp_page->mp_pgno; + } } return mdb_search_page_root(txn, dbi, key, cursor, modify, mpp); @@ -1698,6 +1712,32 @@ mdb_cursor_first(MDB_cursor *cursor, MDB_val *key, MDB_val *data) return mdb_set_key(leaf, key); } +static int +mdb_cursor_last(MDB_cursor *cursor, MDB_val *key, MDB_val *data) +{ + int rc; + MDB_pageparent mpp; + MDB_node *leaf; + MDB_val lkey; + + lkey.mv_size = MAXKEYSIZE+1; + lkey.mv_data = NULL; + + rc = mdb_search_page(cursor->mc_txn, cursor->mc_dbi, &lkey, cursor, 0, &mpp); + if (rc != MDB_SUCCESS) + return rc; + assert(IS_LEAF(mpp.mp_page)); + + leaf = NODEPTR(mpp.mp_page, NUMKEYS(mpp.mp_page)-1); + cursor->mc_initialized = 1; + cursor->mc_eof = 1; + + if (data && (rc = mdb_read_data(cursor->mc_txn->mt_env, leaf, data)) != MDB_SUCCESS) + return rc; + + return mdb_set_key(leaf, key); +} + int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data, MDB_cursor_op op) @@ -1730,6 +1770,11 @@ mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data, cursor_pop_page(cursor); rc = mdb_cursor_first(cursor, key, data); break; + case MDB_LAST: + while (CURSOR_TOP(cursor) != NULL) + cursor_pop_page(cursor); + rc = mdb_cursor_last(cursor, key, data); + break; default: DPRINTF("unhandled/unimplemented cursor operation %u", op); rc = EINVAL; @@ -2561,6 +2606,7 @@ int mdb_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi) MDB_val key, data; MDB_dbi i; int rc; + size_t len; /* main DB? */ if (!name) { @@ -2569,15 +2615,17 @@ int mdb_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi) } /* Is the DB already open? */ + len = strlen(name); for (i=0; imt_numdbs; i++) { - if (!strcmp(name, txn->mt_dbxs[i].md_name)) { + if (len == txn->mt_dbxs[i].md_name.mv_size && + !strcmp(name, txn->mt_dbxs[i].md_name.mv_data)) { *dbi = i; return MDB_SUCCESS; } } /* Find the DB info */ - key.mv_size = strlen(name); + key.mv_size = len; key.mv_data = (void *)name; rc = mdb_get(txn, 0, &key, &data); @@ -2606,7 +2654,8 @@ int mdb_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi) return ENOMEM; txn->mt_dbxs = p1; } - txn->mt_dbxs[txn->mt_numdbs].md_name = strdup(name); + txn->mt_dbxs[txn->mt_numdbs].md_name.mv_data = strdup(name); + txn->mt_dbxs[txn->mt_numdbs].md_name.mv_size = len; txn->mt_dbxs[txn->mt_numdbs].md_cmp = NULL; txn->mt_dbxs[txn->mt_numdbs].md_dcmp = NULL; txn->mt_dbxs[txn->mt_numdbs].md_rel = NULL; @@ -2637,6 +2686,7 @@ void mdb_close(MDB_txn *txn, MDB_dbi dbi) { if (dbi >= txn->mt_numdbs) return; - free(txn->mt_dbxs[dbi].md_name); - txn->mt_dbxs[dbi].md_name = NULL; + free(txn->mt_dbxs[dbi].md_name.mv_data); + txn->mt_dbxs[dbi].md_name.mv_data = NULL; + txn->mt_dbxs[dbi].md_name.mv_size = 0; }