caffe的db_lmdb.hpp文件


先總的說一下:

類:LMDBCursor:  它干了點什么?它需要傳入參數為:mdb_txn(傳入它是因為用完它,把它absort掉), mdb_cursor;它應該是用來讀出數據的;

類:LMDBTransaction:

它主要是用來寫入數據的吧,,用put()函數 ,與commit()函數;

 

最終還是靠類:LMDB應該算是一個對上面兩個類的調用吧。它應該算是做了封裝吧,,干脆直接上代碼啦:

db_lmdb.hpp

1 #ifdef USE_LMDB                                                                                                                                                                            
  2 #ifndef CAFFE_UTIL_DB_LMDB_HPP
  3 #define CAFFE_UTIL_DB_LMDB_HPP
  4 
  5 #include <string>
  6 #include <vector>
  7 
  8 #include "lmdb.h"
  9 
 10 #include "caffe/util/db.hpp"
 11 
 12 namespace caffe { namespace db {
 13 // 下面的MDB_SUCCESS為一個宏定義,為0,表示成功,如果失敗則對應不同的數值,表示不同的錯誤;
 14 //  mdb_strerror,輸出string,它的作用是根據不同的錯誤輸出不同的錯誤語句;
 15 inline void MDB_CHECK(int mdb_status) {
 16   CHECK_EQ(mdb_status, MDB_SUCCESS) << mdb_strerror(mdb_status);
 17 }
 18 
 19 //注意:MDB_cursor是與一個specific的transaction與database相關聯的;
 20 class LMDBCursor : public Cursor {
 21  public:
 22   explicit LMDBCursor(MDB_txn* mdb_txn, MDB_cursor* mdb_cursor)  //初始化時,給mdb_txn,與mdb_curcor賦值;
 23   : mdb_txn_(mdb_txn), mdb_cursor_(mdb_cursor), valid_(false) {
 24     SeekToFirst();
 25   }
 26   virtual ~LMDBCursor() {
 27     mdb_cursor_close(mdb_cursor_); //mdb_cursor_close函數的作用為:關閉一個cursor句柄;
 28     mdb_txn_abort(mdb_txn_);  //該函數的作用為:用於放棄所有對transaction的操作,並釋放掉transaction句柄;
 29   }
 30   virtual void SeekToFirst() { Seek(MDB_FIRST); }  //把database里的第一個key/value的值放入變量:mdb_key_與mdb_value_;
 31   virtual void Next() { Seek(MDB_NEXT); }    //下一個;;
 32   virtual string key() {
 33     return string(static_cast<const char*>(mdb_key_.mv_data), mdb_key_.mv_size); //返回mdb_key_里的數據,以字符串形式;
 34   }
 35   virtual string value() {
 36     return string(static_cast<const char*>(mdb_value_.mv_data),
 37         mdb_value_.mv_size); //返回mdb_value_里的數據(以字符串的方式;,應該是用了strin的構造函數吧.
 38   }
 39   virtual bool valid() { return valid_; }
 40 
 41  private:
 42   void Seek(MDB_cursor_op op) {    //注意,這里的MDB_cursor_op為枚舉類型,代表了curcor的相關操作;
 43     int mdb_status = mdb_cursor_get(mdb_cursor_, &mdb_key_, &mdb_value_, op); //這個函數用於通過curcor恢復key與data;
 44     if (mdb_status == MDB_NOTFOUND) {      //當返回的狀態為MDB_NOTFOUND時,表明,沒有發現匹配的key;
 45       valid_ = false;
 46     } else {
 47       MDB_CHECK(mdb_status);
 48       valid_ = true;
 49     }
 50   }
 51 
 52   MDB_txn* mdb_txn_;         //初始化時,給mdb_txn,與mdb_curcor賦值;
 53   MDB_cursor* mdb_cursor_;
 54   MDB_val mdb_key_, mdb_value_; 
55   bool valid_;
 56 };
 57 
 58 class LMDBTransaction : public Transaction {
 59  public:
 60   explicit LMDBTransaction(MDB_env* mdb_env)     //給一個環境handle賦值;
 61     : mdb_env_(mdb_env) { }
 62   virtual void Put(const string& key, const string& value); //把key與value的值分別push到對應的vector里;
 63   virtual void Commit(); //它做的時,把keys 與 values里的數據提交 ,並清空它們;
 64 
 65  private:
 66   MDB_env* mdb_env_;    //環境句柄;
 67   vector<string> keys, values;  //兩個vector容器;
 68 
 69   void DoubleMapSize();    //把環境的mapsize擴大兩倍;
 70 
 71   DISABLE_COPY_AND_ASSIGN(LMDBTransaction);
 72 };
 73 
 74 class LMDB : public DB {
 75  public:
 76   LMDB() : mdb_env_(NULL) { }
 77   virtual ~LMDB() { Close(); }
 78   virtual void Open(const string& source, Mode mode); //它所做的事情就是創建一個操作環境,根據mode,來決定是讀還是NEW;
 79   virtual void Close() {
 80     if (mdb_env_ != NULL) {                 //它所做的就是:當所創建的環境的handle 不為空時,說明還沒有釋放掉;
 81       mdb_dbi_close(mdb_env_, mdb_dbi_);    //於是呢,把相關的如database的handle,以及mdb_env_釋放掉,釋放先前的內存;
 82       mdb_env_close(mdb_env_);
 83       mdb_env_ = NULL;
 84     }
 85   }
 86   virtual LMDBCursor* NewCursor();         //根據mdb_env_,mdb_dbi_,創建了一個LMDBCursor的類;
 87   virtual LMDBTransaction* NewTransaction(); //返回一個用mdb_env_初始化了的LMDBTransaction類的指針;
 88 
 89  private:
 90   MDB_env* mdb_env_;
 91   MDB_dbi mdb_dbi_;
 92 };
 93 
 94 }  // namespace db
 95 }  // namespace caffe
 96 
 97 #endif  // CAFFE_UTIL_DB_LMDB_HPP
 98 #endif  // USE_LMDB

db_lmdb.cpp

1 #ifdef USE_LMDB
  2 #include "caffe/util/db_lmdb.hpp"
  3 
  4 #include <sys/stat.h>
  5 
  6 #include <string>
  7 
  8 namespace caffe { namespace db {
  9 
 10 void LMDB::Open(const string& source, Mode mode) {
 11   MDB_CHECK(mdb_env_create(&mdb_env_));
 12   if (mode == NEW) {
 13     CHECK_EQ(mkdir(source.c_str(), 0744), 0) << "mkdir " << source << " failed";  //如果為NEW, 則創建一個source的路徑;
 14   }
 15   int flags = 0;
 16   if (mode == READ) {
 17     flags = MDB_RDONLY | MDB_NOTLS; //設置一下它的特別選項,一個是只讀,一個是不使用線程本地存儲;
 18   }
 19   int rc = mdb_env_open(mdb_env_, source.c_str(), flags, 0664);                                                                                                                            
 20 #ifndef ALLOW_LMDB_NOLOCK
 21   MDB_CHECK(rc);
 22 #else
 23   if (rc == EACCES) { //表示:the user didn't have permission to access the environment files. 
 24     LOG(WARNING) << "Permission denied. Trying with MDB_NOLOCK ...";
 25     // Close and re-open environment handle
 26     mdb_env_close(mdb_env_);
 27     MDB_CHECK(mdb_env_create(&mdb_env_));
 28     // Try again with MDB_NOLOCK
 29     flags |= MDB_NOLOCK; //增加了一個選項,它的意思為不作任何鎖操作;
 30     MDB_CHECK(mdb_env_open(mdb_env_, source.c_str(), flags, 0664));
 31   } else {
 32     MDB_CHECK(rc);
 33   }
 34 #endif
 35   LOG(INFO) << "Opened lmdb " << source;
 36 }
 37 
 38 LMDBCursor* LMDB::NewCursor() {
 39   MDB_txn* mdb_txn;
 40   MDB_cursor* mdb_cursor;
 41   MDB_CHECK(mdb_txn_begin(mdb_env_, NULL, MDB_RDONLY, &mdb_txn));
 42   MDB_CHECK(mdb_dbi_open(mdb_txn, NULL, 0, &mdb_dbi_));
 43   MDB_CHECK(mdb_cursor_open(mdb_txn, mdb_dbi_, &mdb_cursor));
 44   return new LMDBCursor(mdb_txn, mdb_cursor); //不明白為什么把局部的mdb_txn返回去,在LMDBCursor類里面,也就析構函數用到了mdb_txn,
 45  //可以就是為了去用函數mdb_txn_abort把它干掉吧;,似乎明白了呢,等用完它,把它干掉吧;
 46 }
 47 
 48 LMDBTransaction* LMDB::NewTransaction() {
 49   return new LMDBTransaction(mdb_env_);
 50 }
 51 
 52 void LMDBTransaction::Put(const string& key, const string& value) {
 53   keys.push_back(key);
 54   values.push_back(value);
55 }
 56 
 57 void LMDBTransaction::Commit() {
 58   MDB_dbi mdb_dbi;
 59   MDB_val mdb_key, mdb_data;
 60   MDB_txn *mdb_txn;
 61 
 62   // Initialize MDB variables
 63   MDB_CHECK(mdb_txn_begin(mdb_env_, NULL, 0, &mdb_txn));
 64   MDB_CHECK(mdb_dbi_open(mdb_txn, NULL, 0, &mdb_dbi));
 65 
 66   for (int i = 0; i < keys.size(); i++) {
 67     mdb_key.mv_size = keys[i].size();
 68     mdb_key.mv_data = const_cast<char*>(keys[i].data());
 69     mdb_data.mv_size = values[i].size();
 70     mdb_data.mv_data = const_cast<char*>(values[i].data());
 71 
 72     // Add data to the transaction
 73     int put_rc = mdb_put(mdb_txn, mdb_dbi, &mdb_key, &mdb_data, 0); //即把key/data的值放入database里去;
 74     if (put_rc == MDB_MAP_FULL) {
 75       // Out of memory - double the map size and retry
 76       mdb_txn_abort(mdb_txn);
 77       mdb_dbi_close(mdb_env_, mdb_dbi);
 78       DoubleMapSize();
 79       Commit(); //不明白 為什么能調用 Commit(),回去復習一下C++;
 80       return;
 81     }
 82     // May have failed for some other reason
 83     MDB_CHECK(put_rc);
 84   }
 85 
 86   // Commit the transaction
 87   int commit_rc = mdb_txn_commit(mdb_txn);
 88   if (commit_rc == MDB_MAP_FULL) {
 89     // Out of memory - double the map size and retry
 90     mdb_dbi_close(mdb_env_, mdb_dbi);
 91     DoubleMapSize();
 92     Commit();
 93     return;
 94   }
 95   // May have failed for some other reason
 96   MDB_CHECK(commit_rc);
 97 
 98   // Cleanup after successful commit
 99   mdb_dbi_close(mdb_env_, mdb_dbi);
100   keys.clear(); //清空keys and values;
101   values.clear();
102 }
103 
104 void LMDBTransaction::DoubleMapSize() {
105   struct MDB_envinfo current_info;
106   MDB_CHECK(mdb_env_info(mdb_env_, &current_info));
107   size_t new_size = current_info.me_mapsize * 2;
108   DLOG(INFO) << "Doubling LMDB map size to " << (new_size>>20) << "MB ..."; 
109   MDB_CHECK(mdb_env_set_mapsize(mdb_env_, new_size));
110 }
111 
112 }  // namespace db
113 }  // namespace caffe
114 #endif  // USE_LMDB


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM