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