LCOV - code coverage report
Current view: top level - lib/ldb/ldb_mdb - ldb_mdb.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 355 490 72.4 %
Date: 2024-06-13 04:01:37 Functions: 30 34 88.2 %

          Line data    Source code
       1             : /*
       2             :    ldb database library using mdb back end
       3             : 
       4             :    Copyright (C) Jakub Hrozek 2014
       5             :    Copyright (C) Catalyst.Net Ltd 2017
       6             : 
       7             :      ** NOTE! The following LGPL license applies to the ldb
       8             :      ** library. This does NOT imply that all of Samba is released
       9             :      ** under the LGPL
      10             : 
      11             :    This library is free software; you can redistribute it and/or
      12             :    modify it under the terms of the GNU Lesser General Public
      13             :    License as published by the Free Software Foundation; either
      14             :    version 3 of the License, or (at your option) any later version.
      15             : 
      16             :    This library is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      19             :    Lesser General Public License for more details.
      20             : 
      21             :    You should have received a copy of the GNU Lesser General Public
      22             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include "ldb_mdb.h"
      26             : #include "../ldb_key_value/ldb_kv.h"
      27             : #include "include/dlinklist.h"
      28             : 
      29             : #define MDB_URL_PREFIX          "mdb://"
      30             : #define MDB_URL_PREFIX_SIZE     (sizeof(MDB_URL_PREFIX)-1)
      31             : 
      32             : #define LDB_MDB_MAX_KEY_LENGTH 511
      33             : 
      34             : #define GIGABYTE (1024*1024*1024)
      35             : 
      36    72175568 : int ldb_mdb_err_map(int lmdb_err)
      37             : {
      38    72175568 :         switch (lmdb_err) {
      39    72131391 :         case MDB_SUCCESS:
      40    72131391 :                 return LDB_SUCCESS;
      41           0 :         case EIO:
      42           0 :                 return LDB_ERR_OPERATIONS_ERROR;
      43             : #ifdef EBADE
      44          53 :         case EBADE:
      45             : #endif
      46             :         case MDB_INCOMPATIBLE:
      47             :         case MDB_CORRUPTED:
      48             :         case MDB_INVALID:
      49          53 :                 return LDB_ERR_UNAVAILABLE;
      50           0 :         case MDB_BAD_TXN:
      51             :         case MDB_BAD_VALSIZE:
      52             : #ifdef MDB_BAD_DBI
      53             :         case MDB_BAD_DBI:
      54             : #endif
      55             :         case MDB_PANIC:
      56             :         case EINVAL:
      57           0 :                 return LDB_ERR_PROTOCOL_ERROR;
      58           0 :         case MDB_MAP_FULL:
      59             :         case MDB_DBS_FULL:
      60             :         case MDB_READERS_FULL:
      61             :         case MDB_TLS_FULL:
      62             :         case MDB_TXN_FULL:
      63             :         case EAGAIN:
      64           0 :                 return LDB_ERR_BUSY;
      65         608 :         case MDB_KEYEXIST:
      66         608 :                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
      67       43516 :         case MDB_NOTFOUND:
      68             :         case ENOENT:
      69       43516 :                 return LDB_ERR_NO_SUCH_OBJECT;
      70           0 :         case EACCES:
      71           0 :                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
      72           0 :         default:
      73           0 :                 break;
      74             :         }
      75           0 :         return LDB_ERR_OTHER;
      76             : }
      77             : 
      78             : #define ldb_mdb_error(ldb, ecode) lmdb_error_at(ldb, ecode, __FILE__, __LINE__)
      79       22062 : static int lmdb_error_at(struct ldb_context *ldb,
      80             :                          int ecode,
      81             :                          const char *file,
      82             :                          int line)
      83             : {
      84       22062 :         int ldb_err = ldb_mdb_err_map(ecode);
      85       22062 :         char *reason = mdb_strerror(ecode);
      86       22062 :         ldb_asprintf_errstring(ldb,
      87             :                                "(%d) - %s at %s:%d",
      88             :                                ecode,
      89             :                                reason,
      90             :                                file,
      91             :                                line);
      92       22062 :         return ldb_err;
      93             : }
      94             : 
      95   177194611 : static bool lmdb_transaction_active(struct ldb_kv_private *ldb_kv)
      96             : {
      97   177194611 :         return ldb_kv->lmdb_private->txlist != NULL;
      98             : }
      99             : 
     100   131967316 : static MDB_txn *lmdb_trans_get_tx(struct lmdb_trans *ltx)
     101             : {
     102   131967316 :         if (ltx == NULL) {
     103    71350849 :                 return NULL;
     104             :         }
     105             : 
     106    60616467 :         return ltx->tx;
     107             : }
     108             : 
     109      747381 : static void trans_push(struct lmdb_private *lmdb, struct lmdb_trans *ltx)
     110             : {
     111      747381 :         if (lmdb->txlist) {
     112      344712 :                 talloc_steal(lmdb->txlist, ltx);
     113             :         }
     114             : 
     115      747381 :         DLIST_ADD(lmdb->txlist, ltx);
     116      747381 : }
     117             : 
     118      747381 : static void trans_finished(struct lmdb_private *lmdb, struct lmdb_trans *ltx)
     119             : {
     120      747381 :         DLIST_REMOVE(lmdb->txlist, ltx);
     121      747381 :         talloc_free(ltx);
     122      747381 : }
     123             : 
     124             : 
     125   132856492 : static struct lmdb_trans *lmdb_private_trans_head(struct lmdb_private *lmdb)
     126             : {
     127             :         struct lmdb_trans *ltx;
     128             : 
     129   132856492 :         ltx = lmdb->txlist;
     130   132856492 :         return ltx;
     131             : }
     132             : 
     133             : 
     134   126939228 : static MDB_txn *get_current_txn(struct lmdb_private *lmdb)
     135             : {
     136   126939228 :         MDB_txn *txn = NULL;
     137             : 
     138   126939228 :         txn = lmdb_trans_get_tx(lmdb_private_trans_head(lmdb));
     139   126939228 :         if (txn != NULL) {
     140    55991048 :                 return txn;
     141             :         }
     142    70948180 :         if (lmdb->read_txn != NULL) {
     143    70948180 :                 return lmdb->read_txn;
     144             :         }
     145           0 :         lmdb->error = MDB_BAD_TXN;
     146           0 :         ldb_set_errstring(lmdb->ldb, __location__":No active transaction\n");
     147           0 :         return NULL;
     148             : }
     149             : 
     150     4124136 : static int lmdb_store(struct ldb_kv_private *ldb_kv,
     151             :                       struct ldb_val key,
     152             :                       struct ldb_val data,
     153             :                       int flags)
     154             : {
     155     4124136 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     156             :         MDB_val mdb_key;
     157             :         MDB_val mdb_data;
     158             :         int mdb_flags;
     159     4124136 :         MDB_txn *txn = NULL;
     160     4124136 :         MDB_dbi dbi = 0;
     161             : 
     162     4124136 :         if (ldb_kv->read_only) {
     163           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     164             :         }
     165             : 
     166     4124136 :         txn = lmdb_trans_get_tx(lmdb_private_trans_head(lmdb));
     167     4124136 :         if (txn == NULL) {
     168           0 :                 ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction");
     169           0 :                 lmdb->error = MDB_PANIC;
     170           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     171             :         }
     172             : 
     173     4124136 :         lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi);
     174     4124136 :         if (lmdb->error != MDB_SUCCESS) {
     175           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     176             :         }
     177             : 
     178     4124136 :         mdb_key.mv_size = key.length;
     179     4124136 :         mdb_key.mv_data = key.data;
     180             : 
     181     4124136 :         mdb_data.mv_size = data.length;
     182     4124136 :         mdb_data.mv_data = data.data;
     183             : 
     184     4124136 :         if (flags == TDB_INSERT) {
     185      216841 :                 mdb_flags = MDB_NOOVERWRITE;
     186     3907295 :         } else if (flags == TDB_MODIFY) {
     187             :                 /*
     188             :                  * Modifying a record, ensure that it exists.
     189             :                  * This mimics the TDB semantics
     190             :                  */
     191             :                 MDB_val value;
     192     1608986 :                 lmdb->error = mdb_get(txn, dbi, &mdb_key, &value);
     193     1608986 :                 if (lmdb->error != MDB_SUCCESS) {
     194           0 :                         return ldb_mdb_error(lmdb->ldb, lmdb->error);
     195             :                 }
     196     1608986 :                 mdb_flags = 0;
     197             :         } else {
     198     2298309 :                 mdb_flags = 0;
     199             :         }
     200             : 
     201     4124136 :         lmdb->error = mdb_put(txn, dbi, &mdb_key, &mdb_data, mdb_flags);
     202     4124136 :         if (lmdb->error != MDB_SUCCESS) {
     203         304 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     204             :         }
     205             : 
     206     4123832 :         return ldb_mdb_err_map(lmdb->error);
     207             : }
     208             : 
     209      156571 : static int lmdb_delete(struct ldb_kv_private *ldb_kv, struct ldb_val key)
     210             : {
     211      156571 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     212             :         MDB_val mdb_key;
     213      156571 :         MDB_txn *txn = NULL;
     214      156571 :         MDB_dbi dbi = 0;
     215             : 
     216      156571 :         if (ldb_kv->read_only) {
     217           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     218             :         }
     219             : 
     220      156571 :         txn = lmdb_trans_get_tx(lmdb_private_trans_head(lmdb));
     221      156571 :         if (txn == NULL) {
     222           0 :                 ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction");
     223           0 :                 lmdb->error = MDB_PANIC;
     224           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     225             :         }
     226             : 
     227      156571 :         lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi);
     228      156571 :         if (lmdb->error != MDB_SUCCESS) {
     229           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     230             :         }
     231             : 
     232      156571 :         mdb_key.mv_size = key.length;
     233      156571 :         mdb_key.mv_data = key.data;
     234             : 
     235      156571 :         lmdb->error = mdb_del(txn, dbi, &mdb_key, NULL);
     236      156571 :         if (lmdb->error != MDB_SUCCESS) {
     237       21758 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     238             :         }
     239      134813 :         return ldb_mdb_err_map(lmdb->error);
     240             : }
     241             : 
     242        5604 : static int lmdb_traverse_fn(struct ldb_kv_private *ldb_kv,
     243             :                             ldb_kv_traverse_fn fn,
     244             :                             void *ctx)
     245             : {
     246        5604 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     247             :         MDB_val mdb_key;
     248             :         MDB_val mdb_data;
     249        5604 :         MDB_txn *txn = NULL;
     250        5604 :         MDB_dbi dbi = 0;
     251        5604 :         MDB_cursor *cursor = NULL;
     252             :         int ret;
     253             : 
     254        5604 :         txn = get_current_txn(lmdb);
     255        5604 :         if (txn == NULL) {
     256           0 :                 ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction");
     257           0 :                 lmdb->error = MDB_PANIC;
     258           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     259             :         }
     260             : 
     261        5604 :         lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi);
     262        5604 :         if (lmdb->error != MDB_SUCCESS) {
     263           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     264             :         }
     265             : 
     266        5604 :         lmdb->error = mdb_cursor_open(txn, dbi, &cursor);
     267        5604 :         if (lmdb->error != MDB_SUCCESS) {
     268           0 :                 goto done;
     269             :         }
     270             : 
     271     6384619 :         while ((lmdb->error = mdb_cursor_get(
     272             :                         cursor, &mdb_key,
     273       85312 :                         &mdb_data, MDB_NEXT)) == MDB_SUCCESS) {
     274             : 
     275    12661934 :                 struct ldb_val key = {
     276     6373553 :                         .length = mdb_key.mv_size,
     277     6373553 :                         .data = mdb_key.mv_data,
     278             :                 };
     279    12661934 :                 struct ldb_val data = {
     280     6373553 :                         .length = mdb_data.mv_size,
     281     6373553 :                         .data = mdb_data.mv_data,
     282             :                 };
     283             : 
     284     6373553 :                 ret = fn(ldb_kv, key, data, ctx);
     285     6373553 :                 if (ret != 0) {
     286             :                         /*
     287             :                          * NOTE: This DOES NOT set lmdb->error!
     288             :                          *
     289             :                          * This means that the caller will get success.
     290             :                          * This matches TDB traverse behaviour, where callbacks
     291             :                          * may terminate the traverse, but do not change the
     292             :                          * return code from success.
     293             :                          *
     294             :                          * Callers SHOULD store their own error codes.
     295             :                          */
     296           2 :                         goto done;
     297             :                 }
     298             :         }
     299        5602 :         if (lmdb->error == MDB_NOTFOUND) {
     300        5602 :                 lmdb->error = MDB_SUCCESS;
     301             :         }
     302        5464 : done:
     303        5604 :         if (cursor != NULL) {
     304        5604 :                 mdb_cursor_close(cursor);
     305             :         }
     306             : 
     307        5604 :         if (lmdb->error != MDB_SUCCESS) {
     308           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     309             :         }
     310        5604 :         return ldb_mdb_err_map(lmdb->error);
     311             : }
     312             : 
     313           0 : static int lmdb_update_in_iterate(struct ldb_kv_private *ldb_kv,
     314             :                                   struct ldb_val key,
     315             :                                   struct ldb_val key2,
     316             :                                   struct ldb_val data,
     317             :                                   void *state)
     318             : {
     319           0 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     320             :         struct ldb_val copy;
     321           0 :         int ret = LDB_SUCCESS;
     322             : 
     323             :         /*
     324             :          * Need to take a copy of the data as the delete operation alters the
     325             :          * data, as it is in private lmdb memory.
     326             :          */
     327           0 :         copy.length = data.length;
     328           0 :         copy.data = talloc_memdup(ldb_kv, data.data, data.length);
     329           0 :         if (copy.data == NULL) {
     330           0 :                 lmdb->error = MDB_PANIC;
     331           0 :                 return ldb_oom(lmdb->ldb);
     332             :         }
     333             : 
     334           0 :         lmdb->error = lmdb_delete(ldb_kv, key);
     335           0 :         if (lmdb->error != MDB_SUCCESS) {
     336           0 :                 ldb_debug(
     337             :                         lmdb->ldb,
     338             :                         LDB_DEBUG_ERROR,
     339             :                         "Failed to delete %*.*s "
     340             :                         "for rekey as %*.*s: %s",
     341           0 :                         (int)key.length, (int)key.length,
     342           0 :                         (const char *)key.data,
     343           0 :                         (int)key2.length, (int)key2.length,
     344           0 :                         (const char *)key.data,
     345             :                         mdb_strerror(lmdb->error));
     346           0 :                 ret = ldb_mdb_error(lmdb->ldb, lmdb->error);
     347           0 :                 goto done;
     348             :         }
     349             : 
     350           0 :         lmdb->error = lmdb_store(ldb_kv, key2, copy, 0);
     351           0 :         if (lmdb->error != MDB_SUCCESS) {
     352           0 :                 ldb_debug(
     353             :                         lmdb->ldb,
     354             :                         LDB_DEBUG_ERROR,
     355             :                         "Failed to rekey %*.*s as %*.*s: %s",
     356           0 :                         (int)key.length, (int)key.length,
     357           0 :                         (const char *)key.data,
     358           0 :                         (int)key2.length, (int)key2.length,
     359           0 :                         (const char *)key.data,
     360             :                         mdb_strerror(lmdb->error));
     361           0 :                 ret = ldb_mdb_error(lmdb->ldb, lmdb->error);
     362           0 :                 goto done;
     363             :         }
     364             : 
     365           0 : done:
     366           0 :         if (copy.data != NULL) {
     367           0 :                 TALLOC_FREE(copy.data);
     368           0 :                 copy.length = 0;
     369             :         }
     370             : 
     371             :         /*
     372             :          * Explicity invalidate the data, as the delete has done this
     373             :          */
     374           0 :         data.length = 0;
     375           0 :         data.data = NULL;
     376             : 
     377           0 :         return ret;
     378             : }
     379             : 
     380             : /* Handles only a single record */
     381   126921674 : static int lmdb_parse_record(struct ldb_kv_private *ldb_kv,
     382             :                              struct ldb_val key,
     383             :                              int (*parser)(struct ldb_val key,
     384             :                                            struct ldb_val data,
     385             :                                            void *private_data),
     386             :                              void *ctx)
     387             : {
     388   126921674 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     389             :         MDB_val mdb_key;
     390             :         MDB_val mdb_data;
     391   126921674 :         MDB_txn *txn = NULL;
     392             :         MDB_dbi dbi;
     393             :         struct ldb_val data;
     394             : 
     395   126921674 :         txn = get_current_txn(lmdb);
     396   126921674 :         if (txn == NULL) {
     397           0 :                 ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction active");
     398           0 :                 lmdb->error = MDB_PANIC;
     399           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     400             :         }
     401             : 
     402   126921674 :         lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi);
     403   126921674 :         if (lmdb->error != MDB_SUCCESS) {
     404           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     405             :         }
     406             : 
     407   126921674 :         mdb_key.mv_size = key.length;
     408   126921674 :         mdb_key.mv_data = key.data;
     409             : 
     410   126921674 :         lmdb->error = mdb_get(txn, dbi, &mdb_key, &mdb_data);
     411   126921674 :         if (lmdb->error != MDB_SUCCESS) {
     412             :                 /* TODO closing a handle should not even be necessary */
     413    15640515 :                 mdb_dbi_close(lmdb->env, dbi);
     414    15640515 :                 if (lmdb->error == MDB_NOTFOUND) {
     415    15640515 :                         return LDB_ERR_NO_SUCH_OBJECT;
     416             :                 }
     417           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     418             :         }
     419   111281159 :         data.data = mdb_data.mv_data;
     420   111281159 :         data.length = mdb_data.mv_size;
     421             : 
     422             :         /* TODO closing a handle should not even be necessary */
     423   111281159 :         mdb_dbi_close(lmdb->env, dbi);
     424             : 
     425   111281159 :         return parser(key, data, ctx);
     426             : }
     427             : 
     428             : /*
     429             :  * Exactly the same as iterate, except we have a start key and an end key
     430             :  * (which are both included in the results if present).
     431             :  *
     432             :  * If start > end, return MDB_PANIC.
     433             :  */
     434       11950 : static int lmdb_iterate_range(struct ldb_kv_private *ldb_kv,
     435             :                               struct ldb_val start_key,
     436             :                               struct ldb_val end_key,
     437             :                               ldb_kv_traverse_fn fn,
     438             :                               void *ctx)
     439             : {
     440       11950 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     441             :         MDB_val mdb_key;
     442             :         MDB_val mdb_data;
     443       11950 :         MDB_txn *txn = NULL;
     444       11950 :         MDB_dbi dbi = 0;
     445       11950 :         MDB_cursor *cursor = NULL;
     446             :         int ret;
     447             : 
     448             :         MDB_val mdb_s_key;
     449             :         MDB_val mdb_e_key;
     450             : 
     451       11950 :         txn = get_current_txn(lmdb);
     452       11950 :         if (txn == NULL) {
     453           0 :                 ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction");
     454           0 :                 lmdb->error = MDB_PANIC;
     455           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     456             :         }
     457             : 
     458       11950 :         lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi);
     459       11950 :         if (lmdb->error != MDB_SUCCESS) {
     460           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     461             :         }
     462             : 
     463       11950 :         mdb_s_key.mv_size = start_key.length;
     464       11950 :         mdb_s_key.mv_data = start_key.data;
     465             : 
     466       11950 :         mdb_e_key.mv_size = end_key.length;
     467       11950 :         mdb_e_key.mv_data = end_key.data;
     468             : 
     469       11950 :         if (mdb_cmp(txn, dbi, &mdb_s_key, &mdb_e_key) > 0) {
     470           0 :                 lmdb->error = MDB_PANIC;
     471           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     472             :         }
     473             : 
     474       11950 :         lmdb->error = mdb_cursor_open(txn, dbi, &cursor);
     475       11950 :         if (lmdb->error != MDB_SUCCESS) {
     476           0 :                 goto done;
     477             :         }
     478             : 
     479       11950 :         lmdb->error = mdb_cursor_get(cursor, &mdb_s_key, &mdb_data, MDB_SET_RANGE);
     480             : 
     481       11950 :         if (lmdb->error != MDB_SUCCESS) {
     482          17 :                 if (lmdb->error == MDB_NOTFOUND) {
     483          17 :                         lmdb->error = MDB_SUCCESS;
     484             :                 }
     485          17 :                 goto done;
     486             :         } else {
     487       23819 :                 struct ldb_val key = {
     488       11933 :                         .length = mdb_s_key.mv_size,
     489       11933 :                         .data = mdb_s_key.mv_data,
     490             :                 };
     491       23819 :                 struct ldb_val data = {
     492       11933 :                         .length = mdb_data.mv_size,
     493       11933 :                         .data = mdb_data.mv_data,
     494             :                 };
     495             : 
     496       11933 :                 if (mdb_cmp(txn, dbi, &mdb_s_key, &mdb_e_key) > 0) {
     497         194 :                         goto done;
     498             :                 }
     499             : 
     500       11836 :                 ret = fn(ldb_kv, key, data, ctx);
     501       11836 :                 if (ret != 0) {
     502             :                         /*
     503             :                          * NOTE: This DOES NOT set lmdb->error!
     504             :                          *
     505             :                          * This means that the caller will get success.
     506             :                          * This matches TDB traverse behaviour, where callbacks
     507             :                          * may terminate the traverse, but do not change the
     508             :                          * return code from success.
     509             :                          *
     510             :                          * Callers SHOULD store their own error codes.
     511             :                          */
     512           0 :                         goto done;
     513             :                 }
     514             :         }
     515             : 
     516    24729398 :         while ((lmdb->error = mdb_cursor_get(
     517             :                         cursor, &mdb_key,
     518       37777 :                         &mdb_data, MDB_NEXT)) == MDB_SUCCESS) {
     519             : 
     520    49375334 :                 struct ldb_val key = {
     521    24706532 :                         .length = mdb_key.mv_size,
     522    24706532 :                         .data = mdb_key.mv_data,
     523             :                 };
     524    49375334 :                 struct ldb_val data = {
     525    24706532 :                         .length = mdb_data.mv_size,
     526    24706532 :                         .data = mdb_data.mv_data,
     527             :                 };
     528             : 
     529    24706532 :                 if (mdb_cmp(txn, dbi, &mdb_key, &mdb_e_key) > 0) {
     530        1509 :                         goto done;
     531             :                 }
     532             : 
     533    24705782 :                 ret = fn(ldb_kv, key, data, ctx);
     534    24705782 :                 if (ret != 0) {
     535             :                         /*
     536             :                          * NOTE: This DOES NOT set lmdb->error!
     537             :                          *
     538             :                          * This means that the caller will get success.
     539             :                          * This matches TDB traverse behaviour, where callbacks
     540             :                          * may terminate the traverse, but do not change the
     541             :                          * return code from success.
     542             :                          *
     543             :                          * Callers SHOULD store their own error codes.
     544             :                          */
     545           9 :                         goto done;
     546             :                 }
     547             :         }
     548       11077 :         if (lmdb->error == MDB_NOTFOUND) {
     549       11077 :                 lmdb->error = MDB_SUCCESS;
     550             :         }
     551       11903 : done:
     552       11950 :         if (cursor != NULL) {
     553       11950 :                 mdb_cursor_close(cursor);
     554             :         }
     555             : 
     556       11950 :         if (lmdb->error != MDB_SUCCESS) {
     557           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     558             :         }
     559       11950 :         return ldb_mdb_err_map(lmdb->error);
     560             : }
     561             : 
     562    67107811 : static int lmdb_lock_read(struct ldb_module *module)
     563             : {
     564    67107811 :         void *data = ldb_module_get_private(module);
     565    65955847 :         struct ldb_kv_private *ldb_kv =
     566     1151964 :             talloc_get_type(data, struct ldb_kv_private);
     567    67107811 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     568    67107811 :         pid_t pid = getpid();
     569             : 
     570    67107811 :         if (pid != lmdb->pid) {
     571           0 :                 ldb_asprintf_errstring(
     572             :                         lmdb->ldb,
     573             :                         __location__": Reusing ldb opened by pid %d in "
     574             :                         "process %d\n",
     575             :                         lmdb->pid,
     576             :                         pid);
     577           0 :                 lmdb->error = MDB_BAD_TXN;
     578           0 :                 return LDB_ERR_PROTOCOL_ERROR;
     579             :         }
     580             : 
     581    67107811 :         lmdb->error = MDB_SUCCESS;
     582   105979916 :         if (lmdb_transaction_active(ldb_kv) == false &&
     583    39257633 :             ldb_kv->read_lock_count == 0) {
     584     9350909 :                 lmdb->error = mdb_txn_begin(lmdb->env,
     585             :                                             NULL,
     586             :                                             MDB_RDONLY,
     587             :                                             &lmdb->read_txn);
     588             :         }
     589    67107811 :         if (lmdb->error != MDB_SUCCESS) {
     590           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     591             :         }
     592             : 
     593    67107811 :         ldb_kv->read_lock_count++;
     594    67107811 :         return ldb_mdb_err_map(lmdb->error);
     595             : }
     596             : 
     597    67107811 : static int lmdb_unlock_read(struct ldb_module *module)
     598             : {
     599    67107811 :         void *data = ldb_module_get_private(module);
     600    65955847 :         struct ldb_kv_private *ldb_kv =
     601     1151964 :             talloc_get_type(data, struct ldb_kv_private);
     602             : 
     603   105979916 :         if (lmdb_transaction_active(ldb_kv) == false &&
     604    39257633 :             ldb_kv->read_lock_count == 1) {
     605     9350909 :                 struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     606     9350909 :                 mdb_txn_commit(lmdb->read_txn);
     607     9350909 :                 lmdb->read_txn = NULL;
     608     9350909 :                 ldb_kv->read_lock_count--;
     609     9350909 :                 return LDB_SUCCESS;
     610             :         }
     611    57756902 :         ldb_kv->read_lock_count--;
     612    57756902 :         return LDB_SUCCESS;
     613             : }
     614             : 
     615      747381 : static int lmdb_transaction_start(struct ldb_kv_private *ldb_kv)
     616             : {
     617      747381 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     618             :         struct lmdb_trans *ltx;
     619             :         struct lmdb_trans *ltx_head;
     620             :         MDB_txn *tx_parent;
     621      747381 :         pid_t pid = getpid();
     622             : 
     623             :         /* Do not take out the transaction lock on a read-only DB */
     624      747381 :         if (ldb_kv->read_only) {
     625           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     626             :         }
     627             : 
     628      747381 :         ltx = talloc_zero(lmdb, struct lmdb_trans);
     629      747381 :         if (ltx == NULL) {
     630           0 :                 return ldb_oom(lmdb->ldb);
     631             :         }
     632             : 
     633      747381 :         if (pid != lmdb->pid) {
     634           0 :                 ldb_asprintf_errstring(
     635             :                         lmdb->ldb,
     636             :                         __location__": Reusing ldb opened by pid %d in "
     637             :                         "process %d\n",
     638             :                         lmdb->pid,
     639             :                         pid);
     640           0 :                 lmdb->error = MDB_BAD_TXN;
     641           0 :                 return LDB_ERR_PROTOCOL_ERROR;
     642             :         }
     643             : 
     644             :         /*
     645             :          * Clear out any stale readers
     646             :          */
     647             :         {
     648      747381 :                 int stale = 0;
     649      747381 :                 mdb_reader_check(lmdb->env, &stale);
     650      747381 :                 if (stale > 0) {
     651           0 :                         ldb_debug(
     652             :                                 lmdb->ldb,
     653             :                                 LDB_DEBUG_ERROR,
     654             :                                 "LMDB Stale readers, deleted (%d)",
     655             :                                 stale);
     656             :                 }
     657             :         }
     658             : 
     659             : 
     660             : 
     661      747381 :         ltx_head = lmdb_private_trans_head(lmdb);
     662             : 
     663      747381 :         tx_parent = lmdb_trans_get_tx(ltx_head);
     664             : 
     665      747381 :         lmdb->error = mdb_txn_begin(lmdb->env, tx_parent, 0, &ltx->tx);
     666      747381 :         if (lmdb->error != MDB_SUCCESS) {
     667           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     668             :         }
     669             : 
     670      747381 :         trans_push(lmdb, ltx);
     671             : 
     672      747381 :         return ldb_mdb_err_map(lmdb->error);
     673             : }
     674             : 
     675       41622 : static int lmdb_transaction_cancel(struct ldb_kv_private *ldb_kv)
     676             : {
     677             :         struct lmdb_trans *ltx;
     678       41622 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     679             : 
     680       41622 :         ltx = lmdb_private_trans_head(lmdb);
     681       41622 :         if (ltx == NULL) {
     682           1 :                 return LDB_ERR_OPERATIONS_ERROR;
     683             :         }
     684             : 
     685       41621 :         mdb_txn_abort(ltx->tx);
     686       41621 :         trans_finished(lmdb, ltx);
     687       41621 :         return LDB_SUCCESS;
     688             : }
     689             : 
     690      361091 : static int lmdb_transaction_prepare_commit(struct ldb_kv_private *ldb_kv)
     691             : {
     692             :         /* No need to prepare a commit */
     693      361091 :         return LDB_SUCCESS;
     694             : }
     695             : 
     696      705760 : static int lmdb_transaction_commit(struct ldb_kv_private *ldb_kv)
     697             : {
     698             :         struct lmdb_trans *ltx;
     699      705760 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     700             : 
     701      705760 :         ltx = lmdb_private_trans_head(lmdb);
     702      705760 :         if (ltx == NULL) {
     703           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     704             :         }
     705             : 
     706      705760 :         lmdb->error = mdb_txn_commit(ltx->tx);
     707      705760 :         trans_finished(lmdb, ltx);
     708             : 
     709      705760 :         return lmdb->error;
     710             : }
     711             : 
     712       22062 : static int lmdb_error(struct ldb_kv_private *ldb_kv)
     713             : {
     714       22062 :         return ldb_mdb_err_map(ldb_kv->lmdb_private->error);
     715             : }
     716             : 
     717           0 : static const char *lmdb_errorstr(struct ldb_kv_private *ldb_kv)
     718             : {
     719           0 :         return mdb_strerror(ldb_kv->lmdb_private->error);
     720             : }
     721             : 
     722           0 : static const char *lmdb_name(struct ldb_kv_private *ldb_kv)
     723             : {
     724           0 :         return "lmdb";
     725             : }
     726             : 
     727    50651570 : static bool lmdb_changed(struct ldb_kv_private *ldb_kv)
     728             : {
     729             :         /*
     730             :          * lmdb does no provide a quick way to determine if the database
     731             :          * has changed.  This function always returns true.
     732             :          *
     733             :          * Note that tdb uses a sequence number that allows this function
     734             :          * to be implemented efficiently.
     735             :          */
     736    50651570 :         return true;
     737             : }
     738             : 
     739             : /*
     740             :  * Get the number of records in the database.
     741             :  *
     742             :  * The mdb_env_stat call returns an accurate count, so we return the actual
     743             :  * number of records in the database rather than an estimate.
     744             :  */
     745           0 : static size_t lmdb_get_size(struct ldb_kv_private *ldb_kv)
     746             : {
     747             : 
     748           0 :         struct MDB_stat stats = {0};
     749           0 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     750           0 :         int ret = 0;
     751             : 
     752           0 :         ret = mdb_env_stat(lmdb->env, &stats);
     753           0 :         if (ret != 0) {
     754           0 :                 return 0;
     755             :         }
     756           0 :         return stats.ms_entries;
     757             : }
     758             : 
     759             : /*
     760             :  * Start a sub transaction
     761             :  * As lmdb supports nested transactions we can start a new transaction
     762             :  */
     763      344712 : static int lmdb_nested_transaction_start(struct ldb_kv_private *ldb_kv)
     764             : {
     765      344712 :         int ret = lmdb_transaction_start(ldb_kv);
     766      344712 :         return ret;
     767             : }
     768             : 
     769             : /*
     770             :  * Commit a sub transaction
     771             :  * As lmdb supports nested transactions we can commit the nested transaction
     772             :  */
     773      343967 : static int lmdb_nested_transaction_commit(struct ldb_kv_private *ldb_kv)
     774             : {
     775      343967 :         int ret = lmdb_transaction_commit(ldb_kv);
     776      343967 :         return ret;
     777             : }
     778             : 
     779             : /*
     780             :  * Cancel a sub transaction
     781             :  * As lmdb supports nested transactions we can cancel the nested transaction
     782             :  */
     783         745 : static int lmdb_nested_transaction_cancel(struct ldb_kv_private *ldb_kv)
     784             : {
     785         745 :         int ret = lmdb_transaction_cancel(ldb_kv);
     786         745 :         return ret;
     787             : }
     788             : 
     789             : static struct kv_db_ops lmdb_key_value_ops = {
     790             :         .options            = LDB_KV_OPTION_STABLE_READ_LOCK,
     791             : 
     792             :         .store              = lmdb_store,
     793             :         .delete             = lmdb_delete,
     794             :         .iterate            = lmdb_traverse_fn,
     795             :         .update_in_iterate  = lmdb_update_in_iterate,
     796             :         .fetch_and_parse    = lmdb_parse_record,
     797             :         .iterate_range      = lmdb_iterate_range,
     798             :         .lock_read          = lmdb_lock_read,
     799             :         .unlock_read        = lmdb_unlock_read,
     800             :         .begin_write        = lmdb_transaction_start,
     801             :         .prepare_write      = lmdb_transaction_prepare_commit,
     802             :         .finish_write       = lmdb_transaction_commit,
     803             :         .abort_write        = lmdb_transaction_cancel,
     804             :         .error              = lmdb_error,
     805             :         .errorstr           = lmdb_errorstr,
     806             :         .name               = lmdb_name,
     807             :         .has_changed        = lmdb_changed,
     808             :         .transaction_active = lmdb_transaction_active,
     809             :         .get_size           = lmdb_get_size,
     810             :         .begin_nested_write = lmdb_nested_transaction_start,
     811             :         .finish_nested_write = lmdb_nested_transaction_commit,
     812             :         .abort_nested_write = lmdb_nested_transaction_cancel,
     813             : };
     814             : 
     815      150865 : static const char *lmdb_get_path(const char *url)
     816             : {
     817             :         const char *path;
     818             : 
     819             :         /* parse the url */
     820      150865 :         if (strchr(url, ':')) {
     821      150812 :                 if (strncmp(url, MDB_URL_PREFIX, MDB_URL_PREFIX_SIZE) != 0) {
     822           0 :                         return NULL;
     823             :                 }
     824      150812 :                 path = url + MDB_URL_PREFIX_SIZE;
     825             :         } else {
     826          53 :                 path = url;
     827             :         }
     828             : 
     829      150865 :         return path;
     830             : }
     831             : 
     832      145344 : static int lmdb_pvt_destructor(struct lmdb_private *lmdb)
     833             : {
     834      145344 :         struct lmdb_trans *ltx = NULL;
     835             : 
     836             :         /* Check if this is a forked child */
     837      145344 :         if (getpid() != lmdb->pid) {
     838        3550 :                 int fd = 0;
     839             :                 /*
     840             :                  * We cannot call mdb_env_close or commit any transactions,
     841             :                  * otherwise they might appear finished in the parent.
     842             :                  *
     843             :                  */
     844             : 
     845        3550 :                 if (mdb_env_get_fd(lmdb->env, &fd) == 0) {
     846        3550 :                         close(fd);
     847             :                 }
     848             : 
     849             :                 /* Remove the pointer, so that no access should occur */
     850        3550 :                 lmdb->env = NULL;
     851             : 
     852        3550 :                 return 0;
     853             :         }
     854             : 
     855             :         /*
     856             :          * Close the read transaction if it's open
     857             :          */
     858      141794 :         if (lmdb->read_txn != NULL) {
     859           0 :                 mdb_txn_abort(lmdb->read_txn);
     860             :         }
     861             : 
     862      141794 :         if (lmdb->env == NULL) {
     863           0 :                 return 0;
     864             :         }
     865             : 
     866             :         /*
     867             :          * Abort any currently active transactions
     868             :          */
     869      141794 :         ltx = lmdb_private_trans_head(lmdb);
     870      277788 :         while (ltx != NULL) {
     871           0 :                 mdb_txn_abort(ltx->tx);
     872           0 :                 trans_finished(lmdb, ltx);
     873           0 :                 ltx = lmdb_private_trans_head(lmdb);
     874             :         }
     875      141794 :         lmdb->env = NULL;
     876             : 
     877      141794 :         return 0;
     878             : }
     879             : 
     880             : struct mdb_env_wrap {
     881             :         struct mdb_env_wrap *next, *prev;
     882             :         dev_t device;
     883             :         ino_t inode;
     884             :         MDB_env *env;
     885             :         pid_t pid;
     886             : };
     887             : 
     888             : static struct mdb_env_wrap *mdb_list;
     889             : 
     890             : /* destroy the last connection to an mdb */
     891       23485 : static int mdb_env_wrap_destructor(struct mdb_env_wrap *w)
     892             : {
     893       23485 :         mdb_env_close(w->env);
     894       23485 :         DLIST_REMOVE(mdb_list, w);
     895       23485 :         return 0;
     896             : }
     897             : 
     898      150865 : static int lmdb_open_env(TALLOC_CTX *mem_ctx,
     899             :                          MDB_env **env,
     900             :                          struct ldb_context *ldb,
     901             :                          const char *path,
     902             :                          const size_t env_map_size,
     903             :                          unsigned int flags)
     904             : {
     905             :         int ret;
     906      150865 :         unsigned int mdb_flags = MDB_NOSUBDIR|MDB_NOTLS;
     907             :         /*
     908             :          * MDB_NOSUBDIR implies there is a separate file called path and a
     909             :          * separate lockfile called path-lock
     910             :          */
     911             : 
     912             :         struct mdb_env_wrap *w;
     913             :         struct stat st;
     914      150865 :         pid_t pid = getpid();
     915      150865 :         int fd = 0;
     916             :         unsigned v;
     917             : 
     918      150865 :         if (stat(path, &st) == 0) {
     919      500336 :                 for (w=mdb_list;w;w=w->next) {
     920      922488 :                         if (st.st_dev == w->device &&
     921      599039 :                             st.st_ino == w->inode &&
     922      132275 :                             pid == w->pid) {
     923             :                                 /*
     924             :                                  * We must have only one MDB_env per process
     925             :                                  */
     926      121895 :                                 if (!talloc_reference(mem_ctx, w)) {
     927           0 :                                         return ldb_oom(ldb);
     928             :                                 }
     929      121895 :                                 *env = w->env;
     930      121895 :                                 return LDB_SUCCESS;
     931             :                         }
     932             :                 }
     933             :         }
     934             : 
     935       28970 :         w = talloc(mem_ctx, struct mdb_env_wrap);
     936       28970 :         if (w == NULL) {
     937           0 :                 return ldb_oom(ldb);
     938             :         }
     939             : 
     940       28970 :         ret = mdb_env_create(env);
     941       28970 :         if (ret != 0) {
     942           0 :                 ldb_asprintf_errstring(
     943             :                         ldb,
     944             :                         "Could not create MDB environment %s: %s\n",
     945             :                         path,
     946             :                         mdb_strerror(ret));
     947           0 :                 return ldb_mdb_err_map(ret);
     948             :         }
     949             : 
     950       28970 :         if (env_map_size > 0) {
     951         199 :                 ret = mdb_env_set_mapsize(*env, env_map_size);
     952         199 :                 if (ret != 0) {
     953           0 :                         ldb_asprintf_errstring(
     954             :                                 ldb,
     955             :                                 "Could not set MDB mmap() size to %llu "
     956             :                                 "on %s: %s\n",
     957             :                                 (unsigned long long)(env_map_size),
     958             :                                 path,
     959             :                                 mdb_strerror(ret));
     960           0 :                         TALLOC_FREE(w);
     961           0 :                         return ldb_mdb_err_map(ret);
     962             :                 }
     963             :         }
     964             : 
     965       28970 :         mdb_env_set_maxreaders(*env, 100000);
     966             :         /*
     967             :          * As we ensure that there is only one MDB_env open per database per
     968             :          * process. We can not use the MDB_RDONLY flag, as another ldb may be
     969             :          * opened in read write mode
     970             :          */
     971       28970 :         if (flags & LDB_FLG_NOSYNC) {
     972       28294 :                 mdb_flags |= MDB_NOSYNC;
     973             :         }
     974       28970 :         ret = mdb_env_open(*env, path, mdb_flags, 0644);
     975       28970 :         if (ret != 0) {
     976          53 :                 ldb_asprintf_errstring(ldb,
     977             :                                 "Could not open DB %s: %s\n",
     978             :                                 path, mdb_strerror(ret));
     979          53 :                 TALLOC_FREE(w);
     980          53 :                 return ldb_mdb_err_map(ret);
     981             :         }
     982             : 
     983             :         {
     984       28917 :                 MDB_envinfo stat = {0};
     985       28917 :                 ret = mdb_env_info (*env, &stat);
     986       28917 :                 if (ret != 0) {
     987           0 :                         ldb_asprintf_errstring(
     988             :                                 ldb,
     989             :                                 "Could not get MDB environment stats %s: %s\n",
     990             :                                 path,
     991             :                                 mdb_strerror(ret));
     992           0 :                 return ldb_mdb_err_map(ret);
     993             :                 }
     994             :         }
     995             : 
     996       28917 :         ret = mdb_env_get_fd(*env, &fd);
     997       28917 :         if (ret != 0) {
     998           0 :                 ldb_asprintf_errstring(ldb,
     999             :                                        "Could not obtain DB FD %s: %s\n",
    1000             :                                        path, mdb_strerror(ret));
    1001           0 :                 TALLOC_FREE(w);
    1002           0 :                 return ldb_mdb_err_map(ret);
    1003             :         }
    1004             : 
    1005             :         /* Just as for TDB: on exec, don't inherit the fd */
    1006       28917 :         v = fcntl(fd, F_GETFD, 0);
    1007       28917 :         if (v == -1) {
    1008           0 :                 TALLOC_FREE(w);
    1009           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1010             :         }
    1011             : 
    1012       28917 :         ret = fcntl(fd, F_SETFD, v | FD_CLOEXEC);
    1013       28917 :         if (ret == -1) {
    1014           0 :                 TALLOC_FREE(w);
    1015           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1016             :         }
    1017             : 
    1018       28917 :         if (fstat(fd, &st) != 0) {
    1019           0 :                 ldb_asprintf_errstring(
    1020             :                         ldb,
    1021             :                         "Could not stat %s:\n",
    1022             :                         path);
    1023           0 :                 TALLOC_FREE(w);
    1024           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1025             :         }
    1026       28917 :         w->env = *env;
    1027       28917 :         w->device = st.st_dev;
    1028       28917 :         w->inode  = st.st_ino;
    1029       28917 :         w->pid = pid;
    1030             : 
    1031       28917 :         talloc_set_destructor(w, mdb_env_wrap_destructor);
    1032             : 
    1033       28917 :         DLIST_ADD(mdb_list, w);
    1034             : 
    1035       28917 :         return LDB_SUCCESS;
    1036             : 
    1037             : }
    1038             : 
    1039      150865 : static int lmdb_pvt_open(struct lmdb_private *lmdb,
    1040             :                          struct ldb_context *ldb,
    1041             :                          const char *path,
    1042             :                          const size_t env_map_size,
    1043             :                          unsigned int flags)
    1044             : {
    1045             :         int ret;
    1046             :         int lmdb_max_key_length;
    1047             : 
    1048      150865 :         if (flags & LDB_FLG_DONT_CREATE_DB) {
    1049             :                 struct stat st;
    1050      149457 :                 if (stat(path, &st) != 0) {
    1051           0 :                         return LDB_ERR_UNAVAILABLE;
    1052             :                 }
    1053             :         }
    1054             : 
    1055      150865 :         ret = lmdb_open_env(lmdb, &lmdb->env, ldb, path, env_map_size, flags);
    1056      150865 :         if (ret != 0) {
    1057          53 :                 return ret;
    1058             :         }
    1059             : 
    1060             :         /* Close when lmdb is released */
    1061      150812 :         talloc_set_destructor(lmdb, lmdb_pvt_destructor);
    1062             : 
    1063             :         /* Store the original pid during the LMDB open */
    1064      150812 :         lmdb->pid = getpid();
    1065             : 
    1066      150812 :         lmdb_max_key_length = mdb_env_get_maxkeysize(lmdb->env);
    1067             : 
    1068             :         /* This will never happen, but if it does make sure to freak out */
    1069      150812 :         if (lmdb_max_key_length < LDB_MDB_MAX_KEY_LENGTH) {
    1070           0 :                 return ldb_operr(ldb);
    1071             :         }
    1072             : 
    1073      150812 :         return LDB_SUCCESS;
    1074             : }
    1075             : 
    1076      150865 : int lmdb_connect(struct ldb_context *ldb,
    1077             :                  const char *url,
    1078             :                  unsigned int flags,
    1079             :                  const char *options[],
    1080             :                  struct ldb_module **_module)
    1081             : {
    1082      150865 :         const char *path = NULL;
    1083      150865 :         struct lmdb_private *lmdb = NULL;
    1084      150865 :         struct ldb_kv_private *ldb_kv = NULL;
    1085             :         int ret;
    1086      150865 :         size_t env_map_size = 0;
    1087             : 
    1088             :         /*
    1089             :          * We hold locks, so we must use a private event context
    1090             :          * on each returned handle
    1091             :          */
    1092      150865 :         ldb_set_require_private_event_context(ldb);
    1093             : 
    1094      150865 :         path = lmdb_get_path(url);
    1095      150865 :         if (path == NULL) {
    1096           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid mdb URL '%s'", url);
    1097           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1098             :         }
    1099             : 
    1100      150865 :         ldb_kv = talloc_zero(ldb, struct ldb_kv_private);
    1101      150865 :         if (!ldb_kv) {
    1102           0 :                 ldb_oom(ldb);
    1103           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1104             :         }
    1105             : 
    1106      150865 :         lmdb = talloc_zero(ldb_kv, struct lmdb_private);
    1107      150865 :         if (lmdb == NULL) {
    1108           0 :                 TALLOC_FREE(ldb_kv);
    1109           0 :                 return ldb_oom(ldb);
    1110             :         }
    1111      150865 :         lmdb->ldb = ldb;
    1112      150865 :         ldb_kv->kv_ops = &lmdb_key_value_ops;
    1113             : 
    1114             :         {
    1115      150865 :                 const char *size = ldb_options_find(
    1116             :                         ldb, ldb->options, "lmdb_env_size");
    1117      150865 :                 if (size != NULL) {
    1118         199 :                         env_map_size = strtoull(size, NULL, 0);
    1119             :                 }
    1120             :         }
    1121             : 
    1122      150865 :         ret = lmdb_pvt_open(lmdb, ldb, path, env_map_size, flags);
    1123      150865 :         if (ret != LDB_SUCCESS) {
    1124          53 :                 TALLOC_FREE(ldb_kv);
    1125          53 :                 return ret;
    1126             :         }
    1127             : 
    1128      150812 :         ldb_kv->lmdb_private = lmdb;
    1129      150812 :         if (flags & LDB_FLG_RDONLY) {
    1130          30 :                 ldb_kv->read_only = true;
    1131             :         }
    1132             : 
    1133             :         /*
    1134             :          * This maximum length becomes encoded in the index values so
    1135             :          * must never change even if LMDB starts to allow longer keys.
    1136             :          * The override option is max_key_len_for_self_test, and is
    1137             :          * used for testing only.
    1138             :          */
    1139      150812 :         ldb_kv->max_key_length = LDB_MDB_MAX_KEY_LENGTH;
    1140             : 
    1141      150812 :         return ldb_kv_init_store(
    1142             :             ldb_kv, "ldb_mdb backend", ldb, options, _module);
    1143             : }

Generated by: LCOV version 1.13