1 /*
2 Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
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
25 #ifndef COMPOSEDSLOTPOOL_HPP
26 #define COMPOSEDSLOTPOOL_HPP
27
28 #include "blocks/record_types.hpp"
29 #include "ndb_global.h"
30 #include "ndb_limits.h"
31 #include "ndb_types.h"
32 #include "vm/Pool.hpp"
33
34 #define JAM_FILE_ID 510
35
36 #define COMPOSED_SLOT_POOL_NO_MAX_COUNT
37
38 template <typename Pool1, typename Pool2>
39 class ComposedSlotPool
40 {
41 public:
42 typedef Slot Type;
43 ComposedSlotPool();
44 Uint32 getUncheckedPtrs(Uint32* from,
45 Ptr<Slot> ptrs[],
46 Uint32 cnt,
47 Uint32 slot_size) const;
48 Uint32 getEntrySize() const;
49 Uint32 getNoOfFree() const;
50 Uint32 getSize() const;
51 Uint32 getUsed() const;
52 Uint32 getUsedHi() const;
53 void resetUsedHi();
54
55 static Uint64 getMemoryNeed(Uint32 slot_size, Uint32 entry_count);
56 bool seize(Ptr<Slot>& p, Uint32 slot_size);
57 bool seize_pool2(Ptr<Slot>& p, Uint32 slot_size);
58 void release(Ptr<Slot> p, Uint32 slot_size);
59 void init(Uint32 type_id,
60 unsigned int slot_size,
61 Uint32* min_recs,
62 Uint32 max_recs,
63 const Pool_context& pool_ctx);
64 #if defined(VM_TRACE) || defined(ERROR_INSERT)
65 void resetMaxSize();
66 void setMaxSize(Uint32 max_recs);
67 #endif
68 bool startup(Uint32 slot_size);
69 bool getValidPtr(Ptr<Slot>& p, Uint32 magic, Uint32 slot_size) const;
70 bool getValidPtr_pool2(Ptr<Slot>& p, Uint32 magic, Uint32 slot_size) const;
71 bool getUncheckedPtrRO(Ptr<Slot>& p, Uint32 slot_size) const;
72 bool getUncheckedPtrRO_pool2(Ptr<Slot>& p, Uint32 slot_size) const;
73 bool getUncheckedPtrRW(Ptr<Slot>& p, Uint32 slot_size) const;
74 bool getUncheckedPtrRW_pool2(Ptr<Slot>& p, Uint32 slot_size) const;
75 bool may_shrink() const;
76 bool rearrange_free_list_and_shrink(Uint32 max_shrinks);
77
78 private:
79 bool inPool1(Uint32 i) const;
80 Uint32 toPool2(Uint32 i) const;
81 Uint32 fromPool2(Uint32 i) const;
82
83 Pool1 m_pool1;
84 #if !defined(COMPOSED_SLOT_POOL_NO_MAX_COUNT) || defined(VM_TRACE) || defined(ERROR_INSERT)
85 Uint32 m_max_count;
86 #endif
87 Uint32 m_use_count;
88 Uint32 m_used_high;
89 Uint32 m_shrink_level;
90 Pool2 m_pool2;
91 Uint32 m_slot_size;
92 Uint32 m_pool1_startup_count;
93 #if defined(VM_TRACE) || defined(ERROR_INSERT)
94 Uint32 m_orig_max_count;
95 #endif
96 };
97
98 template <typename Pool1, typename Pool2>
ComposedSlotPool()99 inline ComposedSlotPool<Pool1, Pool2>::ComposedSlotPool()
100 :
101 #if !defined(COMPOSED_SLOT_POOL_NO_MAX_COUNT)
102 m_max_count(0),
103 #elif defined(VM_TRACE) || defined(ERROR_INSERT)
104 m_max_count(RNIL),
105 #endif
106 m_use_count(0),
107 m_used_high(0),
108 m_shrink_level(0),
109 m_slot_size(0),
110 m_pool1_startup_count(0)
111 #if defined(VM_TRACE) || defined(ERROR_INSERT)
112 ,
113 m_orig_max_count(m_max_count)
114 #endif
115 {
116 }
117
118 template <typename Pool1, typename Pool2>
getUncheckedPtrs(Uint32 * from,Ptr<Slot> ptrs[],Uint32 cnt,Uint32 slot_size) const119 inline Uint32 ComposedSlotPool<Pool1, Pool2>::getUncheckedPtrs(
120 Uint32* from, Ptr<Slot> ptrs[], Uint32 cnt, Uint32 slot_size) const
121 {
122 const Uint32 i = *from;
123 if (likely(inPool1(i)) || (i == RNIL && inPool1(0)))
124 {
125 Uint32 ptr_cnts = m_pool1.getUncheckedPtrs(from, ptrs, cnt, slot_size);
126 if (unlikely(*from == RNIL) && m_pool2.getSize() > 0)
127 {
128 *from = m_pool1.getSize();
129 }
130 return ptr_cnts;
131 }
132 Uint32 from2 = toPool2(i);
133 Uint32 ptr_cnts = m_pool2.getUncheckedPtrs(&from2, ptrs, cnt, slot_size);
134 for (Uint32 i = 0; i < ptr_cnts; i++)
135 {
136 ptrs[i].i = fromPool2(ptrs[i].i);
137 }
138 *from = fromPool2(from2);
139 return ptr_cnts;
140 }
141
142 template <typename Pool1, typename Pool2>
getEntrySize() const143 inline Uint32 ComposedSlotPool<Pool1, Pool2>::getEntrySize() const
144 {
145 return m_slot_size;
146 }
147
148 template <typename Pool1, typename Pool2>
getNoOfFree() const149 inline Uint32 ComposedSlotPool<Pool1, Pool2>::getNoOfFree() const
150 {
151 return getSize() - getUsed();
152 }
153
154 template <typename Pool1, typename Pool2>
getSize() const155 inline Uint32 ComposedSlotPool<Pool1, Pool2>::getSize() const
156 {
157 return m_pool1.getSize() + m_pool2.getSize();
158 }
159
160 template <typename Pool1, typename Pool2>
getUsed() const161 inline Uint32 ComposedSlotPool<Pool1, Pool2>::getUsed() const
162 {
163 return m_use_count;
164 }
165
166 template <typename Pool1, typename Pool2>
getUsedHi() const167 inline Uint32 ComposedSlotPool<Pool1, Pool2>::getUsedHi() const
168 {
169 return m_used_high;
170 }
171
172 template <typename Pool1, typename Pool2>
resetUsedHi()173 inline void ComposedSlotPool<Pool1, Pool2>::resetUsedHi()
174 {
175 m_used_high = m_use_count;
176 }
177
178 template <typename Pool1, typename Pool2>
getMemoryNeed(Uint32 slot_size,Uint32 entry_count)179 inline Uint64 ComposedSlotPool<Pool1, Pool2>::getMemoryNeed(
180 Uint32 slot_size, Uint32 entry_count)
181 {
182 return Pool1::getMemoryNeed(slot_size, entry_count) +
183 Pool2::getMemoryNeed(slot_size, entry_count);
184 }
185
186 template <typename Pool1, typename Pool2>
seize(Ptr<Slot> & p,Uint32 slot_size)187 inline bool ComposedSlotPool<Pool1, Pool2>::seize(Ptr<Slot>& p,
188 Uint32 slot_size)
189 {
190 #if !defined(COMPOSED_SLOT_POOL_NO_MAX_COUNT) || defined(VM_TRACE) || defined(ERROR_INSERT)
191 const Uint32 max_count = m_max_count;
192 #endif
193 const Uint32 use_count = m_use_count;
194 const Uint32 new_use_count = use_count + 1;
195 const Uint32 used_high = m_used_high;
196 #if !defined(COMPOSED_SLOT_POOL_NO_MAX_COUNT)
197 if (unlikely(use_count == max_count))
198 {
199 return false;
200 }
201 #elif defined(VM_TRACE) || defined(ERROR_INSERT)
202 if (unlikely(use_count >= max_count))
203 {
204 return false;
205 }
206 #endif
207 if (unlikely(!m_pool1.seize(p, slot_size)))
208 {
209 if (!seize_pool2(p, slot_size))
210 {
211 return false;
212 }
213 }
214 m_use_count = new_use_count;
215 if (used_high < new_use_count)
216 {
217 m_used_high = new_use_count;
218 }
219 return true;
220 }
221
222 template <typename Pool1, typename Pool2>
seize_pool2(Ptr<Slot> & p,Uint32 slot_size)223 inline bool ComposedSlotPool<Pool1, Pool2>::seize_pool2(Ptr<Slot>& p,
224 Uint32 slot_size)
225 {
226 if (!m_pool2.seize(p, slot_size))
227 {
228 return false;
229 }
230 p.i = fromPool2(p.i);
231 return true;
232 }
233
234 template <typename Pool1, typename Pool2>
release(Ptr<Slot> p,Uint32 slot_size)235 inline void ComposedSlotPool<Pool1, Pool2>::release(Ptr<Slot> p,
236 Uint32 slot_size)
237 {
238 const Uint32 use_count = m_use_count;
239 const Uint32 new_use_count = use_count - 1;
240 if (likely(inPool1(p.i)))
241 {
242 m_pool1.release(p, slot_size);
243 }
244 else
245 {
246 p.i = toPool2(p.i);
247 m_pool2.release(p, slot_size);
248 }
249 m_use_count = new_use_count;
250 }
251
252 template <typename Pool1, typename Pool2>
init(Uint32 type_id,unsigned int slot_size,Uint32 * min_recs,Uint32 max_recs,const Pool_context & pool_ctx)253 inline void ComposedSlotPool<Pool1, Pool2>::init(Uint32 type_id,
254 unsigned int slot_size,
255 Uint32* min_recs,
256 Uint32 max_recs,
257 const Pool_context& pool_ctx)
258 {
259 #if !defined(COMPOSED_SLOT_POOL_NO_MAX_COUNT)
260 m_max_count = max_recs;
261 #else
262 (void) max_recs;
263 #endif
264 #if defined(VM_TRACE) || defined(ERROR_INSERT)
265 m_orig_max_count = m_max_count;
266 #endif
267 const Uint32 req_recs = *min_recs;
268 Uint32 pool1_recs = req_recs;
269 m_pool1.init(type_id, slot_size, &pool1_recs, pool_ctx);
270 Uint32 pool2_recs = req_recs - pool1_recs;
271 m_pool2.init(type_id, slot_size, &pool2_recs, pool_ctx);
272 *min_recs = pool1_recs + pool2_recs;
273
274 m_slot_size = slot_size;
275 m_shrink_level = (16384 / slot_size); /* slots on a half page */
276 }
277
278 template <typename Pool1, typename Pool2>
startup(Uint32 slot_size)279 inline bool ComposedSlotPool<Pool1, Pool2>::startup(Uint32 slot_size)
280 {
281 return m_pool1.startup(&m_pool1_startup_count, slot_size);
282 }
283
284 #if defined(VM_TRACE) || defined(ERROR_INSERT)
285 template <typename Pool1, typename Pool2>
resetMaxSize()286 inline void ComposedSlotPool<Pool1, Pool2>::resetMaxSize()
287 {
288 m_max_count = m_orig_max_count;
289 }
290
291 template <typename Pool1, typename Pool2>
setMaxSize(Uint32 max_recs)292 inline void ComposedSlotPool<Pool1, Pool2>::setMaxSize(Uint32 max_recs)
293 {
294 m_max_count = max_recs;
295 }
296 #endif
297
298 template <typename Pool1, typename Pool2>
getValidPtr(Ptr<Slot> & p,Uint32 magic,Uint32 slot_size) const299 inline bool ComposedSlotPool<Pool1, Pool2>::getValidPtr(
300 Ptr<Slot>& p, Uint32 magic, Uint32 slot_size) const
301 {
302 if (likely(m_pool1.getValidPtr(p, magic, slot_size)))
303 {
304 return true;
305 }
306 if (likely(inPool1(p.i)))
307 {
308 return false;
309 }
310 return getValidPtr_pool2(p,magic, slot_size);
311 }
312
313 template<typename Pool1, typename Pool2>
getValidPtr_pool2(Ptr<Slot> & p,Uint32 magic,Uint32 slot_size) const314 inline bool ComposedSlotPool<Pool1, Pool2>::getValidPtr_pool2(
315 Ptr<Slot>& p, Uint32 magic, Uint32 slot_size) const
316 {
317 p.i = toPool2(p.i);
318 bool ok = m_pool2.getValidPtr(p, magic, slot_size);
319 p.i = fromPool2(p.i);
320 return ok;
321 }
322
323 template <typename Pool1, typename Pool2>
getUncheckedPtrRO(Ptr<Slot> & p,Uint32 slot_size) const324 inline bool ComposedSlotPool<Pool1, Pool2>::getUncheckedPtrRO(
325 Ptr<Slot>& p, Uint32 slot_size) const
326 {
327 if (likely(m_pool1.getUncheckedPtrRO(p, slot_size)))
328 {
329 return true;
330 }
331 if (likely(inPool1(p.i)))
332 {
333 return false;
334 }
335 return getUncheckedPtrRO_pool2(p, slot_size);
336 }
337
338 template<typename Pool1, typename Pool2>
getUncheckedPtrRO_pool2(Ptr<Slot> & p,Uint32 slot_size) const339 inline bool ComposedSlotPool<Pool1, Pool2>::getUncheckedPtrRO_pool2(
340 Ptr<Slot>& p, Uint32 slot_size) const
341 {
342 p.i = toPool2(p.i);
343 bool ok = m_pool2.getUncheckedPtrRO(p, slot_size);
344 p.i = fromPool2(p.i);
345 return ok;
346 }
347
348 template <typename Pool1, typename Pool2>
getUncheckedPtrRW(Ptr<Slot> & p,Uint32 slot_size) const349 inline bool ComposedSlotPool<Pool1, Pool2>::getUncheckedPtrRW(
350 Ptr<Slot>& p, Uint32 slot_size) const
351 {
352 if (likely(m_pool1.getUncheckedPtrRW(p, slot_size)))
353 {
354 return true;
355 }
356 if (likely(inPool1(p.i)))
357 {
358 return false;
359 }
360 return getUncheckedPtrRW_pool2(p, slot_size);
361 }
362
363 template<typename Pool1, typename Pool2>
getUncheckedPtrRW_pool2(Ptr<Slot> & p,Uint32 slot_size) const364 inline bool ComposedSlotPool<Pool1, Pool2>::getUncheckedPtrRW_pool2(
365 Ptr<Slot>& p, Uint32 slot_size) const
366 {
367 p.i = toPool2(p.i);
368 bool ok = m_pool2.getUncheckedPtrRW(p, slot_size);
369 p.i = fromPool2(p.i);
370 return ok;
371 }
372
373 template <typename Pool1, typename Pool2>
may_shrink() const374 inline bool ComposedSlotPool<Pool1, Pool2>::may_shrink() const
375 {
376 return unlikely(m_pool1.may_shrink() || m_pool2.may_shrink()) &&
377 (getNoOfFree() > m_shrink_level);
378 }
379
380 template <typename Pool1, typename Pool2>
rearrange_free_list_and_shrink(Uint32 max_shrinks)381 inline bool ComposedSlotPool<Pool1, Pool2>::rearrange_free_list_and_shrink(
382 Uint32 max_shrinks)
383 {
384 bool more = false;
385 Uint32 pool1_shrinks = max_shrinks;
386 more |= m_pool1.rearrange_free_list_and_shrink(&pool1_shrinks, m_slot_size);
387 Uint32 pool2_shrinks = max_shrinks - pool1_shrinks;
388 more |= m_pool2.rearrange_free_list_and_shrink(&pool2_shrinks, m_slot_size);
389 return more;
390 }
391
392 template <typename Pool1, typename Pool2>
inPool1(Uint32 i) const393 inline bool ComposedSlotPool<Pool1, Pool2>::inPool1(Uint32 i) const
394 {
395 return i < m_pool1.getSize();
396 }
397
398 template <typename Pool1, typename Pool2>
toPool2(Uint32 i) const399 inline Uint32 ComposedSlotPool<Pool1, Pool2>::toPool2(Uint32 i) const
400 {
401 if (unlikely(i == RNIL)) return RNIL;
402 require(i >= m_pool1.getSize());
403 return i - m_pool1.getSize();
404 }
405
406 template <typename Pool1, typename Pool2>
fromPool2(Uint32 i) const407 inline Uint32 ComposedSlotPool<Pool1, Pool2>::fromPool2(Uint32 i) const
408 {
409 if (unlikely(i == RNIL)) return RNIL;
410 assert(i < RNIL - m_pool1.getSize());
411 return (i + m_pool1.getSize());
412 }
413
414 #undef JAM_FILE_ID
415
416 #endif
417