DBTable.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:8k
源码类别:

模拟服务器

开发平台:

C/C++

  1. #include "stdafx.h"
  2. #include "DBTable.h"
  3. #ifndef WIN32
  4. #include <sys/stat.h>
  5. #else
  6. #include <direct.h>
  7. #endif
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. ZDBTable::ZDBTable(const char *path, const char *name) {
  12. #ifdef WIN32
  13. getcwd(env_path, MAX_TABLE_NAME);
  14. #else
  15. #endif
  16. strcat(env_path, "\");
  17. strcat(env_path, path);
  18. #ifdef WIN32
  19. int ret = mkdir(env_path);
  20. #else
  21.         int ret = mkdir(env_path, 0);
  22. #endif
  23. if(!db_env_create(&dbenv, 0)) {
  24. dbenv->set_errpfx(dbenv, "index_db");
  25.             dbenv->set_lg_regionmax(dbenv, 512 * 1024);
  26.             dbenv->set_lg_max(dbenv, 16 * 1024 * 1024);
  27.             dbenv->set_lg_bsize(dbenv, 2 * 1024 * 1024);
  28.             dbenv->set_cachesize(dbenv, 0, 64 * 1024 * 1024, 1);
  29. if(!dbenv->open(dbenv, env_path, DB_CREATE | DB_INIT_LOG | DB_INIT_LOCK | DB_INIT_MPOOL | DB_INIT_TXN | DB_RECOVER | DB_THREAD | DB_PRIVATE, 0)) {
  30. ret = dbenv->set_flags(dbenv, DB_AUTO_COMMIT | DB_TXN_NOSYNC, 1);
  31. index_number = 0;
  32. strcpy(table_name, name);
  33. return; //成功了
  34. }
  35. dbenv->close(dbenv, 0);
  36. }
  37. dbenv = NULL;
  38. }
  39. ZDBTable::~ZDBTable() {
  40. if(dbenv) dbenv->close(dbenv, 0);
  41. }
  42. int ZDBTable::addIndex(GetIndexFunc func, bool isUnique) {
  43. if(!dbenv) return -1;
  44. if(index_number + 1 >= MAX_INDEX) return index_number;
  45. get_index_funcs[index_number] = func;
  46. is_index_unique[index_number] = isUnique;
  47. return index_number++;
  48. }
  49. bool ZDBTable::open() {
  50. if(!dbenv) return false;
  51. bStop = false;
  52. char index_table_name[MAX_TABLE_NAME];
  53.     int index;
  54. int ret;
  55. if(!db_create(&primary_db, dbenv, 0)) {
  56. if(!primary_db->open(primary_db, NULL, table_name, NULL, DB_BTREE, DB_CREATE| DB_AUTO_COMMIT | DB_THREAD, 0664)) { //打开主数据库
  57. for(index = 0; index < index_number; index++) {
  58. sprintf(index_table_name, "%s.%d", table_name, index);
  59. if(!db_create(&index_db[index], dbenv, 0)) {
  60. if(!is_index_unique[index]) {
  61. if(index_db[index]->set_flags(index_db[index], DB_DUP | DB_DUPSORT)) break;
  62. }
  63. if(index_db[index]->open(index_db[index], NULL, index_table_name, NULL, DB_BTREE, DB_CREATE | DB_AUTO_COMMIT | DB_THREAD, 0664)) break;
  64. if(ret = primary_db->associate(primary_db, NULL, index_db[index], get_index_funcs[index], DB_AUTO_COMMIT)) {
  65. index_db[index]->close(index_db[index], 0);
  66. break;
  67. }
  68. }
  69. else break;
  70. }
  71. if(index == index_number) return true; //成功了
  72. else while(--index) (index_db[index])->close(index_db[index], 0); //出错,关闭前面的索引表
  73. primary_db->close(primary_db, 0);
  74. }
  75. }
  76. return false;
  77. }
  78. void ZDBTable::close() {
  79. if(!dbenv) return;
  80. primary_db->close(primary_db, 0);
  81. for(int index = 0; index < index_number; index++) index_db[index]->close(index_db[index], 0);
  82. }
  83. bool ZDBTable::commit() {
  84. return true;
  85. }
  86. bool ZDBTable::add(const char *key_ptr, int key_size, const char *data_ptr, int data_size) {
  87. DBT data, key;
  88. memset(&key, 0, sizeof(DBT));
  89. memset(&data, 0, sizeof(DBT));
  90. key.data = (void *)key_ptr;
  91. key.size = key_size;
  92. data.data = (void *)data_ptr;
  93. data.size = data_size;
  94. int ret;
  95. int retry = 0;
  96. RETRY:
  97. ret = primary_db->put(primary_db, NULL, &key, &data, DB_AUTO_COMMIT);
  98. if(ret == DB_LOCK_DEADLOCK && ++retry < MAX_RETRY) {
  99. if(bStop) return false;
  100. goto RETRY;
  101. }
  102. if(ret) return false;
  103. else return true;
  104. }
  105. bool ZDBTable::remove(const char *key_ptr, int key_size, int index) {
  106. DBT data, key;
  107. memset(&key, 0, sizeof(DBT));
  108. memset(&data, 0, sizeof(DBT));
  109. key.data = (void *)key_ptr;
  110. key.size = key_size;
  111. int ret;
  112. int retry = 0;
  113. RETRY:
  114. ret = primary_db->del(primary_db, NULL, &key, DB_AUTO_COMMIT);
  115. if(ret == DB_LOCK_DEADLOCK && ++retry < MAX_RETRY) {
  116. if(bStop) return false;
  117. goto RETRY;
  118. }
  119. if(ret) return false;
  120. else return true;
  121. }
  122. ZCursor *ZDBTable::_search(bool bKey, const char *key_ptr, int key_size, int index) {
  123. DBT key, data, pkey;
  124. if(index < -1 || index >= index_number) return NULL;
  125. memset(&key, 0, sizeof(key));
  126. memset(&data, 0, sizeof(data));
  127. memset(&pkey, 0, sizeof(pkey));
  128. key.flags = DB_DBT_MALLOC;
  129. data.flags = DB_DBT_MALLOC;
  130. pkey.flags = DB_DBT_MALLOC;
  131. key.data = (void *)key_ptr;
  132. key.size = key_size;
  133. DBC *dbcp;
  134. if(!key_ptr || !key_size) { //没有设定索引值,要求遍历数据库
  135. if(index_db[index]->cursor(index_db[index], NULL, &dbcp, 0)) {
  136. return NULL;
  137. }
  138. if(dbcp->c_get(dbcp, &key, &data, DB_FIRST)) {
  139. dbcp->c_close(dbcp);
  140. return NULL;
  141. }
  142. }
  143. else {
  144. if(index == -1) { //主键搜索
  145. if(primary_db->get(primary_db, NULL, &key, &data, 0)) return NULL;
  146. }
  147. else if(is_index_unique[index]) { //没有重复索引
  148. if(bKey) {
  149. if(index_db[index]->pget(index_db[index], NULL, &key, &pkey, &data, 0)) return NULL;
  150. }
  151. else {
  152. if(index_db[index]->get(index_db[index], NULL, &key, &data, 0)) return NULL;
  153. }
  154. }
  155. else { //打开游标
  156. if(index_db[index]->cursor(index_db[index], NULL, &dbcp, 0)) {
  157. return NULL;
  158. }
  159. if(bKey) {
  160. if(dbcp->c_pget(dbcp, &key, &pkey, &data, DB_SET)) {
  161. dbcp->c_close(dbcp);
  162. return NULL;
  163. }
  164. }
  165. else {
  166. if(dbcp->c_get(dbcp, &key, &data, DB_SET)) {
  167. dbcp->c_close(dbcp);
  168. return NULL;
  169. }
  170. }
  171. }
  172. }
  173. ZCursor *result = new ZCursor;
  174. result->index = 0;
  175. result->dbcp = dbcp;
  176. if (bKey) 
  177.     {
  178. result->data = (char *)pkey.data;
  179. result->size = pkey.size;
  180.         pkey.data    = NULL;
  181. }
  182. else 
  183.     {
  184. result->data = (char *)data.data;
  185. result->size = data.size;
  186.         data.data    = NULL;
  187. }
  188.     if (!key_ptr || !key_size) 
  189.     {
  190. result->key = (char *)key.data;
  191. result->key_size = key.size;
  192. result->bTravel = true;
  193.         key.data = NULL;
  194. }
  195. else 
  196.     {
  197.         result->bTravel = false;
  198.     }
  199.     if(pkey.data) free(pkey.data);
  200. if(data.data) free(data.data);
  201. return result;
  202. }
  203. bool ZDBTable::_next(bool bKey, ZCursor *cursor) {
  204. DBT key, data, pkey;
  205. memset(&key, 0, sizeof(key));
  206. memset(&data, 0, sizeof(data));
  207. memset(&pkey, 0, sizeof(pkey));
  208. key.flags = DB_DBT_MALLOC;
  209. data.flags = DB_DBT_MALLOC;
  210. pkey.flags = DB_DBT_MALLOC;
  211. if(!cursor || !cursor->dbcp) return false;
  212. free(cursor->data);
  213. cursor->index++;
  214. if(cursor->bTravel) {
  215. free(cursor->key);
  216. if(cursor->dbcp->c_get(cursor->dbcp, &key, &data, DB_NEXT)) {
  217. cursor->dbcp->c_close(cursor->dbcp);
  218. delete cursor;
  219. return false;
  220. }
  221. }
  222. else {
  223. if(bKey) {
  224. if(cursor->dbcp->c_pget(cursor->dbcp, &key, &pkey, &data, DB_NEXT_DUP)) {
  225. cursor->dbcp->c_close(cursor->dbcp);
  226. delete cursor;
  227. return false;
  228. }
  229. }
  230. else {
  231. if(cursor->dbcp->c_get(cursor->dbcp, &key, &data, DB_NEXT_DUP)) {
  232. cursor->dbcp->c_close(cursor->dbcp);
  233. delete cursor;
  234. return false;
  235. }
  236. }
  237. }
  238. if (bKey) 
  239.     {
  240. cursor->data = (char *)pkey.data;
  241. cursor->size = pkey.size;
  242.         pkey.data = NULL;
  243. }
  244. else {
  245. cursor->data = (char *)data.data;
  246. cursor->size = data.size;
  247.         data.data = NULL;
  248. }
  249.     if (cursor->bTravel) 
  250.     {
  251. cursor->key = (char *)key.data;
  252. cursor->key_size = key.size;
  253.         key.data = NULL;
  254. }
  255. if (key.data) free(key.data);
  256. if (pkey.data) free(pkey.data);
  257. if (data.data) free(data.data);
  258.     return true;
  259. }
  260. void ZDBTable::removeLog() { //清除日志文件
  261. int ret;
  262. char **begin, **list;
  263. if((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0)) != 0) return;
  264. if((ret = dbenv->log_archive(dbenv, &list, DB_ARCH_ABS)) != 0) {
  265. return ;
  266. }
  267. if (list != NULL) {
  268. for(begin = list; *list != NULL; ++list)
  269. if((ret = ::remove(*list)) != 0) {
  270. return;
  271. }
  272. free(begin);
  273. }
  274. }