Goddess of Justice DB, the database used for storage on IzaroDFS
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

188 linhas
3.5 KiB

5 anos atrás
  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. };