1 /* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22
23 /**
24 @file storage/perfschema/table_events_transactions.cc
25 Table EVENTS_TRANSACTIONS_xxx (implementation).
26 */
27
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "table_events_transactions.h"
31 #include "pfs_instr_class.h"
32 #include "pfs_instr.h"
33 #include "pfs_events_transactions.h"
34 #include "pfs_timer.h"
35 #include "table_helper.h"
36 #include "pfs_buffer_container.h"
37 #include "field.h"
38 #include "xa.h"
39
40 THR_LOCK table_events_transactions_current::m_table_lock;
41
42 static const TABLE_FIELD_TYPE field_types[]=
43 {
44 {
45 { C_STRING_WITH_LEN("THREAD_ID") },
46 { C_STRING_WITH_LEN("bigint(20)") },
47 { NULL, 0}
48 },
49 {
50 { C_STRING_WITH_LEN("EVENT_ID") },
51 { C_STRING_WITH_LEN("bigint(20)") },
52 { NULL, 0}
53 },
54 {
55 { C_STRING_WITH_LEN("END_EVENT_ID") },
56 { C_STRING_WITH_LEN("bigint(20)") },
57 { NULL, 0}
58 },
59 {
60 { C_STRING_WITH_LEN("EVENT_NAME") },
61 { C_STRING_WITH_LEN("varchar(128)") },
62 { NULL, 0}
63 },
64 {
65 { C_STRING_WITH_LEN("STATE") },
66 { C_STRING_WITH_LEN("enum(\'ACTIVE\',\'COMMITTED\',\'ROLLED BACK\'") },
67 { NULL, 0}
68 },
69 {
70 { C_STRING_WITH_LEN("TRX_ID") },
71 { C_STRING_WITH_LEN("bigint(20)") },
72 { NULL, 0}
73 },
74 {
75 { C_STRING_WITH_LEN("GTID") },
76 { C_STRING_WITH_LEN("varchar(64)") },
77 { NULL, 0}
78 },
79 {
80 { C_STRING_WITH_LEN("XID_FORMAT_ID") },
81 { C_STRING_WITH_LEN("int(11)") },
82 { NULL, 0}
83 },
84 {
85 { C_STRING_WITH_LEN("XID_GTRID") },
86 { C_STRING_WITH_LEN("varchar(130)") },
87 { NULL, 0}
88 },
89 {
90 { C_STRING_WITH_LEN("XID_BQUAL") },
91 { C_STRING_WITH_LEN("varchar(130)") },
92 { NULL, 0}
93 },
94 {
95 { C_STRING_WITH_LEN("XA_STATE") },
96 { C_STRING_WITH_LEN("varchar(64)") },
97 { NULL, 0}
98 },
99 {
100 { C_STRING_WITH_LEN("SOURCE") },
101 { C_STRING_WITH_LEN("varchar(64)") },
102 { NULL, 0}
103 },
104 {
105 { C_STRING_WITH_LEN("TIMER_START") },
106 { C_STRING_WITH_LEN("bigint(20)") },
107 { NULL, 0}
108 },
109 {
110 { C_STRING_WITH_LEN("TIMER_END") },
111 { C_STRING_WITH_LEN("bigint(20)") },
112 { NULL, 0}
113 },
114 {
115 { C_STRING_WITH_LEN("TIMER_WAIT") },
116 { C_STRING_WITH_LEN("bigint(20)") },
117 { NULL, 0}
118 },
119 {
120 { C_STRING_WITH_LEN("ACCESS_MODE") },
121 { C_STRING_WITH_LEN("enum(\'READ ONLY\',\'READ WRITE\'") },
122 { NULL, 0}
123 },
124 {
125 { C_STRING_WITH_LEN("ISOLATION_LEVEL") },
126 { C_STRING_WITH_LEN("varchar(64)") },
127 { NULL, 0}
128 },
129 {
130 { C_STRING_WITH_LEN("AUTOCOMMIT") },
131 { C_STRING_WITH_LEN("enum(\'YES\',\'NO\'") },
132 { NULL, 0}
133 },
134 {
135 { C_STRING_WITH_LEN("NUMBER_OF_SAVEPOINTS") },
136 { C_STRING_WITH_LEN("bigint(20)") },
137 { NULL, 0}
138 },
139 {
140 { C_STRING_WITH_LEN("NUMBER_OF_ROLLBACK_TO_SAVEPOINT") },
141 { C_STRING_WITH_LEN("bigint(20)") },
142 { NULL, 0}
143 },
144 {
145 { C_STRING_WITH_LEN("NUMBER_OF_RELEASE_SAVEPOINT") },
146 { C_STRING_WITH_LEN("bigint(20)") },
147 { NULL, 0}
148 },
149 {
150 { C_STRING_WITH_LEN("OBJECT_INSTANCE_BEGIN") },
151 { C_STRING_WITH_LEN("bigint") },
152 { NULL, 0}
153 },
154 {
155 { C_STRING_WITH_LEN("NESTING_EVENT_ID") },
156 { C_STRING_WITH_LEN("bigint(20)") },
157 { NULL, 0}
158 },
159 {
160 { C_STRING_WITH_LEN("NESTING_EVENT_TYPE") },
161 { C_STRING_WITH_LEN("enum(\'TRANSACTION\',\'STATEMENT\',\'STAGE\',\'WAIT\'") },
162 { NULL, 0}
163 }
164 };
165
166 TABLE_FIELD_DEF
167 table_events_transactions_current::m_field_def=
168 {24 , field_types };
169
170 PFS_engine_table_share
171 table_events_transactions_current::m_share=
172 {
173 { C_STRING_WITH_LEN("events_transactions_current") },
174 &pfs_truncatable_acl,
175 table_events_transactions_current::create,
176 NULL, /* write_row */
177 table_events_transactions_current::delete_all_rows,
178 table_events_transactions_current::get_row_count,
179 sizeof(PFS_simple_index), /* ref length */
180 &m_table_lock,
181 &m_field_def,
182 false, /* checked */
183 false /* perpetual */
184 };
185
186 THR_LOCK table_events_transactions_history::m_table_lock;
187
188 PFS_engine_table_share
189 table_events_transactions_history::m_share=
190 {
191 { C_STRING_WITH_LEN("events_transactions_history") },
192 &pfs_truncatable_acl,
193 table_events_transactions_history::create,
194 NULL, /* write_row */
195 table_events_transactions_history::delete_all_rows,
196 table_events_transactions_history::get_row_count,
197 sizeof(pos_events_transactions_history), /* ref length */
198 &m_table_lock,
199 &table_events_transactions_current::m_field_def,
200 false, /* checked */
201 false /* perpetual */
202 };
203
204 THR_LOCK table_events_transactions_history_long::m_table_lock;
205
206 PFS_engine_table_share
207 table_events_transactions_history_long::m_share=
208 {
209 { C_STRING_WITH_LEN("events_transactions_history_long") },
210 &pfs_truncatable_acl,
211 table_events_transactions_history_long::create,
212 NULL, /* write_row */
213 table_events_transactions_history_long::delete_all_rows,
214 table_events_transactions_history_long::get_row_count,
215 sizeof(PFS_simple_index), /* ref length */
216 &m_table_lock,
217 &table_events_transactions_current::m_field_def,
218 false, /* checked */
219 false /* perpetual */
220 };
221
table_events_transactions_common(const PFS_engine_table_share * share,void * pos)222 table_events_transactions_common::table_events_transactions_common
223 (const PFS_engine_table_share *share, void *pos)
224 : PFS_engine_table(share, pos),
225 m_row_exists(false)
226 {}
227
228 /**
229 Build a row.
230 @param transaction the transaction the cursor is reading
231 */
make_row(PFS_events_transactions * transaction)232 void table_events_transactions_common::make_row(PFS_events_transactions *transaction)
233 {
234 ulonglong timer_end;
235
236 m_row_exists= false;
237
238 PFS_transaction_class *unsafe= (PFS_transaction_class*) transaction->m_class;
239 PFS_transaction_class *klass= sanitize_transaction_class(unsafe);
240 if (unlikely(klass == NULL))
241 return;
242
243 m_row.m_thread_internal_id= transaction->m_thread_internal_id;
244 m_row.m_event_id= transaction->m_event_id;
245 m_row.m_end_event_id= transaction->m_end_event_id;
246 m_row.m_nesting_event_id= transaction->m_nesting_event_id;
247 m_row.m_nesting_event_type= transaction->m_nesting_event_type;
248
249 if (m_row.m_end_event_id == 0)
250 {
251 timer_end= get_timer_raw_value(transaction_timer);
252 }
253 else
254 {
255 timer_end= transaction->m_timer_end;
256 }
257
258 m_normalizer->to_pico(transaction->m_timer_start, timer_end,
259 &m_row.m_timer_start, &m_row.m_timer_end, &m_row.m_timer_wait);
260 m_row.m_name= klass->m_name;
261 m_row.m_name_length= klass->m_name_length;
262
263 /* Disable source file and line to avoid stale __FILE__ pointers. */
264 m_row.m_source_length= 0;
265
266 /* A GTID consists of the SID (source id) and GNO (transaction number).
267 The SID is stored in transaction->m_sid and the GNO is stored in
268 transaction->m_gtid_spec.gno.
269
270 On a master, the GTID is assigned when the transaction commit.
271 On a slave, the GTID is assigned before the transaction starts.
272 If GTID_MODE = OFF, all transactions have the special GTID
273 'ANONYMOUS'.
274
275 Therefore, a transaction can be in three different states wrt GTIDs:
276 - Before the GTID has been assigned, the state is 'AUTOMATIC'.
277 On a master, this is the state until the transaction commits.
278 On a slave, this state does not appear.
279 - If GTID_MODE = ON, and a GTID is assigned, the GTID is a string
280 of the form 'UUID:NUMBER'.
281 - If GTID_MODE = OFF, and a GTID is assigned, the GTID is a string
282 of the form 'ANONYMOUS'.
283
284 The Gtid_specification contains the GNO, as well as a type code
285 that specifies which of the three modes is currently in effect.
286 Given a SID, it can generate the textual representation of the
287 GTID.
288 */
289 rpl_sid *sid= &transaction->m_sid;
290 Gtid_specification *gtid_spec= &transaction->m_gtid_spec;
291 m_row.m_gtid_length= gtid_spec->to_string(sid, m_row.m_gtid);
292
293 m_row.m_xid= transaction->m_xid;
294 m_row.m_isolation_level= transaction->m_isolation_level;
295 m_row.m_read_only= transaction->m_read_only;
296 m_row.m_trxid= transaction->m_trxid;
297 m_row.m_state= transaction->m_state;
298 m_row.m_xa_state= transaction->m_xa_state;
299 m_row.m_xa= transaction->m_xa;
300 m_row.m_autocommit= transaction->m_autocommit;
301 m_row.m_savepoint_count= transaction->m_savepoint_count;
302 m_row.m_rollback_to_savepoint_count= transaction->m_rollback_to_savepoint_count;
303 m_row.m_release_savepoint_count= transaction->m_release_savepoint_count;
304 m_row_exists= true;
305 return;
306 }
307
308 /** Size of XID converted to null-terminated hex string prefixed with 0x. */
309 static const ulong XID_BUFFER_SIZE= XIDDATASIZE*2 + 2 + 1;
310
311 /**
312 Convert the XID to HEX string prefixed by '0x'
313
314 @param[out] buf output hex string buffer, null-terminated
315 @param buf_len size of buffer, must be at least @c XID_BUFFER_SIZE
316 @param xid XID structure
317 @param offset offset into XID.data[]
318 @param length number of bytes to process
319 @return number of bytes in hex string
320 */
xid_to_hex(char * buf,size_t buf_len,PSI_xid * xid,size_t offset,size_t length)321 static uint xid_to_hex(char *buf, size_t buf_len, PSI_xid *xid, size_t offset, size_t length)
322 {
323 DBUG_ASSERT(buf_len >= XID_BUFFER_SIZE);
324 DBUG_ASSERT(offset + length <= XIDDATASIZE);
325 *buf++= '0';
326 *buf++= 'x';
327 return bin_to_hex_str(buf, buf_len-2, (char*)(xid->data + offset), length) + 2;
328 }
329
330 /**
331 Store the XID in printable format if possible, otherwise convert
332 to a string of hex digits.
333
334 @param field Record field
335 @param xid XID structure
336 @param offset offset into XID.data[]
337 @param length number of bytes to process
338 */
xid_store(Field * field,PSI_xid * xid,size_t offset,size_t length)339 static void xid_store(Field *field, PSI_xid *xid, size_t offset, size_t length)
340 {
341 DBUG_ASSERT(!xid->is_null());
342 if (xid_printable(xid, offset, length))
343 {
344 field->store(xid->data + offset, length, &my_charset_bin);
345 }
346 else
347 {
348 /*
349 xid_buf contains enough space for 0x followed by hex representation of
350 the binary XID data and one null termination character.
351 */
352 char xid_buf[XID_BUFFER_SIZE];
353
354 size_t xid_str_len= xid_to_hex(xid_buf, sizeof(xid_buf), xid, offset, length);
355 field->store(xid_buf, xid_str_len, &my_charset_bin);
356 }
357 }
358
xid_store_bqual(Field * field,PSI_xid * xid)359 static void xid_store_bqual(Field *field, PSI_xid *xid)
360 {
361 xid_store(field, xid, xid->gtrid_length, xid->bqual_length);
362 }
363
xid_store_gtrid(Field * field,PSI_xid * xid)364 static void xid_store_gtrid(Field *field, PSI_xid *xid)
365 {
366 xid_store(field, xid, 0, xid->gtrid_length);
367 }
368
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)369 int table_events_transactions_common::read_row_values(TABLE *table,
370 unsigned char *buf,
371 Field **fields,
372 bool read_all)
373 {
374 Field *f;
375
376 if (unlikely(! m_row_exists))
377 return HA_ERR_RECORD_DELETED;
378
379 /* Set the null bits */
380 DBUG_ASSERT(table->s->null_bytes == 3);
381 buf[0]= 0;
382 buf[1]= 0;
383 buf[2]= 0;
384
385 for (; (f= *fields) ; fields++)
386 {
387 if (read_all || bitmap_is_set(table->read_set, f->field_index))
388 {
389 switch(f->field_index)
390 {
391 case 0: /* THREAD_ID */
392 set_field_ulonglong(f, m_row.m_thread_internal_id);
393 break;
394 case 1: /* EVENT_ID */
395 set_field_ulonglong(f, m_row.m_event_id);
396 break;
397 case 2: /* END_EVENT_ID */
398 if (m_row.m_end_event_id > 0)
399 set_field_ulonglong(f, m_row.m_end_event_id - 1);
400 else
401 f->set_null();
402 break;
403 case 3: /* EVENT_NAME */
404 set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length);
405 break;
406 case 4: /* STATE */
407 set_field_enum(f, m_row.m_state);
408 break;
409 case 5: /* TRX_ID */
410 if (m_row.m_trxid != 0)
411 set_field_ulonglong(f, m_row.m_trxid);
412 else
413 f->set_null();
414 break;
415 case 6: /* GTID */
416 set_field_varchar_utf8(f, m_row.m_gtid, m_row.m_gtid_length);
417 break;
418 case 7: /* XID_FORMAT_ID */
419 if (!m_row.m_xa || m_row.m_xid.is_null())
420 f->set_null();
421 else
422 set_field_long(f, m_row.m_xid.formatID);
423 break;
424 case 8: /* XID_GTRID */
425 if (!m_row.m_xa || m_row.m_xid.is_null() || m_row.m_xid.gtrid_length <= 0)
426 f->set_null();
427 else
428 xid_store_gtrid(f, &m_row.m_xid);
429 break;
430 case 9: /* XID_BQUAL */
431 if (!m_row.m_xa || m_row.m_xid.is_null() || m_row.m_xid.bqual_length <= 0)
432 f->set_null();
433 else
434 xid_store_bqual(f, &m_row.m_xid);
435 break;
436 case 10: /* XA STATE */
437 if (!m_row.m_xa || m_row.m_xid.is_null())
438 f->set_null();
439 else
440 set_field_xa_state(f, m_row.m_xa_state);
441 break;
442 case 11: /* SOURCE */
443 set_field_varchar_utf8(f, m_row.m_source, m_row.m_source_length);
444 break;
445 case 12: /* TIMER_START */
446 if (m_row.m_timer_start != 0)
447 set_field_ulonglong(f, m_row.m_timer_start);
448 else
449 f->set_null();
450 break;
451 case 13: /* TIMER_END */
452 if (m_row.m_timer_end != 0)
453 set_field_ulonglong(f, m_row.m_timer_end);
454 else
455 f->set_null();
456 break;
457 case 14: /* TIMER_WAIT */
458 if (m_row.m_timer_wait != 0)
459 set_field_ulonglong(f, m_row.m_timer_wait);
460 else
461 f->set_null();
462 break;
463 case 15: /* ACCESS_MODE */
464 set_field_enum(f, m_row.m_read_only ? TRANS_MODE_READ_ONLY
465 : TRANS_MODE_READ_WRITE);
466 break;
467 case 16: /* ISOLATION_LEVEL */
468 set_field_isolation_level(f, m_row.m_isolation_level);
469 break;
470 case 17: /* AUTOCOMMIT */
471 set_field_enum(f, m_row.m_autocommit ? ENUM_YES : ENUM_NO);
472 break;
473 case 18: /* NUMBER_OF_SAVEPOINTS */
474 set_field_ulonglong(f, m_row.m_savepoint_count);
475 break;
476 case 19: /* NUMBER_OF_ROLLBACK_TO_SAVEPOINT */
477 set_field_ulonglong(f, m_row.m_rollback_to_savepoint_count);
478 break;
479 case 20: /* NUMBER_OF_RELEASE_SAVEPOINT */
480 set_field_ulonglong(f, m_row.m_release_savepoint_count);
481 break;
482 case 21: /* OBJECT_INSTANCE_BEGIN */
483 f->set_null();
484 break;
485 case 22: /* NESTING_EVENT_ID */
486 if (m_row.m_nesting_event_id != 0)
487 set_field_ulonglong(f, m_row.m_nesting_event_id);
488 else
489 f->set_null();
490 break;
491 case 23: /* NESTING_EVENT_TYPE */
492 if (m_row.m_nesting_event_id != 0)
493 set_field_enum(f, m_row.m_nesting_event_type);
494 else
495 f->set_null();
496 break;
497 default:
498 DBUG_ASSERT(false);
499 }
500 }
501 }
502 return 0;
503 }
504
create(void)505 PFS_engine_table* table_events_transactions_current::create(void)
506 {
507 return new table_events_transactions_current();
508 }
509
table_events_transactions_current()510 table_events_transactions_current::table_events_transactions_current()
511 : table_events_transactions_common(&m_share, &m_pos),
512 m_pos(0), m_next_pos(0)
513 {}
514
reset_position(void)515 void table_events_transactions_current::reset_position(void)
516 {
517 m_pos.m_index= 0;
518 m_next_pos.m_index= 0;
519 }
520
rnd_init(bool scan)521 int table_events_transactions_current::rnd_init(bool scan)
522 {
523 m_normalizer= time_normalizer::get(transaction_timer);
524 return 0;
525 }
526
rnd_next(void)527 int table_events_transactions_current::rnd_next(void)
528 {
529 PFS_thread *pfs_thread;
530 PFS_events_transactions *transaction;
531 bool has_more_thread= true;
532
533 for (m_pos.set_at(&m_next_pos);
534 has_more_thread;
535 m_pos.next())
536 {
537 pfs_thread= global_thread_container.get(m_pos.m_index, & has_more_thread);
538 if (pfs_thread != NULL)
539 {
540 transaction= &pfs_thread->m_transaction_current;
541 make_row(transaction);
542 m_next_pos.set_after(&m_pos);
543 return 0;
544 }
545 }
546
547 return HA_ERR_END_OF_FILE;
548 }
549
rnd_pos(const void * pos)550 int table_events_transactions_current::rnd_pos(const void *pos)
551 {
552 PFS_thread *pfs_thread;
553 PFS_events_transactions *transaction;
554
555 set_position(pos);
556
557 pfs_thread= global_thread_container.get(m_pos.m_index);
558 if (pfs_thread != NULL)
559 {
560 transaction= &pfs_thread->m_transaction_current;
561 if (transaction->m_class != NULL)
562 {
563 make_row(transaction);
564 return 0;
565 }
566 }
567
568 return HA_ERR_RECORD_DELETED;
569 }
570
delete_all_rows(void)571 int table_events_transactions_current::delete_all_rows(void)
572 {
573 reset_events_transactions_current();
574 return 0;
575 }
576
577 ha_rows
get_row_count(void)578 table_events_transactions_current::get_row_count(void)
579 {
580 return global_thread_container.get_row_count();
581 }
582
create(void)583 PFS_engine_table* table_events_transactions_history::create(void)
584 {
585 return new table_events_transactions_history();
586 }
587
table_events_transactions_history()588 table_events_transactions_history::table_events_transactions_history()
589 : table_events_transactions_common(&m_share, &m_pos),
590 m_pos(), m_next_pos()
591 {}
592
reset_position(void)593 void table_events_transactions_history::reset_position(void)
594 {
595 m_pos.reset();
596 m_next_pos.reset();
597 }
598
rnd_init(bool scan)599 int table_events_transactions_history::rnd_init(bool scan)
600 {
601 m_normalizer= time_normalizer::get(transaction_timer);
602 return 0;
603 }
604
rnd_next(void)605 int table_events_transactions_history::rnd_next(void)
606 {
607 PFS_thread *pfs_thread;
608 PFS_events_transactions *transaction;
609 bool has_more_thread= true;
610
611 if (events_transactions_history_per_thread == 0)
612 return HA_ERR_END_OF_FILE;
613
614 for (m_pos.set_at(&m_next_pos);
615 has_more_thread;
616 m_pos.next_thread())
617 {
618 pfs_thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
619 if (pfs_thread != NULL)
620 {
621 if (m_pos.m_index_2 >= events_transactions_history_per_thread)
622 {
623 /* This thread does not have more (full) history */
624 continue;
625 }
626
627 if ( ! pfs_thread->m_transactions_history_full &&
628 (m_pos.m_index_2 >= pfs_thread->m_transactions_history_index))
629 {
630 /* This thread does not have more (not full) history */
631 continue;
632 }
633
634 transaction= &pfs_thread->m_transactions_history[m_pos.m_index_2];
635 if (transaction->m_class != NULL)
636 {
637 make_row(transaction);
638 /* Next iteration, look for the next history in this thread */
639 m_next_pos.set_after(&m_pos);
640 return 0;
641 }
642 }
643 }
644
645 return HA_ERR_END_OF_FILE;
646 }
647
rnd_pos(const void * pos)648 int table_events_transactions_history::rnd_pos(const void *pos)
649 {
650 PFS_thread *pfs_thread;
651 PFS_events_transactions *transaction;
652
653 DBUG_ASSERT(events_transactions_history_per_thread != 0);
654 set_position(pos);
655
656 DBUG_ASSERT(m_pos.m_index_2 < events_transactions_history_per_thread);
657
658 pfs_thread= global_thread_container.get(m_pos.m_index_1);
659 if (pfs_thread != NULL)
660 {
661 if ( ! pfs_thread->m_transactions_history_full &&
662 (m_pos.m_index_2 >= pfs_thread->m_transactions_history_index))
663 return HA_ERR_RECORD_DELETED;
664
665 transaction= &pfs_thread->m_transactions_history[m_pos.m_index_2];
666 if (transaction->m_class != NULL)
667 {
668 make_row(transaction);
669 return 0;
670 }
671 }
672
673 return HA_ERR_RECORD_DELETED;
674 }
675
delete_all_rows(void)676 int table_events_transactions_history::delete_all_rows(void)
677 {
678 reset_events_transactions_history();
679 return 0;
680 }
681
682 ha_rows
get_row_count(void)683 table_events_transactions_history::get_row_count(void)
684 {
685 return events_transactions_history_per_thread * global_thread_container.get_row_count();
686 }
687
create(void)688 PFS_engine_table* table_events_transactions_history_long::create(void)
689 {
690 return new table_events_transactions_history_long();
691 }
692
table_events_transactions_history_long()693 table_events_transactions_history_long::table_events_transactions_history_long()
694 : table_events_transactions_common(&m_share, &m_pos),
695 m_pos(0), m_next_pos(0)
696 {}
697
reset_position(void)698 void table_events_transactions_history_long::reset_position(void)
699 {
700 m_pos.m_index= 0;
701 m_next_pos.m_index= 0;
702 }
703
rnd_init(bool scan)704 int table_events_transactions_history_long::rnd_init(bool scan)
705 {
706 m_normalizer= time_normalizer::get(transaction_timer);
707 return 0;
708 }
709
rnd_next(void)710 int table_events_transactions_history_long::rnd_next(void)
711 {
712 PFS_events_transactions *transaction;
713 uint limit;
714
715 if (events_transactions_history_long_size == 0)
716 return HA_ERR_END_OF_FILE;
717
718 if (events_transactions_history_long_full)
719 limit= events_transactions_history_long_size;
720 else
721 limit= events_transactions_history_long_index.m_u32 % events_transactions_history_long_size;
722
723 for (m_pos.set_at(&m_next_pos); m_pos.m_index < limit; m_pos.next())
724 {
725 transaction= &events_transactions_history_long_array[m_pos.m_index];
726
727 if (transaction->m_class != NULL)
728 {
729 make_row(transaction);
730 /* Next iteration, look for the next entry */
731 m_next_pos.set_after(&m_pos);
732 return 0;
733 }
734 }
735
736 return HA_ERR_END_OF_FILE;
737 }
738
rnd_pos(const void * pos)739 int table_events_transactions_history_long::rnd_pos(const void *pos)
740 {
741 PFS_events_transactions *transaction;
742 uint limit;
743
744 if (events_transactions_history_long_size == 0)
745 return HA_ERR_RECORD_DELETED;
746
747 set_position(pos);
748
749 if (events_transactions_history_long_full)
750 limit= events_transactions_history_long_size;
751 else
752 limit= events_transactions_history_long_index.m_u32 % events_transactions_history_long_size;
753
754 if (m_pos.m_index >= limit)
755 return HA_ERR_RECORD_DELETED;
756
757 transaction= &events_transactions_history_long_array[m_pos.m_index];
758
759 if (transaction->m_class == NULL)
760 return HA_ERR_RECORD_DELETED;
761
762 make_row(transaction);
763 return 0;
764 }
765
delete_all_rows(void)766 int table_events_transactions_history_long::delete_all_rows(void)
767 {
768 reset_events_transactions_history_long();
769 return 0;
770 }
771
772 ha_rows
get_row_count(void)773 table_events_transactions_history_long::get_row_count(void)
774 {
775 return events_transactions_history_long_size;
776 }
777
778