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,461 @@
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_BASIC_STORE_HPP
9
+ #define NUDB_BASIC_STORE_HPP
10
+
11
+ #include <nudb/context.hpp>
12
+ #include <nudb/file.hpp>
13
+ #include <nudb/type_traits.hpp>
14
+ #include <nudb/detail/cache.hpp>
15
+ #include <nudb/detail/gentex.hpp>
16
+ #include <nudb/detail/mutex.hpp>
17
+ #include <nudb/detail/pool.hpp>
18
+ #include <nudb/detail/store_base.hpp>
19
+ #include <boost/optional.hpp>
20
+ #include <chrono>
21
+
22
+ namespace nudb {
23
+
24
+ /** A high performance, insert-only key/value database for SSDs.
25
+
26
+ To create a database first call the @ref create
27
+ free function. Then construct a @ref basic_store and
28
+ call @ref open on it:
29
+
30
+ @code
31
+ error_code ec;
32
+ create<xxhasher>(
33
+ "db.dat", "db.key", "db.log",
34
+ 1, make_salt(), 8, 4096, 0.5f, ec);
35
+ basic_store<xxhasher, native_file> db;
36
+ db.open("db.dat", "db.key", "db.log", ec);
37
+ @endcode
38
+
39
+ @tparam Hasher The hash function to use. This type
40
+ must meet the requirements of @b Hasher.
41
+
42
+ @tparam File The type of File object to use. This type
43
+ must meet the requirements of @b File.
44
+ */
45
+ template<class Hasher, class File>
46
+ class basic_store
47
+ #if ! NUDB_DOXYGEN
48
+ : private detail::store_base
49
+ #endif
50
+ {
51
+ public:
52
+ using hash_type = Hasher;
53
+ using file_type = File;
54
+
55
+ private:
56
+ using clock_type =
57
+ std::chrono::steady_clock;
58
+
59
+ using time_point =
60
+ typename clock_type::time_point;
61
+
62
+ #if ! NUDB_DOXYGEN
63
+ friend class test::context_test;
64
+ #endif
65
+
66
+ struct state
67
+ {
68
+ File df;
69
+ File kf;
70
+ File lf;
71
+ path_type dp;
72
+ path_type kp;
73
+ path_type lp;
74
+ Hasher hasher;
75
+ detail::pool p0;
76
+ detail::pool p1;
77
+ detail::cache c1;
78
+ detail::key_file_header kh;
79
+
80
+ std::size_t rate = 0;
81
+ time_point when = clock_type::now();
82
+
83
+ state(state const&) = delete;
84
+ state& operator=(state const&) = delete;
85
+
86
+ state(state&&) = default;
87
+ state& operator=(state&&) = default;
88
+
89
+ state(File&& df_, File&& kf_, File&& lf_,
90
+ path_type const& dp_, path_type const& kp_,
91
+ path_type const& lp_,
92
+ detail::key_file_header const& kh_);
93
+ };
94
+
95
+ bool open_ = false;
96
+
97
+ // Use optional because some
98
+ // members cannot be default-constructed.
99
+ //
100
+ boost::optional<state> s_; // State of an open database
101
+
102
+ std::size_t frac_; // accumulates load
103
+ std::size_t thresh_; // split threshold
104
+ nbuck_t buckets_; // number of buckets
105
+ nbuck_t modulus_; // hash modulus
106
+
107
+ std::mutex u_; // serializes insert()
108
+ detail::gentex g_;
109
+ boost::shared_mutex m_;
110
+
111
+ error_code ec_;
112
+ std::atomic<bool> ecb_; // `true` when ec_ set
113
+
114
+ std::size_t dataWriteSize_;
115
+ std::size_t logWriteSize_;
116
+
117
+ struct deleter
118
+ {
119
+ deleter() = default;
120
+ deleter(bool) : free_(true) {}
121
+ void operator() (context* p) const
122
+ {
123
+ if (free_)
124
+ delete p;
125
+ }
126
+
127
+ bool free_ = false;
128
+ };
129
+
130
+ std::unique_ptr<context, deleter> ctx_;
131
+
132
+ public:
133
+ /** Default constructor.
134
+
135
+ A default constructed database is initially closed.
136
+ */
137
+ basic_store() : ctx_(new context, true)
138
+ {
139
+ ctx_->start();
140
+ }
141
+
142
+ basic_store(context& ctx) : ctx_(&ctx) {}
143
+
144
+ /// Copy constructor (disallowed)
145
+ basic_store(basic_store const&) = delete;
146
+
147
+ /// Copy assignment (disallowed)
148
+ basic_store& operator=(basic_store const&) = delete;
149
+
150
+ /** Destroy the database.
151
+
152
+ Files are closed, memory is freed, and data that has not been
153
+ committed is discarded. To ensure that all inserted data is
154
+ written, it is necessary to call @ref close before destroying
155
+ the @ref basic_store.
156
+
157
+ This function ignores errors returned by @ref close; to receive
158
+ those errors it is necessary to call @ref close before the
159
+ @ref basic_store is destroyed.
160
+ */
161
+ ~basic_store();
162
+
163
+ /** Returns `true` if the database is open.
164
+
165
+ @par Thread safety
166
+
167
+ Safe to call concurrently with any function
168
+ except @ref open or @ref close.
169
+ */
170
+ bool
171
+ is_open() const
172
+ {
173
+ return open_;
174
+ }
175
+
176
+ /** Return the path to the data file.
177
+
178
+ @par Requirements
179
+
180
+ The database must be open.
181
+
182
+ @par Thread safety
183
+
184
+ Safe to call concurrently with any function
185
+ except @ref open or @ref close.
186
+
187
+ @return The data file path.
188
+ */
189
+ path_type const&
190
+ dat_path() const;
191
+
192
+ /** Return the path to the key file.
193
+
194
+ @par Requirements
195
+
196
+ The database must be open.
197
+
198
+ @par Thread safety
199
+
200
+ Safe to call concurrently with any function
201
+ except @ref open or @ref close.
202
+
203
+ @return The key file path.
204
+ */
205
+ path_type const&
206
+ key_path() const;
207
+
208
+ /** Return the path to the log file.
209
+
210
+ @par Requirements
211
+
212
+ The database must be open.
213
+
214
+ @par Thread safety
215
+
216
+ Safe to call concurrently with any function
217
+ except @ref open or @ref close.
218
+
219
+ @return The log file path.
220
+ */
221
+ path_type const&
222
+ log_path() const;
223
+
224
+ /** Return the appnum associated with the database.
225
+
226
+ This is an unsigned 64-bit integer associated with the
227
+ database and defined by the application. It is set
228
+ once when the database is created in a call to
229
+ @ref create.
230
+
231
+ @par Requirements
232
+
233
+ The database must be open.
234
+
235
+ @par Thread safety
236
+
237
+ Safe to call concurrently with any function
238
+ except @ref open or @ref close.
239
+
240
+ @return The appnum.
241
+ */
242
+ std::uint64_t
243
+ appnum() const;
244
+
245
+ /** Return the key size associated with the database.
246
+
247
+ The key size is defined by the application when the
248
+ database is created in a call to @ref create. The
249
+ key size cannot be changed on an existing database.
250
+
251
+ @par Requirements
252
+
253
+ The database must be open.
254
+
255
+ @par Thread safety
256
+
257
+ Safe to call concurrently with any function
258
+ except @ref open or @ref close.
259
+
260
+ @return The size of keys in the database.
261
+ */
262
+ std::size_t
263
+ key_size() const;
264
+
265
+ /** Return the block size associated with the database.
266
+
267
+ The block size is defined by the application when the
268
+ database is created in a call to @ref create or when a
269
+ key file is regenerated in a call to @ref rekey. The
270
+ block size cannot be changed on an existing key file.
271
+ Instead, a new key file may be created with a different
272
+ block size.
273
+
274
+ @par Requirements
275
+
276
+ The database must be open.
277
+
278
+ @par Thread safety
279
+
280
+ Safe to call concurrently with any function
281
+ except @ref open or @ref close.
282
+
283
+ @return The size of blocks in the key file.
284
+ */
285
+ std::size_t
286
+ block_size() const;
287
+
288
+ /** Close the database.
289
+
290
+ All data is committed before closing.
291
+
292
+ If an error occurs, the database is still closed.
293
+
294
+ @par Requirements
295
+
296
+ The database must be open.
297
+
298
+ @par Thread safety
299
+
300
+ Not thread safe. The caller is responsible for
301
+ ensuring that no other member functions are
302
+ called concurrently.
303
+
304
+ @param ec Set to the error, if any occurred.
305
+ */
306
+ void
307
+ close(error_code& ec);
308
+
309
+ /** Open a database.
310
+
311
+ The database identified by the specified data, key, and
312
+ log file paths is opened. If a log file is present, the
313
+ recovery mechanism is invoked to restore database integrity
314
+ before the function returns.
315
+
316
+ @par Requirements
317
+
318
+ The database must be not be open.
319
+
320
+ @par Thread safety
321
+
322
+ Not thread safe. The caller is responsible for
323
+ ensuring that no other member functions are
324
+ called concurrently.
325
+
326
+ @param dat_path The path to the data file.
327
+
328
+ @param key_path The path to the key file.
329
+
330
+ @param log_path The path to the log file.
331
+
332
+ @param ec Set to the error, if any occurred.
333
+
334
+ @param args Optional arguments passed to @b File constructors.
335
+
336
+ */
337
+ template<class... Args>
338
+ void
339
+ open(
340
+ path_type const& dat_path,
341
+ path_type const& key_path,
342
+ path_type const& log_path,
343
+ error_code& ec,
344
+ Args&&... args);
345
+
346
+ /** Fetch a value.
347
+
348
+ The function checks the database for the specified
349
+ key, and invokes the callback if it is found. If
350
+ the key is not found, `ec` is set to @ref error::key_not_found.
351
+ If any other errors occur, `ec` is set to the
352
+ corresponding error.
353
+
354
+ @par Requirements
355
+
356
+ The database must be open.
357
+
358
+ @par Thread safety
359
+
360
+ Safe to call concurrently with any function except
361
+ @ref close.
362
+
363
+ @note If the implementation encounters an error while
364
+ committing data to the database, this function will
365
+ immediately return with `ec` set to the error which
366
+ occurred. All subsequent calls to @ref fetch will
367
+ return the same error until the database is closed.
368
+
369
+ @param key A pointer to a memory buffer of at least
370
+ @ref key_size() bytes, containing the key to be searched
371
+ for.
372
+
373
+ @param callback A function which will be called with the
374
+ value data if the fetch is successful. The equivalent
375
+ signature must be:
376
+ @code
377
+ void callback(
378
+ void const* buffer, // A buffer holding the value
379
+ std::size_t size // The size of the value in bytes
380
+ );
381
+ @endcode
382
+ The buffer provided to the callback remains valid
383
+ until the callback returns, ownership is not transferred.
384
+
385
+ @param ec Set to the error, if any occurred.
386
+ */
387
+ template<class Callback>
388
+ void
389
+ fetch(void const* key, Callback && callback, error_code& ec);
390
+
391
+ /** Insert a value.
392
+
393
+ This function attempts to insert the specified key/value
394
+ pair into the database. If the key already exists,
395
+ `ec` is set to @ref error::key_exists. If an error
396
+ occurs, `ec` is set to the corresponding error.
397
+
398
+ @par Requirements
399
+
400
+ The database must be open.
401
+
402
+ @par Thread safety
403
+
404
+ Safe to call concurrently with any function except
405
+ @ref close.
406
+
407
+ @note If the implementation encounters an error while
408
+ committing data to the database, this function will
409
+ immediately return with `ec` set to the error which
410
+ occurred. All subsequent calls to @ref insert will
411
+ return the same error until the database is closed.
412
+
413
+ @param key A buffer holding the key to be inserted. The
414
+ size of the buffer should be at least the `key_size`
415
+ associated with the open database.
416
+
417
+ @param data A buffer holding the value to be inserted.
418
+
419
+ @param bytes The size of the buffer holding the value
420
+ data. This value must be greater than 0 and no more
421
+ than 0xffffffff.
422
+
423
+ @param ec Set to the error, if any occurred.
424
+ */
425
+ void
426
+ insert(void const* key, void const* data,
427
+ nsize_t bytes, error_code& ec);
428
+
429
+ private:
430
+ template<class Callback>
431
+ void
432
+ fetch(detail::nhash_t h, void const* key,
433
+ detail::bucket b, Callback && callback, error_code& ec);
434
+
435
+ bool
436
+ exists(detail::nhash_t h, void const* key,
437
+ detail::shared_lock_type* lock, detail::bucket b, error_code& ec);
438
+
439
+ void
440
+ split(detail::bucket& b1, detail::bucket& b2,
441
+ detail::bucket& tmp, nbuck_t n1, nbuck_t n2,
442
+ nbuck_t buckets, nbuck_t modulus,
443
+ detail::bulk_writer<File>& w, error_code& ec);
444
+
445
+ detail::bucket
446
+ load(nbuck_t n, detail::cache& c1,
447
+ detail::cache& c0, void* buf, error_code& ec);
448
+
449
+ void
450
+ commit(detail::unique_lock_type& m,
451
+ std::size_t& work, error_code& ec);
452
+
453
+ void
454
+ flush() override;
455
+ };
456
+
457
+ } // nudb
458
+
459
+ #include <nudb/impl/basic_store.ipp>
460
+
461
+ #endif
@@ -0,0 +1,205 @@
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_CONCEPTS_HPP
9
+ #define NUDB_CONCEPTS_HPP
10
+
11
+ #include <nudb/error.hpp>
12
+ #include <nudb/file.hpp>
13
+ #include <cstddef>
14
+ #include <cstdint>
15
+ #include <type_traits>
16
+
17
+ namespace nudb {
18
+
19
+ namespace detail {
20
+
21
+ template<class T>
22
+ class check_is_File
23
+ {
24
+ template<class U, class R =
25
+ std::is_convertible<decltype(
26
+ std::declval<U const>().is_open()),
27
+ bool>>
28
+ static R check1(int);
29
+ template<class>
30
+ static std::false_type check1(...);
31
+ using type1 = decltype(check1<T>(0));
32
+
33
+ template<class U, class R = decltype(
34
+ std::declval<U>().close(),
35
+ std::true_type{})>
36
+ static R check2(int);
37
+ template<class>
38
+ static std::false_type check2(...);
39
+ using type2 = decltype(check2<T>(0));
40
+
41
+ template<class U, class R = decltype(
42
+ std::declval<U>().create(
43
+ std::declval<file_mode>(),
44
+ std::declval<path_type>(),
45
+ std::declval<error_code&>()),
46
+ std::true_type{})>
47
+ static R check3(int);
48
+ template<class>
49
+ static std::false_type check3(...);
50
+ using type3 = decltype(check3<T>(0));
51
+
52
+ template<class U, class R = decltype(
53
+ std::declval<U>().open(
54
+ std::declval<file_mode>(),
55
+ std::declval<path_type>(),
56
+ std::declval<error_code&>()),
57
+ std::true_type{})>
58
+ static R check4(int);
59
+ template<class>
60
+ static std::false_type check4(...);
61
+ using type4 = decltype(check4<T>(0));
62
+
63
+ template<class U, class R = decltype(
64
+ U::erase(
65
+ std::declval<path_type>(),
66
+ std::declval<error_code&>()),
67
+ std::true_type{})>
68
+ static R check5(int);
69
+ template<class>
70
+ static std::false_type check5(...);
71
+ using type5 = decltype(check5<T>(0));
72
+
73
+ template<class U, class R =
74
+ std::is_convertible<decltype(
75
+ std::declval<U const>().size(
76
+ std::declval<error_code&>())),
77
+ std::uint64_t>>
78
+ static R check6(int);
79
+ template<class>
80
+ static std::false_type check6(...);
81
+ using type6 = decltype(check6<T>(0));
82
+
83
+ template<class U, class R = decltype(
84
+ std::declval<U>().read(
85
+ std::declval<std::uint64_t>(),
86
+ std::declval<void*>(),
87
+ std::declval<std::size_t>(),
88
+ std::declval<error_code&>()),
89
+ std::true_type{})>
90
+ static R check7(int);
91
+ template<class>
92
+ static std::false_type check7(...);
93
+ using type7 = decltype(check7<T>(0));
94
+
95
+ template<class U, class R = decltype(
96
+ std::declval<U>().write(
97
+ std::declval<std::uint64_t>(),
98
+ std::declval<void const*>(),
99
+ std::declval<std::size_t>(),
100
+ std::declval<error_code&>()),
101
+ std::true_type{})>
102
+ static R check8(int);
103
+ template<class>
104
+ static std::false_type check8(...);
105
+ using type8 = decltype(check8<T>(0));
106
+
107
+ template<class U, class R = decltype(
108
+ std::declval<U>().sync(
109
+ std::declval<error_code&>()),
110
+ std::true_type{})>
111
+ static R check9(int);
112
+ template<class>
113
+ static std::false_type check9(...);
114
+ using type9 = decltype(check9<T>(0));
115
+
116
+ template<class U, class R = decltype(
117
+ std::declval<U>().trunc(
118
+ std::declval<std::uint64_t>(),
119
+ std::declval<error_code&>()),
120
+ std::true_type{})>
121
+ static R check10(int);
122
+ template<class>
123
+ static std::false_type check10(...);
124
+ using type10 = decltype(check10<T>(0));
125
+
126
+ public:
127
+ using type = std::integral_constant<bool,
128
+ std::is_move_constructible<T>::value &&
129
+ type1::value && type2::value && type3::value &&
130
+ type4::value && type5::value && type6::value &&
131
+ type7::value && type8::value && type9::value &&
132
+ type10::value
133
+ >;
134
+ };
135
+
136
+ template<class T>
137
+ class check_is_Hasher
138
+ {
139
+ template<class U, class R =
140
+ std::is_constructible<U, std::uint64_t>>
141
+ static R check1(int);
142
+ template<class>
143
+ static std::false_type check1(...);
144
+ using type1 = decltype(check1<T>(0));
145
+
146
+ template<class U, class R =
147
+ std::is_convertible<decltype(
148
+ std::declval<U const>().operator()(
149
+ std::declval<void const*>(),
150
+ std::declval<std::size_t>())),
151
+ std::uint64_t>>
152
+ static R check2(int);
153
+ template<class>
154
+ static std::false_type check2(...);
155
+ using type2 = decltype(check2<T>(0));
156
+ public:
157
+ using type = std::integral_constant<bool,
158
+ type1::value && type2::value>;
159
+ };
160
+
161
+ template<class T>
162
+ class check_is_Progress
163
+ {
164
+ template<class U, class R = decltype(
165
+ std::declval<U>().operator()(
166
+ std::declval<std::uint64_t>(),
167
+ std::declval<std::uint64_t>()),
168
+ std::true_type{})>
169
+ static R check1(int);
170
+ template<class>
171
+ static std::false_type check1(...);
172
+ public:
173
+ using type = decltype(check1<T>(0));
174
+ };
175
+
176
+ } // detail
177
+
178
+ /// Determine if `T` meets the requirements of @b `File`
179
+ template<class T>
180
+ #if GENERATING_DOCS
181
+ struct is_File : std::integral_constant<bool, ...>{};
182
+ #else
183
+ using is_File = typename detail::check_is_File<T>::type;
184
+ #endif
185
+
186
+
187
+ /// Determine if `T` meets the requirements of @b `Hasher`
188
+ template<class T>
189
+ #if GENERATING_DOCS
190
+ struct is_Hasher : std::integral_constant<bool, ...>{};
191
+ #else
192
+ using is_Hasher = typename detail::check_is_Hasher<T>::type;
193
+ #endif
194
+
195
+ /// Determine if `T` meets the requirements of @b `Progress`
196
+ template<class T>
197
+ #if GENERATING_DOCS
198
+ struct is_Progress : std::integral_constant<bool, ...>{};
199
+ #else
200
+ using is_Progress = typename detail::check_is_Progress<T>::type;
201
+ #endif
202
+
203
+ } // nudb
204
+
205
+ #endif