Goddess of Justice DB, the database used for storage on IzaroDFS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
3.8 KiB

преди 5 години
преди 5 години
преди 5 години
преди 5 години
преди 5 години
преди 5 години
преди 5 години
преди 5 години
преди 5 години
преди 5 години
  1. #pragma once
  2. #include <stdint.h>
  3. #include <endian.hpp>
  4. #include <string>
  5. #include <iostream>
  6. #include <assert.h>
  7. // Unix-y stuff
  8. #include <unistd.h>
  9. #include <fcntl.h>
  10. #include <sys/mman.h>
  11. #include <sys/stat.h>
  12. struct errno_exception : public std::runtime_error {
  13. errno_exception(int err)
  14. : runtime_error{std::string{"errno with value "}+std::to_string(err)}
  15. {}
  16. };
  17. void throw_errno_if(bool pred)
  18. {
  19. if(pred)
  20. {
  21. throw errno_exception{errno};
  22. }
  23. }
  24. constexpr size_t page_size = 4096;
  25. struct [[gnu::packed]] record_identifier{
  26. bitops::regulated<uint32_t> x = 0;
  27. bitops::regulated<uint32_t> y = 0;
  28. std::array<uint8_t, 16> uuid = {0};
  29. };
  30. template<>
  31. struct std::hash<record_identifier> {
  32. uint64_t operator() (const record_identifier& value) {
  33. uint64_t v = static_cast<uint32_t>(value.x);
  34. v <<= 4;
  35. v += static_cast<uint32_t>(value.y);
  36. v ^= *(uint64_t*)&value.uuid;
  37. v ^= *(((uint64_t*)&value.uuid)+1);
  38. return v;
  39. }
  40. };
  41. enum class record_flags : uint32_t {
  42. confirmation = 1
  43. };
  44. struct [[gnu::packed]] record{
  45. record()
  46. {}
  47. union [[gnu::packed]] {
  48. std::array<uint8_t, 24> full;
  49. record_identifier split = record_identifier();
  50. } record_head;
  51. bitops::regulated<uint64_t> timestamp = 0;
  52. bitops::regulated<uint64_t> offset = 0;
  53. bitops::regulated<uint32_t> flags = 0;
  54. };
  55. constexpr size_t db_page_size = 16384;
  56. using db_page = std::array<uint8_t, db_page_size>;
  57. template<typename T>
  58. struct mmap_ptr{
  59. T* start = nullptr;
  60. size_t offset = 0;
  61. T& operator*(){
  62. return start[offset];
  63. }
  64. T& operator[](const size_t& n){
  65. return start[offset+n];
  66. }
  67. mmap_ptr operator+(size_t offset) {
  68. mmap_ptr ret;
  69. ret.start = start;
  70. ret.offset = offset + this->offset;
  71. return ret;
  72. }
  73. mmap_ptr operator++() {
  74. offset+=1;
  75. mmap_ptr ret = *this;
  76. return ret;
  77. }
  78. mmap_ptr operator++(int) {
  79. mmap_ptr ret = *this;
  80. offset+=1;
  81. return ret;
  82. }
  83. bool operator==(const mmap_ptr& oth) {
  84. return (start == oth.start) && (offset == oth.offset);
  85. }
  86. bool operator!=(const mmap_ptr& oth) {
  87. return !(*this == oth);
  88. }
  89. };
  90. template<typename T>
  91. class mmap_array : public mmap_ptr<T>
  92. {
  93. size_t mapping_size = 0;
  94. int fd = 0;
  95. size_t item_size = 0;
  96. public:
  97. mmap_array() = default;
  98. mmap_array(size_t nb_elem, const std::string& filename)
  99. : mmap_ptr<T>() {
  100. const size_t expected_size = nb_elem*sizeof(T);
  101. const size_t expected_size_mod = expected_size + (
  102. (expected_size%page_size != 0)?
  103. page_size - expected_size%page_size
  104. : 0
  105. );
  106. fd = open(
  107. filename.c_str(),
  108. O_RDWR | O_CREAT,
  109. S_ISUID + S_ISGID + S_IRUSR + S_IWUSR + S_IRGRP + S_IWGRP
  110. );
  111. throw_errno_if(fd < 0);
  112. struct stat data;
  113. int status = fstat(fd, &data);
  114. throw_errno_if(status < 0);
  115. if((size_t)data.st_size < expected_size_mod)
  116. {
  117. status = ftruncate(fd, expected_size_mod);
  118. throw_errno_if(status < 0);
  119. }
  120. this->start = (T*)mmap(NULL, expected_size_mod, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  121. throw_errno_if(this->start == nullptr);
  122. mapping_size = expected_size_mod;
  123. item_size = mapping_size / sizeof(T);
  124. auto map_access = MADV_RANDOM;
  125. if(expected_size_mod <= 1 << 20) {
  126. map_access |= MADV_WILLNEED;
  127. }
  128. #ifdef MADV_DONTDUMP
  129. map_access |= MADV_DONTDUMP;
  130. #endif
  131. this->offset = 0;
  132. posix_madvise(this->start, mapping_size, map_access);
  133. }
  134. void enforce_caching() {
  135. posix_madvise(this->start, mapping_size, MADV_WILLNEED);
  136. }
  137. constexpr size_t size() {
  138. return item_size;
  139. }
  140. int fd_v() const {
  141. return fd;
  142. }
  143. constexpr mmap_ptr<T> begin() const {
  144. mmap_ptr<T> ret = *this;
  145. return ret;
  146. }
  147. constexpr mmap_ptr<T> end() const {
  148. mmap_ptr<T> ret = *this;
  149. return ret+item_size;
  150. }
  151. void clear() {
  152. munmap(this->start, mapping_size);
  153. close(fd);
  154. }
  155. ~mmap_array() {
  156. //std::cerr << "unmapping disabled" << std::endl;
  157. if(false)//this->start != nullptr)
  158. {
  159. munmap(this->start, mapping_size);
  160. close(fd);
  161. }
  162. }
  163. };