MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RWPool.cpp
1 /*
2  Copyright (C) 2006-2008 MySQL AB
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include "RWPool.hpp"
20 #include <ndbd_exit_codes.h>
21 #include <NdbOut.hpp>
22 
23 #define REC_NIL GLOBAL_PAGE_SIZE_WORDS
24 
25 RWPool::RWPool()
26 {
27  memset(this, 0, sizeof(* this));
28  m_current_pos = RWPage::RWPAGE_WORDS;
29  m_current_first_free = REC_NIL;
30  m_first_free_page = RNIL;
31 }
32 
33 void
34 RWPool::init(const Record_info& ri, const Pool_context& pc)
35 {
36  m_ctx = pc;
37  m_record_info = ri;
38  m_record_info.m_size = ((ri.m_size + 3) >> 2); // Align to word boundary
39  m_record_info.m_offset_magic = ((ri.m_offset_magic + 3) >> 2);
40  m_record_info.m_offset_next_pool = ((ri.m_offset_next_pool + 3) >> 2);
41  m_memroot = (RWPage*)m_ctx.get_memroot();
42  ndbout_c("RWPool::init(%x, %d)",ri.m_type_id, m_record_info.m_size);
43 }
44 
45 bool
46 RWPool::seize(Ptr<void>& ptr)
47 {
48  Uint32 pos = m_current_pos;
49  Uint32 size = m_record_info.m_size;
50  Uint32 off = m_record_info.m_offset_magic;
51  RWPage *pageP = m_current_page;
52  if (likely(m_current_first_free != REC_NIL))
53  {
54 seize_free:
55  pos = m_current_first_free;
56  ptr.i = (m_current_page_no << POOL_RECORD_BITS) + pos;
57  ptr.p = pageP->m_data + pos;
58  pageP->m_data[pos+off] = ~(Uint32)m_record_info.m_type_id;
59  m_current_ref_count++;
60  m_current_first_free = pageP->m_data[pos+m_record_info.m_offset_next_pool];
61  return true;
62  }
63  else if (pos + size < RWPage::RWPAGE_WORDS)
64  {
65 seize_first:
66  ptr.i = (m_current_page_no << POOL_RECORD_BITS) + pos;
67  ptr.p = (pageP->m_data + pos);
68  pageP->m_data[pos+off] = ~(Uint32)m_record_info.m_type_id;
69  m_current_ref_count++;
70  m_current_pos = pos + size;
71  return true;
72  }
73 
74  if (m_current_page)
75  {
76  m_current_page->m_first_free = REC_NIL;
77  m_current_page->m_next_page = RNIL;
78  m_current_page->m_prev_page = RNIL;
79  m_current_page->m_type_id = m_record_info.m_type_id;
80  m_current_page->m_ref_count = m_current_ref_count;
81  }
82 
83  if (m_first_free_page != RNIL)
84  {
85  pageP = m_current_page = m_memroot + m_first_free_page;
86  m_current_page_no = m_first_free_page;
87  m_current_pos = RWPage::RWPAGE_WORDS;
88  m_current_first_free = m_current_page->m_first_free;
89  m_first_free_page = m_current_page->m_next_page;
90  m_current_ref_count = m_current_page->m_ref_count;
91  if (m_first_free_page != RNIL)
92  {
93  (m_memroot + m_first_free_page)->m_prev_page = RNIL;
94  }
95  goto seize_free;
96  }
97 
98  m_current_ref_count = 0;
99 
100  RWPage* page;
101  Uint32 page_no = RNIL;
102  if ((page = (RWPage*)m_ctx.alloc_page(m_record_info.m_type_id, &page_no)))
103  {
104  pos = 0;
105  m_current_page_no = page_no;
106  pageP = m_current_page = page;
107  m_current_first_free = REC_NIL;
108  page->m_type_id = m_record_info.m_type_id;
109  goto seize_first;
110  }
111 
112  m_current_page = 0;
113  m_current_page_no = RNIL;
114  m_current_pos = RWPage::RWPAGE_WORDS;
115  m_current_first_free = REC_NIL;
116 
117  return false;
118 }
119 
120 void
122 {
123  Uint32 cur_page = m_current_page_no;
124  Uint32 ptr_page = ptr.i >> POOL_RECORD_BITS;
125  Uint32 *record_ptr = (Uint32*)ptr.p;
126  Uint32 magic_val = * (record_ptr + m_record_info.m_offset_magic);
127 
128  if (likely(magic_val == ~(Uint32)m_record_info.m_type_id))
129  {
130  * (record_ptr + m_record_info.m_offset_magic) = 0;
131  if (cur_page == ptr_page)
132  {
133  * (record_ptr + m_record_info.m_offset_next_pool) = m_current_first_free;
134  assert(m_current_ref_count);
135  m_current_ref_count--;
136  m_current_first_free = ptr.i & POOL_RECORD_MASK;
137  return;
138  }
139 
140  // Cache miss on page...
141  RWPage* page = m_memroot + ptr_page;
142  Uint32 ref_cnt = page->m_ref_count;
143  Uint32 ff = page->m_first_free;
144 
145  * (record_ptr + m_record_info.m_offset_next_pool) = ff;
146  page->m_first_free = ptr.i & POOL_RECORD_MASK;
147  page->m_ref_count = ref_cnt - 1;
148 
149  if (ff == REC_NIL)
150  {
154  Uint32 ffp = m_first_free_page;
155  if (ffp != RNIL)
156  {
157  RWPage* next = (m_memroot + ffp);
158  assert(next->m_prev_page == RNIL);
159  next->m_prev_page = ptr_page;
160  }
161  page->m_next_page = ffp;
162  page->m_prev_page = RNIL;
163  m_first_free_page = ptr_page;
164  return;
165  }
166  else if(ref_cnt == 1)
167  {
171  Uint32 prev = page->m_prev_page;
172  Uint32 next = page->m_next_page;
173  if (prev != RNIL)
174  {
175  (m_memroot + prev)->m_next_page = next;
176  }
177  else
178  {
179  assert(m_first_free_page == ptr_page);
180  m_first_free_page = next;
181  }
182 
183  if (next != RNIL)
184  {
185  (m_memroot + next)->m_prev_page = prev;
186  }
187  m_ctx.release_page(m_record_info.m_type_id, ptr_page);
188  return;
189  }
190  return;
191  }
192  handle_invalid_release(ptr);
193 }
194 
195 void
196 RWPool::handle_invalid_release(Ptr<void> ptr)
197 {
198  char buf[255];
199 
200  Uint32 pos = ptr.i & POOL_RECORD_MASK;
201  Uint32 pageI = ptr.i >> POOL_RECORD_BITS;
202  Uint32 * record_ptr_p = (Uint32*)ptr.p;
203  Uint32 * record_ptr_i = (m_memroot+pageI)->m_data + pos;
204 
205  Uint32 magic = * (record_ptr_p + m_record_info.m_offset_magic);
206  BaseString::snprintf(buf, sizeof(buf),
207  "Invalid memory release: ptr (%x %p %p) magic: (%.8x %.8x) memroot: %p page: %x",
208  ptr.i, ptr.p, record_ptr_i, magic, m_record_info.m_type_id,
209  m_memroot,
210  (m_memroot+pageI)->m_type_id);
211 
212  m_ctx.handleAbort(NDBD_EXIT_PRGERR, buf);
213 }
214 
215 void
216 RWPool::handle_invalid_get_ptr(Uint32 ptrI)
217 {
218  char buf[255];
219 
220  Uint32 pos = ptrI & POOL_RECORD_MASK;
221  Uint32 pageI = ptrI >> POOL_RECORD_BITS;
222  Uint32 * record_ptr_i = (m_memroot+pageI)->m_data + pos;
223 
224  Uint32 magic = * (record_ptr_i + m_record_info.m_offset_magic);
225  BaseString::snprintf(buf, sizeof(buf),
226  "Invalid memory access: ptr (%x %p) magic: (%.8x %.8x) memroot: %p page: %x",
227  ptrI, record_ptr_i, magic, m_record_info.m_type_id,
228  m_memroot,
229  (m_memroot+pageI)->m_type_id);
230 
231  m_ctx.handleAbort(NDBD_EXIT_PRGERR, buf);
232 }