@@ -58,76 +58,71 @@ ulint trx_purge(ulint n_tasks, ulint history_size);
58
58
/* * The control structure used in the purge operation */
59
59
class purge_sys_t
60
60
{
61
- /* * Min-heap based priority queue over fixed size array */
61
+ /* * Min-heap based priority queue of (trx_no, trx_sys.rseg_array index)
62
+ pairs, ordered on trx_no. The highest 64-TRX_NO_SHIFT bits of each element is
63
+ trx_no, the lowest 8 bits is rseg's index in trx_sys.rseg_array. */
62
64
class purge_queue
63
65
{
64
- /* * Array of indexes in trx_sys.rseg_array. */
65
- alignas (CPU_LEVEL1_DCACHE_LINESIZE) byte m_array[TRX_SYS_N_RSEGS];
66
- /* * Pointer to the end of m_array. */
67
- byte *m_end= m_array;
68
-
69
66
public:
70
- struct trx_rseg_cmp
71
- {
72
- /* * Compare two trx_rseg_t* based on trx_no.
73
- @param lhs first index in trx_sys.rseg_array to compare
74
- @param rhs second index in trx_sys.rseg_array to compare
75
- @return whether lhs>rhs */
76
- bool operator ()(const byte lhs, const byte rhs)
77
- {
78
- ut_ad (lhs < TRX_SYS_N_RSEGS);
79
- ut_ad (rhs < TRX_SYS_N_RSEGS);
80
- /* We can compare without trx_rseg_t::latch, because rseg last
81
- commit is always set before pushing rseg to purge queue. */
82
- return trx_sys.rseg_array [lhs].last_commit_and_offset >
83
- trx_sys.rseg_array [rhs].last_commit_and_offset ;
84
- }
85
- };
86
- byte *begin () { return m_array; }
87
- byte *end () { return m_end; }
88
- const byte *c_begin () const { return m_array; }
89
- const byte *c_end () const { return m_end; }
90
- size_t size () const
91
- {
92
- size_t s= c_end () - c_begin ();
93
- ut_ad (s <= TRX_SYS_N_RSEGS);
94
- return s;
95
- }
96
- bool empty () const { return !size (); }
97
- void clear () { m_end= m_array; }
67
+ typedef std::vector<uint64_t , ut_allocator<uint64_t >> container_type;
68
+ /* * Number of bits reseved to shift trx_no in purge queue element */
69
+ static constexpr unsigned TRX_NO_SHIFT= 8 ;
70
+
71
+ bool empty () const { return m_array.empty (); }
72
+ void clear () { m_array.clear (); }
98
73
99
- /* * Push index of trx_sys.rseg_array into min-heap.
100
- @param i index to push */
101
- void push_rseg_index (byte i )
74
+ /* * Push (trx_no, trx_sys.rseg_array index) into min-heap.
75
+ @param trx_no_rseg (trx_no << TRX_NO_SHIFT | (trx_sys.rseg_array index)) */
76
+ void push_trx_no_rseg (container_type::value_type trx_no_rseg )
102
77
{
103
- ut_ad (i < TRX_SYS_N_RSEGS);
104
- ut_ad (size () + 1 <= TRX_SYS_N_RSEGS);
105
- *m_end++= i;
106
- std::push_heap (begin (), end (), trx_rseg_cmp ());
78
+ m_array.push_back (trx_no_rseg);
79
+ std::push_heap (m_array.begin (), m_array.end (),
80
+ std::greater<container_type::value_type>());
107
81
}
108
82
109
83
/* * Push rseg to priority queue.
110
- @param rseg trx_rseg_t pointer to push */
111
- void push (const trx_rseg_t *rseg)
84
+ @param trx_no trx_no of committed transaction
85
+ @param rseg rseg of committed transaction*/
86
+ void push (trx_id_t trx_no, const trx_rseg_t &rseg)
112
87
{
113
- ut_ad (rseg >= trx_sys.rseg_array );
114
- ut_ad (rseg < trx_sys.rseg_array + TRX_SYS_N_RSEGS);
115
- byte i= byte (rseg - trx_sys.rseg_array );
116
- push_rseg_index (i);
88
+ ut_ad (trx_no < 1ULL << (DATA_TRX_ID_LEN * CHAR_BIT));
89
+ ut_ad (&rseg >= trx_sys.rseg_array );
90
+ ut_ad (&rseg < trx_sys.rseg_array + TRX_SYS_N_RSEGS);
91
+ push_trx_no_rseg (trx_no << TRX_NO_SHIFT |
92
+ byte (&rseg - trx_sys.rseg_array ));
93
+ }
94
+
95
+ /* * Extracts rseg from (trx_no, trx_sys.rseg_array index) pair.
96
+ @param trx_no_rseg (trx_no << TRX_NO_SHIFT | (trx_sys.rseg_array index)
97
+ @return pointer to rseg in trx_sys.rseg_array */
98
+ static trx_rseg_t *rseg (container_type::value_type trx_no_rseg) {
99
+ byte i= static_cast <byte>(trx_no_rseg);
100
+ ut_ad (i < TRX_SYS_N_RSEGS);
101
+ return &trx_sys.rseg_array [i];
117
102
}
118
103
119
104
/* * Pop rseg from priority queue.
120
105
@return pointer to popped trx_rseg_t object */
121
106
trx_rseg_t *pop ()
122
107
{
123
108
ut_ad (!empty ());
124
- std::pop_heap (begin (), end (), trx_rseg_cmp ());
125
- byte i= *--m_end;
126
- ut_ad (i < TRX_SYS_N_RSEGS);
127
- return &trx_sys.rseg_array [i];
109
+ std::pop_heap (m_array.begin (), m_array.end (),
110
+ std::greater<container_type::value_type>());
111
+ trx_rseg_t *r = rseg (m_array.back ());
112
+ m_array.pop_back ();
113
+ return r;
128
114
}
115
+
116
+ /* * Clone m_array.
117
+ @return m_array clone */
118
+ container_type clone_container () const { return m_array; }
119
+
120
+ private:
121
+ /* * Array of (trx_no, trx_sys.rseg_array index) pairs. */
122
+ container_type m_array;
129
123
};
130
124
125
+
131
126
public:
132
127
/* * latch protecting view, m_enabled */
133
128
alignas (CPU_LEVEL1_DCACHE_LINESIZE) mutable srw_spin_lock latch;
@@ -243,20 +238,29 @@ class purge_sys_t
243
238
record */
244
239
uint16_t hdr_offset; /* !< Header byte offset on the page */
245
240
246
- /* * Binary min-heap of indexes in trx_sys.rseg_array, ordered on
247
- rseg_t::last_trx_no() . It is protected by the pq_mutex */
241
+ /* * Binary min-heap of (trx_no, trx_sys.rseg_array index) pairs , ordered on
242
+ trx_no . It is protected by the pq_mutex */
248
243
purge_queue purge_queue;
249
244
250
245
/* * Mutex protecting purge_queue */
251
246
mysql_mutex_t pq_mutex;
252
247
253
248
public:
249
+
250
+ void enqueue (trx_id_t trx_no, const trx_rseg_t &rseg) {
251
+ mysql_mutex_assert_owner (&pq_mutex);
252
+ purge_queue.push (trx_no, rseg);
253
+ }
254
+
254
255
/* * Push to purge queue without acquiring pq_mutex.
255
256
@param rseg rseg to push */
256
- void enqueue (trx_rseg_t &rseg)
257
- {
257
+ void enqueue (const trx_rseg_t &rseg) { enqueue (rseg.last_trx_no (), rseg); }
258
+
259
+ /* * Clone purge queue container.
260
+ @return purge queue container clone */
261
+ purge_queue::container_type clone_queue_container () const {
258
262
mysql_mutex_assert_owner (&pq_mutex);
259
- purge_queue.push (&rseg );
263
+ return purge_queue.clone_container ( );
260
264
}
261
265
262
266
/* * Acquare purge_queue_mutex */
0 commit comments