1 /*
2 Copyright (c) 2006, 2010, 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 NDB_POOL_HPP
26 #define NDB_POOL_HPP
27
28 #include <ndb_global.h>
29 #include <kernel_types.h>
30
31 /**
32 * Type bits
33 *
34 * Type id is 11 bits record type, and 5 bits resource id
35 * -> 2048 different kind of records and 32 different resource groups
36 *
37 * Resource id is used to handle configuration parameters
38 *
39 * see blocks/records_types.hpp
40 */
41 #define RG_BITS 5
42 #define RG_MASK ((1 << RG_BITS) - 1)
43 #define MAKE_TID(TID,RG) ((TID << RG_BITS) | RG)
44
45 /**
46 * Page bits
47 */
48 #define POOL_RECORD_BITS 13
49 #define POOL_RECORD_MASK ((1 << POOL_RECORD_BITS) - 1)
50
51 /**
52 * Record_info
53 *
54 */
55 struct Record_info
56 {
57 Uint16 m_size;
58 Uint16 m_type_id;
59 Uint16 m_offset_next_pool;
60 Uint16 m_offset_magic;
61 };
62
63 /**
64 * Resource_limit
65 */
66 struct Resource_limit
67 {
68 Uint32 m_min;
69 Uint32 m_max;
70 Uint32 m_curr;
71 Uint32 m_resource_id;
72 };
73
74 struct Pool_context
75 {
Pool_contextPool_context76 Pool_context() {}
77 class SimulatedBlock* m_block;
78
79 /**
80 * Get mem root
81 */
82 void* get_memroot();
83
84 /**
85 * Alloc consekutive pages
86 *
87 * @param i : out : i value of first page
88 * @return : pointer to first page (NULL if failed)
89 *
90 * Will handle resource limit
91 */
92 void* alloc_page(Uint32 type_id, Uint32 *i);
93
94 /**
95 * Release pages
96 *
97 * @param i : in : i value of first page
98 * @param p : in : pointer to first page
99 */
100 void release_page(Uint32 type_id, Uint32 i);
101
102 /**
103 * Alloc consekutive pages
104 *
105 * @param cnt : in/out : no of requested pages,
106 * return no of allocated (undefined return NULL)
107 * out will never be > in
108 * @param i : out : i value of first page
109 * @param min : in : will never allocate less than min
110 * @return : pointer to first page (NULL if failed)
111 *
112 * Will handle resource limit
113 */
114 void* alloc_pages(Uint32 type_id, Uint32 *i, Uint32 *cnt, Uint32 min =1);
115
116 /**
117 * Release pages
118 *
119 * @param i : in : i value of first page
120 * @param p : in : pointer to first page
121 * @param cnt : in : no of pages to release
122 */
123 void release_pages(Uint32 type_id, Uint32 i, Uint32 cnt);
124
125 /**
126 * Abort
127 */
128 void handleAbort(int code, const char* msg) ATTRIBUTE_NORETURN;
129 };
130
131 template <typename T>
132 struct Ptr
133 {
134 T * p;
135 Uint32 i;
isNullPtr136 inline bool isNull() const { return i == RNIL; }
setNullPtr137 inline void setNull() { i = RNIL; }
138 };
139
140 template <typename T>
141 struct ConstPtr
142 {
143 const T * p;
144 Uint32 i;
isNullConstPtr145 inline bool isNull() const { return i == RNIL; }
setNullConstPtr146 inline void setNull() { i = RNIL; }
147 };
148
149 #ifdef XX_DOCUMENTATION_XX
150 /**
151 * Any pool should implement the following
152 */
153 struct PoolImpl
154 {
155 Pool_context m_ctx;
156 Record_info m_record_info;
157
158 void init(const Record_info& ri, const Pool_context& pc);
159 void init(const Record_info& ri, const Pool_context& pc);
160
161 bool seize(Ptr<void>&);
162 void release(Ptr<void>);
163 void * getPtr(Uint32 i);
164 };
165 #endif
166
167 struct ArenaHead; // forward decl.
168 class ArenaAllocator; // forward decl.
169
170 template <typename T, typename P>
171 class RecordPool {
172 public:
173 RecordPool();
174 ~RecordPool();
175
176 void init(Uint32 type_id, const Pool_context& pc);
177 void wo_pool_init(Uint32 type_id, const Pool_context& pc);
178 void arena_pool_init(ArenaAllocator*, Uint32 type_id, const Pool_context& pc);
179
180 /**
181 * Update p value for ptr according to i value
182 */
183 void getPtr(Ptr<T> &);
184 void getPtr(ConstPtr<T> &) const;
185
186 /**
187 * Get pointer for i value
188 */
189 T * getPtr(Uint32 i);
190 const T * getConstPtr(Uint32 i) const;
191
192 /**
193 * Update p & i value for ptr according to <b>i</b> value
194 */
195 void getPtr(Ptr<T> &, Uint32 i);
196 void getPtr(ConstPtr<T> &, Uint32 i) const;
197
198 /**
199 * Allocate an object from pool - update Ptr
200 *
201 * Return i
202 */
203 bool seize(Ptr<T> &);
204
205 /**
206 * Allocate object from arena - update Ptr
207 */
208 bool seize(ArenaHead&, Ptr<T>&);
209
210 /**
211 * Return an object to pool
212 */
213 void release(Uint32 i);
214
215 /**
216 * Return an object to pool
217 */
218 void release(Ptr<T>);
219 private:
220 P m_pool;
221 };
222
223 template <typename T, typename P>
224 inline
RecordPool()225 RecordPool<T, P>::RecordPool()
226 {
227 }
228
229 template <typename T, typename P>
230 inline
231 void
init(Uint32 type_id,const Pool_context & pc)232 RecordPool<T, P>::init(Uint32 type_id, const Pool_context& pc)
233 {
234 T tmp;
235 const char * off_base = (char*)&tmp;
236 const char * off_next = (char*)&tmp.nextPool;
237 const char * off_magic = (char*)&tmp.m_magic;
238
239 Record_info ri;
240 ri.m_size = sizeof(T);
241 ri.m_offset_next_pool = Uint32(off_next - off_base);
242 ri.m_offset_magic = Uint32(off_magic - off_base);
243 ri.m_type_id = type_id;
244 m_pool.init(ri, pc);
245 }
246
247 template <typename T, typename P>
248 inline
249 void
wo_pool_init(Uint32 type_id,const Pool_context & pc)250 RecordPool<T, P>::wo_pool_init(Uint32 type_id, const Pool_context& pc)
251 {
252 T tmp;
253 const char * off_base = (char*)&tmp;
254 const char * off_magic = (char*)&tmp.m_magic;
255
256 Record_info ri;
257 ri.m_size = sizeof(T);
258 ri.m_offset_next_pool = 0;
259 ri.m_offset_magic = Uint32(off_magic - off_base);
260 ri.m_type_id = type_id;
261 m_pool.init(ri, pc);
262 }
263
264 template <typename T, typename P>
265 inline
266 void
arena_pool_init(ArenaAllocator * alloc,Uint32 type_id,const Pool_context & pc)267 RecordPool<T, P>::arena_pool_init(ArenaAllocator* alloc,
268 Uint32 type_id, const Pool_context& pc)
269 {
270 T tmp;
271 const char * off_base = (char*)&tmp;
272 const char * off_next = (char*)&tmp.nextPool;
273 const char * off_magic = (char*)&tmp.m_magic;
274
275 Record_info ri;
276 ri.m_size = sizeof(T);
277 ri.m_offset_next_pool = Uint32(off_next - off_base);
278 ri.m_offset_magic = Uint32(off_magic - off_base);
279 ri.m_type_id = type_id;
280 m_pool.init(alloc, ri, pc);
281 }
282
283
284 template <typename T, typename P>
285 inline
~RecordPool()286 RecordPool<T, P>::~RecordPool()
287 {
288 }
289
290
291 template <typename T, typename P>
292 inline
293 void
getPtr(Ptr<T> & ptr)294 RecordPool<T, P>::getPtr(Ptr<T> & ptr)
295 {
296 ptr.p = static_cast<T*>(m_pool.getPtr(ptr.i));
297 }
298
299 template <typename T, typename P>
300 inline
301 void
getPtr(ConstPtr<T> & ptr) const302 RecordPool<T, P>::getPtr(ConstPtr<T> & ptr) const
303 {
304 ptr.p = static_cast<const T*>(m_pool.getPtr(ptr.i));
305 }
306
307 template <typename T, typename P>
308 inline
309 void
getPtr(Ptr<T> & ptr,Uint32 i)310 RecordPool<T, P>::getPtr(Ptr<T> & ptr, Uint32 i)
311 {
312 ptr.i = i;
313 ptr.p = static_cast<T*>(m_pool.getPtr(ptr.i));
314 }
315
316 template <typename T, typename P>
317 inline
318 void
getPtr(ConstPtr<T> & ptr,Uint32 i) const319 RecordPool<T, P>::getPtr(ConstPtr<T> & ptr, Uint32 i) const
320 {
321 ptr.i = i;
322 ptr.p = static_cast<const T*>(m_pool.getPtr(ptr.i));
323 }
324
325 template <typename T, typename P>
326 inline
327 T *
getPtr(Uint32 i)328 RecordPool<T, P>::getPtr(Uint32 i)
329 {
330 return static_cast<T*>(m_pool.getPtr(i));
331 }
332
333 template <typename T, typename P>
334 inline
335 const T *
getConstPtr(Uint32 i) const336 RecordPool<T, P>::getConstPtr(Uint32 i) const
337 {
338 return static_cast<const T*>(m_pool.getPtr(i));
339 }
340
341 template <typename T, typename P>
342 inline
343 bool
seize(Ptr<T> & ptr)344 RecordPool<T, P>::seize(Ptr<T> & ptr)
345 {
346 Ptr<void> tmp;
347 bool ret = m_pool.seize(tmp);
348 if(likely(ret))
349 {
350 ptr.i = tmp.i;
351 ptr.p = static_cast<T*>(tmp.p);
352 }
353 return ret;
354 }
355
356 template <typename T, typename P>
357 inline
358 bool
seize(ArenaHead & ah,Ptr<T> & ptr)359 RecordPool<T, P>::seize(ArenaHead & ah, Ptr<T> & ptr)
360 {
361 Ptr<void> tmp;
362 bool ret = m_pool.seize(ah, tmp);
363 if(likely(ret))
364 {
365 ptr.i = tmp.i;
366 ptr.p = static_cast<T*>(tmp.p);
367 }
368 return ret;
369 }
370
371 template <typename T, typename P>
372 inline
373 void
release(Uint32 i)374 RecordPool<T, P>::release(Uint32 i)
375 {
376 Ptr<void> ptr;
377 ptr.i = i;
378 ptr.p = m_pool.getPtr(i);
379 m_pool.release(ptr);
380 }
381
382 template <typename T, typename P>
383 inline
384 void
release(Ptr<T> ptr)385 RecordPool<T, P>::release(Ptr<T> ptr)
386 {
387 Ptr<void> tmp;
388 tmp.i = ptr.i;
389 tmp.p = ptr.p;
390 m_pool.release(tmp);
391 }
392
393 #endif
394