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,473 @@
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_BUCKET_HPP
9
+ #define NUDB_DETAIL_BUCKET_HPP
10
+
11
+ #include <nudb/error.hpp>
12
+ #include <nudb/type_traits.hpp>
13
+ #include <nudb/detail/bulkio.hpp>
14
+ #include <nudb/detail/field.hpp>
15
+ #include <nudb/detail/format.hpp>
16
+ #include <boost/assert.hpp>
17
+ #include <cstddef>
18
+ #include <cstdint>
19
+ #include <cstring>
20
+
21
+ namespace nudb {
22
+ namespace detail {
23
+
24
+ // Returns bucket index given hash, buckets, and modulus
25
+ //
26
+ inline
27
+ nbuck_t
28
+ bucket_index(nhash_t h, nbuck_t buckets, std::uint64_t modulus)
29
+ {
30
+ BOOST_ASSERT(modulus <= 0x100000000ULL);
31
+ auto n = h % modulus;
32
+ if(n >= buckets)
33
+ n -= modulus / 2;
34
+ return static_cast<nbuck_t>(n);
35
+ }
36
+
37
+ //------------------------------------------------------------------------------
38
+
39
+ // Tag for constructing empty buckets
40
+ struct empty_t
41
+ {
42
+ constexpr empty_t() = default;
43
+ };
44
+
45
+ static empty_t constexpr empty{};
46
+
47
+ // Allows inspection and manipulation of bucket blobs in memory
48
+ template<class = void>
49
+ class bucket_t
50
+ {
51
+ nsize_t block_size_; // Size of a key file block
52
+ nkey_t size_; // Current key count
53
+ noff_t spill_; // Offset of next spill record or 0
54
+ std::uint8_t* p_; // Pointer to the bucket blob
55
+
56
+ public:
57
+ struct value_type
58
+ {
59
+ noff_t offset;
60
+ nhash_t hash;
61
+ nsize_t size;
62
+ };
63
+
64
+ bucket_t() = default;
65
+ bucket_t(bucket_t const&) = default;
66
+ bucket_t& operator=(bucket_t const&) = default;
67
+
68
+ bucket_t(nsize_t block_size, void* p);
69
+
70
+ bucket_t(nsize_t block_size, void* p, empty_t);
71
+
72
+ nsize_t
73
+ block_size() const
74
+ {
75
+ return block_size_;
76
+ }
77
+
78
+ // Serialized bucket size.
79
+ // Excludes empty
80
+ nsize_t
81
+ actual_size() const
82
+ {
83
+ return bucket_size(size_);
84
+ }
85
+
86
+ bool
87
+ empty() const
88
+ {
89
+ return size_ == 0;
90
+ }
91
+
92
+ bool
93
+ full() const
94
+ {
95
+ return size_ >=
96
+ detail::bucket_capacity(block_size_);
97
+ }
98
+
99
+ nkey_t
100
+ size() const
101
+ {
102
+ return size_;
103
+ }
104
+
105
+ // Returns offset of next spill record or 0
106
+ //
107
+ noff_t
108
+ spill() const
109
+ {
110
+ return spill_;
111
+ }
112
+
113
+ // Set offset of next spill record
114
+ //
115
+ void
116
+ spill(noff_t offset);
117
+
118
+ // Clear contents of the bucket
119
+ //
120
+ void
121
+ clear();
122
+
123
+ // Returns the record for a key
124
+ // entry without bounds checking.
125
+ //
126
+ value_type const
127
+ at(nkey_t i) const;
128
+
129
+ value_type const
130
+ operator[](nkey_t i) const
131
+ {
132
+ return at(i);
133
+ }
134
+
135
+ // Returns index of entry with prefix
136
+ // equal to or greater than the given prefix.
137
+ //
138
+ nkey_t
139
+ lower_bound(nhash_t h) const;
140
+
141
+ void
142
+ insert(noff_t offset, nsize_t size, nhash_t h);
143
+
144
+ // Erase an element by index
145
+ //
146
+ void
147
+ erase(nkey_t i);
148
+
149
+ // Read a full bucket from the
150
+ // file at the specified offset.
151
+ //
152
+ template<class File>
153
+ void
154
+ read(File& f, noff_t, error_code& ec);
155
+
156
+ // Read a compact bucket
157
+ //
158
+ template<class File>
159
+ void
160
+ read(bulk_reader<File>& r, error_code& ec);
161
+
162
+ // Write a compact bucket to the stream.
163
+ // This only writes entries that are not empty.
164
+ //
165
+ void
166
+ write(ostream& os) const;
167
+
168
+ // Write a bucket to the file at the specified offset.
169
+ // The full block_size() bytes are written.
170
+ //
171
+ template<class File>
172
+ void
173
+ write(File& f,noff_t offset, error_code& ec) const;
174
+
175
+ private:
176
+ // Update size and spill in the blob
177
+ void
178
+ update();
179
+ };
180
+
181
+ //------------------------------------------------------------------------------
182
+
183
+ template<class _>
184
+ bucket_t<_>::
185
+ bucket_t(nsize_t block_size, void* p)
186
+ : block_size_(block_size)
187
+ , p_(reinterpret_cast<std::uint8_t*>(p))
188
+ {
189
+ // Bucket Record
190
+ istream is(p_, block_size);
191
+ detail::read<uint16_t>(is, size_); // Count
192
+ detail::read<uint48_t>(is, spill_); // Spill
193
+ }
194
+
195
+ template<class _>
196
+ bucket_t<_>::
197
+ bucket_t(nsize_t block_size, void* p, empty_t)
198
+ : block_size_(block_size)
199
+ , size_(0)
200
+ , spill_(0)
201
+ , p_(reinterpret_cast<std::uint8_t*>(p))
202
+ {
203
+ clear();
204
+ }
205
+
206
+ template<class _>
207
+ void
208
+ bucket_t<_>::
209
+ spill(noff_t offset)
210
+ {
211
+ spill_ = offset;
212
+ update();
213
+ }
214
+
215
+ template<class _>
216
+ void
217
+ bucket_t<_>::clear()
218
+ {
219
+ size_ = 0;
220
+ spill_ = 0;
221
+ std::memset(p_, 0, block_size_);
222
+ }
223
+
224
+ template<class _>
225
+ auto
226
+ bucket_t<_>::
227
+ at(nkey_t i) const ->
228
+ value_type const
229
+ {
230
+ value_type result;
231
+ // Bucket Entry
232
+ auto const w =
233
+ field<uint48_t>::size + // Offset
234
+ field<uint48_t>::size + // Size
235
+ field<f_hash>::size; // Prefix
236
+ // Bucket Record
237
+ detail::istream is{p_ +
238
+ field<std::uint16_t>::size + // Count
239
+ field<uint48_t>::size + // Spill
240
+ i * w, w};
241
+ // Bucket Entry
242
+ detail::read<uint48_t>(
243
+ is, result.offset); // Offset
244
+ detail::read_size48(
245
+ is, result.size); // Size
246
+ detail::read<f_hash>(
247
+ is, result.hash); // Hash
248
+ return result;
249
+ }
250
+
251
+ template<class _>
252
+ nkey_t
253
+ bucket_t<_>::
254
+ lower_bound(nhash_t h) const
255
+ {
256
+ // Bucket Entry
257
+ auto const w =
258
+ field<uint48_t>::size + // Offset
259
+ field<uint48_t>::size + // Size
260
+ field<f_hash>::size; // Hash
261
+ // Bucket Record
262
+ auto const p = p_ +
263
+ field<std::uint16_t>::size + // Count
264
+ field<uint48_t>::size + // Spill
265
+ // Bucket Entry
266
+ field<uint48_t>::size + // Offset
267
+ field<uint48_t>::size; // Size
268
+ nkey_t step;
269
+ nkey_t first = 0;
270
+ nkey_t count = size_;
271
+ while(count > 0)
272
+ {
273
+ step = count / 2;
274
+ nkey_t i = first + step;
275
+ nhash_t h1;
276
+ readp<f_hash>(p + i * w, h1);
277
+ if(h1 < h)
278
+ {
279
+ first = i + 1;
280
+ count -= step + 1;
281
+ }
282
+ else
283
+ {
284
+ count = step;
285
+ }
286
+ }
287
+ return first;
288
+ }
289
+
290
+ template<class _>
291
+ void
292
+ bucket_t<_>::
293
+ insert(
294
+ noff_t offset, nsize_t size, nhash_t h)
295
+ {
296
+ auto const i = lower_bound(h);
297
+ // Bucket Record
298
+ auto const p = p_ +
299
+ field<
300
+ std::uint16_t>::size + // Count
301
+ field<uint48_t>::size; // Spill
302
+ // Bucket Entry
303
+ auto const w =
304
+ field<uint48_t>::size + // Offset
305
+ field<uint48_t>::size + // Size
306
+ field<f_hash>::size; // Hash
307
+ std::memmove(
308
+ p +(i + 1) * w,
309
+ p + i * w,
310
+ (size_ - i) * w);
311
+ ++size_;
312
+ update();
313
+ // Bucket Entry
314
+ ostream os{p + i * w, w};
315
+ detail::write<uint48_t>(
316
+ os, offset); // Offset
317
+ detail::write<uint48_t>(
318
+ os, size); // Size
319
+ detail::write<f_hash>(
320
+ os, h); // Prefix
321
+ }
322
+
323
+ template<class _>
324
+ void
325
+ bucket_t<_>::
326
+ erase(nkey_t i)
327
+ {
328
+ // Bucket Record
329
+ auto const p = p_ +
330
+ field<std::uint16_t>::size + // Count
331
+ field<uint48_t>::size; // Spill
332
+ auto const w =
333
+ field<uint48_t>::size + // Offset
334
+ field<uint48_t>::size + // Size
335
+ field<f_hash>::size; // Hash
336
+ --size_;
337
+ if(i < size_)
338
+ std::memmove(
339
+ p + i * w,
340
+ p +(i + 1) * w,
341
+ (size_ - i) * w);
342
+ std::memset(p + size_ * w, 0, w);
343
+ update();
344
+ }
345
+
346
+ template<class _>
347
+ template<class File>
348
+ void
349
+ bucket_t<_>::
350
+ read(File& f, noff_t offset, error_code& ec)
351
+ {
352
+ auto const cap = bucket_capacity(block_size_);
353
+ // Excludes padding to block size
354
+ f.read(offset, p_, bucket_size(cap), ec);
355
+ if(ec)
356
+ return;
357
+ istream is{p_, block_size_};
358
+ detail::read<std::uint16_t>(is, size_); // Count
359
+ detail::read<uint48_t>(is, spill_); // Spill
360
+ if(size_ > cap)
361
+ {
362
+ ec = error::invalid_bucket_size;
363
+ return;
364
+ }
365
+ }
366
+
367
+ template<class _>
368
+ template<class File>
369
+ void
370
+ bucket_t<_>::
371
+ read(bulk_reader<File>& r, error_code& ec)
372
+ {
373
+ // Bucket Record(compact)
374
+ auto is = r.prepare(
375
+ detail::field<std::uint16_t>::size +
376
+ detail::field<uint48_t>::size, ec);
377
+ if(ec)
378
+ return;
379
+ detail::read<std::uint16_t>(is, size_); // Count
380
+ detail::read<uint48_t>(is, spill_); // Spill
381
+ update();
382
+ // Excludes empty bucket entries
383
+ auto const w = size_ * (
384
+ field<uint48_t>::size + // Offset
385
+ field<uint48_t>::size + // Size
386
+ field<f_hash>::size); // Hash
387
+ is = r.prepare(w, ec);
388
+ if(ec)
389
+ return;
390
+ std::memcpy(p_ +
391
+ field<std::uint16_t>::size + // Count
392
+ field<uint48_t>::size, // Spill
393
+ is.data(w), w); // Entries
394
+ }
395
+
396
+ template<class _>
397
+ void
398
+ bucket_t<_>::
399
+ write(ostream& os) const
400
+ {
401
+ // Does not pad up to the block size. This
402
+ // is called to write to the data file.
403
+ auto const size = actual_size();
404
+ // Bucket Record
405
+ std::memcpy(os.data(size), p_, size);
406
+ }
407
+
408
+ template<class _>
409
+ template<class File>
410
+ void
411
+ bucket_t<_>::
412
+ write(File& f, noff_t offset, error_code& ec) const
413
+ {
414
+ // Includes zero pad up to the block
415
+ // size, to make the key file size always
416
+ // a multiple of the block size.
417
+ auto const size = actual_size();
418
+ std::memset(p_ + size, 0, block_size_ - size);
419
+ // Bucket Record
420
+ f.write(offset, p_, block_size_, ec);
421
+ if(ec)
422
+ return;
423
+ }
424
+
425
+ template<class _>
426
+ void
427
+ bucket_t<_>::
428
+ update()
429
+ {
430
+ // Bucket Record
431
+ ostream os{p_, block_size_};
432
+ detail::write<std::uint16_t>(os, size_); // Count
433
+ detail::write<uint48_t>(os, spill_); // Spill
434
+ }
435
+
436
+ using bucket = bucket_t<>;
437
+
438
+ //------------------------------------------------------------------------------
439
+
440
+ // Spill bucket if full.
441
+ // The bucket is cleared after it spills.
442
+ //
443
+ template<class File>
444
+ void
445
+ maybe_spill(
446
+ bucket& b, bulk_writer<File>& w, error_code& ec)
447
+ {
448
+ if(b.full())
449
+ {
450
+ // Spill Record
451
+ auto const offset = w.offset();
452
+ auto os = w.prepare(
453
+ field<uint48_t>::size + // Zero
454
+ field<uint16_t>::size + // Size
455
+ b.actual_size(), ec);
456
+ if(ec)
457
+ return;
458
+ write<uint48_t>(os, 0ULL); // Zero
459
+ write<std::uint16_t>(
460
+ os, b.actual_size()); // Size
461
+ auto const spill =
462
+ offset + os.size();
463
+ b.write(os); // Bucket
464
+ // Update bucket
465
+ b.clear();
466
+ b.spill(spill);
467
+ }
468
+ }
469
+
470
+ } // detail
471
+ } // nudb
472
+
473
+ #endif
@@ -0,0 +1,86 @@
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_BUFFER_HPP
9
+ #define NUDB_DETAIL_BUFFER_HPP
10
+
11
+ #include <atomic>
12
+ #include <cstdint>
13
+ #include <memory>
14
+
15
+ namespace nudb {
16
+ namespace detail {
17
+
18
+ // Simple growable memory buffer
19
+ class buffer
20
+ {
21
+ private:
22
+ std::size_t size_ = 0;
23
+ std::unique_ptr<std::uint8_t[]> buf_;
24
+
25
+ public:
26
+ ~buffer() = default;
27
+ buffer() = default;
28
+ buffer(buffer const&) = delete;
29
+ buffer& operator=(buffer const&) = delete;
30
+
31
+ explicit
32
+ buffer(std::size_t n)
33
+ : size_(n)
34
+ , buf_(new std::uint8_t[n])
35
+ {
36
+ }
37
+
38
+ buffer(buffer&& other)
39
+ : size_(other.size_)
40
+ , buf_(std::move(other.buf_))
41
+ {
42
+ other.size_ = 0;
43
+ }
44
+
45
+ buffer&
46
+ operator=(buffer&& other)
47
+ {
48
+ size_ = other.size_;
49
+ buf_ = std::move(other.buf_);
50
+ other.size_ = 0;
51
+ return *this;
52
+ }
53
+
54
+ std::size_t
55
+ size() const
56
+ {
57
+ return size_;
58
+ }
59
+
60
+ std::uint8_t*
61
+ get() const
62
+ {
63
+ return buf_.get();
64
+ }
65
+
66
+ void
67
+ reserve(std::size_t n)
68
+ {
69
+ if(size_ < n)
70
+ buf_.reset(new std::uint8_t[n]);
71
+ size_ = n;
72
+ }
73
+
74
+ // BufferFactory
75
+ void*
76
+ operator()(std::size_t n)
77
+ {
78
+ reserve(n);
79
+ return buf_.get();
80
+ }
81
+ };
82
+
83
+ } // detail
84
+ } // nudb
85
+
86
+ #endif