benchmark silo added
[c11concurrency-benchmarks.git] / silo / benchmarks / ndb_wrapper_impl.h
1 #ifndef _NDB_WRAPPER_IMPL_H_
2 #define _NDB_WRAPPER_IMPL_H_
3
4 #include <stdint.h>
5 #include "ndb_wrapper.h"
6 #include "../counter.h"
7 #include "../rcu.h"
8 #include "../varkey.h"
9 #include "../macros.h"
10 #include "../util.h"
11 #include "../scopedperf.hh"
12 #include "../txn.h"
13 //#include "../txn_proto1_impl.h"
14 #include "../txn_proto2_impl.h"
15 #include "../tuple.h"
16
17 struct hint_default_traits : public default_transaction_traits {
18   typedef str_arena StringAllocator;
19 };
20
21 // ycsb profiles
22
23 struct hint_kv_get_put_traits {
24   static const size_t read_set_expected_size = 1;
25   static const size_t write_set_expected_size = 1;
26   static const size_t absent_set_expected_size = 1;
27   static const bool stable_input_memory = true;
28   static const bool hard_expected_sizes = true;
29   static const bool read_own_writes = false;
30   typedef str_arena StringAllocator;
31 };
32
33 struct hint_kv_rmw_traits : public hint_kv_get_put_traits {};
34
35 struct hint_kv_scan_traits {
36   static const size_t read_set_expected_size = 100;
37   static const size_t write_set_expected_size = 1;
38   static const size_t absent_set_expected_size = read_set_expected_size / 7 + 1;
39   static const bool stable_input_memory = true;
40   static const bool hard_expected_sizes = false;
41   static const bool read_own_writes = false;
42   typedef str_arena StringAllocator;
43 };
44
45 // tpcc profiles
46
47 struct hint_read_only_traits {
48   static const size_t read_set_expected_size = 1;
49   static const size_t write_set_expected_size = 1;
50   static const size_t absent_set_expected_size = 1;
51   static const bool stable_input_memory = true;
52   static const bool hard_expected_sizes = true;
53   static const bool read_own_writes = false;
54   typedef str_arena StringAllocator;
55 };
56
57 struct hint_tpcc_new_order_traits {
58   static const size_t read_set_expected_size = 35;
59   static const size_t write_set_expected_size = 35;
60   static const size_t absent_set_expected_size = 1;
61   static const bool stable_input_memory = true;
62   static const bool hard_expected_sizes = true;
63   static const bool read_own_writes = false;
64   typedef str_arena StringAllocator;
65 };
66
67 struct hint_tpcc_payment_traits {
68   static const size_t read_set_expected_size = 85;
69   static const size_t write_set_expected_size = 10;
70   static const size_t absent_set_expected_size = 15;
71   static const bool stable_input_memory = true;
72   static const bool hard_expected_sizes = false;
73   static const bool read_own_writes = false;
74   typedef str_arena StringAllocator;
75 };
76
77 struct hint_tpcc_delivery_traits {
78   static const size_t read_set_expected_size = 175;
79   static const size_t write_set_expected_size = 175;
80   static const size_t absent_set_expected_size = 35;
81   static const bool stable_input_memory = true;
82   static const bool hard_expected_sizes = false;
83   static const bool read_own_writes = false;
84   typedef str_arena StringAllocator;
85 };
86
87 struct hint_tpcc_order_status_traits {
88   static const size_t read_set_expected_size = 95;
89   static const size_t write_set_expected_size = 1;
90   static const size_t absent_set_expected_size = 25;
91   static const bool stable_input_memory = true;
92   static const bool hard_expected_sizes = false;
93   static const bool read_own_writes = false;
94   typedef str_arena StringAllocator;
95 };
96
97 struct hint_tpcc_order_status_read_only_traits : public hint_read_only_traits {};
98
99 struct hint_tpcc_stock_level_traits {
100   static const size_t read_set_expected_size = 500;
101   static const size_t write_set_expected_size = 1;
102   static const size_t absent_set_expected_size = 25;
103   static const bool stable_input_memory = true;
104   static const bool hard_expected_sizes = false;
105   static const bool read_own_writes = false;
106   typedef str_arena StringAllocator;
107 };
108
109 struct hint_tpcc_stock_level_read_only_traits : public hint_read_only_traits {};
110
111 #define TXN_PROFILE_HINT_OP(x) \
112   x(abstract_db::HINT_DEFAULT, hint_default_traits) \
113   x(abstract_db::HINT_KV_GET_PUT, hint_kv_get_put_traits) \
114   x(abstract_db::HINT_KV_RMW, hint_kv_rmw_traits) \
115   x(abstract_db::HINT_KV_SCAN, hint_kv_scan_traits) \
116   x(abstract_db::HINT_TPCC_NEW_ORDER, hint_tpcc_new_order_traits) \
117   x(abstract_db::HINT_TPCC_PAYMENT, hint_tpcc_payment_traits) \
118   x(abstract_db::HINT_TPCC_DELIVERY, hint_tpcc_delivery_traits) \
119   x(abstract_db::HINT_TPCC_ORDER_STATUS, hint_tpcc_order_status_traits) \
120   x(abstract_db::HINT_TPCC_ORDER_STATUS_READ_ONLY, hint_tpcc_order_status_read_only_traits) \
121   x(abstract_db::HINT_TPCC_STOCK_LEVEL, hint_tpcc_stock_level_traits) \
122   x(abstract_db::HINT_TPCC_STOCK_LEVEL_READ_ONLY, hint_tpcc_stock_level_read_only_traits)
123
124 template <template <typename> class Transaction>
125 ndb_wrapper<Transaction>::ndb_wrapper(
126     const std::vector<std::string> &logfiles,
127     const std::vector<std::vector<unsigned>> &assignments_given,
128     bool call_fsync,
129     bool use_compression,
130     bool fake_writes)
131 {
132   if (logfiles.empty())
133     return;
134   std::vector<std::vector<unsigned>> assignments_used;
135   txn_logger::Init(
136       nthreads, logfiles, assignments_given, &assignments_used,
137       call_fsync,
138       use_compression,
139       fake_writes);
140   if (verbose) {
141     std::cerr << "[logging subsystem]" << std::endl;
142     std::cerr << "  assignments: " << assignments_used << std::endl;
143     std::cerr << "  call fsync : " << call_fsync       << std::endl;
144     std::cerr << "  compression: " << use_compression  << std::endl;
145     std::cerr << "  fake_writes: " << fake_writes      << std::endl;
146   }
147 }
148
149 template <template <typename> class Transaction>
150 size_t
151 ndb_wrapper<Transaction>::sizeof_txn_object(uint64_t txn_flags) const
152 {
153 #define MY_OP_X(a, b) sizeof(typename cast< b >::type),
154   const size_t xs[] = {
155     TXN_PROFILE_HINT_OP(MY_OP_X)
156   };
157 #undef MY_OP_X
158   size_t xmax = 0;
159   for (size_t i = 0; i < ARRAY_NELEMS(xs); i++)
160     xmax = std::max(xmax, xs[i]);
161   return xmax;
162 }
163
164 template <template <typename> class Transaction>
165 void *
166 ndb_wrapper<Transaction>::new_txn(
167     uint64_t txn_flags,
168     str_arena &arena,
169     void *buf,
170     TxnProfileHint hint)
171 {
172   ndbtxn * const p = reinterpret_cast<ndbtxn *>(buf);
173   p->hint = hint;
174 #define MY_OP_X(a, b) \
175   case a: \
176     new (&p->buf[0]) typename cast< b >::type(txn_flags, arena); \
177     return p;
178   switch (hint) {
179     TXN_PROFILE_HINT_OP(MY_OP_X)
180   default:
181     ALWAYS_ASSERT(false);
182   }
183 #undef MY_OP_X
184   return 0;
185 }
186
187 template <typename T>
188 static inline ALWAYS_INLINE void
189 Destroy(T *t)
190 {
191   PERF_DECL(static std::string probe1_name(std::string(__PRETTY_FUNCTION__) + std::string(":total:")));
192   ANON_REGION(probe1_name.c_str(), &private_::ndb_dtor_probe0_cg);
193   t->~T();
194 }
195
196 template <template <typename> class Transaction>
197 bool
198 ndb_wrapper<Transaction>::commit_txn(void *txn)
199 {
200   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
201 #define MY_OP_X(a, b) \
202   case a: \
203     { \
204       auto t = cast< b >()(p); \
205       const bool ret = t->commit(); \
206       Destroy(t); \
207       return ret; \
208     }
209   switch (p->hint) {
210     TXN_PROFILE_HINT_OP(MY_OP_X)
211   default:
212     ALWAYS_ASSERT(false);
213   }
214 #undef MY_OP_X
215   return false;
216 }
217
218 template <template <typename> class Transaction>
219 void
220 ndb_wrapper<Transaction>::abort_txn(void *txn)
221 {
222   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
223 #define MY_OP_X(a, b) \
224   case a: \
225     { \
226       auto t = cast< b >()(p); \
227       t->abort(); \
228       Destroy(t); \
229       return; \
230     }
231   switch (p->hint) {
232     TXN_PROFILE_HINT_OP(MY_OP_X)
233   default:
234     ALWAYS_ASSERT(false);
235   }
236 #undef MY_OP_X
237 }
238
239 template <template <typename> class Transaction>
240 void
241 ndb_wrapper<Transaction>::print_txn_debug(void *txn) const
242 {
243   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
244 #define MY_OP_X(a, b) \
245   case a: \
246     { \
247       auto t = cast< b >()(p); \
248       t->dump_debug_info(); \
249       return; \
250     }
251   switch (p->hint) {
252     TXN_PROFILE_HINT_OP(MY_OP_X)
253   default:
254     ALWAYS_ASSERT(false);
255   }
256 #undef MY_OP_X
257 }
258
259 template <template <typename> class Transaction>
260 std::map<std::string, uint64_t>
261 ndb_wrapper<Transaction>::get_txn_counters(void *txn) const
262 {
263   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
264 #define MY_OP_X(a, b) \
265   case a: \
266     { \
267       auto t = cast< b >()(p); \
268       return t->get_txn_counters(); \
269     }
270   switch (p->hint) {
271     TXN_PROFILE_HINT_OP(MY_OP_X)
272   default:
273     ALWAYS_ASSERT(false);
274   }
275 #undef MY_OP_X
276   return std::map<std::string, uint64_t>();
277 }
278
279 template <template <typename> class Transaction>
280 abstract_ordered_index *
281 ndb_wrapper<Transaction>::open_index(const std::string &name, size_t value_size_hint, bool mostly_append)
282 {
283   return new ndb_ordered_index<Transaction>(name, value_size_hint, mostly_append);
284 }
285
286 template <template <typename> class Transaction>
287 void
288 ndb_wrapper<Transaction>::close_index(abstract_ordered_index *idx)
289 {
290   delete idx;
291 }
292
293 template <template <typename> class Transaction>
294 ndb_ordered_index<Transaction>::ndb_ordered_index(
295     const std::string &name, size_t value_size_hint, bool mostly_append)
296   : name(name), btr(value_size_hint, mostly_append, name)
297 {
298   // for debugging
299   //std::cerr << name << " : btree= "
300   //          << btr.get_underlying_btree()
301   //          << std::endl;
302 }
303
304 template <template <typename> class Transaction>
305 bool
306 ndb_ordered_index<Transaction>::get(
307     void *txn,
308     const std::string &key,
309     std::string &value, size_t max_bytes_read)
310 {
311   PERF_DECL(static std::string probe1_name(std::string(__PRETTY_FUNCTION__) + std::string(":total:")));
312   ANON_REGION(probe1_name.c_str(), &private_::ndb_get_probe0_cg);
313   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
314   try {
315 #define MY_OP_X(a, b) \
316   case a: \
317     { \
318       auto t = cast< b >()(p); \
319       if (!btr.search(*t, key, value, max_bytes_read)) \
320         return false; \
321       return true; \
322     }
323     switch (p->hint) {
324       TXN_PROFILE_HINT_OP(MY_OP_X)
325     default:
326       ALWAYS_ASSERT(false);
327     }
328 #undef MY_OP_X
329     INVARIANT(!value.empty());
330     return true;
331   } catch (transaction_abort_exception &ex) {
332     throw abstract_db::abstract_abort_exception();
333   }
334 }
335
336 // XXX: find way to remove code duplication below using C++ templates!
337
338 template <template <typename> class Transaction>
339 const char *
340 ndb_ordered_index<Transaction>::put(
341     void *txn,
342     const std::string &key,
343     const std::string &value)
344 {
345   PERF_DECL(static std::string probe1_name(std::string(__PRETTY_FUNCTION__) + std::string(":total:")));
346   ANON_REGION(probe1_name.c_str(), &private_::ndb_put_probe0_cg);
347   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
348   try {
349 #define MY_OP_X(a, b) \
350   case a: \
351     { \
352       auto t = cast< b >()(p); \
353       btr.put(*t, key, value); \
354       return 0; \
355     }
356     switch (p->hint) {
357       TXN_PROFILE_HINT_OP(MY_OP_X)
358     default:
359       ALWAYS_ASSERT(false);
360     }
361 #undef MY_OP_X
362   } catch (transaction_abort_exception &ex) {
363     throw abstract_db::abstract_abort_exception();
364   }
365   return 0;
366 }
367
368 template <template <typename> class Transaction>
369 const char *
370 ndb_ordered_index<Transaction>::put(
371     void *txn,
372     std::string &&key,
373     std::string &&value)
374 {
375   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
376   try {
377 #define MY_OP_X(a, b) \
378   case a: \
379     { \
380       auto t = cast< b >()(p); \
381       btr.put(*t, std::move(key), std::move(value)); \
382       return 0; \
383     }
384     switch (p->hint) {
385       TXN_PROFILE_HINT_OP(MY_OP_X)
386     default:
387       ALWAYS_ASSERT(false);
388     }
389 #undef MY_OP_X
390   } catch (transaction_abort_exception &ex) {
391     throw abstract_db::abstract_abort_exception();
392   }
393   return 0;
394 }
395
396 template <template <typename> class Transaction>
397 const char *
398 ndb_ordered_index<Transaction>::insert(
399     void *txn,
400     const std::string &key,
401     const std::string &value)
402 {
403   PERF_DECL(static std::string probe1_name(std::string(__PRETTY_FUNCTION__) + std::string(":total:")));
404   ANON_REGION(probe1_name.c_str(), &private_::ndb_insert_probe0_cg);
405   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
406   try {
407 #define MY_OP_X(a, b) \
408   case a: \
409     { \
410       auto t = cast< b >()(p); \
411       btr.insert(*t, key, value); \
412       return 0; \
413     }
414     switch (p->hint) {
415       TXN_PROFILE_HINT_OP(MY_OP_X)
416     default:
417       ALWAYS_ASSERT(false);
418     }
419 #undef MY_OP_X
420   } catch (transaction_abort_exception &ex) {
421     throw abstract_db::abstract_abort_exception();
422   }
423   return 0;
424 }
425
426 template <template <typename> class Transaction>
427 const char *
428 ndb_ordered_index<Transaction>::insert(
429     void *txn,
430     std::string &&key,
431     std::string &&value)
432 {
433   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
434   try {
435 #define MY_OP_X(a, b) \
436   case a: \
437     { \
438       auto t = cast< b >()(p); \
439       btr.insert(*t, std::move(key), std::move(value)); \
440       return 0; \
441     }
442     switch (p->hint) {
443       TXN_PROFILE_HINT_OP(MY_OP_X)
444     default:
445       ALWAYS_ASSERT(false);
446     }
447 #undef MY_OP_X
448   } catch (transaction_abort_exception &ex) {
449     throw abstract_db::abstract_abort_exception();
450   }
451   return 0;
452 }
453
454 template <template <typename> class Transaction>
455 class ndb_wrapper_search_range_callback : public txn_btree<Transaction>::search_range_callback {
456 public:
457   ndb_wrapper_search_range_callback(abstract_ordered_index::scan_callback &upcall)
458     : upcall(&upcall) {}
459
460   virtual bool
461   invoke(const typename txn_btree<Transaction>::keystring_type &k,
462          const typename txn_btree<Transaction>::string_type &v)
463   {
464     return upcall->invoke(k.data(), k.length(), v);
465   }
466
467 private:
468   abstract_ordered_index::scan_callback *upcall;
469 };
470
471 template <template <typename> class Transaction>
472 void
473 ndb_ordered_index<Transaction>::scan(
474     void *txn,
475     const std::string &start_key,
476     const std::string *end_key,
477     scan_callback &callback,
478     str_arena *arena)
479 {
480   PERF_DECL(static std::string probe1_name(std::string(__PRETTY_FUNCTION__) + std::string(":total:")));
481   ANON_REGION(probe1_name.c_str(), &private_::ndb_scan_probe0_cg);
482   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
483   ndb_wrapper_search_range_callback<Transaction> c(callback);
484   try {
485 #define MY_OP_X(a, b) \
486   case a: \
487     { \
488       auto t = cast< b >()(p); \
489       btr.search_range_call(*t, start_key, end_key, c); \
490       return; \
491     }
492     switch (p->hint) {
493       TXN_PROFILE_HINT_OP(MY_OP_X)
494     default:
495       ALWAYS_ASSERT(false);
496     }
497 #undef MY_OP_X
498   } catch (transaction_abort_exception &ex) {
499     throw abstract_db::abstract_abort_exception();
500   }
501 }
502
503 template <template <typename> class Transaction>
504 void
505 ndb_ordered_index<Transaction>::rscan(
506     void *txn,
507     const std::string &start_key,
508     const std::string *end_key,
509     scan_callback &callback,
510     str_arena *arena)
511 {
512   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
513   ndb_wrapper_search_range_callback<Transaction> c(callback);
514   try {
515 #define MY_OP_X(a, b) \
516   case a: \
517     { \
518       auto t = cast< b >()(p); \
519       btr.rsearch_range_call(*t, start_key, end_key, c); \
520       return; \
521     }
522     switch (p->hint) {
523       TXN_PROFILE_HINT_OP(MY_OP_X)
524     default:
525       ALWAYS_ASSERT(false);
526     }
527 #undef MY_OP_X
528   } catch (transaction_abort_exception &ex) {
529     throw abstract_db::abstract_abort_exception();
530   }
531 }
532
533 template <template <typename> class Transaction>
534 void
535 ndb_ordered_index<Transaction>::remove(void *txn, const std::string &key)
536 {
537   PERF_DECL(static std::string probe1_name(std::string(__PRETTY_FUNCTION__) + std::string(":total:")));
538   ANON_REGION(probe1_name.c_str(), &private_::ndb_remove_probe0_cg);
539   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
540   try {
541 #define MY_OP_X(a, b) \
542   case a: \
543     { \
544       auto t = cast< b >()(p); \
545       btr.remove(*t, key); \
546       return; \
547     }
548     switch (p->hint) {
549       TXN_PROFILE_HINT_OP(MY_OP_X)
550     default:
551       ALWAYS_ASSERT(false);
552     }
553 #undef MY_OP_X
554   } catch (transaction_abort_exception &ex) {
555     throw abstract_db::abstract_abort_exception();
556   }
557 }
558
559 template <template <typename> class Transaction>
560 void
561 ndb_ordered_index<Transaction>::remove(void *txn, std::string &&key)
562 {
563   ndbtxn * const p = reinterpret_cast<ndbtxn *>(txn);
564   try {
565 #define MY_OP_X(a, b) \
566   case a: \
567     { \
568       auto t = cast< b >()(p); \
569       btr.remove(*t, std::move(key)); \
570       return; \
571     }
572     switch (p->hint) {
573       TXN_PROFILE_HINT_OP(MY_OP_X)
574     default:
575       ALWAYS_ASSERT(false);
576     }
577 #undef MY_OP_X
578   } catch (transaction_abort_exception &ex) {
579     throw abstract_db::abstract_abort_exception();
580   }
581 }
582
583 template <template <typename> class Transaction>
584 size_t
585 ndb_ordered_index<Transaction>::size() const
586 {
587   return btr.size_estimate();
588 }
589
590 template <template <typename> class Transaction>
591 std::map<std::string, uint64_t>
592 ndb_ordered_index<Transaction>::clear()
593 {
594 #ifdef TXN_BTREE_DUMP_PURGE_STATS
595   std::cerr << "purging txn index: " << name << std::endl;
596 #endif
597   return btr.unsafe_purge(true);
598 }
599
600 #endif /* _NDB_WRAPPER_IMPL_H_ */