rrudb 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +26 -0
  5. data/examples/example.rb +39 -0
  6. data/ext/rudb/NuDB/include/nudb/CMakeLists.txt +104 -0
  7. data/ext/rudb/NuDB/include/nudb/_experimental/basic_seconds_clock.hpp +200 -0
  8. data/ext/rudb/NuDB/include/nudb/_experimental/chrono_util.hpp +58 -0
  9. data/ext/rudb/NuDB/include/nudb/_experimental/test/fail_file.hpp +343 -0
  10. data/ext/rudb/NuDB/include/nudb/_experimental/test/temp_dir.hpp +73 -0
  11. data/ext/rudb/NuDB/include/nudb/_experimental/test/test_store.hpp +451 -0
  12. data/ext/rudb/NuDB/include/nudb/_experimental/test/xor_shift_engine.hpp +105 -0
  13. data/ext/rudb/NuDB/include/nudb/_experimental/util.hpp +288 -0
  14. data/ext/rudb/NuDB/include/nudb/basic_store.hpp +461 -0
  15. data/ext/rudb/NuDB/include/nudb/concepts.hpp +205 -0
  16. data/ext/rudb/NuDB/include/nudb/context.hpp +144 -0
  17. data/ext/rudb/NuDB/include/nudb/create.hpp +117 -0
  18. data/ext/rudb/NuDB/include/nudb/detail/arena.hpp +296 -0
  19. data/ext/rudb/NuDB/include/nudb/detail/bucket.hpp +473 -0
  20. data/ext/rudb/NuDB/include/nudb/detail/buffer.hpp +86 -0
  21. data/ext/rudb/NuDB/include/nudb/detail/bulkio.hpp +196 -0
  22. data/ext/rudb/NuDB/include/nudb/detail/cache.hpp +236 -0
  23. data/ext/rudb/NuDB/include/nudb/detail/endian.hpp +93 -0
  24. data/ext/rudb/NuDB/include/nudb/detail/field.hpp +265 -0
  25. data/ext/rudb/NuDB/include/nudb/detail/format.hpp +630 -0
  26. data/ext/rudb/NuDB/include/nudb/detail/gentex.hpp +259 -0
  27. data/ext/rudb/NuDB/include/nudb/detail/mutex.hpp +26 -0
  28. data/ext/rudb/NuDB/include/nudb/detail/pool.hpp +243 -0
  29. data/ext/rudb/NuDB/include/nudb/detail/store_base.hpp +45 -0
  30. data/ext/rudb/NuDB/include/nudb/detail/stream.hpp +149 -0
  31. data/ext/rudb/NuDB/include/nudb/detail/xxhash.hpp +328 -0
  32. data/ext/rudb/NuDB/include/nudb/error.hpp +257 -0
  33. data/ext/rudb/NuDB/include/nudb/file.hpp +55 -0
  34. data/ext/rudb/NuDB/include/nudb/impl/basic_store.ipp +785 -0
  35. data/ext/rudb/NuDB/include/nudb/impl/context.ipp +241 -0
  36. data/ext/rudb/NuDB/include/nudb/impl/create.ipp +163 -0
  37. data/ext/rudb/NuDB/include/nudb/impl/error.ipp +175 -0
  38. data/ext/rudb/NuDB/include/nudb/impl/posix_file.ipp +248 -0
  39. data/ext/rudb/NuDB/include/nudb/impl/recover.ipp +209 -0
  40. data/ext/rudb/NuDB/include/nudb/impl/rekey.ipp +248 -0
  41. data/ext/rudb/NuDB/include/nudb/impl/verify.ipp +634 -0
  42. data/ext/rudb/NuDB/include/nudb/impl/visit.ipp +96 -0
  43. data/ext/rudb/NuDB/include/nudb/impl/win32_file.ipp +264 -0
  44. data/ext/rudb/NuDB/include/nudb/native_file.hpp +76 -0
  45. data/ext/rudb/NuDB/include/nudb/nudb.hpp +27 -0
  46. data/ext/rudb/NuDB/include/nudb/posix_file.hpp +228 -0
  47. data/ext/rudb/NuDB/include/nudb/progress.hpp +32 -0
  48. data/ext/rudb/NuDB/include/nudb/recover.hpp +73 -0
  49. data/ext/rudb/NuDB/include/nudb/rekey.hpp +110 -0
  50. data/ext/rudb/NuDB/include/nudb/store.hpp +27 -0
  51. data/ext/rudb/NuDB/include/nudb/type_traits.hpp +63 -0
  52. data/ext/rudb/NuDB/include/nudb/verify.hpp +200 -0
  53. data/ext/rudb/NuDB/include/nudb/version.hpp +21 -0
  54. data/ext/rudb/NuDB/include/nudb/visit.hpp +63 -0
  55. data/ext/rudb/NuDB/include/nudb/win32_file.hpp +246 -0
  56. data/ext/rudb/NuDB/include/nudb/xxhasher.hpp +45 -0
  57. data/ext/rudb/extconf.rb +12 -0
  58. data/ext/rudb/rudb.cpp +234 -0
  59. data/lib/rudb/version.rb +3 -0
  60. data/lib/rudb.rb +1 -0
  61. metadata +104 -0
@@ -0,0 +1,144 @@
1
+ //
2
+ // Copyright (c) 2019 Miguel Portilla (miguelportilla64 at gmail dot com)
3
+ //
4
+ // Distributed under the Boost Software License, Version 1.0. (See accompanying
5
+ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
+ //
7
+
8
+ #ifndef NUDB_CONTEXT_HPP
9
+ #define NUDB_CONTEXT_HPP
10
+
11
+ #include <condition_variable>
12
+ #include <memory>
13
+ #include <mutex>
14
+ #include <thread>
15
+
16
+ #define NUDB_DECL inline
17
+
18
+ namespace nudb {
19
+
20
+ namespace test {
21
+ class context_test;
22
+ } // test
23
+
24
+ namespace detail {
25
+ class store_base;
26
+ } // detail
27
+
28
+ class context
29
+ {
30
+ public:
31
+ /// Constructor
32
+ context() = default;
33
+
34
+ /** Destructor.
35
+
36
+ Halts execution of all threads. Blocks until all threads
37
+ have completed any ongoing operation and have stopped.
38
+ */
39
+ NUDB_DECL
40
+ ~context() noexcept (false);
41
+
42
+ /// Copy constructor (disallowed)
43
+ context(context const&) = delete;
44
+
45
+ /// Move constructor (disallowed)
46
+ context(context&&) = delete;
47
+
48
+ // Copy assignment (disallowed)
49
+ context& operator=(context const&) = delete;
50
+
51
+ // Move assignment (disallowed)
52
+ context& operator=(context&&) = delete;
53
+
54
+ /** Start thread execution.
55
+
56
+ Starts the context thread execution.
57
+ */
58
+ NUDB_DECL
59
+ void
60
+ start();
61
+
62
+ /** Stop thread execution.
63
+
64
+ Halts execution of all threads. Blocks until all threads
65
+ have completed any ongoing operation and have stopped.
66
+ */
67
+ NUDB_DECL
68
+ void
69
+ stop_all();
70
+
71
+ /** Thread function.
72
+
73
+ Function to service the databases.
74
+ Thread objects must call this function.
75
+ */
76
+ NUDB_DECL
77
+ void
78
+ run();
79
+
80
+ private:
81
+ using clock_type = std::chrono::steady_clock;
82
+ using store_base = detail::store_base;
83
+
84
+ template<class, class> friend class basic_store;
85
+ #if ! NUDB_DOXYGEN
86
+ friend class test::context_test;
87
+ #endif
88
+
89
+ NUDB_DECL
90
+ void
91
+ insert(store_base& store);
92
+
93
+ NUDB_DECL
94
+ void
95
+ erase(store_base& store);
96
+
97
+ NUDB_DECL
98
+ bool
99
+ flush_one();
100
+
101
+ class list
102
+ {
103
+ public:
104
+ NUDB_DECL
105
+ void
106
+ push_back(store_base* node);
107
+
108
+ NUDB_DECL
109
+ void
110
+ erase(store_base* node);
111
+
112
+ NUDB_DECL
113
+ void
114
+ splice(list& l);
115
+
116
+ bool
117
+ empty() const noexcept
118
+ {
119
+ return head_ == nullptr;
120
+ }
121
+
122
+ store_base* head_ = nullptr;
123
+
124
+ private:
125
+ store_base* tail_ = nullptr;
126
+ };
127
+
128
+ std::mutex m_;
129
+ list waiting_;
130
+ std::condition_variable cv_w_;
131
+ list flushing_;
132
+ std::condition_variable cv_f_;
133
+
134
+ std::uint32_t num_threads_ = 0;
135
+ std::thread t_;
136
+
137
+ bool stop_ = false;
138
+ };
139
+
140
+ } // nudb
141
+
142
+ #include <nudb/impl/context.ipp>
143
+
144
+ #endif
@@ -0,0 +1,117 @@
1
+ //
2
+ // Copyright (c) 2015-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
3
+ //
4
+ // Distributed under the Boost Software License, Version 1.0. (See accompanying
5
+ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
+ //
7
+
8
+ #ifndef NUDB_CREATE_HPP
9
+ #define NUDB_CREATE_HPP
10
+
11
+ #include <nudb/native_file.hpp>
12
+ #include <nudb/detail/bucket.hpp>
13
+ #include <nudb/detail/format.hpp>
14
+ #include <algorithm>
15
+ #include <cstring>
16
+ #include <random>
17
+ #include <stdexcept>
18
+ #include <utility>
19
+
20
+ namespace nudb {
21
+
22
+ /** Return a random salt.
23
+
24
+ This function will use the system provided random
25
+ number device to generate a uniformly distributed
26
+ 64-bit unsigned value suitable for use the salt
27
+ value in a call to @ref create.
28
+ */
29
+ template<class = void>
30
+ std::uint64_t
31
+ make_salt();
32
+
33
+ /** Create a new database.
34
+
35
+ This function creates a set of new database files with
36
+ the given parameters. The files must not already exist or
37
+ else an error is returned.
38
+
39
+ If an error occurs while the files are being created,
40
+ the function attempts to remove the files before
41
+ returning.
42
+
43
+ @par Example
44
+ @code
45
+ error_code ec;
46
+ create<xxhasher>(
47
+ "db.dat", "db.key", "db.log",
48
+ 1, make_salt(), 8, 4096, 0.5f, ec);
49
+ @endcode
50
+
51
+ @par Template Parameters
52
+
53
+ @tparam Hasher The hash function to use. This type must
54
+ meet the requirements of @b Hasher. The same hash
55
+ function must be used every time the database is opened,
56
+ or else an error is returned. The provided @ref xxhasher
57
+ is a suitable general purpose hash function.
58
+
59
+ @tparam File The type of file to use. Use the default of
60
+ @ref native_file unless customizing the file behavior.
61
+
62
+ @param dat_path The path to the data file.
63
+
64
+ @param key_path The path to the key file.
65
+
66
+ @param log_path The path to the log file.
67
+
68
+ @param appnum A caller-defined value stored in the file
69
+ headers. When opening the database, the same value is
70
+ preserved and returned to the caller.
71
+
72
+ @param salt A random unsigned integer used to permute
73
+ the hash function to make it unpredictable. The return
74
+ value of @ref make_salt returns a suitable value.
75
+
76
+ @param key_size The number of bytes in each key.
77
+
78
+ @param blockSize The size of a key file block. Larger
79
+ blocks hold more keys but require more I/O cycles per
80
+ operation. The ideal block size the largest size that
81
+ may be read in a single I/O cycle, and device dependent.
82
+ The return value of @ref block_size returns a suitable
83
+ value for the volume of a given path.
84
+
85
+ @param load_factor A number between zero and one
86
+ representing the average bucket occupancy (number of
87
+ items). A value of 0.5 is perfect. Lower numbers
88
+ waste space, and higher numbers produce negligible
89
+ savings at the cost of increased I/O cycles.
90
+
91
+ @param ec Set to the error, if any occurred.
92
+
93
+ @param args Optional arguments passed to @b File constructors.
94
+ */
95
+ template<
96
+ class Hasher,
97
+ class File = native_file,
98
+ class... Args
99
+ >
100
+ void
101
+ create(
102
+ path_type const& dat_path,
103
+ path_type const& key_path,
104
+ path_type const& log_path,
105
+ std::uint64_t appnum,
106
+ std::uint64_t salt,
107
+ nsize_t key_size,
108
+ nsize_t blockSize,
109
+ float load_factor,
110
+ error_code& ec,
111
+ Args&&... args);
112
+
113
+ } // nudb
114
+
115
+ #include <nudb/impl/create.ipp>
116
+
117
+ #endif
@@ -0,0 +1,296 @@
1
+ //
2
+ // Copyright (c) 2015-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
3
+ //
4
+ // Distributed under the Boost Software License, Version 1.0. (See accompanying
5
+ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
+ //
7
+
8
+ #ifndef NUDB_DETAIL_ARENA_HPP
9
+ #define NUDB_DETAIL_ARENA_HPP
10
+
11
+ #include <boost/assert.hpp>
12
+ #include <algorithm>
13
+ #include <chrono>
14
+ #include <cmath>
15
+ #include <cstddef>
16
+ #include <cstdint>
17
+ #include <memory>
18
+
19
+ #if NUDB_DEBUG_ARENA
20
+ #include <boost/beast/_experimental/unit_test/dstream.hpp>
21
+ #include <iostream>
22
+ #endif
23
+
24
+ namespace nudb {
25
+ namespace detail {
26
+
27
+ /* Custom memory manager that allocates in large blocks.
28
+
29
+ The implementation measures the rate of allocations in
30
+ bytes per second and tunes the large block size to fit
31
+ one second's worth of allocations.
32
+ */
33
+ template<class = void>
34
+ class arena_t
35
+ {
36
+ using clock_type =
37
+ std::chrono::steady_clock;
38
+
39
+ using time_point =
40
+ typename clock_type::time_point;
41
+
42
+ class element;
43
+
44
+ char const* label_; // diagnostic
45
+ std::size_t alloc_ = 0; // block size
46
+ std::size_t used_ = 0; // bytes allocated
47
+ element* list_ = nullptr; // list of blocks
48
+ time_point when_ = clock_type::now();
49
+
50
+ public:
51
+ arena_t(arena_t const&) = delete;
52
+ arena_t& operator=(arena_t&&) = delete;
53
+ arena_t& operator=(arena_t const&) = delete;
54
+
55
+ ~arena_t();
56
+
57
+ explicit
58
+ arena_t(char const* label = "");
59
+
60
+ arena_t(arena_t&& other);
61
+
62
+ // Set the allocation size
63
+ void
64
+ hint(std::size_t alloc)
65
+ {
66
+ alloc_ = alloc;
67
+ }
68
+
69
+ // Free all memory
70
+ void
71
+ clear();
72
+
73
+ void
74
+ periodic_activity();
75
+
76
+ std::uint8_t*
77
+ alloc(std::size_t n);
78
+
79
+ template<class U>
80
+ friend
81
+ void
82
+ swap(arena_t<U>& lhs, arena_t<U>& rhs);
83
+ };
84
+
85
+ //------------------------------------------------------------------------------
86
+
87
+ template<class _>
88
+ class arena_t<_>::element
89
+ {
90
+ std::size_t const capacity_;
91
+ std::size_t used_ = 0;
92
+ element* next_;
93
+
94
+ public:
95
+ element(std::size_t capacity, element* next)
96
+ : capacity_(capacity)
97
+ , next_(next)
98
+ {
99
+ }
100
+
101
+ element*
102
+ next() const
103
+ {
104
+ return next_;
105
+ }
106
+
107
+ void
108
+ clear()
109
+ {
110
+ used_ = 0;
111
+ }
112
+
113
+ std::size_t
114
+ remain() const
115
+ {
116
+ return capacity_ - used_;
117
+ }
118
+
119
+ std::size_t
120
+ capacity() const
121
+ {
122
+ return capacity_;
123
+ }
124
+
125
+ std::uint8_t*
126
+ alloc(std::size_t n);
127
+ };
128
+
129
+ template<class _>
130
+ std::uint8_t*
131
+ arena_t<_>::element::
132
+ alloc(std::size_t n)
133
+ {
134
+ if(n > capacity_ - used_)
135
+ return nullptr;
136
+ auto const p = const_cast<std::uint8_t*>(
137
+ reinterpret_cast<uint8_t const*>(this + 1)
138
+ ) + used_;
139
+ used_ += n;
140
+ return p;
141
+ }
142
+
143
+ //------------------------------------------------------------------------------
144
+
145
+ template<class _>
146
+ arena_t<_>::
147
+ arena_t(char const* label)
148
+ : label_(label)
149
+ {
150
+ }
151
+
152
+ template<class _>
153
+ arena_t<_>::
154
+ ~arena_t()
155
+ {
156
+ clear();
157
+ }
158
+
159
+ template<class _>
160
+ arena_t<_>::
161
+ arena_t(arena_t&& other)
162
+ : label_(other.label_)
163
+ , alloc_(other.alloc_)
164
+ , used_(other.used_)
165
+ , list_(other.list_)
166
+ , when_(other.when_)
167
+ {
168
+ other.used_ = 0;
169
+ other.list_ = nullptr;
170
+ other.when_ = clock_type::now();
171
+ other.alloc_ = 0;
172
+ }
173
+
174
+ template<class _>
175
+ void
176
+ arena_t<_>::
177
+ clear()
178
+ {
179
+ used_ = 0;
180
+ while(list_)
181
+ {
182
+ auto const e = list_;
183
+ list_ = list_->next();
184
+ e->~element();
185
+ delete[] reinterpret_cast<std::uint8_t*>(e);
186
+ }
187
+ }
188
+
189
+ template<class _>
190
+ void
191
+ arena_t<_>::
192
+ periodic_activity()
193
+ {
194
+ using namespace std::chrono;
195
+ auto const now = clock_type::now();
196
+ auto const elapsed = now - when_;
197
+ if(elapsed < milliseconds{500})
198
+ return;
199
+ when_ = now;
200
+ auto const rate = static_cast<std::size_t>(std::ceil(
201
+ used_ / duration_cast<duration<float>>(elapsed).count()));
202
+ #if NUDB_DEBUG_ARENA
203
+ beast::unit_test::dstream dout{std::cout};
204
+ auto const size =
205
+ [](element* e)
206
+ {
207
+ std::size_t n = 0;
208
+ while(e)
209
+ {
210
+ ++n;
211
+ e = e->next();
212
+ }
213
+ return n;
214
+ };
215
+ #endif
216
+ if(rate >= alloc_ * 2)
217
+ {
218
+ // adjust up
219
+ alloc_ = std::max(rate, alloc_ * 2);
220
+ #if NUDB_DEBUG_ARENA
221
+ dout << label_ << ": "
222
+ "rate=" << rate <<
223
+ ", alloc=" << alloc_ << " UP"
224
+ ", nused=" << used_ <<
225
+ ", used=" << size(list_) <<
226
+ "\n";
227
+ #endif
228
+ }
229
+ else if(rate <= alloc_ / 2)
230
+ {
231
+ // adjust down
232
+ alloc_ /= 2;
233
+ #if NUDB_DEBUG_ARENA
234
+ dout << label_ << ": "
235
+ "rate=" << rate <<
236
+ ", alloc=" << alloc_ << " DOWN"
237
+ ", nused=" << used_ <<
238
+ ", used=" << size(list_) <<
239
+ "\n";
240
+ #endif
241
+ }
242
+ else
243
+ {
244
+ #if NUDB_DEBUG_ARENA
245
+ dout << label_ << ": "
246
+ "rate=" << rate <<
247
+ ", alloc=" << alloc_ <<
248
+ ", nused=" << used_ <<
249
+ ", used=" << size(list_) <<
250
+ "\n";
251
+ #endif
252
+ }
253
+ }
254
+
255
+ template<class _>
256
+ std::uint8_t*
257
+ arena_t<_>::
258
+ alloc(std::size_t n)
259
+ {
260
+ // Undefined behavior: Zero byte allocations
261
+ BOOST_ASSERT(n != 0);
262
+ n = 8 *((n + 7) / 8);
263
+ std::uint8_t* p;
264
+ if(list_)
265
+ {
266
+ p = list_->alloc(n);
267
+ if(p)
268
+ {
269
+ used_ += n;
270
+ return p;
271
+ }
272
+ }
273
+ auto const size = std::max(alloc_, n);
274
+ auto const e = reinterpret_cast<element*>(
275
+ new std::uint8_t[sizeof(element) + size]);
276
+ list_ = ::new(e) element{size, list_};
277
+ used_ += n;
278
+ return list_->alloc(n);
279
+ }
280
+
281
+ template<class _>
282
+ void
283
+ swap(arena_t<_>& lhs, arena_t<_>& rhs)
284
+ {
285
+ using std::swap;
286
+ swap(lhs.used_, rhs.used_);
287
+ swap(lhs.list_, rhs.list_);
288
+ // don't swap alloc_ or when_
289
+ }
290
+
291
+ using arena = arena_t<>;
292
+
293
+ } // detail
294
+ } // nudb
295
+
296
+ #endif