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