Goddess of Justice DB, the database used for storage on IzaroDFS
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

222 lignes
5.1 KiB

il y a 5 ans
il y a 5 ans
  1. #pragma once
  2. #include "fsized_map.h"
  3. #include <chrono>
  4. struct metadata_t{
  5. bitops::regulated<uint64_t> record_cnt;
  6. bitops::regulated<uint64_t> page_cnt;
  7. bitops::regulated<uint64_t> delete_cnt;
  8. bitops::regulated<uint64_t> last_page;
  9. bitops::regulated<uint64_t> last_delete;
  10. };
  11. class database {
  12. database(){}
  13. public:
  14. mmap_array<std::pair<bitops::regulated<uint64_t>, record>> records;
  15. mmap_array<db_page> pages;
  16. mmap_array<metadata_t> metadata;
  17. mmap_array<size_t> delete_table;
  18. database(
  19. const std::string& records,
  20. const std::string& pages,
  21. const std::string& deletions,
  22. const std::string& meta,
  23. const size_t& record_cnt = 4096,
  24. const size_t& page_cnt = 4096,
  25. const size_t& delete_cnt = 512
  26. )
  27. : records{record_cnt, records}
  28. , pages{page_cnt, pages}
  29. , metadata{(size_t)1, meta}
  30. , delete_table{delete_cnt, deletions}
  31. {}
  32. static database&& create(const std::string dir, size_t page_nb) {
  33. database ret{
  34. dir+"records",
  35. dir+"pages",
  36. dir+"deleted",
  37. dir+"meta",
  38. page_nb+page_nb/2,
  39. page_nb,
  40. page_nb/8
  41. };
  42. for(auto& n : ret.records)
  43. {
  44. n.second.timestamp = 0;
  45. n.second.offset = 0;
  46. }
  47. for(auto& n : ret.delete_table)
  48. {
  49. n = std::numeric_limits<size_t>::max();
  50. }
  51. (*ret.metadata).last_page = 0;
  52. (*ret.metadata).last_delete = 0;
  53. (*ret.metadata).record_cnt = page_nb+page_nb/2;
  54. (*ret.metadata).page_cnt = page_nb;
  55. (*ret.metadata).delete_cnt = page_nb/8;
  56. #pragma GCC diagnostic push
  57. #pragma GCC diagnostic ignored "-Wreturn-local-addr"
  58. return std::move(ret);
  59. #pragma GCC diagnostic pop
  60. }
  61. static database&& open(const std::string dir) {
  62. mmap_array<metadata_t> tmp{(size_t)1, dir+"meta"};
  63. database ret{
  64. dir+"records",
  65. dir+"pages",
  66. dir+"deleted",
  67. dir+"meta",
  68. (*tmp).record_cnt,
  69. (*tmp).page_cnt,
  70. (*tmp).delete_cnt
  71. };
  72. tmp.clear();
  73. ret.records.enforce_caching();
  74. #pragma GCC diagnostic push
  75. #pragma GCC diagnostic ignored "-Wreturn-local-addr"
  76. return std::move(ret);
  77. #pragma GCC diagnostic pop
  78. }
  79. void write(const record_identifier& target, const db_page& value){
  80. uint64_t page = std::numeric_limits<uint64_t>::max();;
  81. size_t off = std::numeric_limits<size_t>::max();
  82. if(metadata[0].last_delete>0)
  83. {
  84. off = (*metadata).last_delete;
  85. page = delete_table[off-1];
  86. } else {
  87. page = (*metadata).last_page;
  88. if(page>=pages.size()) {
  89. throw std::runtime_error("PAGE STARVATION! MUST EXIT NOW");
  90. }
  91. }
  92. if(page == std::numeric_limits<uint64_t>::max())
  93. {
  94. throw std::runtime_error("PAGE ERROR! MUST EXIT NOW");
  95. }
  96. pages[page] = value;
  97. uint64_t hashed = std::hash<record_identifier>{}(target);
  98. uint64_t hashed_roll = hashed;
  99. bool succeed = false;
  100. uint64_t ts = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
  101. std::pair<bitops::regulated<uint64_t>,record> tmp{0, record{}};
  102. tmp.first = hashed;
  103. tmp.second.record_head.split = target;
  104. tmp.second.timestamp = ts;
  105. tmp.second.offset = page;
  106. do{
  107. uint64_t pos = hashed_roll % records.size();
  108. switch (static_cast<uint64_t>(records[pos].second.timestamp)) {
  109. case 0:
  110. [[fallthrough]];
  111. case std::numeric_limits<uint64_t>::max():
  112. records[pos] = tmp;
  113. succeed = true;
  114. break;
  115. default:
  116. break;
  117. }
  118. hashed_roll++;
  119. }while(!succeed);
  120. if(off != std::numeric_limits<size_t>::max())
  121. {
  122. (*metadata).last_delete += -1;
  123. delete_table[off] = std::numeric_limits<size_t>::max();
  124. } else {
  125. (*metadata).last_page += (size_t)1;
  126. }
  127. }
  128. std::pair<uint64_t, db_page> read(const record_identifier& target) {
  129. std::pair<uint64_t, db_page> ret;
  130. ret.first = 0;
  131. ret.second.fill(0);
  132. uint64_t hashed = std::hash<record_identifier>{}(target);
  133. uint64_t hashed_roll = hashed;
  134. do{
  135. uint64_t pos = hashed_roll % records.size();
  136. auto& value = records[pos].second;
  137. switch (static_cast<uint64_t>(value.timestamp)) {
  138. case 0:
  139. return ret;
  140. case std::numeric_limits<uint64_t>::max():
  141. break;
  142. default:
  143. if(records[pos].first == hashed)
  144. if(std::hash<record_identifier>{}(value.record_head.split) == hashed)
  145. {
  146. if(ret.first<value.timestamp)
  147. {
  148. ret.first = value.timestamp;
  149. ret.second = pages[value.offset];
  150. }
  151. break;
  152. }
  153. }
  154. hashed_roll++;
  155. }while(true);
  156. return ret;
  157. }
  158. void remove(const record_identifier& target) {
  159. uint64_t hashed = std::hash<record_identifier>{}(target);
  160. uint64_t hashed_roll = hashed;
  161. do{
  162. uint64_t pos = hashed_roll % records.size();
  163. auto& value = records[pos].second;
  164. switch (static_cast<uint64_t>(value.timestamp)) {
  165. case 0:
  166. return;
  167. case std::numeric_limits<uint64_t>::max():
  168. break;
  169. default:
  170. if(records[pos].first == hashed)
  171. if(std::hash<record_identifier>{}(value.record_head.split) == hashed)
  172. {
  173. value.timestamp = std::numeric_limits<uint64_t>::max();
  174. (*metadata).last_delete+=1;
  175. delete_table[(*metadata).last_delete-1] = value.offset;
  176. value.offset = 0;
  177. break;
  178. }
  179. }
  180. hashed_roll++;
  181. }while(true); // return only happens on hitting a case 0
  182. }
  183. void rollback(const record_identifier&) {
  184. }
  185. };