Goddess of Justice DB, the database used for storage on IzaroDFS
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

188 строки
3.5 KiB

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 = *(uint32_t*)&value.x.internal;
  34. v <<= 4;
  35. v += *(uint32_t*)&value.y.internal;
  36. v ^= *(uint64_t*)&value.uuid;
  37. v ^= *(((uint64_t*)&value.uuid)+1);
  38. return v;
  39. }
  40. };
  41. struct record{
  42. record()
  43. {}
  44. union{
  45. std::array<uint8_t, 24> full;
  46. record_identifier split = record_identifier();
  47. } record_head;
  48. bitops::regulated<uint64_t> timestamp = 0;
  49. size_t offset = 0;
  50. };
  51. using db_page = std::array<uint8_t, 16384>;
  52. template<typename T>
  53. struct mmap_ptr{
  54. T* start = nullptr;
  55. size_t offset = 0;
  56. T& operator*(){
  57. return start[offset];
  58. }
  59. T& operator[](const size_t& n){
  60. return start[offset+n];
  61. }
  62. mmap_ptr operator+(size_t offset) {
  63. mmap_ptr ret;
  64. ret.start = start;
  65. ret.offset = offset + this->offset;
  66. return ret;
  67. }
  68. mmap_ptr operator++() {
  69. offset+=1;
  70. mmap_ptr ret = *this;
  71. return ret;
  72. }
  73. mmap_ptr operator++(int) {
  74. mmap_ptr ret = *this;
  75. offset+=1;
  76. return ret;
  77. }
  78. bool operator==(const mmap_ptr& oth) {
  79. return (start == oth.start) && (offset == oth.offset);
  80. }
  81. bool operator!=(const mmap_ptr& oth) {
  82. return !(*this == oth);
  83. }
  84. };
  85. template<typename T>
  86. class mmap_array : public mmap_ptr<T>
  87. {
  88. size_t mapping_size = 0;
  89. int fd = 0;
  90. size_t item_size = 0;
  91. public:
  92. mmap_array() = default;
  93. mmap_array(size_t nb_elem, const std::string& filename)
  94. : mmap_ptr<T>() {
  95. const size_t expected_size = nb_elem*sizeof(T);
  96. const size_t expected_size_mod = expected_size + (
  97. (expected_size%page_size != 0)?
  98. page_size - expected_size%page_size
  99. : 0
  100. );
  101. fd = open(
  102. filename.c_str(),
  103. O_RDWR | O_CREAT,
  104. S_ISUID + S_ISGID + S_IRUSR + S_IWUSR + S_IRGRP + S_IWGRP
  105. );
  106. throw_errno_if(fd < 0);
  107. struct stat data;
  108. int status = fstat(fd, &data);
  109. throw_errno_if(status < 0);
  110. if((size_t)data.st_size < expected_size_mod)
  111. {
  112. status = ftruncate(fd, expected_size_mod);
  113. throw_errno_if(status < 0);
  114. }
  115. this->start = (T*)mmap(NULL, expected_size_mod, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  116. throw_errno_if(this->start == nullptr);
  117. mapping_size = expected_size_mod;
  118. item_size = mapping_size / sizeof(T);
  119. auto map_access = MADV_RANDOM;
  120. if(expected_size_mod <= 1 << 20) {
  121. map_access |= MADV_WILLNEED;
  122. }
  123. #ifdef MADV_DONTDUMP
  124. map_access |= MADV_DONTDUMP;
  125. #endif
  126. this->offset = 0;
  127. posix_madvise(this->start, mapping_size, map_access);
  128. }
  129. constexpr size_t size() {
  130. return item_size;
  131. }
  132. constexpr mmap_ptr<T> begin() const {
  133. mmap_ptr<T> ret = *this;
  134. return ret;
  135. }
  136. constexpr mmap_ptr<T> end() const {
  137. mmap_ptr<T> ret = *this;
  138. return ret+item_size;
  139. }
  140. void clear() {
  141. munmap(this->start, mapping_size);
  142. close(fd);
  143. }
  144. ~mmap_array() {
  145. //std::cerr << "unmapping disabled" << std::endl;
  146. if(false)//this->start != nullptr)
  147. {
  148. munmap(this->start, mapping_size);
  149. close(fd);
  150. }
  151. }
  152. };