MySQL 9.1.0
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 const 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 == nullptr) {
280 m_lost++;
281 }
282
283 return pfs;
284 }
285
286 void deallocate(value_type *pfs) { m_array.deallocate(pfs); }
287
289
290 iterator_type iterate(uint index) {
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 nullptr;
348 }
349
350 value_type *get(uint index, bool *has_more) {
351 if (index >= m_max) {
352 *has_more = false;
353 return nullptr;
354 }
355
356 *has_more = true;
357 return get(index);
358 }
359
361 value_type *pfs = m_array.get_first();
362 value_type *pfs_last = m_array.get_last();
363
364 if ((pfs <= unsafe) && (unsafe < pfs_last)) {
365 const intptr offset = ((intptr)unsafe - (intptr)pfs) % sizeof(value_type);
366 if (offset == 0) {
367 return unsafe;
368 }
369 }
370
371 return nullptr;
372 }
373
374 ulong m_lost;
375
376 private:
377 value_type *scan_next(uint &index, uint *found_index) {
378 assert(index <= m_max);
379
380 value_type *pfs_first = m_array.get_first();
381 value_type *pfs = pfs_first + index;
382 value_type *pfs_last = m_array.get_last();
383
384 while (pfs < pfs_last) {
385 if (pfs->m_lock.is_populated()) {
386 const uint found = pfs - pfs_first;
387 *found_index = found;
388 index = found + 1;
389 return pfs;
390 }
391 ++pfs;
392 }
393
394 index = m_max;
395 return nullptr;
396 }
397
398 size_t m_max;
401};
402
403template <class T, int PFS_PAGE_SIZE, int PFS_PAGE_COUNT,
407 public:
408 friend class PFS_buffer_scalable_iterator<T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U,
409 V>;
410
411 /**
412 Type of elements in the buffer.
413 The following attributes are required:
414 - @code pfs_lock m_lock @endcode
415 - @code PFS_opaque_container_page *m_page @endcode
416 */
417 typedef T value_type;
418 /**
419 Type of pages in the buffer.
420 The following attributes are required:
421 - @code PFS_opaque_container *m_container @endcode
422 */
423 typedef U array_type;
424 typedef V allocator_type;
425 /** This container type */
432 typedef void (*function_type)(value_type *);
433
434 static const size_t MAX_SIZE = PFS_PAGE_SIZE * PFS_PAGE_COUNT;
435
437 m_allocator = allocator;
438 m_initialized = false;
439 m_full = true;
440 m_max = PFS_PAGE_COUNT * PFS_PAGE_SIZE;
441 m_max_page_count = PFS_PAGE_COUNT;
442 m_last_page_size = PFS_PAGE_SIZE;
443 m_lost = 0;
444 }
445
446 int init(long max_size) {
447 int i;
448
449 m_initialized = true;
450 m_full = true;
451 m_max = PFS_PAGE_COUNT * PFS_PAGE_SIZE;
452 m_max_page_count = PFS_PAGE_COUNT;
453 m_last_page_size = PFS_PAGE_SIZE;
454 m_lost = 0;
455 m_monotonic.m_size_t.store(0);
456 m_max_page_index.m_size_t.store(0);
457
458 for (i = 0; i < PFS_PAGE_COUNT; i++) {
459 m_pages[i] = nullptr;
460 }
461
462 if (max_size == 0) {
463 /* No allocation. */
465 } else if (max_size > 0) {
466 if (max_size % PFS_PAGE_SIZE == 0) {
467 m_max_page_count = max_size / PFS_PAGE_SIZE;
468 } else {
469 m_max_page_count = max_size / PFS_PAGE_SIZE + 1;
470 m_last_page_size = max_size % PFS_PAGE_SIZE;
471 }
472 /* Bounded allocation. */
473 m_full = false;
474
475 if (m_max_page_count > PFS_PAGE_COUNT) {
476 m_max_page_count = PFS_PAGE_COUNT;
477 m_last_page_size = PFS_PAGE_SIZE;
478 }
479 } else {
480 /* max_size = -1 means unbounded allocation */
481 m_full = false;
482 }
483
484 assert(m_max_page_count <= PFS_PAGE_COUNT);
485 assert(0 < m_last_page_size);
486 assert(m_last_page_size <= PFS_PAGE_SIZE);
487
489 return 0;
490 }
491
492 void cleanup() {
493 int i;
495
496 if (!m_initialized) {
497 return;
498 }
499
500 allocator_type *allocator = m_allocator.load();
501
503
504 for (i = 0; i < PFS_PAGE_COUNT; i++) {
505 page = m_pages[i];
506 if (page != nullptr) {
507 allocator->free_array(page);
508 delete page;
509 m_pages[i] = nullptr;
510 }
511 }
513
515
516 m_initialized = false;
517 }
518
519 size_t get_row_count() {
520 const size_t page_count = m_max_page_index.m_size_t.load();
521 size_t result = page_count * PFS_PAGE_SIZE;
522
523 if ((page_count > 0) && (m_last_page_size != PFS_PAGE_SIZE)) {
524 /* Bounded allocation, the last page may be incomplete. */
525 result = result - PFS_PAGE_SIZE + m_last_page_size;
526 }
527 return result;
528 }
529
530 size_t get_row_size() const { return sizeof(value_type); }
531
532 size_t get_memory() { return get_row_count() * get_row_size(); }
533
535 if (m_full.load()) {
536 m_lost++;
537 return nullptr;
538 }
539
540 size_t index;
541 size_t current_page_count;
543 array_type *array;
544
545 /*
546 1: Try to find an available record within the existing pages
547 */
548 current_page_count = m_max_page_index.m_size_t.load();
549
550 if (current_page_count != 0) {
551 size_t monotonic = m_monotonic.m_size_t.load();
552 size_t monotonic_max = monotonic + current_page_count;
553
554 if (unlikely(monotonic >= monotonic_max)) {
555 /*
556 This will happen once every 2^64 - current_page_count calls.
557 Computation of monotonic_max just overflowed,
558 so reset monotonic counters and start again from the beginning.
559 */
560 m_monotonic.m_size_t.store(0);
561 monotonic = 0;
562 monotonic_max = current_page_count;
563 }
564
565 while (monotonic < monotonic_max) {
566 /*
567 Scan in the [0 .. current_page_count - 1] range,
568 in parallel with m_monotonic (see below)
569 */
570 index = monotonic % current_page_count;
571
572 /* Atomic Load, array= m_pages[index] */
573 array = m_pages[index].load();
574
575 if (array != nullptr) {
576 pfs = array->allocate(dirty_state);
577 if (pfs != nullptr) {
578 /* Keep a pointer to the parent page, for deallocate(). */
579 pfs->m_page = reinterpret_cast<PFS_opaque_container_page *>(array);
580 return pfs;
581 }
582 }
583
584 /*
585 Parallel scans collaborate to increase
586 the common monotonic scan counter.
587
588 Note that when all the existing page are full,
589 one thread will eventually add a new page,
590 and cause m_max_page_index to increase,
591 which fools all the modulo logic for scans already in progress,
592 because the monotonic counter is not folded to the same place
593 (sometime modulo N, sometime modulo N+1).
594
595 This is actually ok: since all the pages are full anyway,
596 there is nothing to miss, so better increase the monotonic
597 counter faster and then move on to the detection of new pages,
598 in part 2: below.
599 */
600 monotonic = m_monotonic.m_size_t++;
601 };
602 }
603
604 /*
605 2: Try to add a new page, beyond the m_max_page_index limit
606 */
607 while (current_page_count < m_max_page_count) {
608 /* Peek for pages added by collaborating threads */
609
610 /* (2-a) Atomic Load, array= m_pages[current_page_count] */
611 array = m_pages[current_page_count].load();
612
613 if (array == nullptr) {
614 // ==================================================================
615 // BEGIN CRITICAL SECTION -- buffer expand
616 // ==================================================================
617
618 /*
619 On a fresh started server, buffers are typically empty.
620 When a sudden load spike is seen by the server,
621 multiple threads may want to expand the buffer at the same time.
622
623 Using a compare and swap to allow multiple pages to be added,
624 possibly freeing duplicate pages on collisions,
625 does not work well because the amount of code involved
626 when creating a new page can be significant (PFS_thread),
627 causing MANY collisions between (2-b) and (2-d).
628
629 A huge number of collisions (which can happen when thousands
630 of new connections hits the server after a restart)
631 leads to a huge memory consumption, and to OOM.
632
633 To mitigate this, we use here a mutex,
634 to enforce that only ONE page is added at a time,
635 so that scaling the buffer happens in a predictable
636 and controlled manner.
637 */
639
640 /*
641 Peek again for pages added by collaborating threads,
642 this time as the only thread allowed to expand the buffer
643 */
644
645 /* (2-b) Atomic Load, array= m_pages[current_page_count] */
646
647 array = m_pages[current_page_count].load();
648
649 if (array == nullptr) {
650 /* (2-c) Found no page, allocate a new one */
651 array = new array_type();
653
654 array->m_max = get_page_logical_size(current_page_count);
655
656 allocator_type *allocator = m_allocator.load();
657
658 const int rc = allocator->alloc_array(array);
659 if (rc != 0) {
660 allocator->free_array(array);
661 delete array;
663 m_lost++;
665 return nullptr;
666 }
667
668 /* Keep a pointer to this container, for static_deallocate(). */
669 array->m_container = reinterpret_cast<PFS_opaque_container *>(this);
670
671 /* (2-d) Atomic STORE, m_pages[current_page_count] = array */
672 m_pages[current_page_count].store(array);
673
674 /* Advertise the new page */
676 }
677
679
680 // ==================================================================
681 // END CRITICAL SECTION -- buffer expand
682 // ==================================================================
683 }
684
685 assert(array != nullptr);
686 pfs = array->allocate(dirty_state);
687 if (pfs != nullptr) {
688 /* Keep a pointer to the parent page, for deallocate(). */
689 pfs->m_page = reinterpret_cast<PFS_opaque_container_page *>(array);
690 return pfs;
691 }
692
693 current_page_count++;
694 }
695
696 m_lost++;
697 m_full.store(true);
698 return nullptr;
699 }
700
701 void dirty_to_free(pfs_dirty_state *dirty_state, value_type *safe_pfs) {
702 /* Find the containing page */
703 PFS_opaque_container_page *opaque_page = safe_pfs->m_page;
704 auto *page = reinterpret_cast<array_type *>(opaque_page);
705
706 /* Mark the object free */
707 safe_pfs->m_lock.dirty_to_free(dirty_state);
708
709 /* Flag the containing page as not full. */
710 if (page->m_full.load()) {
711 page->m_full.store(false);
712 }
713
714 /* Flag the overall container as not full. */
715 if (m_full.load()) {
716 m_full.store(false);
717 }
718 }
719
720 void deallocate(value_type *safe_pfs) {
721 /* Find the containing page */
722 PFS_opaque_container_page *opaque_page = safe_pfs->m_page;
723 auto *page = reinterpret_cast<array_type *>(opaque_page);
724
725 /* Mark the object free */
726 safe_pfs->m_lock.allocated_to_free();
727
728 /* Flag the containing page as not full. */
729 if (page->m_full.load()) {
730 page->m_full.store(false);
731 }
732
733 /* Flag the overall container as not full. */
734 if (m_full.load()) {
735 m_full.store(false);
736 }
737 }
738
739 static void static_deallocate(value_type *safe_pfs) {
740 /* Find the containing page */
741 PFS_opaque_container_page *opaque_page = safe_pfs->m_page;
742 auto *page = reinterpret_cast<array_type *>(opaque_page);
743
744 /* Mark the object free */
745 safe_pfs->m_lock.allocated_to_free();
746
747 /* Flag the containing page as not full. */
748 if (page->m_full.load()) {
749 page->m_full.store(false);
750 }
751
752 /* Find the containing buffer */
753 PFS_opaque_container *opaque_container = page->m_container;
755 container = reinterpret_cast<container_type *>(opaque_container);
756
757 /* Flag the overall container as not full. */
758 if (container->m_full.load()) {
759 container->m_full.store(false);
760 }
761 }
762
765 this, 0);
766 }
767
768 iterator_type iterate(uint index) {
769 assert(index <= m_max);
771 this, index);
772 }
773
775 uint i;
778 value_type *pfs_last;
779
780 for (i = 0; i < PFS_PAGE_COUNT; i++) {
781 page = m_pages[i];
782 if (page != nullptr) {
783 pfs = page->get_first();
784 pfs_last = page->get_last();
785
786 while (pfs < pfs_last) {
787 if (pfs->m_lock.is_populated()) {
788 fct(pfs);
789 }
790 ++pfs;
791 }
792 }
793 }
794 }
795
797 uint i;
800 value_type *pfs_last;
801
802 for (i = 0; i < PFS_PAGE_COUNT; i++) {
803 page = m_pages[i];
804 if (page != nullptr) {
805 pfs = page->get_first();
806 pfs_last = page->get_last();
807
808 while (pfs < pfs_last) {
809 fct(pfs);
810 ++pfs;
811 }
812 }
813 }
814 }
815
816 void apply(processor_type &proc) {
817 uint i;
820 value_type *pfs_last;
821
822 for (i = 0; i < PFS_PAGE_COUNT; i++) {
823 page = m_pages[i];
824 if (page != nullptr) {
825 pfs = page->get_first();
826 pfs_last = page->get_last();
827
828 while (pfs < pfs_last) {
829 if (pfs->m_lock.is_populated()) {
830 proc(pfs);
831 }
832 ++pfs;
833 }
834 }
835 }
836 }
837
839 uint i;
842 value_type *pfs_last;
843
844 for (i = 0; i < PFS_PAGE_COUNT; i++) {
845 page = m_pages[i];
846 if (page != nullptr) {
847 pfs = page->get_first();
848 pfs_last = page->get_last();
849
850 while (pfs < pfs_last) {
851 proc(pfs);
852 ++pfs;
853 }
854 }
855 }
856 }
857
858 value_type *get(uint index) {
859 assert(index < m_max);
860
861 uint index_1 = index / PFS_PAGE_SIZE;
862 array_type *page = m_pages[index_1];
863 if (page != nullptr) {
864 uint index_2 = index % PFS_PAGE_SIZE;
865
866 if (index_2 >= page->m_max) {
867 return nullptr;
868 }
869
870 value_type *pfs = page->m_ptr + index_2;
871
872 if (pfs->m_lock.is_populated()) {
873 return pfs;
874 }
875 }
876
877 return nullptr;
878 }
879
880 value_type *get(uint index, bool *has_more) {
881 if (index >= m_max) {
882 *has_more = false;
883 return nullptr;
884 }
885
886 uint index_1 = index / PFS_PAGE_SIZE;
887 array_type *page = m_pages[index_1];
888
889 if (page == nullptr) {
890 *has_more = false;
891 return nullptr;
892 }
893
894 uint index_2 = index % PFS_PAGE_SIZE;
895
896 if (index_2 >= page->m_max) {
897 *has_more = false;
898 return nullptr;
899 }
900
901 *has_more = true;
902 value_type *pfs = page->m_ptr + index_2;
903
904 if (pfs->m_lock.is_populated()) {
905 return pfs;
906 }
907
908 return nullptr;
909 }
910
912 intptr offset;
913 uint i;
916 value_type *pfs_last;
917
918 for (i = 0; i < PFS_PAGE_COUNT; i++) {
919 page = m_pages[i];
920 if (page != nullptr) {
921 pfs = page->get_first();
922 pfs_last = page->get_last();
923
924 if ((pfs <= unsafe) && (unsafe < pfs_last)) {
925 offset = ((intptr)unsafe - (intptr)pfs) % sizeof(value_type);
926 if (offset == 0) {
927 return unsafe;
928 }
929 }
930 }
931 }
932
933 return nullptr;
934 }
935
936 ulong m_lost;
937
938 private:
939 uint get_page_logical_size(uint page_index) {
940 if (page_index + 1 < m_max_page_count) {
941 return PFS_PAGE_SIZE;
942 }
943 assert(page_index + 1 == m_max_page_count);
944 return m_last_page_size;
945 }
946
947 value_type *scan_next(uint &index, uint *found_index) {
948 assert(index <= m_max);
949
950 uint index_1 = index / PFS_PAGE_SIZE;
951 uint index_2 = index % PFS_PAGE_SIZE;
953 value_type *pfs_first;
955 value_type *pfs_last;
956
957 while (index_1 < PFS_PAGE_COUNT) {
958 page = m_pages[index_1];
959
960 if (page == nullptr) {
961 index = static_cast<uint>(m_max);
962 return nullptr;
963 }
964
965 pfs_first = page->get_first();
966 pfs = pfs_first + index_2;
967 pfs_last = page->get_last();
968
969 while (pfs < pfs_last) {
970 if (pfs->m_lock.is_populated()) {
971 const uint found =
972 index_1 * PFS_PAGE_SIZE + static_cast<uint>(pfs - pfs_first);
973 *found_index = found;
974 index = found + 1;
975 return pfs;
976 }
977 ++pfs;
978 }
979
980 ++index_1;
981 index_2 = 0;
982 }
983
984 index = static_cast<uint>(m_max);
985 return nullptr;
986 }
987
988 /**
989 Initialized full flag.
990
991 Concurrency profile:
992 - write in init / cleanup
993 - readonly during normal operations
994 */
995 std::atomic<bool> m_initialized{false};
996
997 /**
998 Buffer full flag.
999
1000 Concurrency profile:
1001 - mostly read during normal operations.
1002 - do not perform useless write,
1003 check for previous value first
1004 - occasional write on state changes
1005 */
1006 std::atomic<bool> m_full{false};
1007
1008 /**
1009 Max number of items in the buffer.
1010
1011 Concurrency profile:
1012 - written once on page creation
1013 - read only during normal operations.
1014 */
1015 std::atomic<size_t> m_max{0};
1016
1017 /**
1018 Monotonic page counter.
1019 This counter is used to access pages in the array.
1020
1021 Concurrency profile:
1022 - frequent read and write, must be on its own cacheline
1023 */
1025
1026 /**
1027 Current page index.
1028
1029 Concurrency profile:
1030 - occasional write on buffer extend
1031 - mostly read otherwise
1032 */
1034
1035 /**
1036 Max number of pages.
1037
1038 Concurrency profile:
1039 - written once on buffer creation
1040 - read only during normal operations.
1041 */
1042 std::atomic<size_t> m_max_page_count{0};
1043
1044 /**
1045 Size of the last page.
1046
1047 Concurrency profile:
1048 - written once on buffer creation
1049 - read only during normal operations.
1050 */
1051 std::atomic<size_t> m_last_page_size{0};
1052
1053 /**
1054 Array of pages.
1055
1056 Concurrency profile:
1057 - occasional write on buffer extend
1058 - mostly read otherwise
1059 */
1060 std::atomic<array_type *> m_pages[PFS_PAGE_COUNT];
1061
1062 /**
1063 Buffer allocator.
1064
1065 Concurrency profile:
1066 - written once on buffer creation
1067 - read only during normal operations.
1068 */
1069 std::atomic<allocator_type *> m_allocator{nullptr};
1070
1072};
1073
1074template <class T, class U, class V>
1076 friend class PFS_buffer_container<T, U, V>;
1077
1078 typedef T value_type;
1080
1081 public:
1083 uint unused;
1084 return m_container->scan_next(m_index, &unused);
1085 }
1086
1087 value_type *scan_next(uint *found_index) {
1088 return m_container->scan_next(m_index, found_index);
1089 }
1090
1091 private:
1093 : m_container(container), m_index(index) {}
1094
1097};
1098
1099template <class T, int page_size, int page_count, class U, class V>
1101 friend class PFS_buffer_scalable_container<T, page_size, page_count, U, V>;
1102
1103 typedef T value_type;
1106
1107 public:
1109 uint unused;
1110 return m_container->scan_next(m_index, &unused);
1111 }
1112
1113 value_type *scan_next(uint *found_index) {
1114 return m_container->scan_next(m_index, found_index);
1115 }
1116
1117 private:
1119 : m_container(container), m_index(index) {}
1120
1123};
1124
1125template <class T>
1127 public:
1128 virtual ~PFS_buffer_processor() = default;
1129 virtual void operator()(T *element) = 0;
1130};
1131
1132template <class B, int PFS_PARTITION_COUNT>
1134 public:
1135 friend class PFS_partitioned_buffer_scalable_iterator<B, PFS_PARTITION_COUNT>;
1136
1137 typedef typename B::value_type value_type;
1138 typedef typename B::allocator_type allocator_type;
1141 typedef typename B::iterator_type sub_iterator_type;
1142 typedef typename B::processor_type processor_type;
1143 typedef typename B::function_type function_type;
1144
1146 allocator_type *allocator) {
1147 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1148 m_partitions[i] = new B(allocator);
1149 }
1150 }
1151
1153 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1154 delete m_partitions[i];
1155 }
1156 }
1157
1158 int init(long max_size) {
1159 int rc = 0;
1160 // FIXME: we have max_size * PFS_PARTITION_COUNT here
1161 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1162 rc |= m_partitions[i]->init(max_size);
1163 }
1164 return rc;
1165 }
1166
1167 void cleanup() {
1168 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1169 m_partitions[i]->cleanup();
1170 }
1171 }
1172
1173 size_t get_row_count() const {
1174 size_t sum = 0;
1175
1176 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1177 sum += m_partitions[i]->get_row_count();
1178 }
1179
1180 return sum;
1181 }
1182
1183 size_t get_row_size() const { return sizeof(value_type); }
1184
1185 size_t get_memory() const {
1186 size_t sum = 0;
1187
1188 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1189 sum += m_partitions[i]->get_memory();
1190 }
1191
1192 return sum;
1193 }
1194
1196 long sum = 0;
1197
1198 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1199 sum += m_partitions[i]->m_lost;
1200 }
1201
1202 return sum;
1203 }
1204
1205 value_type *allocate(pfs_dirty_state *dirty_state, uint partition) {
1206 assert(partition < PFS_PARTITION_COUNT);
1207
1208 return m_partitions[partition]->allocate(dirty_state);
1209 }
1210
1211 void deallocate(value_type *safe_pfs) {
1212 /*
1213 One issue here is that we do not know which partition
1214 the record belongs to.
1215 Each record points to the parent page,
1216 and each page points to the parent buffer,
1217 so using static_deallocate here,
1218 which will find the correct partition by itself.
1219 */
1220 B::static_deallocate(safe_pfs);
1221 }
1222
1223 iterator_type iterate() { return iterator_type(this, 0, 0); }
1224
1225 iterator_type iterate(uint user_index) {
1226 uint partition_index;
1227 uint sub_index;
1228 unpack_index(user_index, &partition_index, &sub_index);
1229 return iterator_type(this, partition_index, sub_index);
1230 }
1231
1233 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1234 m_partitions[i]->apply(fct);
1235 }
1236 }
1237
1239 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1240 m_partitions[i]->apply_all(fct);
1241 }
1242 }
1243
1244 void apply(processor_type &proc) {
1245 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1246 m_partitions[i]->apply(proc);
1247 }
1248 }
1249
1251 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1252 m_partitions[i]->apply_all(proc);
1253 }
1254 }
1255
1256 value_type *get(uint user_index) {
1257 uint partition_index;
1258 uint sub_index;
1259 unpack_index(user_index, &partition_index, &sub_index);
1260
1261 if (partition_index >= PFS_PARTITION_COUNT) {
1262 return nullptr;
1263 }
1264
1265 return m_partitions[partition_index]->get(sub_index);
1266 }
1267
1268 value_type *get(uint user_index, bool *has_more) {
1269 uint partition_index;
1270 uint sub_index;
1271 unpack_index(user_index, &partition_index, &sub_index);
1272
1273 if (partition_index >= PFS_PARTITION_COUNT) {
1274 *has_more = false;
1275 return nullptr;
1276 }
1277
1278 *has_more = true;
1279 return m_partitions[partition_index]->get(sub_index);
1280 }
1281
1283 value_type *safe = nullptr;
1284
1285 for (int i = 0; i < PFS_PARTITION_COUNT; i++) {
1286 safe = m_partitions[i]->sanitize(unsafe);
1287 if (safe != nullptr) {
1288 return safe;
1289 }
1290 }
1291
1292 return safe;
1293 }
1294
1295 private:
1296 static void pack_index(uint partition_index, uint sub_index,
1297 uint *user_index) {
1298 static_assert(PFS_PARTITION_COUNT <= (1 << 8), "2^8 = 256 partitions max.");
1299 static_assert((B::MAX_SIZE) <= (1 << 24),
1300 "2^24 = 16777216 max per partitioned buffer.");
1301
1302 *user_index = (partition_index << 24) + sub_index;
1303 }
1304
1305 static void unpack_index(uint user_index, uint *partition_index,
1306 uint *sub_index) {
1307 *partition_index = user_index >> 24;
1308 *sub_index = user_index & 0x00FFFFFF;
1309 }
1310
1311 value_type *scan_next(uint &partition_index, uint &sub_index,
1312 uint *found_partition, uint *found_sub_index) {
1313 value_type *record = nullptr;
1314 assert(partition_index < PFS_PARTITION_COUNT);
1315
1316 while (partition_index < PFS_PARTITION_COUNT) {
1317 sub_iterator_type sub_iterator =
1318 m_partitions[partition_index]->iterate(sub_index);
1319 record = sub_iterator.scan_next(found_sub_index);
1320 if (record != nullptr) {
1321 *found_partition = partition_index;
1322 sub_index = *found_sub_index + 1;
1323 return record;
1324 }
1325
1326 partition_index++;
1327 sub_index = 0;
1328 }
1329
1330 *found_partition = PFS_PARTITION_COUNT;
1331 *found_sub_index = 0;
1332 sub_index = 0;
1333 return nullptr;
1334 }
1335
1336 B *m_partitions[PFS_PARTITION_COUNT];
1337};
1338
1339template <class B, int PFS_PARTITION_COUNT>
1341 public:
1343 PFS_PARTITION_COUNT>;
1344
1345 typedef typename B::value_type value_type;
1348
1350 uint unused_partition;
1351 uint unused_sub_index;
1352 return m_container->scan_next(m_partition, m_sub_index, &unused_partition,
1353 &unused_sub_index);
1354 }
1355
1356 value_type *scan_next(uint *found_user_index) {
1357 uint found_partition;
1358 uint found_sub_index;
1360 record = m_container->scan_next(m_partition, m_sub_index, &found_partition,
1361 &found_sub_index);
1362 container_type::pack_index(found_partition, found_sub_index,
1363 found_user_index);
1364 return record;
1365 }
1366
1367 private:
1369 uint partition, uint sub_index)
1371 m_partition(partition),
1372 m_sub_index(sub_index) {}
1373
1377};
1378
1379#ifdef USE_SCALABLE
1385#else
1387#endif
1390
1391#ifdef USE_SCALABLE
1394#else
1396#endif
1399
1400#ifdef USE_SCALABLE
1402#else
1404#endif
1407
1408#ifdef USE_SCALABLE
1411#else
1413#endif
1416
1417#ifdef USE_SCALABLE
1420#else
1422#endif
1425
1426#ifdef USE_SCALABLE
1429#else
1431#endif
1434
1435#ifdef USE_SCALABLE
1438#else
1440#endif
1443
1444#ifdef USE_SCALABLE
1447#else
1449#endif
1452
1453#ifdef USE_SCALABLE
1456#else
1458#endif
1461
1462#ifdef USE_SCALABLE
1465#else
1467#endif
1470
1471#ifdef USE_SCALABLE
1474#else
1477#endif
1481
1482#ifdef USE_SCALABLE
1485#else
1488#endif
1492
1493#ifdef USE_SCALABLE
1496#else
1498#endif
1501
1502#ifdef USE_SCALABLE
1505#else
1507#endif
1510
1511class PFS_account_array : public PFS_buffer_default_array<PFS_account> {
1512 public:
1519};
1520
1522 public:
1523 int alloc_array(PFS_account_array *array);
1524 void free_array(PFS_account_array *array);
1525};
1526
1527#ifdef USE_SCALABLE
1531#else
1535#endif
1538
1540 public:
1547};
1548
1550 public:
1551 int alloc_array(PFS_host_array *array);
1552 void free_array(PFS_host_array *array);
1553};
1554
1555#ifdef USE_SCALABLE
1559#else
1562#endif
1565
1566class PFS_thread_array : public PFS_buffer_default_array<PFS_thread> {
1567 public:
1574
1581
1584 unsigned char *m_current_stmts_digest_token_array{nullptr};
1585 unsigned char *m_history_stmts_digest_token_array{nullptr};
1586};
1587
1589 public:
1590 int alloc_array(PFS_thread_array *array);
1591 void free_array(PFS_thread_array *array);
1592};
1593
1594#ifdef USE_SCALABLE
1598#else
1601#endif
1604
1606 public:
1613};
1614
1616 public:
1617 int alloc_array(PFS_user_array *array);
1618 void free_array(PFS_user_array *array);
1619};
1620
1621#ifdef USE_SCALABLE
1625#else
1628#endif
1631
1632#endif
Definition: pfs_buffer_container.h:1521
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:1511
PFS_stage_stat * m_instr_class_stages_array
Definition: pfs_buffer_container.h:1514
PFS_memory_shared_stat * m_instr_class_memory_array
Definition: pfs_buffer_container.h:1518
PFS_error_stat * m_instr_class_errors_array
Definition: pfs_buffer_container.h:1517
PFS_single_stat * m_instr_class_waits_array
Definition: pfs_buffer_container.h:1513
PFS_transaction_stat * m_instr_class_transactions_array
Definition: pfs_buffer_container.h:1516
PFS_statement_stat * m_instr_class_statements_array
Definition: pfs_buffer_container.h:1515
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:398
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:374
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:377
allocator_type * m_allocator
Definition: pfs_buffer_container.h:400
array_type m_array
Definition: pfs_buffer_container.h:399
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:1075
T value_type
Definition: pfs_buffer_container.h:1078
PFS_buffer_container< T, U, V > container_type
Definition: pfs_buffer_container.h:1079
container_type * m_container
Definition: pfs_buffer_container.h:1095
value_type * scan_next()
Definition: pfs_buffer_container.h:1082
value_type * scan_next(uint *found_index)
Definition: pfs_buffer_container.h:1087
PFS_buffer_iterator(container_type *container, uint index)
Definition: pfs_buffer_container.h:1092
uint m_index
Definition: pfs_buffer_container.h:1096
Definition: pfs_buffer_container.h:1126
virtual void operator()(T *element)=0
virtual ~PFS_buffer_processor()=default
Definition: pfs_buffer_container.h:406
void(* function_type)(value_type *)
Definition: pfs_buffer_container.h:432
static const size_t MAX_SIZE
Definition: pfs_buffer_container.h:434
int init(long max_size)
Definition: pfs_buffer_container.h:446
size_t get_row_size() const
Definition: pfs_buffer_container.h:530
std::atomic< size_t > m_last_page_size
Size of the last page.
Definition: pfs_buffer_container.h:1051
friend class PFS_buffer_scalable_iterator< T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U, V >
Definition: pfs_buffer_container.h:409
void apply(processor_type &proc)
Definition: pfs_buffer_container.h:816
void apply_all(function_type fct)
Definition: pfs_buffer_container.h:796
void apply_all(processor_type &proc)
Definition: pfs_buffer_container.h:838
void dirty_to_free(pfs_dirty_state *dirty_state, value_type *safe_pfs)
Definition: pfs_buffer_container.h:701
PFS_buffer_scalable_container< T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U, V > container_type
This container type.
Definition: pfs_buffer_container.h:427
value_type * sanitize(value_type *unsafe)
Definition: pfs_buffer_container.h:911
PFS_buffer_scalable_iterator< T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U, V > iterator_type
Definition: pfs_buffer_container.h:430
value_type * allocate(pfs_dirty_state *dirty_state)
Definition: pfs_buffer_container.h:534
native_mutex_t m_critical_section
Definition: pfs_buffer_container.h:1071
std::atomic< size_t > m_max
Max number of items in the buffer.
Definition: pfs_buffer_container.h:1015
PFS_cacheline_atomic_size_t m_max_page_index
Current page index.
Definition: pfs_buffer_container.h:1033
size_t get_memory()
Definition: pfs_buffer_container.h:532
iterator_type iterate()
Definition: pfs_buffer_container.h:763
uint get_page_logical_size(uint page_index)
Definition: pfs_buffer_container.h:939
void apply(function_type fct)
Definition: pfs_buffer_container.h:774
iterator_type iterate(uint index)
Definition: pfs_buffer_container.h:768
V allocator_type
Definition: pfs_buffer_container.h:424
U array_type
Type of pages in the buffer.
Definition: pfs_buffer_container.h:423
PFS_buffer_processor< T > processor_type
Definition: pfs_buffer_container.h:431
value_type * get(uint index, bool *has_more)
Definition: pfs_buffer_container.h:880
PFS_cacheline_atomic_size_t m_monotonic
Monotonic page counter.
Definition: pfs_buffer_container.h:1024
std::atomic< size_t > m_max_page_count
Max number of pages.
Definition: pfs_buffer_container.h:1042
void cleanup()
Definition: pfs_buffer_container.h:492
size_t get_row_count()
Definition: pfs_buffer_container.h:519
std::atomic< bool > m_initialized
Initialized full flag.
Definition: pfs_buffer_container.h:995
PFS_buffer_const_iterator< T > const_iterator_type
Definition: pfs_buffer_container.h:428
value_type * get(uint index)
Definition: pfs_buffer_container.h:858
static void static_deallocate(value_type *safe_pfs)
Definition: pfs_buffer_container.h:739
std::atomic< bool > m_full
Buffer full flag.
Definition: pfs_buffer_container.h:1006
T value_type
Type of elements in the buffer.
Definition: pfs_buffer_container.h:417
PFS_buffer_scalable_container(allocator_type *allocator)
Definition: pfs_buffer_container.h:436
value_type * scan_next(uint &index, uint *found_index)
Definition: pfs_buffer_container.h:947
std::atomic< allocator_type * > m_allocator
Buffer allocator.
Definition: pfs_buffer_container.h:1069
void deallocate(value_type *safe_pfs)
Definition: pfs_buffer_container.h:720
ulong m_lost
Definition: pfs_buffer_container.h:936
std::atomic< array_type * > m_pages[PFS_PAGE_COUNT]
Array of pages.
Definition: pfs_buffer_container.h:1060
Definition: pfs_buffer_container.h:1100
T value_type
Definition: pfs_buffer_container.h:1103
uint m_index
Definition: pfs_buffer_container.h:1122
value_type * scan_next(uint *found_index)
Definition: pfs_buffer_container.h:1113
value_type * scan_next()
Definition: pfs_buffer_container.h:1108
PFS_buffer_scalable_container< T, page_size, page_count, U, V > container_type
Definition: pfs_buffer_container.h:1105
PFS_buffer_scalable_iterator(container_type *container, uint index)
Definition: pfs_buffer_container.h:1118
container_type * m_container
Definition: pfs_buffer_container.h:1121
Definition: pfs_buffer_container.h:1549
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:1539
PFS_transaction_stat * m_instr_class_transactions_array
Definition: pfs_buffer_container.h:1544
PFS_memory_shared_stat * m_instr_class_memory_array
Definition: pfs_buffer_container.h:1546
PFS_error_stat * m_instr_class_errors_array
Definition: pfs_buffer_container.h:1545
PFS_single_stat * m_instr_class_waits_array
Definition: pfs_buffer_container.h:1541
PFS_stage_stat * m_instr_class_stages_array
Definition: pfs_buffer_container.h:1542
PFS_statement_stat * m_instr_class_statements_array
Definition: pfs_buffer_container.h:1543
Definition: pfs_buffer_container.h:1133
B::function_type function_type
Definition: pfs_buffer_container.h:1143
value_type * get(uint user_index, bool *has_more)
Definition: pfs_buffer_container.h:1268
B::allocator_type allocator_type
Definition: pfs_buffer_container.h:1138
void apply(processor_type &proc)
Definition: pfs_buffer_container.h:1244
void apply(function_type fct)
Definition: pfs_buffer_container.h:1232
B * m_partitions[PFS_PARTITION_COUNT]
Definition: pfs_buffer_container.h:1336
value_type * scan_next(uint &partition_index, uint &sub_index, uint *found_partition, uint *found_sub_index)
Definition: pfs_buffer_container.h:1311
iterator_type iterate()
Definition: pfs_buffer_container.h:1223
PFS_partitioned_buffer_scalable_iterator< B, PFS_PARTITION_COUNT > iterator_type
Definition: pfs_buffer_container.h:1140
size_t get_row_count() const
Definition: pfs_buffer_container.h:1173
void apply_all(function_type fct)
Definition: pfs_buffer_container.h:1238
value_type * sanitize(value_type *unsafe)
Definition: pfs_buffer_container.h:1282
B::value_type value_type
Definition: pfs_buffer_container.h:1137
static void unpack_index(uint user_index, uint *partition_index, uint *sub_index)
Definition: pfs_buffer_container.h:1305
PFS_partitioned_buffer_scalable_container(allocator_type *allocator)
Definition: pfs_buffer_container.h:1145
void deallocate(value_type *safe_pfs)
Definition: pfs_buffer_container.h:1211
int init(long max_size)
Definition: pfs_buffer_container.h:1158
~PFS_partitioned_buffer_scalable_container()
Definition: pfs_buffer_container.h:1152
B::iterator_type sub_iterator_type
Definition: pfs_buffer_container.h:1141
size_t get_memory() const
Definition: pfs_buffer_container.h:1185
iterator_type iterate(uint user_index)
Definition: pfs_buffer_container.h:1225
size_t get_row_size() const
Definition: pfs_buffer_container.h:1183
B::processor_type processor_type
Definition: pfs_buffer_container.h:1142
void apply_all(processor_type &proc)
Definition: pfs_buffer_container.h:1250
value_type * get(uint user_index)
Definition: pfs_buffer_container.h:1256
value_type * allocate(pfs_dirty_state *dirty_state, uint partition)
Definition: pfs_buffer_container.h:1205
void cleanup()
Definition: pfs_buffer_container.h:1167
long get_lost_counter()
Definition: pfs_buffer_container.h:1195
static void pack_index(uint partition_index, uint sub_index, uint *user_index)
Definition: pfs_buffer_container.h:1296
Definition: pfs_buffer_container.h:1340
uint m_sub_index
Definition: pfs_buffer_container.h:1376
PFS_partitioned_buffer_scalable_container< B, PFS_PARTITION_COUNT > container_type
Definition: pfs_buffer_container.h:1347
container_type * m_container
Definition: pfs_buffer_container.h:1374
B::value_type value_type
Definition: pfs_buffer_container.h:1345
value_type * scan_next(uint *found_user_index)
Definition: pfs_buffer_container.h:1356
value_type * scan_next()
Definition: pfs_buffer_container.h:1349
PFS_partitioned_buffer_scalable_iterator(container_type *container, uint partition, uint sub_index)
Definition: pfs_buffer_container.h:1368
uint m_partition
Definition: pfs_buffer_container.h:1375
Definition: pfs_buffer_container.h:1588
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:1566
PFS_statement_stat * m_instr_class_statements_array
Definition: pfs_buffer_container.h:1570
PFS_single_stat * m_instr_class_waits_array
Definition: pfs_buffer_container.h:1568
PFS_error_stat * m_instr_class_errors_array
Definition: pfs_buffer_container.h:1572
PFS_events_statements * m_statements_stack_array
Definition: pfs_buffer_container.h:1578
PFS_events_statements * m_statements_history_array
Definition: pfs_buffer_container.h:1577
PFS_stage_stat * m_instr_class_stages_array
Definition: pfs_buffer_container.h:1569
unsigned char * m_current_stmts_digest_token_array
Definition: pfs_buffer_container.h:1584
PFS_events_stages * m_stages_history_array
Definition: pfs_buffer_container.h:1576
char * m_current_stmts_text_array
Definition: pfs_buffer_container.h:1582
PFS_memory_safe_stat * m_instr_class_memory_array
Definition: pfs_buffer_container.h:1573
unsigned char * m_history_stmts_digest_token_array
Definition: pfs_buffer_container.h:1585
PFS_transaction_stat * m_instr_class_transactions_array
Definition: pfs_buffer_container.h:1571
char * m_session_connect_attrs_array
Definition: pfs_buffer_container.h:1580
PFS_events_waits * m_waits_history_array
Definition: pfs_buffer_container.h:1575
PFS_events_transactions * m_transactions_history_array
Definition: pfs_buffer_container.h:1579
char * m_history_stmts_text_array
Definition: pfs_buffer_container.h:1583
Definition: pfs_buffer_container.h:1615
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:1605
PFS_statement_stat * m_instr_class_statements_array
Definition: pfs_buffer_container.h:1609
PFS_transaction_stat * m_instr_class_transactions_array
Definition: pfs_buffer_container.h:1610
PFS_stage_stat * m_instr_class_stages_array
Definition: pfs_buffer_container.h:1608
PFS_single_stat * m_instr_class_waits_array
Definition: pfs_buffer_container.h:1607
PFS_error_stat * m_instr_class_errors_array
Definition: pfs_buffer_container.h:1611
PFS_memory_shared_stat * m_instr_class_memory_array
Definition: pfs_buffer_container.h:1612
int page
Definition: ctype-mb.cc:1224
#define MY_ZEROFILL
Definition: my_sys.h:143
#define PFS_MUTEX_PARTITIONS
Definition: pfs_instr_class.h:360
constexpr bool unlikely(bool expr)
Definition: my_compiler.h:58
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:193
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:1381
PFS_host_container global_host_container
PFS_buffer_scalable_container< PFS_socket, 256, 256 > PFS_socket_container
Definition: pfs_buffer_container.h:1419
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:1405
PFS_buffer_scalable_container< PFS_table, 1024, 1024 > PFS_table_container
Definition: pfs_buffer_container.h:1455
PFS_file_container::iterator_type PFS_file_iterator
Definition: pfs_buffer_container.h:1414
PFS_user_container::iterator_type PFS_user_iterator
Definition: pfs_buffer_container.h:1629
PFS_mutex_container::iterator_type PFS_mutex_iterator
Definition: pfs_buffer_container.h:1388
PFS_prepared_stmt_container::iterator_type PFS_prepared_stmt_iterator
Definition: pfs_buffer_container.h:1508
PFS_buffer_scalable_container< PFS_table_share, 4 *1024, 4 *1024 > PFS_table_share_container
Definition: pfs_buffer_container.h:1464
PFS_setup_object_container::iterator_type PFS_setup_object_iterator
Definition: pfs_buffer_container.h:1450
PFS_cond_container global_cond_container
PFS_buffer_scalable_container< PFS_prepared_stmt, 1024, 1024 > PFS_prepared_stmt_container
Definition: pfs_buffer_container.h:1504
PFS_buffer_scalable_container< PFS_table_share_lock, 4 *1024, 4 *1024 > PFS_table_share_lock_container
Definition: pfs_buffer_container.h:1484
PFS_socket_container::iterator_type PFS_socket_iterator
Definition: pfs_buffer_container.h:1423
PFS_table_share_container global_table_share_container
PFS_rwlock_container::iterator_type PFS_rwlock_iterator
Definition: pfs_buffer_container.h:1397
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:1597
PFS_host_container::iterator_type PFS_host_iterator
Definition: pfs_buffer_container.h:1563
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:1384
PFS_table_share_lock_container::iterator_type PFS_table_share_lock_iterator
Definition: pfs_buffer_container.h:1490
PFS_buffer_scalable_container< PFS_program, 1024, 1024 > PFS_program_container
Definition: pfs_buffer_container.h:1495
PFS_account_container::iterator_type PFS_account_iterator
Definition: pfs_buffer_container.h:1536
PFS_buffer_scalable_container< PFS_file, 4 *1024, 4 *1024 > PFS_file_container
Definition: pfs_buffer_container.h:1410
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:1479
PFS_mdl_container global_mdl_container
PFS_buffer_scalable_container< PFS_setup_actor, 128, 1024 > PFS_setup_actor_container
Definition: pfs_buffer_container.h:1437
PFS_rwlock_container global_rwlock_container
PFS_thread_container::iterator_type PFS_thread_iterator
Definition: pfs_buffer_container.h:1602
PFS_mdl_container::iterator_type PFS_mdl_iterator
Definition: pfs_buffer_container.h:1432
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:1459
PFS_buffer_scalable_container< PFS_host, 128, 128, PFS_host_array, PFS_host_allocator > PFS_host_container
Definition: pfs_buffer_container.h:1558
PFS_account_container global_account_container
PFS_buffer_scalable_container< PFS_cond, 256, 256 > PFS_cond_container
Definition: pfs_buffer_container.h:1401
PFS_setup_actor_container::iterator_type PFS_setup_actor_iterator
Definition: pfs_buffer_container.h:1441
PFS_program_container::iterator_type PFS_program_iterator
Definition: pfs_buffer_container.h:1499
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:1624
PFS_buffer_scalable_container< PFS_table_share_index, 8 *1024, 8 *1024 > PFS_table_share_index_container
Definition: pfs_buffer_container.h:1473
PFS_buffer_scalable_container< PFS_setup_object, 128, 1024 > PFS_setup_object_container
Definition: pfs_buffer_container.h:1446
PFS_table_share_container::iterator_type PFS_table_share_iterator
Definition: pfs_buffer_container.h:1468
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:1428
PFS_buffer_scalable_container< PFS_rwlock, 1024, 1024 > PFS_rwlock_container
Definition: pfs_buffer_container.h:1393
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:1530
PFS_builtin_memory_class builtin_memory_scalable_buffer
Definition: pfs_builtin_memory.cc:129
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:86
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:375
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
Definition: dtoa.cc:595