CCF
Loading...
Searching...
No Matches
tpcc_transactions.h
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the Apache 2.0 License.
3#pragma once
4
5#include "tpcc_common.h"
6#include "tpcc_output.h"
7#include "tpcc_tables.h"
8
9#include <cinttypes>
10#include <string.h>
11#include <vector>
12
13namespace tpcc
14{
16 {
17 private:
19 std::mt19937 rand_generator;
20
21 static constexpr int STOCK_LEVEL_ORDERS = 20;
22 static constexpr float MIN_PAYMENT_AMOUNT = 1.00;
23 static constexpr float MAX_PAYMENT_AMOUNT = 5000.00;
24 static constexpr int32_t MAX_OL_QUANTITY = 10;
25 static constexpr int32_t INVALID_QUANTITY = -1;
26 static constexpr char INVALID_ITEM_STATUS[] = "Item number is not valid";
27
28 District find_district(int32_t w_id, int32_t d_id)
29 {
30 District::Key key = {w_id, d_id};
31
32 auto districts_table = args.tx.ro(tpcc::TpccTables::districts);
33 auto districts = districts_table->get(key);
34
35 if (!districts.has_value())
36 {
37 throw std::logic_error("district does not exist");
38 }
39 return districts.value();
40 }
41
42 std::optional<OrderLine> find_order_line(
43 int32_t w_id, int32_t d_id, int32_t o_id, int32_t number)
44 {
45 OrderLine::Key key = {o_id, d_id, w_id, number};
46 auto order_lines_table = args.tx.ro(tpcc::TpccTables::order_lines);
47 return order_lines_table->get(key);
48 }
49
50 std::optional<Item> find_item(int32_t id)
51 {
52 Item::Key key = {id};
53 auto items_table = args.tx.ro(tpcc::TpccTables::items);
54 return items_table->get(key);
55 }
56
57 Stock find_stock(int32_t w_id, int32_t s_id)
58 {
59 Stock::Key key = {s_id, w_id};
60 auto stocks_table = args.tx.ro(tpcc::TpccTables::stocks);
61 auto stock = stocks_table->get(key);
62 if (!stock.has_value())
63 {
64 throw std::logic_error("stock does not exist");
65 }
66 return stock.value();
67 }
68
69 Customer find_customer(int32_t w_id, int32_t d_id, int32_t c_id)
70 {
72 table_key.v.w_id = w_id;
73 table_key.v.d_id = d_id;
74 auto it = tpcc::TpccTables::customers.find(table_key.k);
75 Customer::Key key = {c_id};
76 auto customers_table = args.tx.ro(it->second);
77 auto customers = customers_table->get(key);
78 if (!customers.has_value())
79 {
80 throw std::logic_error("customers does not exist");
81 }
82 return customers.value();
83 }
84
85 Warehouse find_warehouse(int32_t w_id)
86 {
87 Warehouse::Key key = {w_id};
88 auto warehouses_table = args.tx.ro(tpcc::TpccTables::warehouses);
89 auto warehouse = warehouses_table->get(key);
90 if (!warehouse.has_value())
91 {
92 throw std::logic_error("warehouse does not exist");
93 }
94 return warehouse.value();
95 }
96
97 void insert_order(Order& o)
98 {
100 table_key.v.w_id = o.w_id;
101 table_key.v.d_id = o.d_id;
102 auto it = tpcc::TpccTables::orders.find(table_key.k);
103 auto orders_table = args.tx.rw(it->second);
104 orders_table->put(o.get_key(), o);
105 }
106
107 void insert_new_order(int32_t w_id, int32_t d_id, int32_t o_id)
108 {
109 NewOrder no;
110 no.w_id = w_id;
111 no.d_id = d_id;
112 no.o_id = o_id;
113
115 table_key.v.w_id = w_id;
116 table_key.v.d_id = d_id;
117 auto it = tpcc::TpccTables::new_orders.find(table_key.k);
118
119 auto new_orders_table = args.tx.rw(it->second);
120 new_orders_table->put(no.get_key(), no);
121 }
122
123 void insert_order_line(OrderLine& line)
124 {
125 auto order_lines = args.tx.rw(tpcc::TpccTables::order_lines);
126 order_lines->put(line.get_key(), line);
127 }
128
129 void order_status(
130 int32_t warehouse_id,
131 int32_t district_id,
132 int32_t customer_id,
133 OrderStatusOutput* output)
134 {
135 auto customer = find_customer(warehouse_id, district_id, customer_id);
136 internal_order_status(customer, output);
137 }
138
139 Customer find_customer_by_name(
140 int32_t w_id, int32_t d_id, const char* c_last)
141 {
142 Customer customer_ret;
144 table_key.v.w_id = w_id;
145 table_key.v.d_id = d_id;
146 auto it = tpcc::TpccTables::customers.find(table_key.k);
147 auto customers_table = args.tx.ro(it->second);
148 customers_table->foreach([&](const Customer::Key&, const Customer& c) {
149 if (strcmp(c.last.data(), c_last) == 0)
150 {
151 customer_ret = c;
152 return false;
153 }
154 return true;
155 });
156 return customer_ret;
157 }
158
159 void order_status(
160 int32_t warehouse_id,
161 int32_t district_id,
162 const char* c_last,
163 OrderStatusOutput* output)
164 {
165 Customer customer =
166 find_customer_by_name(warehouse_id, district_id, c_last);
167 internal_order_status(customer, output);
168 }
169
170 Order find_last_order_by_customer(
171 const int32_t w_id, const int32_t d_id, const int32_t c_id)
172 {
173 Order order;
174
176 table_key.v.w_id = w_id;
177 table_key.v.d_id = d_id;
178 auto it = tpcc::TpccTables::orders.find(table_key.k);
179
180 auto orders_table = args.tx.ro(it->second);
181 orders_table->foreach([&](const Order::Key&, const Order& o) {
182 if (o.c_id == c_id)
183 {
184 order = o;
185 return false;
186 }
187 return true;
188 });
189
190 return order;
191 }
192
193 void internal_order_status(Customer& customer, OrderStatusOutput* output)
194 {
195 output->c_id = customer.id;
196 // retrieve from customer: balance, first, middle, last
197 output->c_balance = customer.balance;
198 output->c_first = customer.first;
199 output->c_middle = customer.middle;
200 output->c_last = customer.last;
201
202 // Find the row in the order table with largest o_id
203 Order order =
204 find_last_order_by_customer(customer.w_id, customer.d_id, customer.id);
205 output->o_id = order.id;
206 output->o_carrier_id = order.carrier_id;
207 output->o_entry_d = order.entry_d;
208
209 output->lines.resize(order.ol_cnt);
210 for (int32_t line_number = 1; line_number <= order.ol_cnt; ++line_number)
211 {
212 OrderLine line =
213 find_order_line(customer.w_id, customer.d_id, order.id, line_number)
214 .value();
215 output->lines[line_number - 1].i_id = line.i_id;
216 output->lines[line_number - 1].supply_w_id = line.supply_w_id;
217 output->lines[line_number - 1].quantity = line.quantity;
218 output->lines[line_number - 1].amount = line.amount;
219 output->lines[line_number - 1].delivery_d = line.delivery_d;
220 }
221 }
222
223 int32_t generate_item_id()
224 {
225 return random_int(1, num_items);
226 }
227
228 int32_t generate_warehouse()
229 {
230 return random_int(1, num_warehouses);
231 }
232
233 int32_t generate_district()
234 {
235 return random_int(1, districts_per_warehouse);
236 }
237
238 int32_t generate_cid()
239 {
240 return random_int(1, customers_per_district);
241 }
242
243 Order find_order(int32_t w_id, int32_t d_id, int32_t o_id)
244 {
246 table_key.v.w_id = w_id;
247 table_key.v.d_id = d_id;
248
249 auto it = tpcc::TpccTables::orders.find(table_key.k);
250 auto orders_table = args.tx.ro(it->second);
251 Order::Key key = {o_id};
252 auto order = orders_table->get(key);
253 return order.value();
254 }
255
256 void delivery(
257 int32_t warehouse_id,
258 int32_t carrier_id,
259 std::array<char, DATETIME_SIZE + 1>& now,
260 std::vector<DeliveryOrderInfo>* orders)
261 {
262 for (int32_t d_id = 1; d_id <= District::NUM_PER_WAREHOUSE; ++d_id)
263 {
265 table_key.v.w_id = warehouse_id;
266 table_key.v.d_id = d_id;
267 auto it = tpcc::TpccTables::new_orders.find(table_key.k);
268
269 auto new_orders_table = args.tx.rw(it->second);
270 bool new_order_exists = false;
271 NewOrder::Key new_order_key = {warehouse_id, d_id, 1};
272 int32_t o_id;
273 new_orders_table->foreach(
274 [&](const NewOrder::Key& k, const NewOrder& no) {
275 new_order_key = k;
276 o_id = no.o_id;
277 new_order_exists = true;
278 return false;
279 });
280 if (!new_order_exists)
281 {
282 continue;
283 }
284 new_orders_table->remove(new_order_key);
285
286 DeliveryOrderInfo order;
287 order.d_id = d_id;
288 order.o_id = o_id;
289 orders->push_back(order);
290
291 Order o = find_order(warehouse_id, d_id, o_id);
292 o.carrier_id = carrier_id;
293
294 float total = 0;
295 for (int32_t i = 1; i <= o.ol_cnt; ++i)
296 {
297 std::optional<OrderLine> line =
298 find_order_line(warehouse_id, d_id, o_id, i);
299 line->delivery_d = now;
300 total += line->amount;
301 }
302
303 Customer c = find_customer(warehouse_id, d_id, o.c_id);
304 c.balance += total;
305 c.delivery_cnt += 1;
306 }
307 }
308
309 void payment_home(
310 int32_t warehouse_id,
311 int32_t district_id,
312 int32_t c_warehouse_id,
313 int32_t c_district_id,
314 int32_t customer_id,
315 float h_amount,
316 std::array<char, DATETIME_SIZE + 1> now,
317 PaymentOutput* output)
318 {
319 Warehouse w = find_warehouse(warehouse_id);
320 w.ytd += h_amount;
321 output->w_street_1 = w.street_1;
322 output->w_street_2 = w.street_2;
323 output->w_city = w.city;
324 output->w_state = w.state;
325 output->w_zip = w.zip;
326
327 District d = find_district(warehouse_id, district_id);
328 d.ytd += h_amount;
329
330 output->d_street_1 = d.street_1;
331 output->d_street_2 = d.street_2;
332 output->d_city = d.city;
333 output->d_state = d.state;
334 output->d_zip = d.zip;
335
336 // Insert the line into the history table
337 History h;
338 h.w_id = warehouse_id;
339 h.d_id = district_id;
340 h.c_w_id = c_warehouse_id;
341 h.c_d_id = c_district_id;
342 h.c_id = customer_id;
343 h.amount = h_amount;
344 h.date = now;
345 std::copy_n(h.data.data(), w.name.size(), w.name.data());
346 // strcat(h.data.data(), " ");
347
348 auto history_table = args.tx.rw(tpcc::TpccTables::histories);
349 history_table->put(h.get_key(), h);
350 }
351
352 void internal_payment_remote(
353 int32_t warehouse_id,
354 int32_t district_id,
355 Customer& c,
356 float h_amount,
357 PaymentOutput* output)
358 {
359 c.balance -= h_amount;
360 c.ytd_payment += h_amount;
361 c.payment_cnt += 1;
362 if (strcmp(c.credit.data(), Customer::BAD_CREDIT) == 0)
363 {
364 // Bad credit: insert history into c_data
365 static const int HISTORY_SIZE = Customer::MAX_DATA + 1;
366 std::array<char, HISTORY_SIZE> history;
367 int characters = snprintf(
368 history.data(),
369 HISTORY_SIZE,
370 "(%d, %d, %d, %d, %d, %.2f)\n",
371 c.id,
372 c.d_id,
373 c.w_id,
374 district_id,
375 warehouse_id,
376 h_amount);
377
378 // Perform the insert with a move and copy
379 int current_keep = static_cast<int>(strlen(c.data.data()));
380 if (current_keep + characters > Customer::MAX_DATA)
381 {
382 current_keep = Customer::MAX_DATA - characters;
383 }
384 memmove(c.data.data() + characters, c.data.data(), current_keep);
385 memcpy(c.data.data(), history.data(), characters);
386 c.data[characters + current_keep] = '\0';
387 }
388
389 output->c_credit_lim = c.credit_lim;
390 output->c_discount = c.discount;
391 output->c_balance = c.balance;
392 output->c_first = c.first;
393 output->c_middle = c.middle;
394 output->c_last = c.last;
395 output->c_street_1 = c.street_1;
396 output->c_street_2 = c.street_2;
397 output->c_city = c.city;
398 output->c_state = c.state;
399 output->c_zip = c.zip;
400 output->c_phone = c.phone;
401 output->c_since = c.since;
402 output->c_credit = c.credit;
403 output->c_data = c.data;
404 }
405
406 void payment(
407 int32_t warehouse_id,
408 int32_t district_id,
409 int32_t c_warehouse_id,
410 int32_t c_district_id,
411 int32_t customer_id,
412 float h_amount,
413 std::array<char, DATETIME_SIZE + 1> now,
414 PaymentOutput* output)
415 {
416 // c_warehouse_id, c_district_id, customer_id, h_amount, now);
417 Customer customer =
418 find_customer(c_warehouse_id, c_district_id, customer_id);
419 payment_home(
420 warehouse_id,
421 district_id,
422 c_warehouse_id,
423 c_district_id,
424 customer_id,
425 h_amount,
426 now,
427 output);
428 internal_payment_remote(
429 warehouse_id, district_id, customer, h_amount, output);
430 }
431
432 void payment(
433 int32_t warehouse_id,
434 int32_t district_id,
435 int32_t c_warehouse_id,
436 int32_t c_district_id,
437 std::array<char, Customer::MAX_LAST + 1> c_last,
438 float h_amount,
439 std::array<char, DATETIME_SIZE + 1> now,
440 PaymentOutput* output)
441 {
442 Customer customer =
443 find_customer_by_name(c_warehouse_id, c_district_id, c_last.data());
444 payment_home(
445 warehouse_id,
446 district_id,
447 c_warehouse_id,
448 c_district_id,
449 customer.id,
450 h_amount,
451 now,
452 output);
453 internal_payment_remote(
454 warehouse_id, district_id, customer, h_amount, output);
455 }
456
457 void new_order_combine(
458 const std::vector<int32_t>& remote_quantities, NewOrderOutput* output)
459 {
460 for (size_t i = 0; i < remote_quantities.size(); ++i)
461 {
462 if (remote_quantities[i] != INVALID_QUANTITY)
463 {
464 output->items[i].s_quantity = remote_quantities[i];
465 }
466 }
467 }
468
469 void new_order_combine(
470 const std::vector<int32_t>& remote_quantities,
471 std::vector<int32_t>* output)
472 {
473 for (size_t i = 0; i < remote_quantities.size(); ++i)
474 {
475 if (remote_quantities[i] != INVALID_QUANTITY)
476 {
477 (*output)[i] = remote_quantities[i];
478 }
479 }
480 }
481
482 bool new_order_remote(
483 int32_t home_warehouse,
484 int32_t remote_warehouse,
485 const std::vector<NewOrderItem>& items,
486 std::vector<int32_t>* out_quantities)
487 {
488 out_quantities->resize(items.size());
489 for (uint32_t i = 0; i < items.size(); ++i)
490 {
491 // Skip items that don't belong to remote warehouse
492 if (items[i].ol_supply_w_id != remote_warehouse)
493 {
494 (*out_quantities)[i] = INVALID_QUANTITY;
495 continue;
496 }
497
498 // update stock
499 Stock stock = find_stock(items[i].ol_supply_w_id, items[i].i_id);
500 if (stock.quantity >= items[i].ol_quantity + 10)
501 {
502 stock.quantity -= items[i].ol_quantity;
503 }
504 else
505 {
506 stock.quantity = stock.quantity - items[i].ol_quantity + 91;
507 }
508 (*out_quantities)[i] = stock.quantity;
509 stock.ytd += items[i].ol_quantity;
510 stock.order_cnt += 1;
511
512 if (items[i].ol_supply_w_id != home_warehouse)
513 {
514 stock.remote_cnt += 1;
515 }
516 }
517
518 return true;
519 }
520
521 std::set<int32_t> new_order_remote_warehouses(
522 int32_t home_warehouse, const std::vector<NewOrderItem>& items)
523 {
524 std::set<int32_t> out;
525 for (size_t i = 0; i < items.size(); ++i)
526 {
527 if (items[i].ol_supply_w_id != home_warehouse)
528 {
529 out.insert(items[i].ol_supply_w_id);
530 }
531 }
532 return out;
533 }
534
535 bool new_order(
536 int32_t warehouse_id,
537 int32_t district_id,
538 int32_t customer_id,
539 const std::vector<NewOrderItem>& items,
540 std::array<char, DATETIME_SIZE + 1> now,
541 NewOrderOutput* output)
542 {
543 // perform the home part
544 bool result = new_order_home(
545 warehouse_id, district_id, customer_id, items, now, output);
546 if (!result)
547 {
548 return false;
549 }
550
551 // Process all remote warehouses
552 std::set<int32_t> warehouses =
553 new_order_remote_warehouses(warehouse_id, items);
554 for (auto i = warehouses.begin(); i != warehouses.end(); ++i)
555 {
556 std::vector<int32_t> quantities;
557 result = new_order_remote(warehouse_id, *i, items, &quantities);
558 assert(result);
559 new_order_combine(quantities, output);
560 }
561
562 return true;
563 }
564
565 bool find_and_validate_items(
566 const std::vector<NewOrderItem>& items,
567 std::vector<std::optional<Item>>* item_tuples)
568 {
569 // CHEAT: Validate all items to see if we will need to abort
570 item_tuples->resize(items.size());
571 for (uint32_t i = 0; i < items.size(); ++i)
572 {
573 (*item_tuples)[i] = find_item(items[i].i_id);
574 if (!(*item_tuples)[i].has_value())
575 {
576 return false;
577 }
578 }
579 return true;
580 }
581
582 bool new_order_home(
583 int32_t warehouse_id,
584 int32_t district_id,
585 int32_t customer_id,
586 const std::vector<NewOrderItem>& items,
587 std::array<char, DATETIME_SIZE + 1> now,
588 NewOrderOutput* output)
589 {
590 // 2.4.3.4. requires that we display c_last, c_credit, and o_id for rolled
591 // back transactions: read those values first
592 District d = find_district(warehouse_id, district_id);
593 output->d_tax = d.tax;
594 output->o_id = d.next_o_id;
595
596 Customer c = find_customer(warehouse_id, district_id, customer_id);
597 output->c_last = c.last;
598 output->c_credit = c.credit;
599 output->c_discount = c.discount;
600
601 // CHEAT: Validate all items to see if we will need to abort
602 std::vector<std::optional<Item>> item_tuples(items.size());
603 if (!find_and_validate_items(items, &item_tuples))
604 {
605 strcpy(output->status.data(), INVALID_ITEM_STATUS);
606 return false;
607 }
608
609 // Check if this is an all local transaction
610 bool all_local = true;
611 for (size_t i = 0; i < items.size(); ++i)
612 {
613 if (items[i].ol_supply_w_id != warehouse_id)
614 {
615 all_local = false;
616 break;
617 }
618 }
619
620 output->status[0] = '\0';
621 d.next_o_id += 1;
622
623 Warehouse w = find_warehouse(warehouse_id);
624 output->w_tax = w.tax;
625
626 Order order;
627 order.w_id = warehouse_id;
628 order.d_id = district_id;
629 order.id = output->o_id;
630 order.c_id = customer_id;
632 order.ol_cnt = static_cast<int32_t>(items.size());
633 order.all_local = all_local ? 1 : 0;
634 order.entry_d = now;
635 insert_order(order);
636 insert_new_order(warehouse_id, district_id, output->o_id);
637
638 OrderLine line;
639 line.o_id = output->o_id;
640 line.d_id = district_id;
641 line.w_id = warehouse_id;
642 memset(line.delivery_d.data(), 0, DATETIME_SIZE + 1);
643
644 output->items.resize(items.size());
645 output->total = 0;
646 for (uint32_t i = 0; i < items.size(); ++i)
647 {
648 line.number = i + 1;
649 line.i_id = items[i].i_id;
650 line.supply_w_id = items[i].ol_supply_w_id;
651 line.quantity = items[i].ol_quantity;
652
653 Stock stock = find_stock(items[i].ol_supply_w_id, items[i].i_id);
654 memcpy(
655 line.dist_info.data(),
656 stock.dist[district_id].data(),
657 sizeof(line.dist_info));
658
659 bool stock_is_original =
660 (strstr(stock.data.data(), "ORIGINAL") != NULL);
661 if (
662 stock_is_original &&
663 strstr(item_tuples[i]->data.data(), "ORIGINAL") != NULL)
664 {
665 output->items[i].brand_generic = NewOrderOutput::ItemInfo::BRAND;
666 }
667 else
668 {
669 output->items[i].brand_generic = NewOrderOutput::ItemInfo::GENERIC;
670 }
671
672 output->items[i].i_name = item_tuples[i]->name;
673 output->items[i].i_price = item_tuples[i]->price;
674 output->items[i].ol_amount =
675 static_cast<float>(items[i].ol_quantity) * item_tuples[i]->price;
676 line.amount = output->items[i].ol_amount;
677 output->total += output->items[i].ol_amount;
678 insert_order_line(line);
679 }
680
681 std::vector<int32_t> quantities;
682 new_order_remote(warehouse_id, warehouse_id, items, &quantities);
683 new_order_combine(quantities, output);
684
685 return true;
686 }
687
688 float random_float(float min, float max)
689 {
690 return tpcc::random_float(min, max, rand_generator);
691 }
692
693 uint32_t random_int(uint32_t min, uint32_t max)
694 {
695 return tpcc::random_int(min, max, rand_generator);
696 }
697
698 int32_t random_int_excluding(int lower, int upper, int excluding)
699 {
700 return tpcc::random_int_excluding(
701 lower, upper, excluding, rand_generator);
702 }
703
704 public:
706 args(args_)
707 {
708 rand_generator.seed(seed);
709 }
710
711 int32_t stock_level(
712 int32_t warehouse_id, int32_t district_id, int32_t threshold)
713 {
714 District d = find_district(warehouse_id, district_id);
715 int32_t o_id = d.next_o_id;
716
717 std::vector<int32_t> s_i_ids;
718 s_i_ids.reserve(300);
719
720 for (int order_id = o_id - STOCK_LEVEL_ORDERS; order_id < o_id;
721 ++order_id)
722 {
723 for (int line_number = 1; line_number <= Order::MAX_OL_CNT;
724 ++line_number)
725 {
726 std::optional<OrderLine> line_ret =
727 find_order_line(warehouse_id, district_id, order_id, line_number);
728 if (!line_ret.has_value())
729 {
730 break;
731 }
732 auto& line = line_ret.value();
733
734 // Check if s_quantity < threshold
735 Stock stock = find_stock(warehouse_id, line.i_id);
736 if (stock.quantity < threshold)
737 {
738 s_i_ids.push_back(line.i_id);
739 }
740 }
741 }
742
743 std::sort(s_i_ids.begin(), s_i_ids.end());
744 int num_distinct = 0;
745 int32_t last = -1;
746 for (size_t i = 0; i < s_i_ids.size(); ++i)
747 {
748 if (s_i_ids[i] != last)
749 {
750 last = s_i_ids[i];
751 num_distinct += 1;
752 }
753 }
754 return num_distinct;
755 }
756
758 {
759 OrderStatusOutput output;
760 int y = random_int(0, 100);
761 if (y <= 60)
762 {
763 // 60%: order status by last name
764 char c_last[Customer::MAX_LAST + 1];
765 tpcc::make_last_name(random_int(1, customers_per_district), c_last);
766 uint32_t w_id = generate_warehouse();
767 uint32_t d_id = generate_district();
768 order_status(w_id, d_id, c_last, &output);
769 }
770 else
771 {
772 // 40%: order status by id
774 generate_warehouse(), generate_district(), generate_cid(), &output);
775 }
776 }
777
778 void delivery()
779 {
780 int carrier = random_int(Order::MIN_CARRIER_ID, Order::MAX_CARRIER_ID);
781 std::array<char, DATETIME_SIZE + 1> now = tx_time;
782
783 std::vector<DeliveryOrderInfo> orders;
784 delivery(generate_warehouse(), carrier, now, &orders);
785 }
786
787 void payment()
788 {
789 PaymentOutput output;
790 int x = random_int(1, 100);
791 int y = random_int(1, 100);
792
793 int32_t w_id = generate_warehouse();
794 int32_t d_id = generate_district();
795
796 int32_t c_w_id;
797 int32_t c_d_id;
798 if (num_warehouses == 1 || x <= 85)
799 {
800 // 85%: paying through own warehouse (or there is only 1 warehouse)
801 c_w_id = w_id;
802 c_d_id = d_id;
803 }
804 else
805 {
806 // 15%: paying through another warehouse:
807 c_w_id = random_int_excluding(1, num_warehouses, w_id);
808 c_d_id = generate_district();
809 }
810 float h_amount = random_float(MIN_PAYMENT_AMOUNT, MAX_PAYMENT_AMOUNT);
811
812 std::array<char, DATETIME_SIZE + 1> now = tx_time;
813 if (y <= 60)
814 {
815 // 60%: payment by last name
816 std::array<char, Customer::MAX_LAST + 1> c_last;
817 make_last_name(random_int(1, customers_per_district), c_last.data());
818 payment(w_id, d_id, c_w_id, c_d_id, c_last, h_amount, now, &output);
819 }
820 else
821 {
822 // 40%: payment by id
823 payment(
824 w_id, d_id, c_w_id, c_d_id, generate_cid(), h_amount, now, &output);
825 }
826 }
827
829 {
830 int32_t w_id = generate_warehouse();
831 int ol_cnt = random_int(Order::MIN_OL_CNT, Order::MAX_OL_CNT);
832
833 // 1% of transactions roll back
834 bool rollback = random_int(1, 100) == 1;
835
836 std::vector<NewOrderItem> items(ol_cnt);
837 for (int i = 0; i < ol_cnt; ++i)
838 {
839 if (rollback && i + 1 == ol_cnt)
840 {
841 items[i].i_id = Item::NUM_ITEMS + 1;
842 }
843 else
844 {
845 items[i].i_id = generate_item_id();
846 }
847
848 // TPC-C suggests generating a number in range (1, 100) and selecting
849 // remote on 1
850 bool remote = (random_int(1, 100) == 1);
851 if (num_warehouses > 1 && remote)
852 {
853 items[i].ol_supply_w_id =
854 random_int_excluding(1, num_warehouses, w_id);
855 }
856 else
857 {
858 items[i].ol_supply_w_id = w_id;
859 }
860 items[i].ol_quantity = random_int(1, MAX_OL_QUANTITY);
861 }
862
863 std::array<char, DATETIME_SIZE + 1> now = tx_time;
864 NewOrderOutput output;
865 bool result = new_order(
866 w_id, generate_district(), generate_cid(), items, now, &output);
867 return result;
868 }
869 };
870}
M::ReadOnlyHandle * ro(M &m)
Definition tx.h:170
M::Handle * rw(M &m)
Definition tx.h:213
Definition tpcc_transactions.h:16
void order_status()
Definition tpcc_transactions.h:757
bool new_order()
Definition tpcc_transactions.h:828
int32_t stock_level(int32_t warehouse_id, int32_t district_id, int32_t threshold)
Definition tpcc_transactions.h:711
void delivery()
Definition tpcc_transactions.h:778
void payment()
Definition tpcc_transactions.h:787
TpccTransactions(ccf::endpoints::EndpointContext &args_, uint32_t seed)
Definition tpcc_transactions.h:705
Definition tpcc_common.h:8
Definition endpoint_context.h:55
ccf::kv::Tx & tx
Definition endpoint_context.h:61
Definition tpcc_tables.h:334
Definition tpcc_tables.h:313
float balance
Definition tpcc_tables.h:348
std::array< char, CREDIT+1 > credit
Definition tpcc_tables.h:362
int32_t id
Definition tpcc_tables.h:343
std::array< char, MIDDLE+1 > middle
Definition tpcc_tables.h:353
std::array< char, MAX_DATA+1 > data
Definition tpcc_tables.h:363
float ytd_payment
Definition tpcc_tables.h:349
static const int MAX_LAST
Definition tpcc_tables.h:324
int32_t w_id
Definition tpcc_tables.h:345
int32_t payment_cnt
Definition tpcc_tables.h:350
std::array< char, Address::ZIP+1 > zip
Definition tpcc_tables.h:359
static constexpr char BAD_CREDIT[]
Definition tpcc_tables.h:331
std::array< char, Address::MAX_STREET+1 > street_1
Definition tpcc_tables.h:355
int32_t delivery_cnt
Definition tpcc_tables.h:351
std::array< char, Address::STATE+1 > state
Definition tpcc_tables.h:358
float credit_lim
Definition tpcc_tables.h:346
std::array< char, PHONE+1 > phone
Definition tpcc_tables.h:360
std::array< char, Address::MAX_CITY+1 > city
Definition tpcc_tables.h:357
float discount
Definition tpcc_tables.h:347
std::array< char, Address::MAX_STREET+1 > street_2
Definition tpcc_tables.h:356
std::array< char, DATETIME_SIZE+1 > since
Definition tpcc_tables.h:361
static const int MAX_DATA
Definition tpcc_tables.h:328
std::array< char, MAX_FIRST+1 > first
Definition tpcc_tables.h:352
std::array< char, MAX_LAST+1 > last
Definition tpcc_tables.h:354
int32_t d_id
Definition tpcc_tables.h:344
Definition tpcc_output.h:48
int32_t d_id
Definition tpcc_output.h:49
int32_t o_id
Definition tpcc_output.h:50
Definition tpcc_tables.h:236
Definition tpcc_tables.h:226
std::array< char, Address::MAX_STREET+1 > street_1
Definition tpcc_tables.h:247
static const int NUM_PER_WAREHOUSE
Definition tpcc_tables.h:233
std::array< char, Address::ZIP+1 > zip
Definition tpcc_tables.h:251
float tax
Definition tpcc_tables.h:243
int32_t next_o_id
Definition tpcc_tables.h:245
float ytd
Definition tpcc_tables.h:244
std::array< char, Address::STATE+1 > state
Definition tpcc_tables.h:250
std::array< char, Address::MAX_STREET+1 > street_2
Definition tpcc_tables.h:248
std::array< char, Address::MAX_CITY+1 > city
Definition tpcc_tables.h:249
Definition tpcc_tables.h:507
int32_t w_id
Definition tpcc_tables.h:530
Key get_key()
Definition tpcc_tables.h:521
int32_t c_id
Definition tpcc_tables.h:526
int32_t c_w_id
Definition tpcc_tables.h:528
int32_t d_id
Definition tpcc_tables.h:529
int32_t c_d_id
Definition tpcc_tables.h:527
std::array< char, MAX_DATA+1 > data
Definition tpcc_tables.h:533
std::array< char, DATETIME_SIZE+1 > date
Definition tpcc_tables.h:532
float amount
Definition tpcc_tables.h:531
Definition tpcc_tables.h:169
static const int NUM_ITEMS
Definition tpcc_tables.h:166
static const char GENERIC
Definition tpcc_output.h:102
static const char BRAND
Definition tpcc_output.h:101
Definition tpcc_output.h:85
std::array< char, MAX_STATUS+1 > status
Definition tpcc_output.h:117
std::array< char, Customer::CREDIT+1 > c_credit
Definition tpcc_output.h:113
std::array< char, Customer::MAX_LAST+1 > c_last
Definition tpcc_output.h:112
std::vector< ItemInfo > items
Definition tpcc_output.h:111
float w_tax
Definition tpcc_output.h:93
float d_tax
Definition tpcc_output.h:94
float total
Definition tpcc_output.h:97
float c_discount
Definition tpcc_output.h:96
int32_t o_id
Definition tpcc_output.h:95
Definition tpcc_tables.h:486
Definition tpcc_tables.h:482
int32_t w_id
Definition tpcc_tables.h:497
Key get_key()
Definition tpcc_tables.h:492
int32_t o_id
Definition tpcc_tables.h:499
int32_t d_id
Definition tpcc_tables.h:498
Definition tpcc_tables.h:441
Definition tpcc_tables.h:432
int32_t supply_w_id
Definition tpcc_tables.h:458
Key get_key()
Definition tpcc_tables.h:448
std::array< char, Stock::DIST+1 > dist_info
Definition tpcc_tables.h:462
int32_t o_id
Definition tpcc_tables.h:453
int32_t number
Definition tpcc_tables.h:456
std::array< char, DATETIME_SIZE+1 > delivery_d
Definition tpcc_tables.h:461
int32_t quantity
Definition tpcc_tables.h:459
int32_t d_id
Definition tpcc_tables.h:454
float amount
Definition tpcc_tables.h:460
int32_t i_id
Definition tpcc_tables.h:457
int32_t w_id
Definition tpcc_tables.h:455
Definition tpcc_output.h:54
int32_t c_id
Definition tpcc_output.h:55
int32_t o_id
Definition tpcc_output.h:58
float c_balance
Definition tpcc_output.h:56
std::array< char, Customer::MIDDLE+1 > c_middle
Definition tpcc_output.h:72
int32_t o_carrier_id
Definition tpcc_output.h:59
std::array< char, Customer::MAX_FIRST+1 > c_first
Definition tpcc_output.h:71
std::array< char, Customer::MAX_LAST+1 > c_last
Definition tpcc_output.h:73
std::vector< OrderLineSubset > lines
Definition tpcc_output.h:70
std::array< char, DATETIME_SIZE+1 > o_entry_d
Definition tpcc_output.h:74
Definition tpcc_tables.h:407
Definition tpcc_tables.h:394
Key get_key()
Definition tpcc_tables.h:411
int32_t w_id
Definition tpcc_tables.h:419
int32_t carrier_id
Definition tpcc_tables.h:420
int32_t c_id
Definition tpcc_tables.h:417
static const int MAX_OL_CNT
Definition tpcc_tables.h:400
int32_t id
Definition tpcc_tables.h:416
std::array< char, DATETIME_SIZE+1 > entry_d
Definition tpcc_tables.h:423
static const int MAX_CARRIER_ID
Definition tpcc_tables.h:396
int32_t d_id
Definition tpcc_tables.h:418
int32_t all_local
Definition tpcc_tables.h:422
static const int MIN_CARRIER_ID
Definition tpcc_tables.h:395
static const int MIN_OL_CNT
Definition tpcc_tables.h:399
static const int NULL_CARRIER_ID
Definition tpcc_tables.h:397
int32_t ol_cnt
Definition tpcc_tables.h:421
Definition tpcc_output.h:16
std::array< char, Address::MAX_STREET+1 > d_street_2
Definition tpcc_output.h:25
std::array< char, Address::MAX_STREET+1 > w_street_1
Definition tpcc_output.h:18
std::array< char, Customer::MIDDLE+1 > c_middle
Definition tpcc_output.h:34
std::array< char, Customer::PHONE+1 > c_phone
Definition tpcc_output.h:41
std::array< char, Address::MAX_CITY+1 > c_city
Definition tpcc_output.h:38
std::array< char, Address::ZIP+1 > c_zip
Definition tpcc_output.h:40
std::array< char, Address::MAX_STREET+1 > c_street_1
Definition tpcc_output.h:36
std::array< char, Address::MAX_STREET+1 > c_street_2
Definition tpcc_output.h:37
std::array< char, Address::ZIP+1 > d_zip
Definition tpcc_output.h:28
std::array< char, Customer::MAX_FIRST+1 > c_first
Definition tpcc_output.h:33
std::array< char, Address::MAX_CITY+1 > w_city
Definition tpcc_output.h:20
std::array< char, DATETIME_SIZE+1 > c_since
Definition tpcc_output.h:42
std::array< char, Address::STATE+1 > d_state
Definition tpcc_output.h:27
float c_discount
Definition tpcc_output.h:31
std::array< char, Address::STATE+1 > c_state
Definition tpcc_output.h:39
std::array< char, Address::MAX_STREET+1 > w_street_2
Definition tpcc_output.h:19
std::array< char, Address::MAX_CITY+1 > d_city
Definition tpcc_output.h:26
std::array< char, Address::MAX_STREET+1 > d_street_1
Definition tpcc_output.h:24
std::array< char, Customer::CREDIT+1 > c_credit
Definition tpcc_output.h:43
std::array< char, Customer::MAX_LAST+1 > c_last
Definition tpcc_output.h:35
std::array< char, Address::ZIP+1 > w_zip
Definition tpcc_output.h:22
float c_balance
Definition tpcc_output.h:32
float c_credit_lim
Definition tpcc_output.h:30
std::array< char, Address::STATE+1 > w_state
Definition tpcc_output.h:21
std::array< char, Customer::MAX_DATA+1 > c_data
Definition tpcc_output.h:44
Definition tpcc_tables.h:296
Definition tpcc_tables.h:277
int32_t ytd
Definition tpcc_tables.h:288
int32_t order_cnt
Definition tpcc_tables.h:289
int32_t quantity
Definition tpcc_tables.h:287
std::array< std::array< char, DIST+1 >, District::NUM_PER_WAREHOUSE > dist
Definition tpcc_tables.h:291
int32_t remote_cnt
Definition tpcc_tables.h:290
std::array< char, MAX_DATA+1 > data
Definition tpcc_tables.h:293
static std::unordered_map< uint64_t, TpccMap< Order::Key, Order > > orders
Definition tpcc_tables.h:565
static TpccMap< Stock::Key, Stock > stocks
Definition tpcc_tables.h:559
static std::unordered_map< uint64_t, TpccMap< NewOrder::Key, NewOrder > > new_orders
Definition tpcc_tables.h:568
static TpccMap< District::Key, District > districts
Definition tpcc_tables.h:561
static TpccMap< OrderLine::Key, OrderLine > order_lines
Definition tpcc_tables.h:566
static TpccMap< History::Key, History > histories
Definition tpcc_tables.h:562
static TpccMap< Warehouse::Key, Warehouse > warehouses
Definition tpcc_tables.h:560
static std::unordered_map< uint64_t, TpccMap< Customer::Key, Customer > > customers
Definition tpcc_tables.h:564
static TpccMap< Item::Key, Item > items
Definition tpcc_tables.h:569
Definition tpcc_tables.h:200
Definition tpcc_tables.h:190
std::array< char, Address::ZIP+1 > zip
Definition tpcc_tables.h:217
std::array< char, MAX_NAME+1 > name
Definition tpcc_tables.h:212
float ytd
Definition tpcc_tables.h:211
std::array< char, Address::MAX_STREET+1 > city
Definition tpcc_tables.h:215
std::array< char, Address::MAX_STREET+1 > street_2
Definition tpcc_tables.h:214
std::array< char, Address::STATE+1 > state
Definition tpcc_tables.h:216
float tax
Definition tpcc_tables.h:210
std::array< char, Address::MAX_STREET+1 > street_1
Definition tpcc_tables.h:213
Definition tpcc_tables.h:547
int32_t d_id
Definition tpcc_tables.h:551
int32_t w_id
Definition tpcc_tables.h:550
struct tpcc::TpccTables::DistributeKey::@2 v
uint64_t k
Definition tpcc_tables.h:553