Goddess of Justice DB, the database used for storage on IzaroDFS
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

202 rader
3.8 KiB

5 år sedan
5 år sedan
5 år sedan
5 år sedan
5 år sedan
5 år sedan
5 år sedan
5 år sedan
5 år sedan
  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. };