]> git.sur5r.net Git - openldap/commitdiff
Check DB flags when refreshing a stale MDB DBI.
authorHallvard Furuseth <hallvard@openldap.org>
Tue, 19 Feb 2013 21:02:37 +0000 (22:02 +0100)
committerHallvard Furuseth <hallvard@openldap.org>
Tue, 19 Feb 2013 21:02:37 +0000 (22:02 +0100)
It's hairy to figure out when a DBI is valid. Catch destructive
user errors, and flags which another process changed under us.

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

index b91de4df96156d02cf6254adecfc6a87ff299b58..5b6ff6ef5834b158978c17fce7fb99b3faf1e429 100644 (file)
@@ -362,7 +362,9 @@ typedef enum MDB_cursor_op {
 #define MDB_PAGE_FULL  (-30786)
        /** Database contents grew beyond environment mapsize */
 #define MDB_MAP_RESIZED        (-30785)
-#define MDB_LAST_ERRCODE       MDB_MAP_RESIZED
+       /** Operation is incompatible with database */
+#define MDB_INCOMPATIBLE       (-30784)
+#define MDB_LAST_ERRCODE       MDB_INCOMPATIBLE
 /** @} */
 
 /** @brief Statistics for a database in the environment */
index c9dc1a5ee3afa4e0bfadc9b194340265f6d4ff53..f1b7480673e569e7553626aad2f4d676467b1142 100644 (file)
@@ -1056,6 +1056,7 @@ static char *const mdb_errstr[] = {
        "MDB_CURSOR_FULL: Internal error - cursor stack limit reached",
        "MDB_PAGE_FULL: Internal error - page has no more space",
        "MDB_MAP_RESIZED: Database contents grew beyond environment mapsize",
+       "MDB_INCOMPATIBLE: Operation is incompatible with database",
 };
 
 char *
@@ -4056,6 +4057,12 @@ mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags)
                                        if (!exact)
                                                return MDB_NOTFOUND;
                                        mdb_node_read(mc->mc_txn, leaf, &data);
+                                       /* The txn may not know this DBI, or another process may
+                                        * have dropped and recreated the DB with other flags.
+                                        */
+                                       if (mc->mc_db->md_flags != *(uint16_t *)
+                                               ((char *) data.mv_data + offsetof(MDB_db, md_flags)))
+                                               return MDB_INCOMPATIBLE;
                                        memcpy(mc->mc_db, data.mv_data, sizeof(MDB_db));
                                }
                                if (flags & MDB_PS_MODIFY)