1
/* Copyright (C) 2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
#include <ndbd_exit_codes.h>
20
#define REC_NIL GLOBAL_PAGE_SIZE_WORDS
24
bzero(this, sizeof(* this));
25
m_current_pos = RWPage::RWPAGE_WORDS;
26
m_current_first_free = REC_NIL;
27
m_first_free_page = RNIL;
31
RWPool::init(const Record_info& ri, const Pool_context& pc)
35
m_record_info.m_size = ((ri.m_size + 3) >> 2); // Align to word boundary
36
m_record_info.m_offset_magic = ((ri.m_offset_magic + 3) >> 2);
37
m_record_info.m_offset_next_pool = ((ri.m_offset_next_pool + 3) >> 2);
38
m_memroot = (RWPage*)m_ctx.get_memroot();
39
ndbout_c("RWPool::init(%x, %d)",ri.m_type_id, m_record_info.m_size);
43
RWPool::seize(Ptr<void>& ptr)
45
Uint32 pos = m_current_pos;
46
Uint32 size = m_record_info.m_size;
47
Uint32 off = m_record_info.m_offset_magic;
48
RWPage *pageP = m_current_page;
49
if (likely(m_current_first_free != REC_NIL))
52
pos = m_current_first_free;
53
ptr.i = (m_current_page_no << POOL_RECORD_BITS) + pos;
54
ptr.p = pageP->m_data + pos;
55
pageP->m_data[pos+off] = ~(Uint32)m_record_info.m_type_id;
56
m_current_ref_count++;
57
m_current_first_free = pageP->m_data[pos+m_record_info.m_offset_next_pool];
60
else if (pos + size < RWPage::RWPAGE_WORDS)
63
ptr.i = (m_current_page_no << POOL_RECORD_BITS) + pos;
64
ptr.p = (pageP->m_data + pos);
65
pageP->m_data[pos+off] = ~(Uint32)m_record_info.m_type_id;
66
m_current_ref_count++;
67
m_current_pos = pos + size;
73
m_current_page->m_first_free = REC_NIL;
74
m_current_page->m_next_page = RNIL;
75
m_current_page->m_prev_page = RNIL;
76
m_current_page->m_type_id = m_record_info.m_type_id;
77
m_current_page->m_ref_count = m_current_ref_count;
80
if (m_first_free_page != RNIL)
82
pageP = m_current_page = m_memroot + m_first_free_page;
83
m_current_page_no = m_first_free_page;
84
m_current_pos = RWPage::RWPAGE_WORDS;
85
m_current_first_free = m_current_page->m_first_free;
86
m_first_free_page = m_current_page->m_next_page;
87
m_current_ref_count = m_current_page->m_ref_count;
88
if (m_first_free_page != RNIL)
90
(m_memroot + m_first_free_page)->m_prev_page = RNIL;
95
m_current_ref_count = 0;
98
Uint32 page_no = RNIL;
99
if ((page = (RWPage*)m_ctx.alloc_page(m_record_info.m_type_id, &page_no)))
102
m_current_page_no = page_no;
103
pageP = m_current_page = page;
104
m_current_first_free = REC_NIL;
105
page->m_type_id = m_record_info.m_type_id;
110
m_current_page_no = RNIL;
111
m_current_pos = RWPage::RWPAGE_WORDS;
112
m_current_first_free = REC_NIL;
118
RWPool::release(Ptr<void> ptr)
120
Uint32 cur_page = m_current_page_no;
121
Uint32 ptr_page = ptr.i >> POOL_RECORD_BITS;
122
Uint32 *record_ptr = (Uint32*)ptr.p;
123
Uint32 magic_val = * (record_ptr + m_record_info.m_offset_magic);
125
if (likely(magic_val == ~(Uint32)m_record_info.m_type_id))
127
* (record_ptr + m_record_info.m_offset_magic) = 0;
128
if (cur_page == ptr_page)
130
* (record_ptr + m_record_info.m_offset_next_pool) = m_current_first_free;
131
assert(m_current_ref_count);
132
m_current_ref_count--;
133
m_current_first_free = ptr.i & POOL_RECORD_MASK;
137
// Cache miss on page...
138
RWPage* page = m_memroot + ptr_page;
139
Uint32 ref_cnt = page->m_ref_count;
140
Uint32 ff = page->m_first_free;
142
* (record_ptr + m_record_info.m_offset_next_pool) = ff;
143
page->m_first_free = ptr.i & POOL_RECORD_MASK;
144
page->m_ref_count = ref_cnt - 1;
149
* It was full...add to free page list
151
Uint32 ffp = m_first_free_page;
154
RWPage* next = (m_memroot + ffp);
155
assert(next->m_prev_page == RNIL);
156
next->m_prev_page = ptr_page;
158
page->m_next_page = ffp;
159
page->m_prev_page = RNIL;
160
m_first_free_page = ptr_page;
163
else if(ref_cnt == 1)
166
* It's now empty...release it
168
Uint32 prev = page->m_prev_page;
169
Uint32 next = page->m_next_page;
172
(m_memroot + prev)->m_next_page = next;
176
assert(m_first_free_page == ptr_page);
177
m_first_free_page = next;
182
(m_memroot + next)->m_prev_page = prev;
184
m_ctx.release_page(m_record_info.m_type_id, ptr_page);
189
handle_invalid_release(ptr);
193
RWPool::handle_invalid_release(Ptr<void> ptr)
197
Uint32 pos = ptr.i & POOL_RECORD_MASK;
198
Uint32 pageI = ptr.i >> POOL_RECORD_BITS;
199
Uint32 * record_ptr_p = (Uint32*)ptr.p;
200
Uint32 * record_ptr_i = (m_memroot+pageI)->m_data + pos;
202
Uint32 magic = * (record_ptr_p + m_record_info.m_offset_magic);
203
snprintf(buf, sizeof(buf),
204
"Invalid memory release: ptr (%x %p %p) magic: (%.8x %.8x) memroot: %p page: %x",
205
ptr.i, ptr.p, record_ptr_i, magic, m_record_info.m_type_id,
207
(m_memroot+pageI)->m_type_id);
209
m_ctx.handleAbort(NDBD_EXIT_PRGERR, buf);
213
RWPool::handle_invalid_get_ptr(Uint32 ptrI)
217
Uint32 pos = ptrI & POOL_RECORD_MASK;
218
Uint32 pageI = ptrI >> POOL_RECORD_BITS;
219
Uint32 * record_ptr_i = (m_memroot+pageI)->m_data + pos;
221
Uint32 magic = * (record_ptr_i + m_record_info.m_offset_magic);
222
snprintf(buf, sizeof(buf),
223
"Invalid memory access: ptr (%x %p) magic: (%.8x %.8x) memroot: %p page: %x",
224
ptrI, record_ptr_i, magic, m_record_info.m_type_id,
226
(m_memroot+pageI)->m_type_id);
228
m_ctx.handleAbort(NDBD_EXIT_PRGERR, buf);