LCOV - code coverage report
Current view: top level - lib/ldb/ldb_mdb - ldb_mdb.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 436 527 82.7 %
Date: 2024-04-21 15:09:00 Functions: 32 34 94.1 %

          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   144839549 : int ldb_mdb_err_map(int lmdb_err)
      37             : {
      38   144839549 :         switch (lmdb_err) {
      39   139016284 :         case MDB_SUCCESS:
      40   139016284 :                 return LDB_SUCCESS;
      41           0 :         case EIO:
      42           0 :                 return LDB_ERR_OPERATIONS_ERROR;
      43             : #ifdef EBADE
      44          62 :         case EBADE:
      45             : #endif
      46             :         case MDB_INCOMPATIBLE:
      47             :         case MDB_CORRUPTED:
      48             :         case MDB_INVALID:
      49          62 :                 return LDB_ERR_UNAVAILABLE;
      50           6 :         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           6 :                 return LDB_ERR_PROTOCOL_ERROR;
      58           1 :         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           1 :                 return LDB_ERR_BUSY;
      65         754 :         case MDB_KEYEXIST:
      66         754 :                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
      67       67842 :         case MDB_NOTFOUND:
      68             :         case ENOENT:
      69       67842 :                 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       34304 : static int lmdb_error_at(struct ldb_context *ldb,
      80             :                          int ecode,
      81             :                          const char *file,
      82             :                          int line)
      83             : {
      84       34304 :         int ldb_err = ldb_mdb_err_map(ecode);
      85       34304 :         char *reason = mdb_strerror(ecode);
      86       34304 :         ldb_asprintf_errstring(ldb,
      87             :                                "(%d) - %s at %s:%d",
      88             :                                ecode,
      89             :                                reason,
      90             :                                file,
      91             :                                line);
      92       34304 :         return ldb_err;
      93             : }
      94             : 
      95   357884202 : static bool lmdb_transaction_active(struct ldb_kv_private *ldb_kv)
      96             : {
      97   357884202 :         return ldb_kv->lmdb_private->txlist != NULL;
      98             : }
      99             : 
     100   259816376 : static MDB_txn *lmdb_trans_get_tx(struct lmdb_trans *ltx)
     101             : {
     102   259816376 :         if (ltx == NULL) {
     103   147963432 :                 return NULL;
     104             :         }
     105             : 
     106   103575345 :         return ltx->tx;
     107             : }
     108             : 
     109     1444167 : static void trans_push(struct lmdb_private *lmdb, struct lmdb_trans *ltx)
     110             : {
     111     1444167 :         if (lmdb->txlist) {
     112      686843 :                 talloc_steal(lmdb->txlist, ltx);
     113             :         }
     114             : 
     115     1444167 :         DLIST_ADD(lmdb->txlist, ltx);
     116     1444167 : }
     117             : 
     118     1444168 : static void trans_finished(struct lmdb_private *lmdb, struct lmdb_trans *ltx)
     119             : {
     120     1444168 :         DLIST_REMOVE(lmdb->txlist, ltx);
     121     1444168 :         talloc_free(ltx);
     122     1444168 : }
     123             : 
     124             : 
     125   261690184 : static struct lmdb_trans *lmdb_private_trans_head(struct lmdb_private *lmdb)
     126             : {
     127     8391180 :         struct lmdb_trans *ltx;
     128             : 
     129   261690184 :         ltx = lmdb->txlist;
     130   261690184 :         return ltx;
     131             : }
     132             : 
     133             : 
     134   251236684 : static MDB_txn *get_current_txn(struct lmdb_private *lmdb)
     135             : {
     136   251236684 :         MDB_txn *txn = NULL;
     137             : 
     138   251236684 :         txn = lmdb_trans_get_tx(lmdb_private_trans_head(lmdb));
     139   246142045 :         if (txn != NULL) {
     140    96213848 :                 return txn;
     141             :         }
     142   152313248 :         if (lmdb->read_txn != NULL) {
     143   147218609 :                 return lmdb->read_txn;
     144             :         }
     145           1 :         lmdb->error = MDB_BAD_TXN;
     146           1 :         ldb_set_errstring(lmdb->ldb, __location__":No active transaction\n");
     147           1 :         return NULL;
     148             : }
     149             : 
     150     6850605 : 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     6850605 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     156      454769 :         MDB_val mdb_key;
     157      454769 :         MDB_val mdb_data;
     158      454769 :         int mdb_flags;
     159     6850605 :         MDB_txn *txn = NULL;
     160     6850605 :         MDB_dbi dbi = 0;
     161             : 
     162     6850605 :         if (ldb_kv->read_only) {
     163           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     164             :         }
     165             : 
     166     6850605 :         txn = lmdb_trans_get_tx(lmdb_private_trans_head(lmdb));
     167     6850604 :         if (txn == NULL) {
     168           1 :                 ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction");
     169           1 :                 lmdb->error = MDB_PANIC;
     170           1 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     171             :         }
     172             : 
     173     6850604 :         lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi);
     174     6850604 :         if (lmdb->error != MDB_SUCCESS) {
     175           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     176             :         }
     177             : 
     178     6850604 :         mdb_key.mv_size = key.length;
     179     6850604 :         mdb_key.mv_data = key.data;
     180             : 
     181     6850604 :         mdb_data.mv_size = data.length;
     182     6850604 :         mdb_data.mv_data = data.data;
     183             : 
     184     6850604 :         if (flags == TDB_INSERT) {
     185      354880 :                 mdb_flags = MDB_NOOVERWRITE;
     186     6464191 :         } else if (flags == TDB_MODIFY) {
     187             :                 /*
     188             :                  * Modifying a record, ensure that it exists.
     189             :                  * This mimics the TDB semantics
     190             :                  */
     191      238723 :                 MDB_val value;
     192     2889797 :                 lmdb->error = mdb_get(txn, dbi, &mdb_key, &value);
     193     2889797 :                 if (lmdb->error != MDB_SUCCESS) {
     194           0 :                         return ldb_mdb_error(lmdb->ldb, lmdb->error);
     195             :                 }
     196     2889797 :                 mdb_flags = 0;
     197             :         } else {
     198     3389882 :                 mdb_flags = 0;
     199             :         }
     200             : 
     201     6850604 :         lmdb->error = mdb_put(txn, dbi, &mdb_key, &mdb_data, mdb_flags);
     202     6850604 :         if (lmdb->error != MDB_SUCCESS) {
     203         379 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     204             :         }
     205             : 
     206     6850225 :         return ldb_mdb_err_map(lmdb->error);
     207             : }
     208             : 
     209      284920 : static int lmdb_delete(struct ldb_kv_private *ldb_kv, struct ldb_val key)
     210             : {
     211      284920 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     212        6102 :         MDB_val mdb_key;
     213      284920 :         MDB_txn *txn = NULL;
     214      284920 :         MDB_dbi dbi = 0;
     215             : 
     216      284920 :         if (ldb_kv->read_only) {
     217           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     218             :         }
     219             : 
     220      284920 :         txn = lmdb_trans_get_tx(lmdb_private_trans_head(lmdb));
     221      284919 :         if (txn == NULL) {
     222           1 :                 ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction");
     223           1 :                 lmdb->error = MDB_PANIC;
     224           1 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     225             :         }
     226             : 
     227      284919 :         lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi);
     228      284919 :         if (lmdb->error != MDB_SUCCESS) {
     229           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     230             :         }
     231             : 
     232      284919 :         mdb_key.mv_size = key.length;
     233      284919 :         mdb_key.mv_data = key.data;
     234             : 
     235      284919 :         lmdb->error = mdb_del(txn, dbi, &mdb_key, NULL);
     236      284919 :         if (lmdb->error != MDB_SUCCESS) {
     237       33921 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     238             :         }
     239      250998 :         return ldb_mdb_err_map(lmdb->error);
     240             : }
     241             : 
     242       10913 : static int lmdb_traverse_fn(struct ldb_kv_private *ldb_kv,
     243             :                             ldb_kv_traverse_fn fn,
     244             :                             void *ctx)
     245             : {
     246       10913 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     247        1020 :         MDB_val mdb_key;
     248        1020 :         MDB_val mdb_data;
     249       10913 :         MDB_txn *txn = NULL;
     250       10913 :         MDB_dbi dbi = 0;
     251       10913 :         MDB_cursor *cursor = NULL;
     252        1020 :         int ret;
     253             : 
     254       10913 :         txn = get_current_txn(lmdb);
     255       10913 :         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       10913 :         lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi);
     262       10913 :         if (lmdb->error != MDB_SUCCESS) {
     263           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     264             :         }
     265             : 
     266       10913 :         lmdb->error = mdb_cursor_open(txn, dbi, &cursor);
     267       10913 :         if (lmdb->error != MDB_SUCCESS) {
     268           0 :                 goto done;
     269             :         }
     270             : 
     271     8611193 :         while ((lmdb->error = mdb_cursor_get(
     272             :                         cursor, &mdb_key,
     273     8277794 :                         &mdb_data, MDB_NEXT)) == MDB_SUCCESS) {
     274             : 
     275     8266885 :                 struct ldb_val key = {
     276     8266885 :                         .length = mdb_key.mv_size,
     277     8266885 :                         .data = mdb_key.mv_data,
     278             :                 };
     279     8266885 :                 struct ldb_val data = {
     280     8266885 :                         .length = mdb_data.mv_size,
     281     8266885 :                         .data = mdb_data.mv_data,
     282             :                 };
     283             : 
     284     8266885 :                 ret = fn(ldb_kv, key, data, ctx);
     285     8266885 :                 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           4 :                         goto done;
     297             :                 }
     298             :         }
     299       10909 :         if (lmdb->error == MDB_NOTFOUND) {
     300       10909 :                 lmdb->error = MDB_SUCCESS;
     301             :         }
     302           0 : done:
     303       10913 :         if (cursor != NULL) {
     304       10913 :                 mdb_cursor_close(cursor);
     305             :         }
     306             : 
     307       10913 :         if (lmdb->error != MDB_SUCCESS) {
     308           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     309             :         }
     310       10913 :         return ldb_mdb_err_map(lmdb->error);
     311             : }
     312             : 
     313        1032 : 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        1032 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     320        1032 :         struct ldb_val copy;
     321        1032 :         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        1032 :         copy.length = data.length;
     328        1032 :         copy.data = talloc_memdup(ldb_kv, data.data, data.length);
     329        1032 :         if (copy.data == NULL) {
     330           0 :                 lmdb->error = MDB_PANIC;
     331           0 :                 return ldb_oom(lmdb->ldb);
     332             :         }
     333             : 
     334        1032 :         lmdb->error = lmdb_delete(ldb_kv, key);
     335        1032 :         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        1032 :         lmdb->error = lmdb_store(ldb_kv, key2, copy, 0);
     351        1032 :         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        1032 : done:
     366        1032 :         if (copy.data != NULL) {
     367        1032 :                 TALLOC_FREE(copy.data);
     368        1032 :                 copy.length = 0;
     369             :         }
     370             : 
     371             :         /*
     372             :          * Explicitly invalidate the data, as the delete has done this
     373             :          */
     374        1032 :         data.length = 0;
     375        1032 :         data.data = NULL;
     376             : 
     377        1032 :         return ret;
     378             : }
     379             : 
     380             : /* Handles only a single record */
     381   251211906 : 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   251211906 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     389     7803008 :         MDB_val mdb_key;
     390     7803008 :         MDB_val mdb_data;
     391   251211906 :         MDB_txn *txn = NULL;
     392     7803008 :         MDB_dbi dbi;
     393     7803008 :         struct ldb_val data;
     394             : 
     395   251211906 :         txn = get_current_txn(lmdb);
     396   251211906 :         if (txn == NULL) {
     397           1 :                 ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction active");
     398           1 :                 lmdb->error = MDB_PANIC;
     399           1 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     400             :         }
     401             : 
     402   251211905 :         lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi);
     403   251211905 :         if (lmdb->error != MDB_SUCCESS) {
     404           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     405             :         }
     406             : 
     407   251211905 :         mdb_key.mv_size = key.length;
     408   251211905 :         mdb_key.mv_data = key.data;
     409             : 
     410   251211905 :         lmdb->error = mdb_get(txn, dbi, &mdb_key, &mdb_data);
     411   251211905 :         if (lmdb->error != MDB_SUCCESS) {
     412             :                 /* TODO closing a handle should not even be necessary */
     413    30936979 :                 mdb_dbi_close(lmdb->env, dbi);
     414    30936979 :                 if (lmdb->error == MDB_NOTFOUND) {
     415    29874192 :                         return LDB_ERR_NO_SUCH_OBJECT;
     416             :                 }
     417           0 :                 if (lmdb->error == MDB_CORRUPTED) {
     418           0 :                         ldb_debug(lmdb->ldb, LDB_DEBUG_ERROR,
     419             :                                 __location__
     420             :                                 ": MDB corrupted for key [%*.*s]\n",
     421           0 :                                 (int)key.length,
     422           0 :                                 (int)key.length,
     423             :                                 key.data);
     424             :                 }
     425           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     426             :         }
     427   220274926 :         data.data = mdb_data.mv_data;
     428   220274926 :         data.length = mdb_data.mv_size;
     429             : 
     430             :         /* TODO closing a handle should not even be necessary */
     431   220274926 :         mdb_dbi_close(lmdb->env, dbi);
     432             : 
     433   220274926 :         return parser(key, data, ctx);
     434             : }
     435             : 
     436             : /*
     437             :  * Exactly the same as iterate, except we have a start key and an end key
     438             :  * (which are both included in the results if present).
     439             :  *
     440             :  * If start > end, return MDB_PANIC.
     441             :  */
     442       13865 : static int lmdb_iterate_range(struct ldb_kv_private *ldb_kv,
     443             :                               struct ldb_val start_key,
     444             :                               struct ldb_val end_key,
     445             :                               ldb_kv_traverse_fn fn,
     446             :                               void *ctx)
     447             : {
     448       13865 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     449         199 :         MDB_val mdb_key;
     450         199 :         MDB_val mdb_data;
     451       13865 :         MDB_txn *txn = NULL;
     452       13865 :         MDB_dbi dbi = 0;
     453       13865 :         MDB_cursor *cursor = NULL;
     454         199 :         int ret;
     455             : 
     456         199 :         MDB_val mdb_s_key;
     457         199 :         MDB_val mdb_e_key;
     458             : 
     459       13865 :         txn = get_current_txn(lmdb);
     460       13865 :         if (txn == NULL) {
     461           0 :                 ldb_debug(lmdb->ldb, LDB_DEBUG_FATAL, "No transaction");
     462           0 :                 lmdb->error = MDB_PANIC;
     463           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     464             :         }
     465             : 
     466       13865 :         lmdb->error = mdb_dbi_open(txn, NULL, 0, &dbi);
     467       13865 :         if (lmdb->error != MDB_SUCCESS) {
     468           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     469             :         }
     470             : 
     471       13865 :         mdb_s_key.mv_size = start_key.length;
     472       13865 :         mdb_s_key.mv_data = start_key.data;
     473             : 
     474       13865 :         mdb_e_key.mv_size = end_key.length;
     475       13865 :         mdb_e_key.mv_data = end_key.data;
     476             : 
     477       13865 :         if (mdb_cmp(txn, dbi, &mdb_s_key, &mdb_e_key) > 0) {
     478           1 :                 lmdb->error = MDB_PANIC;
     479           1 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     480             :         }
     481             : 
     482       13864 :         lmdb->error = mdb_cursor_open(txn, dbi, &cursor);
     483       13864 :         if (lmdb->error != MDB_SUCCESS) {
     484           0 :                 goto done;
     485             :         }
     486             : 
     487       13864 :         lmdb->error = mdb_cursor_get(cursor, &mdb_s_key, &mdb_data, MDB_SET_RANGE);
     488             : 
     489       13864 :         if (lmdb->error != MDB_SUCCESS) {
     490          37 :                 if (lmdb->error == MDB_NOTFOUND) {
     491          37 :                         lmdb->error = MDB_SUCCESS;
     492             :                 }
     493          37 :                 goto done;
     494             :         } else {
     495       13827 :                 struct ldb_val key = {
     496       13827 :                         .length = mdb_s_key.mv_size,
     497       13827 :                         .data = mdb_s_key.mv_data,
     498             :                 };
     499       13827 :                 struct ldb_val data = {
     500       13827 :                         .length = mdb_data.mv_size,
     501       13827 :                         .data = mdb_data.mv_data,
     502             :                 };
     503             : 
     504       13827 :                 if (mdb_cmp(txn, dbi, &mdb_s_key, &mdb_e_key) > 0) {
     505         149 :                         goto done;
     506             :                 }
     507             : 
     508       13678 :                 ret = fn(ldb_kv, key, data, ctx);
     509       13678 :                 if (ret != 0) {
     510             :                         /*
     511             :                          * NOTE: This DOES NOT set lmdb->error!
     512             :                          *
     513             :                          * This means that the caller will get success.
     514             :                          * This matches TDB traverse behaviour, where callbacks
     515             :                          * may terminate the traverse, but do not change the
     516             :                          * return code from success.
     517             :                          *
     518             :                          * Callers SHOULD store their own error codes.
     519             :                          */
     520           0 :                         goto done;
     521             :                 }
     522             :         }
     523             : 
     524    29217967 :         while ((lmdb->error = mdb_cursor_get(
     525             :                         cursor, &mdb_key,
     526    29284069 :                         &mdb_data, MDB_NEXT)) == MDB_SUCCESS) {
     527             : 
     528    29271263 :                 struct ldb_val key = {
     529    29271263 :                         .length = mdb_key.mv_size,
     530    29271263 :                         .data = mdb_key.mv_data,
     531             :                 };
     532    29271263 :                 struct ldb_val data = {
     533    29271263 :                         .length = mdb_data.mv_size,
     534    29271263 :                         .data = mdb_data.mv_data,
     535             :                 };
     536             : 
     537    29271263 :                 if (mdb_cmp(txn, dbi, &mdb_key, &mdb_e_key) > 0) {
     538         872 :                         goto done;
     539             :                 }
     540             : 
     541    29270400 :                 ret = fn(ldb_kv, key, data, ctx);
     542    29270400 :                 if (ret != 0) {
     543             :                         /*
     544             :                          * NOTE: This DOES NOT set lmdb->error!
     545             :                          *
     546             :                          * This means that the caller will get success.
     547             :                          * This matches TDB traverse behaviour, where callbacks
     548             :                          * may terminate the traverse, but do not change the
     549             :                          * return code from success.
     550             :                          *
     551             :                          * Callers SHOULD store their own error codes.
     552             :                          */
     553           9 :                         goto done;
     554             :                 }
     555             :         }
     556       12806 :         if (lmdb->error == MDB_NOTFOUND) {
     557       12806 :                 lmdb->error = MDB_SUCCESS;
     558             :         }
     559           0 : done:
     560       13864 :         if (cursor != NULL) {
     561       13864 :                 mdb_cursor_close(cursor);
     562             :         }
     563             : 
     564       13864 :         if (lmdb->error != MDB_SUCCESS) {
     565           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     566             :         }
     567       13864 :         return ldb_mdb_err_map(lmdb->error);
     568             : }
     569             : 
     570   136200718 : static int lmdb_lock_read(struct ldb_module *module)
     571             : {
     572   136200718 :         void *data = ldb_module_get_private(module);
     573     5245085 :         struct ldb_kv_private *ldb_kv =
     574   136200718 :             talloc_get_type(data, struct ldb_kv_private);
     575   136200718 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     576   136200718 :         pid_t pid = getpid();
     577             : 
     578   136200718 :         if (pid != lmdb->pid) {
     579           1 :                 ldb_asprintf_errstring(
     580             :                         lmdb->ldb,
     581             :                         __location__": Reusing ldb opened by pid %d in "
     582             :                         "process %d\n",
     583             :                         lmdb->pid,
     584             :                         pid);
     585           1 :                 lmdb->error = MDB_BAD_TXN;
     586           1 :                 return LDB_ERR_PROTOCOL_ERROR;
     587             :         }
     588             : 
     589   136200717 :         lmdb->error = MDB_SUCCESS;
     590   136200717 :         if (lmdb_transaction_active(ldb_kv) == false &&
     591    84877711 :             ldb_kv->read_lock_count == 0) {
     592    23038131 :                 lmdb->error = mdb_txn_begin(lmdb->env,
     593             :                                             NULL,
     594             :                                             MDB_RDONLY,
     595             :                                             &lmdb->read_txn);
     596             :         }
     597   136200717 :         if (lmdb->error != MDB_SUCCESS) {
     598           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     599             :         }
     600             : 
     601   136200717 :         ldb_kv->read_lock_count++;
     602   136200717 :         return ldb_mdb_err_map(lmdb->error);
     603             : }
     604             : 
     605   136200716 : static int lmdb_unlock_read(struct ldb_module *module)
     606             : {
     607   136200716 :         void *data = ldb_module_get_private(module);
     608     5245083 :         struct ldb_kv_private *ldb_kv =
     609   136200716 :             talloc_get_type(data, struct ldb_kv_private);
     610             : 
     611   136200716 :         if (lmdb_transaction_active(ldb_kv) == false &&
     612    84877710 :             ldb_kv->read_lock_count == 1) {
     613    23038129 :                 struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     614    23038129 :                 mdb_txn_commit(lmdb->read_txn);
     615    23038129 :                 lmdb->read_txn = NULL;
     616    23038129 :                 ldb_kv->read_lock_count--;
     617    23038129 :                 return LDB_SUCCESS;
     618             :         }
     619   113162587 :         ldb_kv->read_lock_count--;
     620   113162587 :         return LDB_SUCCESS;
     621             : }
     622             : 
     623     1444167 : static int lmdb_transaction_start(struct ldb_kv_private *ldb_kv)
     624             : {
     625     1444167 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     626       50554 :         struct lmdb_trans *ltx;
     627       50554 :         struct lmdb_trans *ltx_head;
     628       50554 :         MDB_txn *tx_parent;
     629     1444167 :         pid_t pid = getpid();
     630             : 
     631             :         /* Do not take out the transaction lock on a read-only DB */
     632     1444167 :         if (ldb_kv->read_only) {
     633           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     634             :         }
     635             : 
     636     1444167 :         ltx = talloc_zero(lmdb, struct lmdb_trans);
     637     1444167 :         if (ltx == NULL) {
     638           0 :                 return ldb_oom(lmdb->ldb);
     639             :         }
     640             : 
     641     1444167 :         if (pid != lmdb->pid) {
     642           0 :                 ldb_asprintf_errstring(
     643             :                         lmdb->ldb,
     644             :                         __location__": Reusing ldb opened by pid %d in "
     645             :                         "process %d\n",
     646             :                         lmdb->pid,
     647             :                         pid);
     648           0 :                 lmdb->error = MDB_BAD_TXN;
     649           0 :                 return LDB_ERR_PROTOCOL_ERROR;
     650             :         }
     651             : 
     652             :         /*
     653             :          * Clear out any stale readers
     654             :          */
     655             :         {
     656     1444167 :                 int stale = 0;
     657     1444167 :                 mdb_reader_check(lmdb->env, &stale);
     658     1444167 :                 if (stale > 0) {
     659           1 :                         ldb_debug(
     660             :                                 lmdb->ldb,
     661             :                                 LDB_DEBUG_ERROR,
     662             :                                 "LMDB Stale readers, deleted (%d)",
     663             :                                 stale);
     664             :                 }
     665             :         }
     666             : 
     667             : 
     668             : 
     669     1444167 :         ltx_head = lmdb_private_trans_head(lmdb);
     670             : 
     671     1444167 :         tx_parent = lmdb_trans_get_tx(ltx_head);
     672             : 
     673     1444167 :         lmdb->error = mdb_txn_begin(lmdb->env, tx_parent, 0, &ltx->tx);
     674     1444167 :         if (lmdb->error != MDB_SUCCESS) {
     675           0 :                 return ldb_mdb_error(lmdb->ldb, lmdb->error);
     676             :         }
     677             : 
     678     1444167 :         trans_push(lmdb, ltx);
     679             : 
     680     1444167 :         return ldb_mdb_err_map(lmdb->error);
     681             : }
     682             : 
     683       74539 : static int lmdb_transaction_cancel(struct ldb_kv_private *ldb_kv)
     684             : {
     685         235 :         struct lmdb_trans *ltx;
     686       74539 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     687             : 
     688       74539 :         ltx = lmdb_private_trans_head(lmdb);
     689       74539 :         if (ltx == NULL) {
     690           2 :                 return LDB_ERR_OPERATIONS_ERROR;
     691             :         }
     692             : 
     693       74537 :         mdb_txn_abort(ltx->tx);
     694       74537 :         trans_finished(lmdb, ltx);
     695       74537 :         return LDB_SUCCESS;
     696             : }
     697             : 
     698      681108 : static int lmdb_transaction_prepare_commit(struct ldb_kv_private *ldb_kv)
     699             : {
     700             :         /* No need to prepare a commit */
     701      681108 :         return LDB_SUCCESS;
     702             : }
     703             : 
     704     1369629 : static int lmdb_transaction_commit(struct ldb_kv_private *ldb_kv)
     705             : {
     706       50318 :         struct lmdb_trans *ltx;
     707     1369629 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     708             : 
     709     1369629 :         ltx = lmdb_private_trans_head(lmdb);
     710     1369629 :         if (ltx == NULL) {
     711           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     712             :         }
     713             : 
     714     1369629 :         lmdb->error = mdb_txn_commit(ltx->tx);
     715     1369629 :         trans_finished(lmdb, ltx);
     716             : 
     717     1369629 :         return lmdb->error;
     718             : }
     719             : 
     720       34299 : static int lmdb_error(struct ldb_kv_private *ldb_kv)
     721             : {
     722       34299 :         return ldb_mdb_err_map(ldb_kv->lmdb_private->error);
     723             : }
     724             : 
     725           0 : static const char *lmdb_errorstr(struct ldb_kv_private *ldb_kv)
     726             : {
     727           0 :         return mdb_strerror(ldb_kv->lmdb_private->error);
     728             : }
     729             : 
     730           0 : static const char *lmdb_name(struct ldb_kv_private *ldb_kv)
     731             : {
     732           0 :         return "lmdb";
     733             : }
     734             : 
     735    99675982 : static bool lmdb_changed(struct ldb_kv_private *ldb_kv)
     736             : {
     737             :         /*
     738             :          * lmdb does no provide a quick way to determine if the database
     739             :          * has changed.  This function always returns true.
     740             :          *
     741             :          * Note that tdb uses a sequence number that allows this function
     742             :          * to be implemented efficiently.
     743             :          */
     744    99675982 :         return true;
     745             : }
     746             : 
     747             : /*
     748             :  * Get the number of records in the database.
     749             :  *
     750             :  * The mdb_env_stat call returns an accurate count, so we return the actual
     751             :  * number of records in the database rather than an estimate.
     752             :  */
     753           2 : static size_t lmdb_get_size(struct ldb_kv_private *ldb_kv)
     754             : {
     755             : 
     756           2 :         struct MDB_stat stats = {0};
     757           2 :         struct lmdb_private *lmdb = ldb_kv->lmdb_private;
     758           2 :         int ret = 0;
     759             : 
     760           2 :         ret = mdb_env_stat(lmdb->env, &stats);
     761           2 :         if (ret != 0) {
     762           0 :                 return 0;
     763             :         }
     764           2 :         return stats.ms_entries;
     765             : }
     766             : 
     767             : /*
     768             :  * Start a sub transaction
     769             :  * As lmdb supports nested transactions we can start a new transaction
     770             :  */
     771      686843 : static int lmdb_nested_transaction_start(struct ldb_kv_private *ldb_kv)
     772             : {
     773      686843 :         int ret = lmdb_transaction_start(ldb_kv);
     774      686843 :         return ret;
     775             : }
     776             : 
     777             : /*
     778             :  * Commit a sub transaction
     779             :  * As lmdb supports nested transactions we can commit the nested transaction
     780             :  */
     781      684822 : static int lmdb_nested_transaction_commit(struct ldb_kv_private *ldb_kv)
     782             : {
     783      684822 :         int ret = lmdb_transaction_commit(ldb_kv);
     784      684822 :         return ret;
     785             : }
     786             : 
     787             : /*
     788             :  * Cancel a sub transaction
     789             :  * As lmdb supports nested transactions we can cancel the nested transaction
     790             :  */
     791        2021 : static int lmdb_nested_transaction_cancel(struct ldb_kv_private *ldb_kv)
     792             : {
     793        2021 :         int ret = lmdb_transaction_cancel(ldb_kv);
     794        2021 :         return ret;
     795             : }
     796             : 
     797             : static struct kv_db_ops lmdb_key_value_ops = {
     798             :         .options            = LDB_KV_OPTION_STABLE_READ_LOCK,
     799             : 
     800             :         .store              = lmdb_store,
     801             :         .delete             = lmdb_delete,
     802             :         .iterate            = lmdb_traverse_fn,
     803             :         .update_in_iterate  = lmdb_update_in_iterate,
     804             :         .fetch_and_parse    = lmdb_parse_record,
     805             :         .iterate_range      = lmdb_iterate_range,
     806             :         .lock_read          = lmdb_lock_read,
     807             :         .unlock_read        = lmdb_unlock_read,
     808             :         .begin_write        = lmdb_transaction_start,
     809             :         .prepare_write      = lmdb_transaction_prepare_commit,
     810             :         .finish_write       = lmdb_transaction_commit,
     811             :         .abort_write        = lmdb_transaction_cancel,
     812             :         .error              = lmdb_error,
     813             :         .errorstr           = lmdb_errorstr,
     814             :         .name               = lmdb_name,
     815             :         .has_changed        = lmdb_changed,
     816             :         .transaction_active = lmdb_transaction_active,
     817             :         .get_size           = lmdb_get_size,
     818             :         .begin_nested_write = lmdb_nested_transaction_start,
     819             :         .finish_nested_write = lmdb_nested_transaction_commit,
     820             :         .abort_nested_write = lmdb_nested_transaction_cancel,
     821             : };
     822             : 
     823      468730 : static const char *lmdb_get_path(const char *url)
     824             : {
     825       29220 :         const char *path;
     826             : 
     827             :         /* parse the url */
     828      468730 :         if (strchr(url, ':')) {
     829      468668 :                 if (strncmp(url, MDB_URL_PREFIX, MDB_URL_PREFIX_SIZE) != 0) {
     830           0 :                         return NULL;
     831             :                 }
     832      468668 :                 path = url + MDB_URL_PREFIX_SIZE;
     833             :         } else {
     834          57 :                 path = url;
     835             :         }
     836             : 
     837      439510 :         return path;
     838             : }
     839             : 
     840      434415 : static int lmdb_pvt_destructor(struct lmdb_private *lmdb)
     841             : {
     842      434415 :         struct lmdb_trans *ltx = NULL;
     843             : 
     844             :         /* Check if this is a forked child */
     845      434415 :         if (getpid() != lmdb->pid) {
     846        4777 :                 int fd = 0;
     847             :                 /*
     848             :                  * We cannot call mdb_env_close or commit any transactions,
     849             :                  * otherwise they might appear finished in the parent.
     850             :                  *
     851             :                  */
     852             : 
     853        4777 :                 if (mdb_env_get_fd(lmdb->env, &fd) == 0) {
     854        4777 :                         close(fd);
     855             :                 }
     856             : 
     857             :                 /* Remove the pointer, so that no access should occur */
     858        4777 :                 lmdb->env = NULL;
     859             : 
     860        4777 :                 return 0;
     861             :         }
     862             : 
     863             :         /*
     864             :          * Close the read transaction if it's open
     865             :          */
     866      429638 :         if (lmdb->read_txn != NULL) {
     867           1 :                 mdb_txn_abort(lmdb->read_txn);
     868             :         }
     869             : 
     870      429638 :         if (lmdb->env == NULL) {
     871           0 :                 return 0;
     872             :         }
     873             : 
     874             :         /*
     875             :          * Abort any currently active transactions
     876             :          */
     877      429638 :         ltx = lmdb_private_trans_head(lmdb);
     878      429640 :         while (ltx != NULL) {
     879           2 :                 mdb_txn_abort(ltx->tx);
     880           2 :                 trans_finished(lmdb, ltx);
     881           2 :                 ltx = lmdb_private_trans_head(lmdb);
     882             :         }
     883      429638 :         lmdb->env = NULL;
     884             : 
     885      429638 :         return 0;
     886             : }
     887             : 
     888             : struct mdb_env_wrap {
     889             :         struct mdb_env_wrap *next, *prev;
     890             :         dev_t device;
     891             :         ino_t inode;
     892             :         MDB_env *env;
     893             :         pid_t pid;
     894             : };
     895             : 
     896             : static struct mdb_env_wrap *mdb_list;
     897             : 
     898             : /* destroy the last connection to an mdb */
     899       56149 : static int mdb_env_wrap_destructor(struct mdb_env_wrap *w)
     900             : {
     901       56149 :         mdb_env_close(w->env);
     902       56149 :         DLIST_REMOVE(mdb_list, w);
     903       56149 :         return 0;
     904             : }
     905             : 
     906      468730 : static int lmdb_open_env(TALLOC_CTX *mem_ctx,
     907             :                          MDB_env **env,
     908             :                          struct ldb_context *ldb,
     909             :                          const char *path,
     910             :                          const size_t env_map_size,
     911             :                          unsigned int flags)
     912             : {
     913       29220 :         int ret;
     914      468730 :         unsigned int mdb_flags = MDB_NOSUBDIR|MDB_NOTLS;
     915             :         /*
     916             :          * MDB_NOSUBDIR implies there is a separate file called path and a
     917             :          * separate lockfile called path-lock
     918             :          */
     919             : 
     920       29220 :         struct mdb_env_wrap *w;
     921       29220 :         struct stat st;
     922      468730 :         pid_t pid = getpid();
     923      468730 :         int fd = 0;
     924       29220 :         unsigned v;
     925             : 
     926      468730 :         if (stat(path, &st) == 0) {
     927     1597712 :                 for (w=mdb_list;w;w=w->next) {
     928     1508885 :                         if (st.st_dev == w->device &&
     929     1508885 :                             st.st_ino == w->inode &&
     930      418266 :                             pid == w->pid) {
     931             :                                 /*
     932             :                                  * We must have only one MDB_env per process
     933             :                                  */
     934      378399 :                                 if (!talloc_reference(mem_ctx, w)) {
     935           0 :                                         return ldb_oom(ldb);
     936             :                                 }
     937      378399 :                                 *env = w->env;
     938      378399 :                                 return LDB_SUCCESS;
     939             :                         }
     940             :                 }
     941             :         }
     942             : 
     943       90331 :         w = talloc(mem_ctx, struct mdb_env_wrap);
     944       90331 :         if (w == NULL) {
     945           0 :                 return ldb_oom(ldb);
     946             :         }
     947             : 
     948       90331 :         ret = mdb_env_create(env);
     949       90331 :         if (ret != 0) {
     950           0 :                 ldb_asprintf_errstring(
     951             :                         ldb,
     952             :                         "Could not create MDB environment %s: %s\n",
     953             :                         path,
     954             :                         mdb_strerror(ret));
     955           0 :                 return ldb_mdb_err_map(ret);
     956             :         }
     957             : 
     958       90331 :         if (env_map_size > 0) {
     959         342 :                 ret = mdb_env_set_mapsize(*env, env_map_size);
     960         342 :                 if (ret != 0) {
     961           0 :                         ldb_asprintf_errstring(
     962             :                                 ldb,
     963             :                                 "Could not set MDB mmap() size to %llu "
     964             :                                 "on %s: %s\n",
     965             :                                 (unsigned long long)(env_map_size),
     966             :                                 path,
     967             :                                 mdb_strerror(ret));
     968           0 :                         TALLOC_FREE(w);
     969           0 :                         return ldb_mdb_err_map(ret);
     970             :                 }
     971             :         }
     972             : 
     973       90331 :         mdb_env_set_maxreaders(*env, 100000);
     974             :         /*
     975             :          * As we ensure that there is only one MDB_env open per database per
     976             :          * process. We can not use the MDB_RDONLY flag, as another ldb may be
     977             :          * opened in read write mode
     978             :          */
     979       90331 :         if (flags & LDB_FLG_NOSYNC) {
     980       89105 :                 mdb_flags |= MDB_NOSYNC;
     981             :         }
     982       90331 :         ret = mdb_env_open(*env, path, mdb_flags, 0644);
     983       90331 :         if (ret != 0) {
     984          62 :                 ldb_asprintf_errstring(ldb,
     985             :                                 "Could not open DB %s: %s\n",
     986             :                                 path, mdb_strerror(ret));
     987          62 :                 TALLOC_FREE(w);
     988          62 :                 return ldb_mdb_err_map(ret);
     989             :         }
     990             : 
     991             :         {
     992       90269 :                 MDB_envinfo stat = {0};
     993       90269 :                 ret = mdb_env_info (*env, &stat);
     994       90269 :                 if (ret != 0) {
     995           0 :                         ldb_asprintf_errstring(
     996             :                                 ldb,
     997             :                                 "Could not get MDB environment stats %s: %s\n",
     998             :                                 path,
     999             :                                 mdb_strerror(ret));
    1000           0 :                 return ldb_mdb_err_map(ret);
    1001             :                 }
    1002             :         }
    1003             : 
    1004       90269 :         ret = mdb_env_get_fd(*env, &fd);
    1005       90269 :         if (ret != 0) {
    1006           0 :                 ldb_asprintf_errstring(ldb,
    1007             :                                        "Could not obtain DB FD %s: %s\n",
    1008             :                                        path, mdb_strerror(ret));
    1009           0 :                 TALLOC_FREE(w);
    1010           0 :                 return ldb_mdb_err_map(ret);
    1011             :         }
    1012             : 
    1013             :         /* Just as for TDB: on exec, don't inherit the fd */
    1014       90269 :         v = fcntl(fd, F_GETFD, 0);
    1015       90269 :         if (v == -1) {
    1016           0 :                 TALLOC_FREE(w);
    1017           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1018             :         }
    1019             : 
    1020       90269 :         ret = fcntl(fd, F_SETFD, v | FD_CLOEXEC);
    1021       90269 :         if (ret == -1) {
    1022           0 :                 TALLOC_FREE(w);
    1023           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1024             :         }
    1025             : 
    1026       90269 :         if (fstat(fd, &st) != 0) {
    1027           0 :                 ldb_asprintf_errstring(
    1028             :                         ldb,
    1029             :                         "Could not stat %s:\n",
    1030             :                         path);
    1031           0 :                 TALLOC_FREE(w);
    1032           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1033             :         }
    1034       90269 :         w->env = *env;
    1035       90269 :         w->device = st.st_dev;
    1036       90269 :         w->inode  = st.st_ino;
    1037       90269 :         w->pid = pid;
    1038             : 
    1039       90269 :         talloc_set_destructor(w, mdb_env_wrap_destructor);
    1040             : 
    1041       90269 :         DLIST_ADD(mdb_list, w);
    1042             : 
    1043       82779 :         return LDB_SUCCESS;
    1044             : 
    1045             : }
    1046             : 
    1047      468730 : static int lmdb_pvt_open(struct lmdb_private *lmdb,
    1048             :                          struct ldb_context *ldb,
    1049             :                          const char *path,
    1050             :                          const size_t env_map_size,
    1051             :                          unsigned int flags)
    1052             : {
    1053       29220 :         int ret;
    1054       29220 :         int lmdb_max_key_length;
    1055             : 
    1056      468730 :         if (flags & LDB_FLG_DONT_CREATE_DB) {
    1057       28958 :                 struct stat st;
    1058      465516 :                 if (stat(path, &st) != 0) {
    1059           0 :                         return LDB_ERR_UNAVAILABLE;
    1060             :                 }
    1061             :         }
    1062             : 
    1063      468730 :         ret = lmdb_open_env(lmdb, &lmdb->env, ldb, path, env_map_size, flags);
    1064      468730 :         if (ret != 0) {
    1065          57 :                 return ret;
    1066             :         }
    1067             : 
    1068             :         /* Close when lmdb is released */
    1069      468668 :         talloc_set_destructor(lmdb, lmdb_pvt_destructor);
    1070             : 
    1071             :         /* Store the original pid during the LMDB open */
    1072      468668 :         lmdb->pid = getpid();
    1073             : 
    1074      468668 :         lmdb_max_key_length = mdb_env_get_maxkeysize(lmdb->env);
    1075             : 
    1076             :         /* This will never happen, but if it does make sure to freak out */
    1077      468668 :         if (lmdb_max_key_length < LDB_MDB_MAX_KEY_LENGTH) {
    1078           0 :                 return ldb_operr(ldb);
    1079             :         }
    1080             : 
    1081      439453 :         return LDB_SUCCESS;
    1082             : }
    1083             : 
    1084      468730 : int lmdb_connect(struct ldb_context *ldb,
    1085             :                  const char *url,
    1086             :                  unsigned int flags,
    1087             :                  const char *options[],
    1088             :                  struct ldb_module **_module)
    1089             : {
    1090      468730 :         const char *path = NULL;
    1091      468730 :         struct lmdb_private *lmdb = NULL;
    1092      468730 :         struct ldb_kv_private *ldb_kv = NULL;
    1093       29220 :         int ret;
    1094      468730 :         size_t env_map_size = 0;
    1095             : 
    1096             :         /*
    1097             :          * We hold locks, so we must use a private event context
    1098             :          * on each returned handle
    1099             :          */
    1100      468730 :         ldb_set_require_private_event_context(ldb);
    1101             : 
    1102      468730 :         path = lmdb_get_path(url);
    1103      468730 :         if (path == NULL) {
    1104           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid mdb URL '%s'", url);
    1105           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1106             :         }
    1107             : 
    1108      468730 :         ldb_kv = talloc_zero(ldb, struct ldb_kv_private);
    1109      468730 :         if (!ldb_kv) {
    1110           0 :                 ldb_oom(ldb);
    1111           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1112             :         }
    1113             : 
    1114      468730 :         lmdb = talloc_zero(ldb_kv, struct lmdb_private);
    1115      468730 :         if (lmdb == NULL) {
    1116           0 :                 TALLOC_FREE(ldb_kv);
    1117           0 :                 return ldb_oom(ldb);
    1118             :         }
    1119      468730 :         lmdb->ldb = ldb;
    1120      468730 :         ldb_kv->kv_ops = &lmdb_key_value_ops;
    1121             : 
    1122             :         {
    1123      468730 :                 const char *size = ldb_options_find(
    1124             :                         ldb, ldb->options, "lmdb_env_size");
    1125      468730 :                 if (size != NULL) {
    1126         342 :                         env_map_size = strtoull(size, NULL, 0);
    1127             :                 }
    1128             :         }
    1129             : 
    1130      468730 :         ret = lmdb_pvt_open(lmdb, ldb, path, env_map_size, flags);
    1131      468730 :         if (ret != LDB_SUCCESS) {
    1132          62 :                 TALLOC_FREE(ldb_kv);
    1133          62 :                 return ret;
    1134             :         }
    1135             : 
    1136      468668 :         ldb_kv->lmdb_private = lmdb;
    1137      468668 :         if (flags & LDB_FLG_RDONLY) {
    1138          36 :                 ldb_kv->read_only = true;
    1139             :         }
    1140             : 
    1141             :         /*
    1142             :          * This maximum length becomes encoded in the index values so
    1143             :          * must never change even if LMDB starts to allow longer keys.
    1144             :          * The override option is max_key_len_for_self_test, and is
    1145             :          * used for testing only.
    1146             :          */
    1147      468668 :         ldb_kv->max_key_length = LDB_MDB_MAX_KEY_LENGTH;
    1148             : 
    1149      468668 :         return ldb_kv_init_store(
    1150             :             ldb_kv, "ldb_mdb backend", ldb, options, _module);
    1151             : }

Generated by: LCOV version 1.14