You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

history.cpp 5.2 kB

8 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include "history.h"
  2. #include <iostream>
  3. #include "defer.h"
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include "defer.h"
  8. #define FELLOW_TABLE "fellow"
  9. #define MESSAGE_TABLE "message"
  10. #define CHECK_SQLITE_RET(ret, action, result)\
  11. if (ret != SQLITE_OK)\
  12. {\
  13. cout<<"failed to"#action":"<<ret<<endl;\
  14. return result;\
  15. }
  16. #define CHECK_SQLITE_RET2(ret, action)\
  17. if (ret != SQLITE_OK)\
  18. {\
  19. cout<<"failed to"#action":"<<ret<<endl;\
  20. return;\
  21. }
  22. History::History()
  23. {
  24. }
  25. bool History::init(const string &dbPath)
  26. {
  27. unInit();
  28. //检查数据库文件是否存在,若不存在,需要创建表
  29. bool needCreateTable=false;
  30. auto ret = access(dbPath.c_str(), F_OK);
  31. if (ret == -1)
  32. {
  33. cout<<"db may be new created:"<<strerror(errno)<<endl;
  34. needCreateTable=true;
  35. }
  36. //打开数据库
  37. ret = sqlite3_open(dbPath.c_str(), &mDb);
  38. bool success = false;
  39. Defer closeDbIfErr{
  40. [this, success]()
  41. {
  42. if (!success)
  43. {
  44. cerr<<"init failed, close db now"<<endl;
  45. sqlite3_close(mDb);//除非内存不够,否则open总是会分配mDb的内存,总是需要close
  46. mDb = nullptr;
  47. }
  48. }
  49. };
  50. CHECK_SQLITE_RET(ret, "open sqlite", false);
  51. //创建表
  52. if (needCreateTable)
  53. {
  54. string createFellowTable = "create table " FELLOW_TABLE "(id integer,ip text, name text, mac text, primary key(id));";
  55. string createMessageTable = "create table " MESSAGE_TABLE " (id integer, fellow integer, when integer, content blob, primary key(id))";
  56. ret = sqlite3_exec(mDb, createFellowTable.c_str(), nullptr, nullptr, nullptr);
  57. CHECK_SQLITE_RET(ret, "create fellow table", false);
  58. ret = sqlite3_exec(mDb, createMessageTable.c_str(), nullptr, nullptr, nullptr);
  59. CHECK_SQLITE_RET(ret, "create message table", false);
  60. }
  61. success=true;
  62. return true;
  63. }
  64. void History::unInit()
  65. {
  66. if (mDb != nullptr)
  67. {
  68. sqlite3_close(mDb);
  69. mDb = nullptr;
  70. }
  71. }
  72. void History::add(const HistoryRecord& record)
  73. {
  74. int ret;
  75. //先更新好友信息
  76. auto fellowId = findFellowId(record.who->getIp());
  77. if (fellowId < 0)
  78. {
  79. string sql = "insert into " FELLOW_TABLE " values(null,"
  80. +record.who->getIp()
  81. +","+record.who->getName()
  82. +","+record.who->getMac()
  83. +");";
  84. ret = sqlite3_exec(mDb, sql.c_str(), nullptr, nullptr, nullptr);
  85. CHECK_SQLITE_RET2(ret, "insert fellow to db");
  86. fellowId = findFellowId(record.who->getIp());
  87. }
  88. //再增加记录
  89. Parcel parcel;
  90. record.what->writeTo(parcel);
  91. string sql = "insert into " MESSAGE_TABLE "values(null,"
  92. +to_string(fellowId)
  93. +","+ to_string(record.when.time_since_epoch().count())
  94. +",?);";
  95. sqlite3_stmt* stmt = nullptr;
  96. ret = sqlite3_prepare_v2(mDb, sql.c_str(), sql.length(), &stmt, nullptr);
  97. CHECK_SQLITE_RET2(ret, "prepare to insert message");
  98. Defer finalizeStmt{
  99. [stmt](){
  100. sqlite3_finalize(stmt);
  101. }
  102. };
  103. auto buf = parcel.raw();
  104. ret = sqlite3_bind_blob(stmt, 1, buf.data(), buf.size(), nullptr);
  105. CHECK_SQLITE_RET2(ret, "bind content to blob");
  106. ret = sqlite3_step(stmt);
  107. CHECK_SQLITE_RET2(ret, "insert message");
  108. }
  109. vector<HistoryRecord> History::query(const string& selection, const vector<string>& args)
  110. {
  111. vector<HistoryRecord> result;
  112. sqlite3_stmt* stmt;
  113. string sql = "select * from " MESSAGE_TABLE " where "+selection;
  114. auto ret = sqlite3_prepare_v2(mDb, sql.c_str(), sql.length(), &stmt, nullptr);
  115. CHECK_SQLITE_RET(ret, "prepare to query", result);
  116. Defer finalizeStmt{
  117. [stmt](){
  118. sqlite3_finalize(stmt);
  119. }
  120. };
  121. int len = args.size();
  122. for (auto i = 0; i < len; i++)
  123. {
  124. ret = sqlite3_bind_blob(stmt, i+1, args[i].c_str(), args[i].length(), nullptr);
  125. CHECK_SQLITE_RET(ret, "bind args", result);
  126. }
  127. while(true)
  128. {
  129. ret = sqlite3_step(stmt);
  130. if (ret == SQLITE_DONE)
  131. {
  132. return result;
  133. }
  134. else if (ret != SQLITE_ROW)
  135. {
  136. cerr<<"error occur while step query:"<<ret<<endl;
  137. return result;
  138. }
  139. else
  140. {
  141. auto fellowId = sqlite3_column_int(stmt, 1);
  142. auto when = sqlite3_column_int(stmt, 2);
  143. auto contentData = sqlite3_column_blob(stmt, 3);
  144. auto contentLen = sqlite3_column_bytes(stmt, 3);
  145. HistoryRecord record;
  146. auto fellow = getFellow(fellowId);
  147. record.who = shared_ptr<Fellow>(std::move(fellow));
  148. record.when = time_point<steady_clock, milliseconds>(milliseconds(when));
  149. Parcel parcel;
  150. parcel.fillWith(contentData, contentLen);
  151. parcel.resetForRead();
  152. record.what = ContentParcelFactory::createFromParcel(parcel);
  153. result.push_back(record);
  154. }
  155. }
  156. return result;
  157. }
  158. unique_ptr<Fellow> History::getFellow(int id)
  159. {
  160. }
  161. int History::findFellowId(const string &ip)
  162. {
  163. }

mac下的“飞秋”大多数只是飞鸽传书协议,而且未发现令人满意的开源项目,所以基于c++与qt实现了基础的飞秋协议。

Contributors (1)