MySQL 8.0.40
Source Code Documentation
pfs_buffer_container.h
Go to the documentation of this file.
1/* Copyright (c) 2014, 2024, Oracle and/or its affiliates.
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 designed to work 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 either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef PFS_BUFFER_CONTAINER_H
25#define PFS_BUFFER_CONTAINER_H
26
27/**
28 @file storage/perfschema/pfs_buffer_container.h
29 Generic buffer container.
30*/
31
32#include <assert.h>
33#include <stddef.h>
34#include <sys/types.h>
35#include <atomic>
36
37#include "my_inttypes.h"
48
49#define USE_SCALABLE
50
51class PFS_opaque_container_page;
52class PFS_opaque_container;
53
55
56template <class T>
58
59template <class T>
61
62template <class T, class U, class V>
64
65template <class T, int PFS_PAGE_SIZE, int PFS_PAGE_COUNT, class U, class V>
67
68template <class T>
70
71template <class T>
73
74template <class T, class U, class V>
76
77template <class T, int PFS_PAGE_SIZE, int PFS_PAGE_COUNT, class U, class V>
79
80template <class B, int COUNT>
82
83template <class B, int COUNT>
85
86template <class T>
88 public:
89 typedef T value_type;
90
92 size_t index;
93 size_t monotonic;
94 size_t monotonic_max;
96
97 if (m_full.load()) {
98 return nullptr;
99 }
100
101 // Immutable
102 size_t max = m_max.load();
103 // Immutable
104 T *ptr = m_ptr.load();
105
106 monotonic = m_monotonic.m_size_t++;
107 monotonic_max = monotonic + max;
108
109 if (unlikely(monotonic >= monotonic_max)) {
110 /*
111 This will happen once every 2^64 - m_max calls.
112 Computation of monotonic_max just overflowed,
113 so reset monotonic counters and start again from the beginning.
114 */
115 m_monotonic.m_size_t.store(0);
116 monotonic = 0;
117 monotonic_max = max;
118 }
119
120 while (monotonic < monotonic_max) {
121 index = monotonic % max;
122 pfs = ptr + index;
123
124 if (pfs->m_lock.free_to_dirty(dirty_state)) {
125 return pfs;
126 }
127 monotonic = m_monotonic.m_size_t++;
128 }
129
130 m_full.store(true);
131 return nullptr;
132 }
133
135 pfs->m_lock.allocated_to_free();
136
137 if (m_full.load()) {
138 m_full.store(false);
139 }
140 }
141
142 T *get_first() { return m_ptr; }
143
144 T *get_last() { return m_ptr + m_max; }
145
146 /**
147 Page full flag.
148
149 Concurrency profile:
150 - mostly read during normal operations.
151 - do not perform useless write,
152 check for previous value first
153 - occasional write on state changes
154 */
155 std::atomic<bool> m_full{false};
156
157 /**
158 Monotonic counter.
159 This counter is used to access items in the page.
160
161 Concurrency profile:
162 - frequent read and write, must be on its own cacheline
163 */
165
166 /**
167 Array of values.
168
169 Concurrency profile:
170 - written once on page creation
171 - read only during normal operations.
172 */
173 std::atomic<T *> m_ptr{nullptr};
174
175 /**
176 Max number of items in the page.
177
178 Concurrency profile:
179 - written once on page creation
180 - read only during normal operations.
181 */
182 std::atomic<size_t> m_max{0};
183
184 /**
185 Container.
186
187 Concurrency profile:
188 - written once on page creation
189 - read only during normal operations.
190 */
191 std::atomic<PFS_opaque_container *> m_container{nullptr};
192};
193
194template <class T>
196 public:
198
200 : m_builtin_class(klass) {}
201
203 array->m_ptr = nullptr;
204 array->m_full = true;
205 array->m_monotonic.m_size_t.store(0);
206
207 if (array->m_max > 0) {
208 array->m_ptr = PFS_MALLOC_ARRAY(m_builtin_class, array->m_max, sizeof(T),
209 T, MYF(MY_ZEROFILL));
210 if (array->m_ptr == nullptr) {
211 return 1;
212 }
213 array->m_full = false;
214 }
215 return 0;
216 }
217
218 void free_array(array_type *array) {
219 assert(array->m_max > 0);
220
221 PFS_FREE_ARRAY(m_builtin_class, array->m_max, sizeof(T), array->m_ptr);
222 array->m_ptr = nullptr;
223 }
224
225 private:
227};
228
229template <class T, class U = PFS_buffer_default_array<T>,
230 class V = PFS_buffer_default_allocator<T>>
232 public:
233 friend class PFS_buffer_iterator<T, U, V>;
234
235 typedef T value_type;
236 typedef U array_type;
237 typedef V allocator_type;
241 typedef void (*function_type)(value_type *);
242
244 m_array.m_full = true;
245 m_array.m_ptr = NULL;
246 m_array.m_max = 0;
247 m_array.m_monotonic.m_size_t = 0;
248 m_lost = 0;
249 m_max = 0;
250 m_allocator = allocator;
251 }
252
253 int init(size_t max_size) {
254 if (max_size > 0) {
255 m_array.m_max = max_size;
256 int rc = m_allocator->alloc_array(&m_array);
257 if (rc != 0) {
258 m_allocator->free_array(&m_array);
259 return 1;
260 }
261 m_max = max_size;
262 m_array.m_full = false;
263 }
264 return 0;
265 }
266
267 void cleanup() { m_allocator->free_array(&m_array); }
268
269 size_t get_row_count() const { return m_max; }
270
271 size_t get_row_size() const { return sizeof(value_type); }
272
273 size_t get_memory() const { return get_row_count() * get_row_size(); }
274
277
278 pfs = m_array.allocate(dirty_state, m_max);
279 if (pfs == NULL) {
280 m_lost++;
281 }
282
283 return pfs;
284 }
285
286 void deallocate(value_type *pfs) { m_array.deallocate(pfs); }
287
289
291 assert(index <= m_max);
292 return PFS_buffer_iterator<T, U, V>(this, index);
293 }
294
296 value_type *pfs = m_array.get_first();
297 value_type *pfs_last = m_array.get_last();
298
299 while (pfs < pfs_last) {
300 if (pfs->m_lock.is_populated()) {
301 fct(pfs);
302 }
303 pfs++;
304 }
305 }
306
308 value_type *pfs = m_array.get_first();
309 value_type *pfs_last = m_array.get_last();
310
311 while (pfs < pfs_last) {
312 fct(pfs);
313 pfs++;
314 }
315 }
316
317 void apply(processor_type &proc) {
318 value_type *pfs = m_array.get_first();
319 value_type *pfs_last = m_array.get_last();
320
321 while (pfs < pfs_last) {
322 if (pfs->m_lock.is_populated()) {
323 proc(pfs);
324 }
325 pfs++;
326 }
327 }
328
330 value_type *pfs = m_array.get_first();
331 value_type *pfs_last = m_array.get_last();
332
333 while (pfs < pfs_last) {
334 proc(pfs);
335 pfs++;
336 }
337 }
338
339 inline value_type *get(uint index) {
340 assert(index < m_max);
341
342 value_type *pfs = m_array.m_ptr + index;
343 if (pfs->m_lock.is_populated()) {
344 return pfs;
345 }
346
347 return NULL;
348 }
349
350 value_type *get(uint index, bool *has_more) {
351 if (index >= m_max) {
352 *has_more = false;
353 return NULL;
354 }
355
356 *has_more = true;
357 return get(index);
358 }
359
361 intptr offset;
362 value_type *pfs = m_array.get_first();
363 value_type *pfs_last = m_array.get_last();
364
365 if ((pfs <= unsafe) && (unsafe < pfs_last)) {
366 offset = ((intptr)unsafe - (intptr)pfs) % sizeof(value_type);
367 if (offset == 0) {
368 return unsafe;
369 }
370 }
371
372 return NULL;
373 }
374
375 ulong m_lost;
376
377 private:
378 value_type *scan_next(uint &index, uint *found_index) {
379 assert(index <= m_max);
380
381 value_type *pfs_first = m_array.get_first();
382 value_type *pfs = pfs_first + index;
383 value_type *pfs_last = m_array.get_last();
384
385 while (pfs < pfs_last) {
386 if (pfs->m_lock.is_populated()) {
387 uint found = pfs - pfs_first;
388 *found_index = found;
389 index = found + 1;
390 return pfs;
391 }
392 pfs++;
393 }
394
395 index = m_max;
396 return NULL;
397 }
398
399 size_t m_max;
402};
403
404template <class T, int PFS_PAGE_SIZE, int PFS_PAGE_COUNT,
408 public:
409 friend class PFS_buffer_scalable_iterator<T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U,
410 V>;
411
412 /**
413 Type of elements in the buffer.
414 The following attributes are required:
415 - @code pfs_lock m_lock @endcode
416 - @code PFS_opaque_container_page *m_page @endcode
417 */
418 typedef T value_type;
419 /**
420 Type of pages in the buffer.
421 The following attributes are required:
422 - @code PFS_opaque_container *m_container @endcode
423 */
424 typedef U array_type;
425 typedef V allocator_type;
426 /** This container type */
433 typedef void (*function_type)(value_type *);
434
435 static const size_t MAX_SIZE = PFS_PAGE_SIZE * PFS_PAGE_COUNT;
436
438 m_allocator = allocator;
439 m_initialized = false;
440 }
441
442 int init(long max_size) {
443 int i;
444
445 m_initialized = true;
446 m_full = true;
447 m_max = PFS_PAGE_COUNT * PFS_PAGE_SIZE;
448 m_max_page_count = PFS_PAGE_COUNT;
449 m_last_page_size = PFS_PAGE_SIZE;
450 m_lost = 0;
451 m_monotonic.m_size_t.store(0);
452 m_max_page_index.m_size_t.store(0);
453
454 for (i = 0; i < PFS_PAGE_COUNT; i++) {
455 m_pages[i] = nullptr;
456 }
457
458 if (max_size == 0) {
459 /* No allocation. */
461 } else if (max_size > 0) {
462 if (max_size % PFS_PAGE_SIZE == 0) {
463 m_max_page_count = max_size / PFS_PAGE_SIZE;
464 } else {
465 m_max_page_count = max_size / PFS_PAGE_SIZE + 1;
466 m_last_page_size = max_size % PFS_PAGE_SIZE;
467 }
468 /* Bounded allocation. */
469 m_full = false;
470
471 if (m_max_page_count > PFS_PAGE_COUNT) {
472 m_max_page_count = PFS_PAGE_COUNT;
473 m_last_page_size = PFS_PAGE_SIZE;
474 }
475 } else {
476 /* max_size = -1 means unbounded allocation */
477 m_full = false;
478 }
479
480 assert(m_max_page_count <= PFS_PAGE_COUNT);
481 assert(0 < m_last_page_size);
482 assert(m_last_page_size <= PFS_PAGE_SIZE);
483
485 return 0;
486 }
487
488 void cleanup() {
489 int i;
491
492 if (!m_initialized) {
493 return;
494 }
495
496 allocator_type *allocator = m_allocator.load();
497
499
500 for (i = 0; i < PFS_PAGE_COUNT; i++) {
501 page = m_pages[i];
502 if (page != nullptr) {
503 allocator->free_array(page);
504 delete page;
505 m_pages[i] = nullptr;
506 }
507 }
509
511
512 m_initialized = false;
513 }
514
515 size_t get_row_count() {
516 size_t page_count = m_max_page_index.m_size_t.load();
517 size_t result = page_count * PFS_PAGE_SIZE;
518
519 if ((page_count > 0) && (m_last_page_size != PFS_PAGE_SIZE)) {
520 /* Bounded allocation, the last page may be incomplete. */
521 result = result - PFS_PAGE_SIZE + m_last_page_size;
522 }
523 return result;
524 }
525
526 size_t get_row_size() const { return sizeof(value_type); }
527
528 size_t get_memory() { return get_row_count() * get_row_size(); }
529
531 if (m_full.load()) {
532 m_lost++;
533 return nullptr;
534 }
535
536 size_t index;
537 size_t monotonic;
538 size_t monotonic_max;
539 size_t current_page_count;
541 array_type *array;
542
543 /*
544 1: Try to find an available record within the existing pages
545 */
546 current_page_count = m_max_page_index.m_size_t.load();
547
548 if (current_page_count != 0) {
549 monotonic = m_monotonic.m_size_t.load();
550 monotonic_max = monotonic + current_page_count;
551
552 if (unlikely(monotonic >= monotonic_max)) {
553 /*
554 This will happen once every 2^64 - current_page_count calls.
555 Computation of monotonic_max just overflowed,
556 so reset monotonic counters and start again from the beginning.
557 */
558 m_monotonic.m_size_t.store(0);
559 monotonic = 0;
560 monotonic_max = current_page_count;
561 }
562
563 while (monotonic < monotonic_max) {
564 /*
565 Scan in the [0 .. current_page_count - 1] range,
566 in parallel with m_monotonic (see below)
567 */
568 index = monotonic % current_page_count;
569
570 /* Atomic Load, array= m_pages[index] */
571 array = m_pages[index].load();
572
573 if (array != nullptr) {
574 pfs = array->allocate(dirty_state);
575 if (pfs != nullptr) {
576 /* Keep a pointer to the parent page, for deallocate(). */
577 pfs->m_page = reinterpret_cast<PFS_opaque_container_page *>(array);
578 return pfs;
579 }
580 }
581
582 /*
583 Parallel scans collaborate to increase
584 the common monotonic scan counter.
585
586 Note that when all the existing page are full,
587 one thread will eventually add a new page,
588 and cause m_max_page_index to increase,
589 which fools all the modulo logic for scans already in progress,
590 because the monotonic counter is not folded to the same place
591 (sometime modulo N, sometime modulo N+1).
592
593 This is actually ok: since all the pages are full anyway,
594 there is nothing to miss, so better increase the monotonic
595 counter faster and then move on to the detection of new pages,
596 in part 2: below.
597 */
598 monotonic = m_monotonic.m_size_t++;
599 };
600 }
601
602 /*
603 2: Try to add a new page, beyond the m_max_page_index limit
604 */
605 while (current_page_count < m_max_page_count) {
606 /* Peek for pages added by collaborating threads */
607
608 /* (2-a) Atomic Load, array= m_pages[current_page_count] */
609 array = m_pages[current_page_count].load();
610
611 if (array == nullptr) {
612 // ==================================================================
613 // BEGIN CRITICAL SECTION -- buffer expand
614 // ==================================================================
615
616 /*
617 On a fresh started server, buffers are typically empty.
618 When a sudden load spike is seen by the server,
619 multiple threads may want to expand the buffer at the same time.
620
621 Using a compare and swap to allow multiple pages to be added,
622 possibly freeing duplicate pages on collisions,
623 does not work well because the amount of code involved
624 when creating a new page can be significant (PFS_thread),
625 causing MANY collisions between (2-b) and (2-d).
626
627 A huge number of collisions (which can happen when thousands
628 of new connections hits the server after a restart)
629 leads to a huge memory consumption, and to OOM.
630
631 To mitigate this, we use here a mutex,
632 to enforce that only ONE page is added at a time,
633 so that scaling the buffer happens in a predictable
634 and controlled manner.
635 */
637
638 /*
639 Peek again for pages added by collaborating threads,
640 this time as the only thread allowed to expand the buffer
641 */
642
643 /* (2-b) Atomic Load, array= m_pages[current_page_count] */
644
645 array = m_pages[current_page_count].load();
646
647 if (array == nullptr) {
648 /* (2-c) Found no page, allocate a new one */
649 array = new array_type();
651
652 array->m_max = get_page_logical_size(current_page_count);
653
654 allocator_type *allocator = m_allocator.load();
655
656 int rc = allocator->alloc_array(array);
657 if (rc != 0) {
658 allocator->free_array(array);
659 delete array;
661 m_lost++;
663 return nullptr;
664 }
665
666 /* Keep a pointer to this container, for static_deallocate(). */
667 array->m_container = reinterpret_cast<PFS_opaque_container *>(this);
668
669 /* (2-d) Atomic STORE, m_pages[current_page_count] = array */
670 m_pages[current_page_count].store(array);
671
672 /* Advertise the new page */
674 }
675
677
678 // ==================================================================
679 // END CRITICAL SECTION -- buffer expand
680 // ==================================================================
681 }
682
683 assert(array != nullptr);
684 pfs = array->allocate(dirty_state);
685 if (pfs != nullptr) {
686 /* Keep a pointer to the parent page, for deallocate(). */
687 pfs->m_page = reinterpret_cast<PFS_opaque_container_page *>(array);
688 return pfs;
689 }
690
691 current_page_count++;
692 }
693
694 m_lost++;
695 m_full.store(true);
696 return nullptr;
697 }
698
699 void deallocate(value_type *safe_pfs) {
700 /* Find the containing page */
701 PFS_opaque_container_page *opaque_page = safe_pfs->m_page;
702 auto *page = reinterpret_cast<array_type *>(opaque_page);
703
704 /* Mark the object free */
705 safe_pfs->m_lock.allocated_to_free();
706
707 /* Flag the containing page as not full. */
708 if (page->m_full.load()) {
709 page->m_full.store(false);
710 }
711
712 /* Flag the overall container as not full. */
713 if (m_full.load()) {
714 m_full.store(false);
715 }
716 }
717
718 static void static_deallocate(value_type *safe_pfs) {
719 /* Find the containing page */
720 PFS_opaque_container_page *opaque_page = safe_pfs->m_page;
721 auto *page = reinterpret_cast<array_type *>(opaque_page);
722
723 /* Mark the object free */
724 safe_pfs->m_lock.allocated_to_free();
725
726 /* Flag the containing page as not full. */
727 if (page->m_full.load()) {
728 page->m_full.store(false);
729 }
730
731 /* Find the containing buffer */
732 PFS_opaque_container *opaque_container = page->m_container;
734 container = reinterpret_cast<container_type *>(opaque_container);
735
736 /* Flag the overall container as not full. */
737 if (container->m_full.load()) {
738 container->m_full.store(false);
739 }
740 }
741
744 this, 0);
745 }
746
748 assert(index <= m_max);
750 this, index);
751 }
752
754 uint i;
757 value_type *pfs_last;
758
759 for (i = 0; i < PFS_PAGE_COUNT; i++) {
760 page = m_pages[i];
761 if (page != nullptr) {
762 pfs = page->get_first();
763 pfs_last = page->get_last();
764
765 while (pfs < pfs_last) {
766 if (pfs->m_lock.is_populated()) {
767 fct(pfs);
768 }
769 pfs++;
770 }
771 }
772 }
773 }
774
776 uint i;
779 value_type *pfs_last;
780
781 for (i = 0; i < PFS_PAGE_COUNT; i++) {
782 page = m_pages[i];
783 if (page != nullptr) {
784 pfs = page->get_first();
785 pfs_last = page->get_last();
786
787 while (pfs < pfs_last) {
788 fct(pfs);
789 pfs++;
790 }
791 }
792 }
793 }
794
795 void apply(processor_type &proc) {
796 uint i;
799 value_type *pfs_last;
800
801 for (i = 0; i < PFS_PAGE_COUNT; i++) {
802 page = m_pages[i];
803 if (page != nullptr) {
804 pfs = page->get_first();
805 pfs_last = page->get_last();
806
807 while (pfs < pfs_last) {
808 if (pfs->m_lock.is_populated()) {
809 proc(pfs);
810 }
811 pfs++;
812 }
813 }
814 }
815 }
816
818 uint i;
821 value_type *pfs_last;
822
823 for (i = 0; i < PFS_PAGE_COUNT; i++) {
824 page = m_pages[i];
825 if (page != NULL) {
826 pfs = page->get_first();
827 pfs_last = page->get_last();
828
829 while (pfs < pfs_last) {
830 proc(pfs);
831 pfs++;
832 }
833 }
834 }
835 }
836
838 assert(index < m_max);
839
840 uint index_1 = index / PFS_PAGE_SIZE;
841 array_type *page = m_pages[index_1];
842 if (page != nullptr) {
843 uint index_2 = index % PFS_PAGE_SIZE;
844
845 if (index_2 >= page->m_max) {
846 return nullptr;
847 }
848
849 value_type *pfs = page->m_ptr + index_2;
850
851 if (pfs->m_lock.is_populated()) {
852 return pfs;
853 }
854 }
855
856 return nullptr;
857 }
858
859 value_type *get(uint index, bool *has_more) {
860 if (index >= m_max) {
861 *has_more = false;
862 return nullptr;
863 }
864
865 uint index_1 = index / PFS_PAGE_SIZE;
866 array_type *page = m_pages[index_1];
867
868 if (page == nullptr) {
869 *has_more = false;
870 return nullptr;
871 }
872
873 uint index_2 = index % PFS_PAGE_SIZE;
874
875 if (index_2 >= page->m_max) {
876 *has_more = false;
877 return nullptr;
878 }
879
880 *has_more = true;
881 value_type *pfs = page->m_ptr + index_2;
882
883 if (pfs->m_lock.is_populated()) {
884 return pfs;
885 }
886
887 return nullptr;
888 }
889
891 intptr offset;
892 uint i;
895 value_type *pfs_last;
896
897 for (i = 0; i < PFS_PAGE_COUNT; i++) {
898 page = m_pages[i];
899 if (page != nullptr) {
900 pfs = page->get_first();
901 pfs_last = page->get_last();
902
903 if ((pfs <= unsafe) && (unsafe < pfs_last)) {
904 offset = ((intptr)unsafe - (intptr)pfs) % sizeof(value_type);
905 if (offset == 0) {
906 return unsafe;
907 }
908 }
909 }
910 }
911
912 return nullptr;
913 }
914
915 ulong m_lost;
916
917 private:
919 if (page_index + 1 < m_max_page_count) {
920 return PFS_PAGE_SIZE;
921 }
922 assert(page_index + 1 == m_max_page_count);
923 return m_last_page_size;
924 }
925
926 value_type *scan_next(uint &index, uint *found_index) {
927 assert(index <= m_max);
928
929 uint index_1 = index / PFS_PAGE_SIZE;
930 uint index_2 = index % PFS_PAGE_SIZE;
932 value_type *pfs_first;
934 value_type *pfs_last;
935
936 while (index_1 < PFS_PAGE_COUNT) {
937 page = m_pages[index_1];
938
939 if (page == nullptr) {
940 index = static_cast<uint>(m_max);
941 return nullptr;
942 }
943
944 pfs_first = page->get_first();
945 pfs = pfs_first + index_2;
946 pfs_last = page->get_last();
947
948 while (pfs < pfs_last) {
949 if (pfs->m_lock.is_populated()) {
950 uint found =
951 index_1 * PFS_PAGE_SIZE + static_cast<uint>(pfs - pfs_first);
952 *found_index = found;
953 index = found + 1;
954 return pfs;
955 }
956 pfs++;
957 }
958
959 index_1++;
960 index_2 = 0;
961 }
962
963 index = static_cast<uint>(m_max);
964 return nullptr;
965 }
966
967 /**
968 Initialized full flag.
969
970 Concurrency profile:
971 - write in init / cleanup
972 - readonly during normal operations
973 */
974 std::atomic<bool> m_initialized{false};
975
976 /**
977 Buffer full flag.
978
979 Concurrency profile:
980 - mostly read during normal operations.
981 - do not perform useless write,
982 check for previous value first
983 - occasional write on state changes
984 */
985 std::atomic<bool> m_full{false};
986
987 /**
988 Max number of items in the buffer.
989
990 Concurrency profile:
991 - written once on page creation
992 - read only during normal operations.
993 */
994 std::atomic<size_t> m_max{0};
995
996 /**
997 Monotonic page counter.
998 This counter is used to access pages in the array.
999
1000 Concurrency profile:
1001 - frequent read and write, must be on its own cacheline
1002 */
1004
1005 /**
1006 Current page index.
1007
1008 Concurrency profile:
1009 - occasional write on buffer extend
1010 - mostly read otherwise
1011 */
1013
1014 /**
1015 Max number of pages.
1016
1017 Concurrency profile:
1018 - written once on buffer creation
1019 - read only during normal operations.
1020 */
1021 std::atomic<size_t> m_max_page_count{0};
1022
1023 /**
1024 Size of the last page.
1025
1026 Concurrency profile:
1027 - written once on buffer creation
1028 - read only during normal operations.
1029 */
1030 std::atomic<size_t> m_last_page_size{0};
1031
1032 /**
1033 Array of pages.
1034
1035 Concurrency profile:
1036 - occasional write on buffer extend
1037 - mostly read otherwise
1038 */
1039 std::atomic<array_type *> m_pages[PFS_PAGE_COUNT];
1040
1041 /**
1042 Buffer allocator.
1043
1044 Concurrency profile:
1045 - written once on buffer creation
1046 - read only during normal operations.
1047 */
1048 std::atomic<allocator_type *> m_allocator{nullptr};
1049
1051};
1052
1053template <class T, class U, class V>
1055 friend class PFS_buffer_container<T, U, V>;
1056
1057 typedef T value_type;
1059
1060 public:
1062 uint unused;
1063 return m_container->scan_next(m_index, &unused);
1064 }
1065
1066 value_type *scan_next(uint *found_index) {
1067 return m_container->scan_next(m_index, found_index);
1068 }
1069
1070 private:
1072 : m_container(container), m_index(index) {}
1073
1076};
1077
1078template <class T, int page_size, int page_count, class U, class V>
1080 friend class PFS_buffer_scalable_container<T, page_size, page_count, U, V>;
1081
1082 typedef T value_type;
1085
1086 public:
1088 uint unused;
1089 return m_container->scan_next(m_index, &unused);
1090 }
1091
1092 value_type *scan_next(uint *found_index) {
1093 return m_container->scan_next(m_index, found_index);
1094 }
1095
1096 private:
1098 : m_container(container), m_index(index) {}
1099
1102};
1103
1104template <class T>
1106 public:
1107 virtual ~PFS_buffer_processor() = default;
1108 virtual void operator()(T *element) = 0;
1109};
1110
1111template <class B, int PFS_PARTITION_COUNT>
1113 public:
1114 friend class PFS_partitioned_buffer_scalable_iterator<B, PFS_PARTITION_COUNT>;
1115
1116 typedef typename B::value_type value_type;
1117 typedef typename B::allocator_type allocator_type;
1120 typedef typename B::iterator_type sub_iterator_type;
1121 typedef typename B::processor_type processor_type;
1122 typedef typename B::function_type function_type;
1123
1125 allocator_type *allocator) {
1126 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1127 m_partitions[i] = new B(allocator);
1128 }
1129 }
1130
1132 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1133 delete m_partitions[i];
1134 }
1135 }
1136
1137 int init(long max_size) {
1138 int rc = 0;
1139 // FIXME: we have max_size * PFS_PARTITION_COUNT here
1140 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1141 rc |= m_partitions[i]->init(max_size);
1142 }
1143 return rc;
1144 }
1145
1146 void cleanup() {
1147 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1148 m_partitions[i]->cleanup();
1149 }
1150 }
1151
1152 size_t get_row_count() const {
1153 size_t sum = 0;
1154
1155 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1156 sum += m_partitions[i]->get_row_count();
1157 }
1158
1159 return sum;
1160 }
1161
1162 size_t get_row_size() const { return sizeof(value_type); }
1163
1164 size_t get_memory() const {
1165 size_t sum = 0;
1166
1167 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1168 sum += m_partitions[i]->get_memory();
1169 }
1170
1171 return sum;
1172 }
1173
1175 long sum = 0;
1176
1177 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1178 sum += m_partitions[i]->m_lost;
1179 }
1180
1181 return sum;
1182 }
1183
1184 value_type *allocate(pfs_dirty_state *dirty_state, uint partition) {
1185 assert(partition < PFS_PARTITION_COUNT);
1186
1187 return m_partitions[partition]->allocate(dirty_state);
1188 }
1189
1190 void deallocate(value_type *safe_pfs) {
1191 /*
1192 One issue here is that we do not know which partition
1193 the record belongs to.
1194 Each record points to the parent page,
1195 and each page points to the parent buffer,
1196 so using static_deallocate here,
1197 which will find the correct partition by itself.
1198 */
1199 B::static_deallocate(safe_pfs);
1200 }
1201
1202 iterator_type iterate() { return iterator_type(this, 0, 0); }
1203
1205 uint partition_index;
1206 uint sub_index;
1207 unpack_index(user_index, &partition_index, &sub_index);
1208 return iterator_type(this, partition_index, sub_index);
1209 }
1210
1212 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1213 m_partitions[i]->apply(fct);
1214 }
1215 }
1216
1218 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1219 m_partitions[i]->apply_all(fct);
1220 }
1221 }
1222
1223 void apply(processor_type &proc) {
1224 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1225 m_partitions[i]->apply(proc);
1226 }
1227 }
1228
1230 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1231 m_partitions[i]->apply_all(proc);
1232 }
1233 }
1234
1235 value_type *get(uint user_index) {
1236 uint partition_index;
1237 uint sub_index;
1238 unpack_index(user_index, &partition_index, &sub_index);
1239
1240 if (partition_index >= PFS_PARTITION_COUNT) {
1241 return nullptr;
1242 }
1243
1244 return m_partitions[partition_index]->get(sub_index);
1245 }
1246
1247 value_type *get(uint user_index, bool *has_more) {
1248 uint partition_index;
1249 uint sub_index;
1250 unpack_index(user_index, &partition_index, &sub_index);
1251
1252 if (partition_index >= PFS_PARTITION_COUNT) {
1253 *has_more = false;
1254 return NULL;
1255 }
1256
1257 *has_more = true;
1258 return m_partitions[partition_index]->get(sub_index);
1259 }
1260
1262 value_type *safe = nullptr;
1263
1264 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1265 safe = m_partitions[i]->sanitize(unsafe);
1266 if (safe != nullptr) {
1267 return safe;
1268 }
1269 }
1270
1271 return safe;
1272 }
1273
1274 private:
1275 static void pack_index(uint partition_index, uint sub_index,
1276 uint *user_index) {
1277 static_assert(PFS_PARTITION_COUNT <= (1 << 8), "2^8 = 256 partitions max.");
1278 static_assert((B::MAX_SIZE) <= (1 << 24),
1279 "2^24 = 16777216 max per partitioned buffer.");
1280
1281 *user_index = (partition_index << 24) + sub_index;
1282 }
1283
1284 static void unpack_index(uint user_index, uint *partition_index,
1285 uint *sub_index) {
1286 *partition_index = user_index >> 24;
1287 *sub_index = user_index & 0x00FFFFFF;
1288 }
1289
1290 value_type *scan_next(uint &partition_index, uint &sub_index,
1291 uint *found_partition, uint *found_sub_index) {
1292 value_type *record = nullptr;
1293 assert(partition_index < PFS_PARTITION_COUNT);
1294
1295 while (partition_index < PFS_PARTITION_COUNT) {
1296 sub_iterator_type sub_iterator =
1297 m_partitions[partition_index]->iterate(sub_index);
1298 record = sub_iterator.scan_next(found_sub_index);
1299 if (record != nullptr) {
1300 *found_partition = partition_index;
1301 sub_index = *found_sub_index + 1;
1302 return record;
1303 }
1304
1305 partition_index++;
1306 sub_index = 0;
1307 }
1308
1309 *found_partition = PFS_PARTITION_COUNT;
1310 *found_sub_index = 0;
1311 sub_index = 0;
1312 return nullptr;
1313 }
1314
1315 B *m_partitions[PFS_PARTITION_COUNT];
1316};
1317
1318template <class B, int PFS_PARTITION_COUNT>
1320 public:
1322 PFS_PARTITION_COUNT>;
1323
1324 typedef typename B::value_type value_type;
1327
1329 uint unused_partition;
1330 uint unused_sub_index;
1331 return m_container->scan_next(m_partition, m_sub_index, &unused_partition,
1332 &unused_sub_index);
1333 }
1334
1335 value_type *scan_next(uint *found_user_index) {
1336 uint found_partition;
1337 uint found_sub_index;
1339 record = m_container->scan_next(m_partition, m_sub_index, &found_partition,
1340 &found_sub_index);
1341 container_type::pack_index(found_partition, found_sub_index,
1342 found_user_index);
1343 return record;
1344 }
1345
1346 private:
1348 uint partition, uint sub_index)
1350 m_partition(partition),
1351 m_sub_index(sub_index) {}
1352
1356};
1357
1358#ifdef USE_SCALABLE
1364#else
1366#endif
1369
1370#ifdef USE_SCALABLE
1373#else
1375#endif
1378
1379#ifdef USE_SCALABLE
1381#else
1383#endif
1386
1387#ifdef USE_SCALABLE
1390#else
1392#endif
1395
1396#ifdef USE_SCALABLE
1399#else
1401#endif
1404
1405#ifdef USE_SCALABLE
1408#else
1410#endif
1413
1414#ifdef USE_SCALABLE
1417#else
1419#endif
1422
1423#ifdef USE_SCALABLE
1426#else
1428#endif
1431
1432#ifdef USE_SCALABLE
1435#else
1437#endif
1440
1441#ifdef USE_SCALABLE
1444#else
1446#endif
1449
1450#ifdef USE_SCALABLE
1453#else
1456#endif
1460
1461#ifdef USE_SCALABLE
1464#else
1467#endif
1471
1472#ifdef USE_SCALABLE
1475#else
1477#endif
1480
1481#ifdef USE_SCALABLE
1484#else
1486#endif
1489
1490class PFS_account_array : public PFS_buffer_default_array<PFS_account> {
1491 public:
1498};
1499
1501 public:
1502 int alloc_array(PFS_account_array *array);
1503 void free_array(PFS_account_array *array);
1504};
1505
1506#ifdef USE_SCALABLE
1510#else
1514#endif
1517
1519 public:
1526};
1527
1529 public:
1530 int alloc_array(PFS_host_array *array);
1531 void free_array(PFS_host_array *array);
1532};
1533
1534#ifdef USE_SCALABLE
1538#else
1541#endif
1544
1545class PFS_thread_array : public PFS_buffer_default_array<PFS_thread> {
1546 public:
1553
1560
1565};
1566
1568 public:
1569 int alloc_array(PFS_thread_array *array);
1570 void free_array(PFS_thread_array *array);
1571};
1572
1573#ifdef USE_SCALABLE
1577#else
1580#endif
1583
1585 public:
1592};
1593
1595 public:
1596 int alloc_array(PFS_user_array *array);
1597 void free_array(PFS_user_array *array);
1598};
1599
1600#ifdef USE_SCALABLE
1604#else
1607#endif
1610
1611#endif
Definition: pfs_buffer_container.h:1500
void free_array(PFS_account_array *array)
Definition: pfs_buffer_container.cc:235
int alloc_array(PFS_account_array *array)
Definition: pfs_buffer_container.cc:102
Definition: pfs_buffer_container.h:1490
PFS_stage_stat * m_instr_class_stages_array
Definition: pfs_buffer_container.h:1493
PFS_memory_shared_stat * m_instr_class_memory_array
Definition: pfs_buffer_container.h:1497
PFS_error_stat * m_instr_class_errors_array
Definition: pfs_buffer_container.h:1496
PFS_single_stat * m_instr_class_waits_array
Definition: pfs_buffer_container.h:1492
PFS_transaction_stat * m_instr_class_transactions_array
Definition: pfs_buffer_container.h:1495
PFS_statement_stat * m_instr_class_statements_array
Definition: pfs_buffer_container.h:1494
Definition: pfs_buffer_container.h:57
Definition: pfs_buffer_container.h:231
PFS_buffer_processor< T > processor_type
Definition: pfs_buffer_container.h:240
void apply(function_type fct)
Definition: pfs_buffer_container.h:295
void cleanup()
Definition: pfs_buffer_container.h:267
size_t get_memory() const
Definition: pfs_buffer_container.h:273
size_t get_row_count() const
Definition: pfs_buffer_container.h:269
size_t m_max
Definition: pfs_buffer_container.h:399
value_type * get(uint index)
Definition: pfs_buffer_container.h:339
size_t get_row_size() const
Definition: pfs_buffer_container.h:271
U array_type
Definition: pfs_buffer_container.h:236
int init(size_t max_size)
Definition: pfs_buffer_container.h:253
void apply(processor_type &proc)
Definition: pfs_buffer_container.h:317
value_type * get(uint index, bool *has_more)
Definition: pfs_buffer_container.h:350
PFS_buffer_const_iterator< T > const_iterator_type
Definition: pfs_buffer_container.h:238
void apply_all(function_type fct)
Definition: pfs_buffer_container.h:307
void(* function_type)(value_type *)
Definition: pfs_buffer_container.h:241
iterator_type iterate()
Definition: pfs_buffer_container.h:288
ulong m_lost
Definition: pfs_buffer_container.h:375
value_type * allocate(pfs_dirty_state *dirty_state)
Definition: pfs_buffer_container.h:275
void apply_all(processor_type &proc)
Definition: pfs_buffer_container.h:329
value_type * sanitize(value_type *unsafe)
Definition: pfs_buffer_container.h:360
V allocator_type
Definition: pfs_buffer_container.h:237
PFS_buffer_container(allocator_type *allocator)
Definition: pfs_buffer_container.h:243
PFS_buffer_iterator< T, U, V > iterator_type
Definition: pfs_buffer_container.h:239
void deallocate(value_type *pfs)
Definition: pfs_buffer_container.h:286
iterator_type iterate(uint index)
Definition: pfs_buffer_container.h:290
friend class PFS_buffer_iterator< T, U, V >
Definition: pfs_buffer_container.h:233
value_type * scan_next(uint &index, uint *found_index)
Definition: pfs_buffer_container.h:378
allocator_type * m_allocator
Definition: pfs_buffer_container.h:401
array_type m_array
Definition: pfs_buffer_container.h:400
T value_type
Definition: pfs_buffer_container.h:235
Definition: pfs_buffer_container.h:195
PFS_buffer_default_array< T > array_type
Definition: pfs_buffer_container.h:197
PFS_buffer_default_allocator(PFS_builtin_memory_class *klass)
Definition: pfs_buffer_container.h:199
int alloc_array(array_type *array)
Definition: pfs_buffer_container.h:202
void free_array(array_type *array)
Definition: pfs_buffer_container.h:218
PFS_builtin_memory_class * m_builtin_class
Definition: pfs_buffer_container.h:226
Definition: pfs_buffer_container.h:87
std::atomic< bool > m_full
Page full flag.
Definition: pfs_buffer_container.h:155
T * get_last()
Definition: pfs_buffer_container.h:144
std::atomic< T * > m_ptr
Array of values.
Definition: pfs_buffer_container.h:173
PFS_cacheline_atomic_size_t m_monotonic
Monotonic counter.
Definition: pfs_buffer_container.h:164
std::atomic< PFS_opaque_container * > m_container
Container.
Definition: pfs_buffer_container.h:191
std::atomic< size_t > m_max
Max number of items in the page.
Definition: pfs_buffer_container.h:182
value_type * allocate(pfs_dirty_state *dirty_state)
Definition: pfs_buffer_container.h:91
T value_type
Definition: pfs_buffer_container.h:89
T * get_first()
Definition: pfs_buffer_container.h:142
void deallocate(value_type *pfs)
Definition: pfs_buffer_container.h:134
Definition: pfs_buffer_container.h:1054
T value_type
Definition: pfs_buffer_container.h:1057
PFS_buffer_container< T, U, V > container_type
Definition: pfs_buffer_container.h:1058
container_type * m_container
Definition: pfs_buffer_container.h:1074
value_type * scan_next()
Definition: pfs_buffer_container.h:1061
value_type * scan_next(uint *found_index)
Definition: pfs_buffer_container.h:1066
PFS_buffer_iterator(container_type *container, uint index)
Definition: pfs_buffer_container.h:1071
uint m_index
Definition: pfs_buffer_container.h:1075
Definition: pfs_buffer_container.h:1105
virtual void operator()(T *element)=0
virtual ~PFS_buffer_processor()=default
Definition: pfs_buffer_container.h:407
void(* function_type)(value_type *)
Definition: pfs_buffer_container.h:433
static const size_t MAX_SIZE
Definition: pfs_buffer_container.h:435
int init(long max_size)
Definition: pfs_buffer_container.h:442
size_t get_row_size() const
Definition: pfs_buffer_container.h:526
std::atomic< size_t > m_last_page_size
Size of the last page.
Definition: pfs_buffer_container.h:1030
friend class PFS_buffer_scalable_iterator< T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U, V >
Definition: pfs_buffer_container.h:410
void apply(processor_type &proc)
Definition: pfs_buffer_container.h:795
void apply_all(function_type fct)
Definition: pfs_buffer_container.h:775
void apply_all(processor_type &proc)
Definition: pfs_buffer_container.h:817
PFS_buffer_scalable_container< T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U, V > container_type
This container type.
Definition: pfs_buffer_container.h:428
value_type * sanitize(value_type *unsafe)
Definition: pfs_buffer_container.h:890
PFS_buffer_scalable_iterator< T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U, V > iterator_type
Definition: pfs_buffer_container.h:431
value_type * allocate(pfs_dirty_state *dirty_state)
Definition: pfs_buffer_container.h:530
native_mutex_t m_critical_section
Definition: pfs_buffer_container.h:1050
std::atomic< size_t > m_max
Max number of items in the buffer.
Definition: pfs_buffer_container.h:994
PFS_cacheline_atomic_size_t m_max_page_index
Current page index.
Definition: pfs_buffer_container.h:1012
size_t get_memory()
Definition: pfs_buffer_container.h:528
iterator_type iterate()
Definition: pfs_buffer_container.h:742
uint get_page_logical_size(uint page_index)
Definition: pfs_buffer_container.h:918
void apply(function_type fct)
Definition: pfs_buffer_container.h:753
iterator_type iterate(uint index)
Definition: pfs_buffer_container.h:747
V allocator_type
Definition: pfs_buffer_container.h:425
U array_type
Type of pages in the buffer.
Definition: pfs_buffer_container.h:424
PFS_buffer_processor< T > processor_type
Definition: pfs_buffer_container.h:432
value_type * get(uint index, bool *has_more)
Definition: pfs_buffer_container.h:859
PFS_cacheline_atomic_size_t m_monotonic
Monotonic page counter.
Definition: pfs_buffer_container.h:1003
std::atomic< size_t > m_max_page_count
Max number of pages.
Definition: pfs_buffer_container.h:1021
void cleanup()
Definition: pfs_buffer_container.h:488
size_t get_row_count()
Definition: pfs_buffer_container.h:515
std::atomic< bool > m_initialized
Initialized full flag.
Definition: pfs_buffer_container.h:974
PFS_buffer_const_iterator< T > const_iterator_type
Definition: pfs_buffer_container.h:429
value_type * get(uint index)
Definition: pfs_buffer_container.h:837
static void static_deallocate(value_type *safe_pfs)
Definition: pfs_buffer_container.h:718
std::atomic< bool > m_full
Buffer full flag.
Definition: pfs_buffer_container.h:985
T value_type
Type of elements in the buffer.
Definition: pfs_buffer_container.h:418
PFS_buffer_scalable_container(allocator_type *allocator)
Definition: pfs_buffer_container.h:437
value_type * scan_next(uint &index, uint *found_index)
Definition: pfs_buffer_container.h:926
std::atomic< allocator_type * > m_allocator
Buffer allocator.
Definition: pfs_buffer_container.h:1048
void deallocate(value_type *safe_pfs)
Definition: pfs_buffer_container.h:699
ulong m_lost
Definition: pfs_buffer_container.h:915
std::atomic< array_type * > m_pages[PFS_PAGE_COUNT]
Array of pages.
Definition: pfs_buffer_container.h:1039
Definition: pfs_buffer_container.h:1079
T value_type
Definition: pfs_buffer_container.h:1082
uint m_index
Definition: pfs_buffer_container.h:1101
value_type * scan_next(uint *found_index)
Definition: pfs_buffer_container.h:1092
value_type * scan_next()
Definition: pfs_buffer_container.h:1087
PFS_buffer_scalable_container< T, page_size, page_count, U, V > container_type
Definition: pfs_buffer_container.h:1084
PFS_buffer_scalable_iterator(container_type *container, uint index)
Definition: pfs_buffer_container.h:1097
container_type * m_container
Definition: pfs_buffer_container.h:1100
Definition: pfs_buffer_container.h:1528
int alloc_array(PFS_host_array *array)
Definition: pfs_buffer_container.cc:285
void free_array(PFS_host_array *array)
Definition: pfs_buffer_container.cc:418
Definition: pfs_buffer_container.h:1518
PFS_transaction_stat * m_instr_class_transactions_array
Definition: pfs_buffer_container.h:1523
PFS_memory_shared_stat * m_instr_class_memory_array
Definition: pfs_buffer_container.h:1525
PFS_error_stat * m_instr_class_errors_array
Definition: pfs_buffer_container.h:1524
PFS_single_stat * m_instr_class_waits_array
Definition: pfs_buffer_container.h:1520
PFS_stage_stat * m_instr_class_stages_array
Definition: pfs_buffer_container.h:1521
PFS_statement_stat * m_instr_class_statements_array
Definition: pfs_buffer_container.h:1522
Definition: pfs_buffer_container.h:1112
B::function_type function_type
Definition: pfs_buffer_container.h:1122
value_type * get(uint user_index, bool *has_more)
Definition: pfs_buffer_container.h:1247
B::allocator_type allocator_type
Definition: pfs_buffer_container.h:1117
void apply(processor_type &proc)
Definition: pfs_buffer_container.h:1223
void apply(function_type fct)
Definition: pfs_buffer_container.h:1211
B * m_partitions[PFS_PARTITION_COUNT]
Definition: pfs_buffer_container.h:1315
value_type * scan_next(uint &partition_index, uint &sub_index, uint *found_partition, uint *found_sub_index)
Definition: pfs_buffer_container.h:1290
iterator_type iterate()
Definition: pfs_buffer_container.h:1202
PFS_partitioned_buffer_scalable_iterator< B, PFS_PARTITION_COUNT > iterator_type
Definition: pfs_buffer_container.h:1119
size_t get_row_count() const
Definition: pfs_buffer_container.h:1152
void apply_all(function_type fct)
Definition: pfs_buffer_container.h:1217
value_type * sanitize(value_type *unsafe)
Definition: pfs_buffer_container.h:1261
B::value_type value_type
Definition: pfs_buffer_container.h:1116
static void unpack_index(uint user_index, uint *partition_index, uint *sub_index)
Definition: pfs_buffer_container.h:1284
PFS_partitioned_buffer_scalable_container(allocator_type *allocator)
Definition: pfs_buffer_container.h:1124
void deallocate(value_type *safe_pfs)
Definition: pfs_buffer_container.h:1190
int init(long max_size)
Definition: pfs_buffer_container.h:1137
~PFS_partitioned_buffer_scalable_container()
Definition: pfs_buffer_container.h:1131
B::iterator_type sub_iterator_type
Definition: pfs_buffer_container.h:1120
size_t get_memory() const
Definition: pfs_buffer_container.h:1164
iterator_type iterate(uint user_index)
Definition: pfs_buffer_container.h:1204
size_t get_row_size() const
Definition: pfs_buffer_container.h:1162
B::processor_type processor_type
Definition: pfs_buffer_container.h:1121
void apply_all(processor_type &proc)
Definition: pfs_buffer_container.h:1229
value_type * get(uint user_index)
Definition: pfs_buffer_container.h:1235
value_type * allocate(pfs_dirty_state *dirty_state, uint partition)
Definition: pfs_buffer_container.h:1184
void cleanup()
Definition: pfs_buffer_container.h:1146
long get_lost_counter()
Definition: pfs_buffer_container.h:1174
static void pack_index(uint partition_index, uint sub_index, uint *user_index)
Definition: pfs_buffer_container.h:1275
Definition: pfs_buffer_container.h:1319
uint m_sub_index
Definition: pfs_buffer_container.h:1355
PFS_partitioned_buffer_scalable_container< B, PFS_PARTITION_COUNT > container_type
Definition: pfs_buffer_container.h:1326
container_type * m_container
Definition: pfs_buffer_container.h:1353
B::value_type value_type
Definition: pfs_buffer_container.h:1324
value_type * scan_next(uint *found_user_index)
Definition: pfs_buffer_container.h:1335
value_type * scan_next()
Definition: pfs_buffer_container.h:1328
PFS_partitioned_buffer_scalable_iterator(container_type *container, uint partition, uint sub_index)
Definition: pfs_buffer_container.h:1347
uint m_partition
Definition: pfs_buffer_container.h:1354
Definition: pfs_buffer_container.h:1567
void free_array(PFS_thread_array *array)
Definition: pfs_buffer_container.cc:766
int alloc_array(PFS_thread_array *array)
Definition: pfs_buffer_container.cc:467
Definition: pfs_buffer_container.h:1545
PFS_statement_stat * m_instr_class_statements_array
Definition: pfs_buffer_container.h:1549
PFS_single_stat * m_instr_class_waits_array
Definition: pfs_buffer_container.h:1547
PFS_error_stat * m_instr_class_errors_array
Definition: pfs_buffer_container.h:1551
PFS_events_statements * m_statements_stack_array
Definition: pfs_buffer_container.h:1557
PFS_events_statements * m_statements_history_array
Definition: pfs_buffer_container.h:1556
PFS_stage_stat * m_instr_class_stages_array
Definition: pfs_buffer_container.h:1548
unsigned char * m_current_stmts_digest_token_array
Definition: pfs_buffer_container.h:1563
PFS_events_stages * m_stages_history_array
Definition: pfs_buffer_container.h:1555
char * m_current_stmts_text_array
Definition: pfs_buffer_container.h:1561
PFS_memory_safe_stat * m_instr_class_memory_array
Definition: pfs_buffer_container.h:1552
unsigned char * m_history_stmts_digest_token_array
Definition: pfs_buffer_container.h:1564
PFS_transaction_stat * m_instr_class_transactions_array
Definition: pfs_buffer_container.h:1550
char * m_session_connect_attrs_array
Definition: pfs_buffer_container.h:1559
PFS_events_waits * m_waits_history_array
Definition: pfs_buffer_container.h:1554
PFS_events_transactions * m_transactions_history_array
Definition: pfs_buffer_container.h:1558
char * m_history_stmts_text_array
Definition: pfs_buffer_container.h:1562
Definition: pfs_buffer_container.h:1594
void free_array(PFS_user_array *array)
Definition: pfs_buffer_container.cc:1013
int alloc_array(PFS_user_array *array)
Definition: pfs_buffer_container.cc:880
Definition: pfs_buffer_container.h:1584
PFS_statement_stat * m_instr_class_statements_array
Definition: pfs_buffer_container.h:1588
PFS_transaction_stat * m_instr_class_transactions_array
Definition: pfs_buffer_container.h:1589
PFS_stage_stat * m_instr_class_stages_array
Definition: pfs_buffer_container.h:1587
PFS_single_stat * m_instr_class_waits_array
Definition: pfs_buffer_container.h:1586
PFS_error_stat * m_instr_class_errors_array
Definition: pfs_buffer_container.h:1590
PFS_memory_shared_stat * m_instr_class_memory_array
Definition: pfs_buffer_container.h:1591
int page
Definition: ctype-mb.cc:1236
#define MY_ZEROFILL
Definition: my_sys.h:136
#define PFS_MUTEX_PARTITIONS
Definition: pfs_instr_class.h:319
constexpr bool unlikely(bool expr)
Definition: my_compiler.h:56
Some integer typedefs for easier portability.
intptr_t intptr
Definition: my_inttypes.h:70
#define MYF(v)
Definition: my_inttypes.h:97
static int record
Definition: mysqltest.cc:188
uint16_t value_type
Definition: vt100.h:184
Definition: atomics_array.h:39
const ulint MAX_SIZE
The maximum size possible for an LOB.
Definition: lob0lob.h:84
Performance schema account (declarations).
PFS_file_container global_file_container
PFS_buffer_scalable_container< PFS_mutex, 1024, 1024 > PFS_mutex_basic_container
Definition: pfs_buffer_container.h:1360
PFS_host_container global_host_container
PFS_buffer_scalable_container< PFS_socket, 256, 256 > PFS_socket_container
Definition: pfs_buffer_container.h:1398
PFS_thread_container global_thread_container
PFS_table_share_index_container global_table_share_index_container
PFS_cond_container::iterator_type PFS_cond_iterator
Definition: pfs_buffer_container.h:1384
PFS_buffer_scalable_container< PFS_table, 1024, 1024 > PFS_table_container
Definition: pfs_buffer_container.h:1434
PFS_file_container::iterator_type PFS_file_iterator
Definition: pfs_buffer_container.h:1393
PFS_user_container::iterator_type PFS_user_iterator
Definition: pfs_buffer_container.h:1608
PFS_mutex_container::iterator_type PFS_mutex_iterator
Definition: pfs_buffer_container.h:1367
PFS_prepared_stmt_container::iterator_type PFS_prepared_stmt_iterator
Definition: pfs_buffer_container.h:1487
PFS_buffer_scalable_container< PFS_table_share, 4 *1024, 4 *1024 > PFS_table_share_container
Definition: pfs_buffer_container.h:1443
PFS_setup_object_container::iterator_type PFS_setup_object_iterator
Definition: pfs_buffer_container.h:1429
PFS_cond_container global_cond_container
PFS_buffer_scalable_container< PFS_prepared_stmt, 1024, 1024 > PFS_prepared_stmt_container
Definition: pfs_buffer_container.h:1483
PFS_buffer_scalable_container< PFS_table_share_lock, 4 *1024, 4 *1024 > PFS_table_share_lock_container
Definition: pfs_buffer_container.h:1463
PFS_socket_container::iterator_type PFS_socket_iterator
Definition: pfs_buffer_container.h:1402
PFS_table_share_container global_table_share_container
PFS_rwlock_container::iterator_type PFS_rwlock_iterator
Definition: pfs_buffer_container.h:1376
PFS_program_container global_program_container
PFS_buffer_scalable_container< PFS_thread, 256, 256, PFS_thread_array, PFS_thread_allocator > PFS_thread_container
Definition: pfs_buffer_container.h:1576
PFS_host_container::iterator_type PFS_host_iterator
Definition: pfs_buffer_container.h:1542
PFS_socket_container global_socket_container
PFS_partitioned_buffer_scalable_container< PFS_mutex_basic_container, PFS_MUTEX_PARTITIONS > PFS_mutex_container
Definition: pfs_buffer_container.h:1363
PFS_table_share_lock_container::iterator_type PFS_table_share_lock_iterator
Definition: pfs_buffer_container.h:1469
PFS_buffer_scalable_container< PFS_program, 1024, 1024 > PFS_program_container
Definition: pfs_buffer_container.h:1474
PFS_account_container::iterator_type PFS_account_iterator
Definition: pfs_buffer_container.h:1515
PFS_buffer_scalable_container< PFS_file, 4 *1024, 4 *1024 > PFS_file_container
Definition: pfs_buffer_container.h:1389
PFS_setup_object_container global_setup_object_container
PFS_table_share_index_container::iterator_type PFS_table_share_index_iterator
Definition: pfs_buffer_container.h:1458
PFS_mdl_container global_mdl_container
PFS_buffer_scalable_container< PFS_setup_actor, 128, 1024 > PFS_setup_actor_container
Definition: pfs_buffer_container.h:1416
PFS_rwlock_container global_rwlock_container
PFS_thread_container::iterator_type PFS_thread_iterator
Definition: pfs_buffer_container.h:1581
PFS_mdl_container::iterator_type PFS_mdl_iterator
Definition: pfs_buffer_container.h:1411
PFS_table_share_lock_container global_table_share_lock_container
PFS_table_container global_table_container
PFS_table_container::iterator_type PFS_table_iterator
Definition: pfs_buffer_container.h:1438
PFS_buffer_scalable_container< PFS_host, 128, 128, PFS_host_array, PFS_host_allocator > PFS_host_container
Definition: pfs_buffer_container.h:1537
PFS_account_container global_account_container
PFS_buffer_scalable_container< PFS_cond, 256, 256 > PFS_cond_container
Definition: pfs_buffer_container.h:1380
PFS_setup_actor_container::iterator_type PFS_setup_actor_iterator
Definition: pfs_buffer_container.h:1420
PFS_program_container::iterator_type PFS_program_iterator
Definition: pfs_buffer_container.h:1478
PFS_prepared_stmt_container global_prepared_stmt_container
PFS_buffer_scalable_container< PFS_user, 128, 128, PFS_user_array, PFS_user_allocator > PFS_user_container
Definition: pfs_buffer_container.h:1603
PFS_buffer_scalable_container< PFS_table_share_index, 8 *1024, 8 *1024 > PFS_table_share_index_container
Definition: pfs_buffer_container.h:1452
PFS_buffer_scalable_container< PFS_setup_object, 128, 1024 > PFS_setup_object_container
Definition: pfs_buffer_container.h:1425
PFS_table_share_container::iterator_type PFS_table_share_iterator
Definition: pfs_buffer_container.h:1447
PFS_setup_actor_container global_setup_actor_container
PFS_mutex_container global_mutex_container
PFS_buffer_scalable_container< PFS_metadata_lock, 1024, 1024 > PFS_mdl_container
Definition: pfs_buffer_container.h:1407
PFS_buffer_scalable_container< PFS_rwlock, 1024, 1024 > PFS_rwlock_container
Definition: pfs_buffer_container.h:1372
PFS_user_container global_user_container
PFS_buffer_scalable_container< PFS_account, 128, 128, PFS_account_array, PFS_account_allocator > PFS_account_container
Definition: pfs_buffer_container.h:1509
PFS_builtin_memory_class builtin_memory_scalable_buffer
Definition: pfs_builtin_memory.cc:123
Performance schema instruments metadata (declarations).
#define PFS_MALLOC_ARRAY(k, n, s, T, f)
Helper, to allocate an array of structures.
Definition: pfs_global.h:135
#define PFS_FREE_ARRAY(k, n, s, p)
Helper, to free an array of structures.
Definition: pfs_global.h:152
Performance schema host (declarations).
Performance schema instruments (declarations).
Performance schema internal locks (declarations).
Stored Program data structures (declarations).
Stored Program data structures (declarations).
Performance schema setup actors (declarations).
Performance schema setup object (declarations).
Performance schema user (declarations).
struct result result
Definition: result.h:34
static const LEX_CSTRING pfs
Definition: sql_show_processlist.cc:66
Per account statistics.
Definition: pfs_account.h:67
Definition: pfs_builtin_memory.h:39
void count_alloc(size_t size)
Definition: pfs_builtin_memory.h:43
void count_free(size_t size)
Definition: pfs_builtin_memory.h:45
An atomic size_t variable, guaranteed to be alone in a CPU cache line.
Definition: pfs_global.h:99
std::atomic< size_t > m_size_t
Definition: pfs_global.h:100
Statistics for all server errors.
Definition: pfs_stat.h:557
A stage record.
Definition: pfs_events_stages.h:45
A statement record.
Definition: pfs_events_statements.h:47
A transaction record.
Definition: pfs_events_transactions.h:85
A wait event record.
Definition: pfs_events_waits.h:69
Per host statistics.
Definition: pfs_host.h:64
Memory statistics.
Definition: pfs_stat.h:913
Definition: pfs_stat.h:937
Single statistic.
Definition: pfs_stat.h:52
Statistics for stage usage.
Definition: pfs_stat.h:323
Statistics for statement usage.
Definition: pfs_stat.h:376
Instrumented thread implementation.
Definition: pfs_instr.h:373
Statistics for transaction usage.
Definition: pfs_stat.h:459
Per user statistics.
Definition: pfs_user.h:63
Definition: pfs_lock.h:77
Definition: result.h:30
static int native_mutex_unlock(native_mutex_t *mutex)
Definition: thr_mutex.h:115
static int native_mutex_destroy(native_mutex_t *mutex)
Definition: thr_mutex.h:124
static int native_mutex_lock(native_mutex_t *mutex)
Definition: thr_mutex.h:90
static int native_mutex_init(native_mutex_t *mutex, const native_mutexattr_t *attr)
Definition: thr_mutex.h:79
pthread_mutex_t native_mutex_t
Definition: thr_mutex_bits.h:55
#define NULL
Definition: types.h:55
unsigned int uint
Definition: uca9-dump.cc:75
Definition: dtoa.cc:594