先总的说一下:

类:LMDBCursor:  它干了点什么?它需要传入参数为:mdb_txn(传入它是因为用完它,把它absort掉), mdb_cursor;它应该是用来读出数据的;

类:LMDBTransaction:

它主要是用来写入数据的吧,,用put()函数 ,与commit()函数;

最终还是靠类:LMDB应该算是一个对上面两个类的调用吧。它应该算是做了封装吧,,干脆直接上代码啦:

db_lmdb.hpp

  1. 1 #ifdef USE_LMDB
  2. 2 #ifndef CAFFE_UTIL_DB_LMDB_HPP
  3. 3 #define CAFFE_UTIL_DB_LMDB_HPP
  4. 4
  5. 5 #include <string>
  6. 6 #include <vector>
  7. 7
  8. 8 #include "lmdb.h"
  9. 9
  10. 10 #include "caffe/util/db.hpp"
  11. 11
  12. 12 namespace caffe { namespace db {
  13. 13 // 下面的MDB_SUCCESS为一个宏定义,为0,表示成功,如果失败则对应不同的数值,表示不同的错误;
  14. 14 // mdb_strerror,输出string,它的作用是根据不同的错误输出不同的错误语句;
  15. 15 inline void MDB_CHECK(int mdb_status) {
  16. 16 CHECK_EQ(mdb_status, MDB_SUCCESS) << mdb_strerror(mdb_status);
  17. 17 }
  18. 18
  19. 19 //注意:MDB_cursor是与一个specific的transaction与database相关联的;
  20. 20 class LMDBCursor : public Cursor {
  21. 21 public:
  22. 22 explicit LMDBCursor(MDB_txn* mdb_txn, MDB_cursor* mdb_cursor) //初始化时,给mdb_txn,与mdb_curcor赋值;
  23. 23 : mdb_txn_(mdb_txn), mdb_cursor_(mdb_cursor), valid_(false) {
  24. 24 SeekToFirst();
  25. 25 }
  26. 26 virtual ~LMDBCursor() {
  27. 27 mdb_cursor_close(mdb_cursor_); //mdb_cursor_close函数的作用为:关闭一个cursor句柄;
  28. 28 mdb_txn_abort(mdb_txn_); //该函数的作用为:用于放弃所有对transaction的操作,并释放掉transaction句柄;
  29. 29 }
  30. 30 virtual void SeekToFirst() { Seek(MDB_FIRST); } //把database里的第一个key/value的值放入变量:mdb_key_与mdb_value_;
  31. 31 virtual void Next() { Seek(MDB_NEXT); } //下一个;;
  32. 32 virtual string key() {
  33. 33 return string(static_cast<const char*>(mdb_key_.mv_data), mdb_key_.mv_size); //返回mdb_key_里的数据,以字符串形式;
  34. 34 }
  35. 35 virtual string value() {
  36. 36 return string(static_cast<const char*>(mdb_value_.mv_data),
  37. 37 mdb_value_.mv_size); //返回mdb_value_里的数据(以字符串的方式;,应该是用了strin的构造函数吧.
  38. 38 }
  39. 39 virtual bool valid() { return valid_; }
  40. 40
  41. 41 private:
  42. 42 void Seek(MDB_cursor_op op) { //注意,这里的MDB_cursor_op为枚举类型,代表了curcor的相关操作;
  43. 43 int mdb_status = mdb_cursor_get(mdb_cursor_, &mdb_key_, &mdb_value_, op); //这个函数用于通过curcor恢复key与data;
  44. 44 if (mdb_status == MDB_NOTFOUND) { //当返回的状态为MDB_NOTFOUND时,表明,没有发现匹配的key;
  45. 45 valid_ = false;
  46. 46 } else {
  47. 47 MDB_CHECK(mdb_status);
  48. 48 valid_ = true;
  49. 49 }
  50. 50 }
  51. 51
  52. 52 MDB_txn* mdb_txn_; //初始化时,给mdb_txn,与mdb_curcor赋值;
  53. 53 MDB_cursor* mdb_cursor_;
  54. 54 MDB_val mdb_key_, mdb_value_;
  55. 55 bool valid_;
  56. 56 };
  57. 57
  58. 58 class LMDBTransaction : public Transaction {
  59. 59 public:
  60. 60 explicit LMDBTransaction(MDB_env* mdb_env) //给一个环境handle赋值;
  61. 61 : mdb_env_(mdb_env) { }
  62. 62 virtual void Put(const string& key, const string& value); //把key与value的值分别push到对应的vector里;
  63. 63 virtual void Commit(); //它做的时,把keys 与 values里的数据提交 ,并清空它们;
  64. 64
  65. 65 private:
  66. 66 MDB_env* mdb_env_; //环境句柄;
  67. 67 vector<string> keys, values; //两个vector容器;
  68. 68
  69. 69 void DoubleMapSize(); //把环境的mapsize扩大两倍;
  70. 70
  71. 71 DISABLE_COPY_AND_ASSIGN(LMDBTransaction);
  72. 72 };
  73. 73
  74. 74 class LMDB : public DB {
  75. 75 public:
  76. 76 LMDB() : mdb_env_(NULL) { }
  77. 77 virtual ~LMDB() { Close(); }
  78. 78 virtual void Open(const string& source, Mode mode); //它所做的事情就是创建一个操作环境,根据mode,来决定是读还是NEW;
  79. 79 virtual void Close() {
  80. 80 if (mdb_env_ != NULL) { //它所做的就是:当所创建的环境的handle 不为空时,说明还没有释放掉;
  81. 81 mdb_dbi_close(mdb_env_, mdb_dbi_); //于是呢,把相关的如database的handle,以及mdb_env_释放掉,释放先前的内存;
  82. 82 mdb_env_close(mdb_env_);
  83. 83 mdb_env_ = NULL;
  84. 84 }
  85. 85 }
  86. 86 virtual LMDBCursor* NewCursor(); //根据mdb_env_,mdb_dbi_,创建了一个LMDBCursor的类;
  87. 87 virtual LMDBTransaction* NewTransaction(); //返回一个用mdb_env_初始化了的LMDBTransaction类的指针;
  88. 88
  89. 89 private:
  90. 90 MDB_env* mdb_env_;
  91. 91 MDB_dbi mdb_dbi_;
  92. 92 };
  93. 93
  94. 94 } // namespace db
  95. 95 } // namespace caffe
  96. 96
  97. 97 #endif // CAFFE_UTIL_DB_LMDB_HPP
  98. 98 #endif // USE_LMDB

db_lmdb.cpp

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

caffe的db_lmdb.hpp文件的更多相关文章

  1. Caffe源代码中Solver文件分析

    Caffe源代码(caffe version commit: 09868ac , date: 2015.08.15)中有一些重要的头文件,这里介绍下include/caffe/solver.hpp文件 ...

  2. .hpp文件

    hpp在C++中的含义 以前在开源代码里面遇到过,今天看boost源码的时候又遇到了,故学习一下. hPP,计算机术语,用C/C++语言编写的头文件,通常用来定义数据类型,声明变量.函数.结构和类.而 ...

  3. .h 与 .hpp 文件

    hpp,顾名思义等于.h加上.cpp,在boost.Xerces等开源库中频繁出现,偶在机缘巧合之下,学得一招半式,遂记录如下,以供参考学习.     hpp,其实质就是将.cpp的实现代码混入.h头 ...

  4. c++中的.hpp文件

    http://blog.chinaunix.net/uid-24118190-id-75239.html hpp,其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的 ...

  5. 安装caffe框架所需文件

    安装caffe框架所需文件: 1.微软提供的快速卷积神经网络框架caffe-master安装包或者windows提供的caffe-windows安装包. 链接:http://pan.baidu.com ...

  6. hpp文件简介

    Boost库文件采用的.hpp的后缀,而不是分成两个文件,也就是”.h+.cpp”,之所以这样做是有理由的,首先就是与普通的C/C++头文件区分,另外一个原因就是使Boost库不需要预先编译,直接引用 ...

  7. boost/config.hpp文件详解

    简要概述 今天突发奇想想看一下boost/config.hpp的内部实现,以及他有哪些功能. 这个头文件都有一个类似的结构,先包含一个头文件,假设为头文件1,然后包含这个头文 件中定义的宏.对于头文件 ...

  8. .hpp 文件

    .hpp 是 Header Plus Plus 的简写,是 C++程序头文件. 其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp ...

  9. 【caffe】三种文件类别:solver,model和weights

    @tags: caffe 文件类别 solver文件 是一堆超参数,比如迭代次数,是否用GPU,多少次迭代暂存一次训练所得参数,动量项,权重衰减(即正则化参数),基本的learning rate,多少 ...

随机推荐

  1. python: linux下安装redis

    Python连接时报拒绝连接,需要重装redis: 1) 卸载redis sudo apt-get remove redis-server sudo apt-get autoremove 2)编译安装 ...

  2. ACM第二站————归并排序

    转载请注明出处,谢谢!http://www.cnblogs.com/Asimple/p/5459664.html 归并排序————二分的思想 以中间的数为基准,每次排序都将比其小[升序排](大[降序排 ...

  3. cocos2dx lua bug之module 'lsqlite3' not found

    05-27 15:41:01.360: D/cocos2d-x debug info(7261): [LUA-print] -------------------------------------- ...

  4. JVM的classloader(转)

    Java中一共有四个类加载器,之所以叫类加载器,是程序要用到某个类的时候,要用类加载器载入内存.    这四个类加载器分别为:Bootstrap ClassLoader.Extension Class ...

  5. 使用KNN对MNIST数据集进行实验

    由于KNN的计算量太大,还没有使用KD-tree进行优化,所以对于60000训练集,10000测试集的数据计算比较慢.这里只是想测试观察一下KNN的效果而已,不调参. K选择之前看过貌似最好不要超过2 ...

  6. Uva(10048),最短路Floyd

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  7. Android:onNewIntent()触发机制及注意事项

    一.onNewIntent() 在IntentActivity中重写下列方法:onCreate onStart onRestart  onResume  onPause onStop onDestro ...

  8. 2016年11月4日 星期五 --出埃及记 Exodus 19:20

    2016年11月4日 星期五 --出埃及记 Exodus 19:20 The LORD descended to the top of Mount Sinai and called Moses to ...

  9. centos 安装smplayer

    安装这个播放器首先得安装第三方插件 1): rpmforge wget  pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el ...

  10. 如何提高android串口kernel log等级

    在 /device/qcom/common/rootdir/etc/init.qcom.rc write /proc/sys/kernel/printk  "6 6 1 7" 第一 ...