rrudb 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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