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