2222#include  < string> 
2323#include  < memory> 
2424
25+ #include  < pthread.h> 
26+ 
2527#include  " modsecurity/variable_value.h" 
2628#include  " src/utils/regex.h" 
2729#include  " src/variables/variable.h" 
@@ -36,21 +38,22 @@ namespace backend {
3638#ifdef  WITH_LMDB
3739
3840LMDB::LMDB (std::string name) :
39-     Collection(name), m_env(NULL ) {
40-     MDB_txn *txn;
41-     mdb_env_create (&m_env);
42-     mdb_env_open (m_env, " ./modsec-shared-collections" 
43-         MDB_WRITEMAP | MDB_NOSUBDIR, 0664 );
44-     mdb_txn_begin (m_env, NULL , 0 , &txn);
45-     mdb_dbi_open (txn, NULL , MDB_CREATE | MDB_DUPSORT, &m_dbi);
46-     mdb_txn_commit (txn);
47- }
41+     Collection(name), m_env(NULL ), isOpen(false ) {}
4842
4943
5044LMDB::~LMDB () {
5145    mdb_env_close (m_env);
5246}
5347
48+ int  LMDB::txn_begin (unsigned  int  flags, MDB_txn **ret) {
49+     if  (!isOpen) {
50+         MDBEnvProvider* provider = MDBEnvProvider::GetInstance ();
51+         m_env = provider->GetEnv ();
52+         m_dbi = *(provider->GetDBI ());
53+         isOpen = true ;
54+     }
55+     return  mdb_txn_begin (m_env, NULL , flags, ret);
56+ }
5457
5558void  LMDB::string2val (const  std::string& str, MDB_val *val) {
5659    val->mv_size  = sizeof (char )*(str.size ());
@@ -159,7 +162,7 @@ std::unique_ptr<std::string> LMDB::resolveFirst(const std::string& var) {
159162
160163    string2val (var, &mdb_key);
161164
162-     rc = mdb_txn_begin (m_env,  NULL ,  MDB_RDONLY, &txn);
165+     rc = txn_begin ( MDB_RDONLY, &txn);
163166    lmdb_debug (rc, " txn" " resolveFirst" 
164167    if  (rc != 0 ) {
165168        goto  end_txn;
@@ -192,7 +195,7 @@ bool LMDB::storeOrUpdateFirst(const std::string &key,
192195    string2val (key, &mdb_key);
193196    string2val (value, &mdb_value);
194197
195-     rc = mdb_txn_begin (m_env,  NULL ,  0 , &txn);
198+     rc = txn_begin ( 0 , &txn);
196199    lmdb_debug (rc, " txn" " storeOrUpdateFirst" 
197200    if  (rc != 0 ) {
198201        goto  end_txn;
@@ -240,7 +243,7 @@ void LMDB::resolveSingleMatch(const std::string& var,
240243    MDB_val mdb_value_ret;
241244    MDB_cursor *cursor;
242245
243-     rc = mdb_txn_begin (m_env,  NULL ,  MDB_RDONLY, &txn);
246+     rc = txn_begin ( MDB_RDONLY, &txn);
244247    lmdb_debug (rc, " txn" " resolveSingleMatch" 
245248    if  (rc != 0 ) {
246249        goto  end_txn;
@@ -271,7 +274,7 @@ void LMDB::store(std::string key, std::string value) {
271274    int  rc;
272275    MDB_stat mst;
273276
274-     rc = mdb_txn_begin (m_env,  NULL ,  0 , &txn);
277+     rc = txn_begin ( 0 , &txn);
275278    lmdb_debug (rc, " txn" " store" 
276279    if  (rc != 0 ) {
277280        goto  end_txn;
@@ -310,7 +313,7 @@ bool LMDB::updateFirst(const std::string &key,
310313    MDB_val mdb_value;
311314    MDB_val mdb_value_ret;
312315
313-     rc = mdb_txn_begin (m_env,  NULL ,  0 , &txn);
316+     rc = txn_begin ( 0 , &txn);
314317    lmdb_debug (rc, " txn" " updateFirst" 
315318    if  (rc != 0 ) {
316319        goto  end_txn;
@@ -364,7 +367,7 @@ void LMDB::del(const std::string& key) {
364367    MDB_val mdb_value_ret;
365368    MDB_stat mst;
366369
367-     rc = mdb_txn_begin (m_env,  NULL ,  0 , &txn);
370+     rc = txn_begin ( 0 , &txn);
368371    lmdb_debug (rc, " txn" " del" 
369372    if  (rc != 0 ) {
370373        goto  end_txn;
@@ -411,7 +414,7 @@ void LMDB::resolveMultiMatches(const std::string& var,
411414    size_t  keySize = var.size ();
412415    MDB_cursor *cursor;
413416
414-     rc = mdb_txn_begin (m_env,  NULL ,  MDB_RDONLY, &txn);
417+     rc = txn_begin ( MDB_RDONLY, &txn);
415418    lmdb_debug (rc, " txn" " resolveMultiMatches" 
416419    if  (rc != 0 ) {
417420        goto  end_txn;
@@ -465,7 +468,7 @@ void LMDB::resolveRegularExpression(const std::string& var,
465468
466469    Utils::Regex r (var, true );
467470
468-     rc = mdb_txn_begin (m_env,  NULL ,  MDB_RDONLY, &txn);
471+     rc = txn_begin ( MDB_RDONLY, &txn);
469472    lmdb_debug (rc, " txn" " resolveRegularExpression" 
470473    if  (rc != 0 ) {
471474        goto  end_txn;
@@ -503,6 +506,61 @@ void LMDB::resolveRegularExpression(const std::string& var,
503506    return ;
504507}
505508
509+ 
510+ MDBEnvProvider* MDBEnvProvider::provider_ = nullptr ;;
511+ 
512+ MDBEnvProvider* MDBEnvProvider::GetInstance () {
513+     if  (provider_==nullptr ) {
514+         provider_ = new  MDBEnvProvider ();
515+     }
516+     return  provider_;
517+ }
518+ 
519+ void  MDBEnvProvider::Finalize () {
520+     if  (provider_!=nullptr ) {
521+         provider_->close ();
522+         provider_ = nullptr ;
523+     }
524+ }
525+ 
526+ MDBEnvProvider::MDBEnvProvider () :
527+     m_env(NULL ), initialized(false ) {
528+     pthread_mutex_init (&m_lock, NULL );
529+ }
530+ 
531+ MDB_env* MDBEnvProvider::GetEnv () {
532+     init ();
533+     return  m_env;
534+ }
535+ 
536+ MDB_dbi* MDBEnvProvider::GetDBI () {
537+     init ();
538+     return  &m_dbi;
539+ }
540+ 
541+ void  MDBEnvProvider::init () {
542+     pthread_mutex_lock (&m_lock);
543+     if  (!initialized) {
544+         MDB_txn *txn;
545+         mdb_env_create (&m_env);
546+         mdb_env_open (m_env, " ./modsec-shared-collections" 
547+             MDB_WRITEMAP | MDB_NOSUBDIR, 0664 );
548+         mdb_txn_begin (m_env, NULL , 0 , &txn);
549+         mdb_dbi_open (txn, NULL , MDB_CREATE | MDB_DUPSORT, &m_dbi);
550+         mdb_txn_commit (txn);
551+     }
552+     pthread_mutex_unlock (&m_lock);
553+ }
554+ 
555+ void  MDBEnvProvider::close () {
556+     pthread_mutex_lock (&m_lock);
557+     if  (initialized) {
558+         mdb_dbi_close (m_env, m_dbi);
559+         mdb_env_close (m_env);
560+     }
561+     pthread_mutex_unlock (&m_lock);
562+ }
563+ 
506564#endif 
507565
508566}  //  namespace backend
0 commit comments