example_tc_multi_hashmap.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. /**
  2. * Tencent is pleased to support the open source community by making Tars available.
  3. *
  4. * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
  5. *
  6. * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  7. * in compliance with the License. You may obtain a copy of the License at
  8. *
  9. * https://opensource.org/licenses/BSD-3-Clause
  10. *
  11. * Unless required by applicable law or agreed to in writing, software distributed
  12. * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  14. * specific language governing permissions and limitations under the License.
  15. */
  16. #include "util/tc_multi_hashmap.h"
  17. #include "util/tc_shm.h"
  18. #include "util/tc_option.h"
  19. #include <stdlib.h>
  20. #include <iostream>
  21. #include "util/tc_common.h"
  22. #include <sys/time.h>
  23. using namespace tars;
  24. ////////////////////////////////////////////////////////////////////
  25. //
  26. TC_Shm g_shm;
  27. TC_Multi_HashMap g_hmap;
  28. bool g_bSilent = false; // 是否为安静模式,不输出日志,可以取得更高的速度
  29. // 普通的功能测试
  30. struct FunctionTest
  31. {
  32. static void initMem()
  33. {
  34. #if __WORDSIZE == 64 || defined _WIN64
  35. size_t iMemSize = 1024*20;
  36. #else
  37. size_t iMemSize = 1024*10;
  38. #endif
  39. g_shm.init(iMemSize, 0x12345);
  40. cout << "init mem, shm key=0x" << hex << 0x12345 << dec << endl;
  41. }
  42. static void initMap()
  43. {
  44. if (g_shm.iscreate())
  45. {
  46. size_t iMinSize = 2, iMaxSize = 8;
  47. g_hmap.initDataBlockSize(iMinSize, iMaxSize, 2.0);
  48. g_hmap.create(g_shm.getPointer(), g_shm.size());
  49. g_hmap.setEraseCount(3);
  50. }
  51. else
  52. {
  53. g_hmap.connect(g_shm.getPointer(), g_shm.size());
  54. }
  55. }
  56. };
  57. // 大数据量性能测试
  58. struct PerformanceTest
  59. {
  60. static void initMem()
  61. {
  62. size_t iMemSize = 1073741824; // 1G
  63. g_shm.init(iMemSize, 0x23456);
  64. cout << "init mem, shm key=0x" << hex << 0x23456 << dec << endl;
  65. }
  66. static void initMap()
  67. {
  68. if (g_shm.iscreate())
  69. {
  70. size_t iMinSize = 5, iMaxSize = 20;
  71. g_hmap.initDataBlockSize(iMinSize, iMaxSize, 2.0);
  72. g_hmap.create(g_shm.getPointer(), g_shm.size());
  73. g_hmap.setEraseCount(10);
  74. }
  75. else
  76. {
  77. g_hmap.connect(g_shm.getPointer(), g_shm.size());
  78. }
  79. }
  80. };
  81. void set(const string &mk, const string &uk, const string &v, uint8_t version, bool dirty, bool full, bool head)
  82. {
  83. vector<TC_Multi_HashMap::Value> vRecords;
  84. TC_Multi_HashMap::DATATYPE eType = (full ? TC_Multi_HashMap::FULL_DATA : TC_Multi_HashMap::PART_DATA);
  85. timeval tv_1, tv_2;
  86. gettimeofday(&tv_1, NULL);
  87. int ret = TC_Multi_HashMap::RT_OK;
  88. if(uk.empty())
  89. {
  90. // 设置主key的only key
  91. ret = g_hmap.set(mk, vRecords);
  92. }
  93. else
  94. {
  95. if(v.empty())
  96. {
  97. // 设置主键的only key
  98. ret = g_hmap.set(mk, uk, eType, head, vRecords);
  99. }
  100. else
  101. {
  102. ret = g_hmap.set(mk, uk, v, version, dirty, eType, head, vRecords);
  103. }
  104. }
  105. gettimeofday(&tv_2, NULL);
  106. long lTime = 0;
  107. if(tv_2.tv_usec < tv_1.tv_usec)
  108. {
  109. lTime = (tv_2.tv_sec -1 - tv_1.tv_sec) * 1000000;
  110. }
  111. else
  112. {
  113. lTime = (tv_2.tv_sec - tv_1.tv_sec) * 1000000 + (tv_2.tv_usec - tv_1.tv_usec);
  114. }
  115. //assert(ret == 0);
  116. cout << "set:" << mk << "|" << uk << "|" << v << "|" << ret << "|" << lTime << endl;
  117. for(size_t i = 0; i < vRecords.size(); i++)
  118. {
  119. cout << "set erase:" << vRecords[i]._mkey << "|" << vRecords[i]._data._key
  120. << "|" << vRecords[i]._data._value << endl;
  121. }
  122. }
  123. void get(const string &mk, const string &uk)
  124. {
  125. TC_Multi_HashMap::Value v;
  126. if(!uk.empty())
  127. {
  128. // 根据主键查询数据
  129. int ret = g_hmap.get(mk, uk, v);
  130. cout << "get:" << mk << "|" << uk << "|" << v._data._value << "|"
  131. << (int)v._data._iVersion << "|" << v._data._dirty << "|" << ret << endl;
  132. }
  133. else
  134. {
  135. // 查主key下的所有数据
  136. size_t count = g_hmap.count(mk);
  137. cout << "count of " << mk << ": " << count << endl;
  138. TC_Multi_HashMap::lock_iterator it = g_hmap.find(mk);
  139. while(it != g_hmap.end())
  140. {
  141. TC_Multi_HashMap::Value v;
  142. int ret = it->get(v);
  143. cout << v._mkey << "|" << v._data._key << "|" << v._data._value
  144. << "|" << (int)v._data._iVersion << "|" << v._data._dirty << "|" << ret << endl;
  145. it ++;
  146. }
  147. }
  148. }
  149. void del(const string &mk, const string &uk)
  150. {
  151. vector<TC_Multi_HashMap::Value> vtDel;
  152. int ret = TC_Multi_HashMap::RT_OK;
  153. if(uk.empty())
  154. {
  155. ret = g_hmap.del(mk, vtDel);
  156. }
  157. else
  158. {
  159. TC_Multi_HashMap::Value v;
  160. ret = g_hmap.del(mk, uk, v);
  161. vtDel.push_back(v);
  162. }
  163. cout << "del:" << mk << "|" << uk << "|" << ret << endl;
  164. for(size_t i = 0; i < vtDel.size(); i ++)
  165. {
  166. cout << "del:" << vtDel[i]._mkey << "|" << vtDel[i]._data._key << "|" << vtDel[i]._data._value << endl;
  167. }
  168. }
  169. void sync()
  170. {
  171. TC_Multi_HashMap::Value data;
  172. size_t n = 0;
  173. g_hmap.setSyncTime(30);
  174. g_hmap.sync();
  175. while(true)
  176. {
  177. int ret = g_hmap.sync(time(NULL), data);
  178. if (ret == TC_Multi_HashMap::RT_OK)
  179. {
  180. break;
  181. }
  182. else if(ret == TC_Multi_HashMap::RT_NEED_SYNC)
  183. {
  184. ++n;
  185. cout << "sync:" << data._mkey << "|" << data._data._key << "|"
  186. << data._data._value << "|" << data._data._synct << endl;
  187. }
  188. }
  189. cout << n << " records synced" << endl;
  190. }
  191. void erase(int ratio)
  192. {
  193. vector<TC_Multi_HashMap::Value> vtErased;
  194. int ret = g_hmap.erase(ratio, vtErased, true);
  195. cout << "erase:" << ratio << "|" << vtErased.size() << "|" << ret << endl;
  196. for(size_t i = 0; i < vtErased.size(); i++)
  197. {
  198. cout << "erase:" << vtErased[i]._mkey << "|" << vtErased[i]._data._key
  199. << "|" << vtErased[i]._data._value << endl;
  200. }
  201. }
  202. void listh()
  203. {
  204. const TC_Multi_HashMap::tagMapHead &head = g_hmap.getMapHead();
  205. cout << "list hash count: " << head._iElementCount << endl;
  206. TC_Multi_HashMap::hash_iterator it = g_hmap.hashBegin();
  207. while(it != g_hmap.hashEnd())
  208. {
  209. vector<TC_Multi_HashMap::Value> vv;
  210. it->get(vv);
  211. ++it;
  212. for(size_t i = 0; i < vv.size(); i ++)
  213. {
  214. cout << vv[i]._mkey << "|" << vv[i]._data._key << "|" << vv[i]._data._value
  215. << "|" << (int)vv[i]._data._iVersion << "|" << vv[i]._data._dirty << "|" << vv[i]._data._synct << endl;
  216. }
  217. }
  218. }
  219. void list(int type, bool asc = true)
  220. {
  221. TC_Multi_HashMap::lock_iterator it;
  222. switch(type)
  223. {
  224. case 0:
  225. // 按block链遍历
  226. if(asc)
  227. {
  228. // 升序
  229. it = g_hmap.begin();
  230. }
  231. else
  232. {
  233. // 降序
  234. it = g_hmap.rbegin();
  235. }
  236. break;
  237. case 1:
  238. // 按get时间链遍历
  239. if(asc)
  240. {
  241. // 升序
  242. it = g_hmap.beginGetTime();
  243. }
  244. else
  245. {
  246. // 降序
  247. it = g_hmap.rbeginGetTime();
  248. }
  249. break;
  250. case 2:
  251. // 按set时间链遍历
  252. if(asc)
  253. {
  254. // 升序
  255. it = g_hmap.beginSetTime();
  256. }
  257. else
  258. {
  259. // 降序
  260. it = g_hmap.rbeginSetTime();
  261. }
  262. break;
  263. case 3:
  264. // 按脏数据链遍历
  265. it = g_hmap.beginDirty();
  266. break;
  267. default:
  268. return;
  269. }
  270. while(it != g_hmap.end())
  271. {
  272. TC_Multi_HashMap::Value v;
  273. it->get(v);
  274. ++it;
  275. cout << v._mkey << "|" << v._data._key << "|" << v._data._value
  276. << "|" << (int)v._data._iVersion << "|" << v._data._dirty << "|" << v._data._synct << endl;
  277. }
  278. }
  279. void batchset(size_t iCount, size_t iAvgRec)
  280. {
  281. srand(time(NULL));
  282. string mk, uk, v;
  283. vector<TC_Multi_HashMap::Value> vRecords;
  284. timeval tv_1, tv_2;
  285. gettimeofday(&tv_1, NULL);
  286. for(size_t i = 1; i <= iCount / iAvgRec; i ++)
  287. {
  288. mk = TC_Common::tostr(i);
  289. size_t iRec = rand() % iAvgRec + 1;
  290. for(size_t j = 1; j <= iRec; j ++)
  291. {
  292. uk = TC_Common::tostr(j);
  293. v = mk + uk;
  294. timeval tv_1, tv_2;
  295. if(!g_bSilent)
  296. {
  297. gettimeofday(&tv_1, NULL);
  298. }
  299. vRecords.clear();
  300. int ret = g_hmap.set(mk, uk, v, 0, true, TC_Multi_HashMap::FULL_DATA, true, vRecords);
  301. if(!g_bSilent)
  302. {
  303. gettimeofday(&tv_2, NULL);
  304. long lTime = 0;
  305. if(tv_2.tv_usec < tv_1.tv_usec)
  306. {
  307. lTime = (tv_2.tv_sec -1 - tv_1.tv_sec) * 1000000;
  308. }
  309. else
  310. {
  311. lTime = (tv_2.tv_sec - tv_1.tv_sec) * 1000000 + (tv_2.tv_usec - tv_1.tv_usec);
  312. }
  313. //assert(ret == 0);
  314. cout << "set:" << mk << "|" << uk << "|" << v << "|" << ret << "|" << lTime << endl;
  315. for(size_t i = 0; i < vRecords.size(); i++)
  316. {
  317. cout << "set erase:" << vRecords[i]._mkey << "|" << vRecords[i]._data._key
  318. << "|" << vRecords[i]._data._value << endl;
  319. }
  320. }
  321. }
  322. }
  323. gettimeofday(&tv_2, NULL);
  324. long lTime = 0;
  325. if(tv_2.tv_usec < tv_1.tv_usec)
  326. {
  327. lTime = (tv_2.tv_sec -1 - tv_1.tv_sec) * 1000000;
  328. }
  329. else
  330. {
  331. lTime = (tv_2.tv_sec - tv_1.tv_sec) * 1000000 + (tv_2.tv_usec - tv_1.tv_usec);
  332. }
  333. cout << "batchset:" << iCount << "|" << iAvgRec << "|" << lTime << endl;
  334. }
  335. void batchset()
  336. {
  337. vector<TC_Multi_HashMap::Value> vtSet, vtErased;
  338. TC_Multi_HashMap::Value v;
  339. v._mkey = "1", v._data._key = "1", v._data._value = "11";
  340. vtSet.push_back(v);
  341. v._mkey = "1", v._data._key = "2", v._data._value = "12";
  342. vtSet.push_back(v);
  343. v._mkey = "2", v._data._key = "1", v._data._value = "21";
  344. vtSet.push_back(v);
  345. v._mkey = "3", v._data._key = "1", v._data._value = "31";
  346. vtSet.push_back(v);
  347. v._mkey = "4", v._data._key = "1", v._data._value = "41";
  348. vtSet.push_back(v);
  349. int ret = g_hmap.set(vtSet, TC_Multi_HashMap::FULL_DATA, true, true, vtErased);
  350. for(size_t i = 0; i < vtSet.size(); i ++)
  351. {
  352. cout << "set:" << vtSet[i]._mkey << "|" << vtSet[i]._data._key << "|" << vtSet[i]._data._value << "|" << ret << endl;
  353. }
  354. for(size_t i = 0; i < vtErased.size(); i++)
  355. {
  356. cout << "set erase:" << vtErased[i]._mkey << "|" << vtErased[i]._data._key
  357. << "|" << vtErased[i]._data._value << endl;
  358. }
  359. }
  360. void batchget(size_t iCount, size_t iAvgRec)
  361. {
  362. srand(time(NULL));
  363. string mk, uk;
  364. TC_Multi_HashMap::Value v;
  365. timeval tv_1, tv_2;
  366. gettimeofday(&tv_1, NULL);
  367. for(size_t i = 1; i <= iCount / iAvgRec; i ++)
  368. {
  369. mk = TC_Common::tostr(i);
  370. size_t iRec = rand() % iAvgRec + 1;
  371. for(size_t j = 1; j <= iRec; j ++)
  372. {
  373. uk = TC_Common::tostr(j);
  374. timeval tv_1, tv_2;
  375. if(!g_bSilent)
  376. {
  377. gettimeofday(&tv_1, NULL);
  378. }
  379. int ret = g_hmap.get(mk, uk, v);
  380. if(!g_bSilent)
  381. {
  382. gettimeofday(&tv_2, NULL);
  383. long lTime = 0;
  384. if(tv_2.tv_usec < tv_1.tv_usec)
  385. {
  386. lTime = (tv_2.tv_sec -1 - tv_1.tv_sec) * 1000000;
  387. }
  388. else
  389. {
  390. lTime = (tv_2.tv_sec - tv_1.tv_sec) * 1000000 + (tv_2.tv_usec - tv_1.tv_usec);
  391. }
  392. //assert(ret == 0);
  393. cout << "get:" << mk << "|" << uk << "|" << v._data._value << "|"
  394. << (int)v._data._iVersion << "|" << v._data._dirty << "|" << ret << "|" << lTime << endl;
  395. }
  396. }
  397. }
  398. gettimeofday(&tv_2, NULL);
  399. long lTime = 0;
  400. if(tv_2.tv_usec < tv_1.tv_usec)
  401. {
  402. lTime = (tv_2.tv_sec -1 - tv_1.tv_sec) * 1000000;
  403. }
  404. else
  405. {
  406. lTime = (tv_2.tv_sec - tv_1.tv_sec) * 1000000 + (tv_2.tv_usec - tv_1.tv_usec);
  407. }
  408. cout << "batchset:" << iCount << "|" << iAvgRec << "|" << lTime << endl;
  409. }
  410. // 内存大小测试,测试一些结构在不同的机器上所占用字节数
  411. void testMemSize()
  412. {
  413. cout << "sizeof(int)=" << sizeof(int) << endl;
  414. cout << "sizeof(long)=" << sizeof(long) << endl;
  415. cout << "sizeof(size_t)=" << sizeof(size_t) << endl;
  416. cout << "sizeof(time_t)=" << sizeof(time_t) << endl;
  417. cout << "sizeof(tagBlockHead)=" << sizeof(TC_Multi_HashMap::Block::tagBlockHead) << endl;
  418. cout << "sizeof(tagMainKeyHead)=" << sizeof(TC_Multi_HashMap::MainKey::tagMainKeyHead) << endl;
  419. cout << "sizeof(tagChunkHead)=" << sizeof(TC_Multi_HashMap::Block::tagChunkHead) << endl;
  420. cout << "sizeof(tagHashItem)=" << sizeof(TC_Multi_HashMap::tagHashItem) << endl;
  421. cout << "sizeof(tagMainKeyHashItem)=" << sizeof(TC_Multi_HashMap::tagMainKeyHashItem) << endl;
  422. }
  423. void usage(char *argv)
  424. {
  425. cout << argv << " --help\tshow this help message" << endl;
  426. cout << "\t --mem\tview memory size of some structs" << endl;
  427. cout << "\t --f\tdo the functionality test(default option)" << endl;
  428. cout << "\t --p\tdo the performance test" << endl;
  429. cout << "\t --s\tsilent mode in performance test, no output" << endl;
  430. cout << "\t --release\trelease the allocated share memory" << endl;
  431. cout << "\t --view\tview statistic information of this map" << endl;
  432. cout << "\t --set [--mkey=] [--ukey=] [--value=] [--version] [--clean] [--full] [--tail]" << endl;
  433. cout << "\t --get [--mkey=] [--ukey=]" << endl;
  434. cout << "\t --del [--mkey=] [--ukey=]" << endl;
  435. cout << "\t --sync" << endl;
  436. cout << "\t --erase [--ratio]" << endl;
  437. cout << "\t --isdirty [--mkey=] [--ukey=]" << endl;
  438. cout << "\t --listh\tlist data by hash index" << endl;
  439. cout << "\t --listb [--desc]\tlist data by block chain" << endl;
  440. cout << "\t --listg [--desc]\tlist data by get time chain" << endl;
  441. cout << "\t --lists [--desc]\tlist data by set time chain" << endl;
  442. cout << "\t --listd\tlist data by dirty data chain" << endl;
  443. cout << "\t --set-batch [--count] [--avgrec]\tdo batch set operation, will set total count records with avgrec records per main key" << endl;
  444. cout << "\t --get-batch [--count] [--avgrec]\tdo batch get operation" << endl;
  445. cout << "\t --chkmk [--mkey]\tcheck if main key exists" << endl;
  446. cout << "\t --setstate [--mkey] [--ukey] [--dirty] [--clean] [--part] [--full]\tcheck if main key exists" << endl;
  447. cout << "\t --chkbad [--hash] [--repair]" << endl;
  448. }
  449. int main(int argc, char *argv[])
  450. {
  451. try
  452. {
  453. TC_Option option;
  454. option.decode(argc, argv);
  455. map<string, string> m = option.getMulti();
  456. if(option.hasParam("help") || option.getMulti().empty())
  457. {
  458. usage(argv[0]);
  459. return 0;
  460. }
  461. if(option.hasParam("mem"))
  462. {
  463. testMemSize();
  464. return 0;
  465. }
  466. g_bSilent = option.hasParam("s");
  467. // 随机设置和获取时也当作性能测试
  468. bool bPerfTest = option.hasParam("p");
  469. if(bPerfTest)
  470. {
  471. PerformanceTest::initMem();
  472. }
  473. else
  474. {
  475. FunctionTest::initMem();
  476. }
  477. if(option.hasParam("release"))
  478. {
  479. g_shm.del();
  480. return 0;
  481. }
  482. if(bPerfTest)
  483. {
  484. PerformanceTest::initMap();
  485. }
  486. else
  487. {
  488. FunctionTest::initMap();
  489. }
  490. if(option.hasParam("view"))
  491. {
  492. cout << g_hmap.desc() << endl;
  493. }
  494. else if(option.hasParam("set"))
  495. {
  496. string mk = option.getValue("mkey");
  497. string uk = option.getValue("ukey");
  498. string v = option.getValue("value");
  499. uint8_t version = option.getValue("version").empty() ? 0 : atoi(option.getValue("version").c_str());
  500. bool dirty = option.getValue("clean").empty() ? true : false;
  501. bool full = option.getValue("full").empty() ? false : true;
  502. bool head = option.getValue("tail").empty() ? true : false;
  503. if(mk.empty())
  504. {
  505. usage(argv[0]);
  506. return 0;
  507. }
  508. set(mk, uk, v, version, dirty, full, head);
  509. }
  510. else if(option.hasParam("get"))
  511. {
  512. string mk;
  513. string uk;
  514. mk = option.getValue("mkey");
  515. uk = option.getValue("ukey");
  516. if(mk.empty())
  517. {
  518. usage(argv[0]);
  519. return 0;
  520. }
  521. get(mk, uk);
  522. }
  523. else if(option.hasParam("del"))
  524. {
  525. string mk;
  526. string uk;
  527. mk = option.getValue("mkey");
  528. uk = option.getValue("ukey");
  529. if(mk.empty())
  530. {
  531. usage(argv[0]);
  532. return 0;
  533. }
  534. del(mk, uk);
  535. }
  536. else if(option.hasParam("sync"))
  537. {
  538. sync();
  539. }
  540. else if(option.hasParam("erase"))
  541. {
  542. string ratio = option.getValue("ratio");
  543. if(ratio.empty())
  544. {
  545. usage(argv[0]);
  546. return 0;
  547. }
  548. erase(TC_Common::strto<int>(ratio));
  549. }
  550. else if(option.hasParam("isdirty"))
  551. {
  552. string mk;
  553. string uk;
  554. mk = option.getValue("mkey");
  555. uk = option.getValue("ukey");
  556. if(mk.empty())
  557. {
  558. usage(argv[0]);
  559. return 0;
  560. }
  561. int ret = TC_Multi_HashMap::RT_OK;
  562. if(uk.empty())
  563. {
  564. ret = g_hmap.checkDirty(mk);
  565. }
  566. else
  567. {
  568. ret = g_hmap.checkDirty(mk, uk);
  569. }
  570. cout << "isdirty:" << mk << "|" << uk << "|" << (ret == TC_Multi_HashMap::RT_DIRTY_DATA) << endl;
  571. }
  572. else if(option.hasParam("listh"))
  573. {
  574. listh();
  575. }
  576. else if(option.hasParam("listb"))
  577. {
  578. if(option.hasParam("desc"))
  579. {
  580. list(0, false);
  581. }
  582. else
  583. {
  584. list(0, true);
  585. }
  586. }
  587. else if(option.hasParam("listg"))
  588. {
  589. if(option.hasParam("desc"))
  590. {
  591. list(1, false);
  592. }
  593. else
  594. {
  595. list(1, true);
  596. }
  597. }
  598. else if(option.hasParam("lists"))
  599. {
  600. if(option.hasParam("desc"))
  601. {
  602. list(2, false);
  603. }
  604. else
  605. {
  606. list(2, true);
  607. }
  608. }
  609. else if(option.hasParam("listd"))
  610. {
  611. list(3);
  612. }
  613. else if(option.hasParam("set-batch"))
  614. {
  615. string sCount = option.getValue("count");
  616. string sAvgRec = option.getValue("avgrec");
  617. if(!sCount.empty())
  618. {
  619. batchset(TC_Common::strto<size_t>(sCount), sAvgRec.empty() ? 2 : TC_Common::strto<size_t>(sAvgRec));
  620. }
  621. else
  622. {
  623. // 不带参数的批量设置
  624. batchset();
  625. }
  626. }
  627. else if(option.hasParam("get-batch"))
  628. {
  629. string sCount = option.getValue("count");
  630. string sAvgRec = option.getValue("avgrec");
  631. if(sCount.empty())
  632. {
  633. usage(argv[0]);
  634. return 0;
  635. }
  636. batchget(TC_Common::strto<size_t>(sCount), sAvgRec.empty() ? 2 : TC_Common::strto<size_t>(sAvgRec));
  637. }
  638. else if(option.hasParam("chkmk"))
  639. {
  640. string mk = option.getValue("mkey");
  641. if(mk.empty())
  642. {
  643. usage(argv[0]);
  644. return 0;
  645. }
  646. int ret = g_hmap.checkMainKey(mk);
  647. if(ret == TC_Multi_HashMap::RT_OK)
  648. {
  649. cout << "main key " << mk << " exists" << endl;
  650. }
  651. else if(ret == TC_Multi_HashMap::RT_ONLY_KEY)
  652. {
  653. cout << "main key " << mk << " exists, but only key" << endl;
  654. }
  655. else if(ret == TC_Multi_HashMap::RT_PART_DATA)
  656. {
  657. cout << "main key " << mk << " exists, and possible part data" << endl;
  658. }
  659. else if(ret == TC_Multi_HashMap::RT_NO_DATA)
  660. {
  661. cout << "main key " << mk << " not exists" << endl;
  662. }
  663. else
  664. {
  665. cout << "chkmk " << mk << " failed: " << ret << endl;
  666. }
  667. }
  668. else if(option.hasParam("setstate"))
  669. {
  670. string mk = option.getValue("mkey");
  671. string uk = option.getValue("ukey");
  672. bool bDirty = option.hasParam("dirty");
  673. bool bClean = option.hasParam("clean");
  674. bool bFull = option.hasParam("full");
  675. bool bPart = option.hasParam("part");
  676. if(mk.empty())
  677. {
  678. usage(argv[0]);
  679. return 0;
  680. }
  681. if(!uk.empty())
  682. {
  683. if(bDirty)
  684. {
  685. int ret = g_hmap.setDirty(mk, uk);
  686. cout << "setdirty:" << mk << "|" << uk << "|" << ret << endl;
  687. }
  688. else if(bClean)
  689. {
  690. int ret = g_hmap.setClean(mk, uk);
  691. cout << "setclean:" << mk << "|" << uk << "|" << ret << endl;
  692. }
  693. else
  694. {
  695. usage(argv[0]);
  696. return 0;
  697. }
  698. }
  699. else
  700. {
  701. if(bFull)
  702. {
  703. int ret = g_hmap.setFullData(mk, true);
  704. cout << "set full data:" << mk << "|" << ret << endl;
  705. }
  706. else if(bPart)
  707. {
  708. int ret = g_hmap.setFullData(mk, false);
  709. cout << "set part data:" << mk << "|" << ret << endl;
  710. }
  711. else
  712. {
  713. usage(argv[0]);
  714. return 0;
  715. }
  716. }
  717. }
  718. else if(option.hasParam("chkbad"))
  719. {
  720. string sHash = option.getValue("hash");
  721. if(sHash.empty())
  722. {
  723. usage(argv[0]);
  724. return 0;
  725. }
  726. uint32_t iHash = TC_Common::strto<uint32_t>(sHash);
  727. size_t iCount = g_hmap.checkBadBlock(iHash, option.hasParam("repair"));
  728. cout << iCount << " bad block under hash " << iHash << endl;
  729. }
  730. else
  731. {
  732. usage(argv[0]);
  733. }
  734. }
  735. catch(exception &e)
  736. {
  737. cout << "error! " << e.what() << endl;
  738. }
  739. return 0;
  740. }