MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DbtupFixAlloc.cpp
1 /*
2  Copyright (c) 2003, 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 as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #define DBTUP_C
19 #define DBTUP_FIXALLOC_CPP
20 #include "Dbtup.hpp"
21 #include <RefConvert.hpp>
22 #include <ndb_limits.h>
23 #include <pc.hpp>
24 
25 //
26 // Fixed Allocator
27 // This module is used to allocate and free fixed size tuples from the
28 // set of pages attached to a fragment. The fixed size is preset per
29 // fragment and their can only be one such value per fragment in the
30 // current implementation.
31 //
32 // Public methods
33 // bool
34 // alloc_fix_rec(Fragrecord* const regFragPtr, # In
35 // Tablerec* const regTabPtr, # In
36 // Uint32 pageType, # In
37 // Signal* signal, # In
38 // Uint32& pageOffset, # Out
39 // PagePtr& pagePtr) # In/Out
40 // This method allocates a fixed size and the pagePtr is a reference
41 // to the page and pageOffset is the offset in the page of the tuple.
42 //
43 // freeTh()
44 // This method is used to free a tuple header in normal transaction
45 // handling.
46 //
47 // getThAtPageSr()
48 // This method is used to allocate a tuple on a set page as part of
49 // undo log execution.
50 //
51 //
52 // Private methods
53 // getThAtPage()
54 // This method gets a tuple from a page with free tuples.
55 //
56 // convertThPage()
57 // Convert an empty page into a page of free tuples in a linked list.
58 //
59 // getEmptyPageTh()
60 // A page recently taken from the set of empty pages on the fragment is
61 // is made part of the set of free pages with fixed size tuples in the
62 // fragment.
63 //
64 Uint32*
65 Dbtup::alloc_fix_rec(Uint32 * err,
66  Fragrecord* const regFragPtr,
67  Tablerec* const regTabPtr,
68  Local_key* key,
69  Uint32 * out_frag_page_id)
70 {
71 /* ---------------------------------------------------------------- */
72 /* EITHER NORMAL PAGE REQUESTED OR ALLOCATION FROM COPY PAGE */
73 /* FAILED. TRY ALLOCATING FROM NORMAL PAGE. */
74 /* ---------------------------------------------------------------- */
75  PagePtr pagePtr;
76  pagePtr.i = regFragPtr->thFreeFirst.firstItem;
77  if (pagePtr.i == RNIL) {
78 /* ---------------------------------------------------------------- */
79 // No prepared tuple header page with free entries exists.
80 /* ---------------------------------------------------------------- */
81  pagePtr.i = allocFragPage(err, regFragPtr);
82  if (pagePtr.i != RNIL) {
83  jam();
84 /* ---------------------------------------------------------------- */
85 // We found empty pages on the fragment. Allocate an empty page and
86 // convert it into a tuple header page and put it in thFreeFirst-list.
87 /* ---------------------------------------------------------------- */
88  c_page_pool.getPtr(pagePtr);
89 
90  convertThPage((Fix_page*)pagePtr.p, regTabPtr, MM);
91  pagePtr.p->page_state = ZTH_MM_FREE;
92 
93  LocalDLFifoList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
94  free_pages.addFirst(pagePtr);
95  } else {
96  jam();
97 /* ---------------------------------------------------------------- */
98 /* THERE ARE NO EMPTY PAGES. MEMORY CAN NOT BE ALLOCATED. */
99 /* ---------------------------------------------------------------- */
100  return 0;
101  }
102  } else {
103  jam();
104 /* ---------------------------------------------------------------- */
105 /* THIS SHOULD BE THE COMMON PATH THROUGH THE CODE, FREE */
106 /* COPY PAGE EXISTED. */
107 /* ---------------------------------------------------------------- */
108  c_page_pool.getPtr(pagePtr);
109  }
110 
111  Uint32 page_offset= alloc_tuple_from_page(regFragPtr, (Fix_page*)pagePtr.p);
112 
113  *out_frag_page_id= pagePtr.p->frag_page_id;
114  key->m_page_no = pagePtr.i;
115  key->m_page_idx = page_offset;
116  return pagePtr.p->m_data + page_offset;
117 }
118 
119 void Dbtup::convertThPage(Fix_page* regPagePtr,
120  Tablerec* regTabPtr,
121  Uint32 mm)
122 {
123  Uint32 nextTuple = regTabPtr->m_offsets[mm].m_fix_header_size;
124  /*
125  ASSUMES AT LEAST ONE TUPLE HEADER FITS AND THEREFORE NO HANDLING
126  OF ZERO AS EXTREME CASE
127  */
128  Uint32 cnt= 0;
129  Uint32 pos= 0;
130  Uint32 prev = 0xFFFF;
131 #ifdef VM_TRACE
132  memset(regPagePtr->m_data, 0xF1, 4*Fix_page::DATA_WORDS);
133 #endif
134  Uint32 gci_pos = 2;
135  Uint32 gci_val = 0xF1F1F1F1;
136  if (regTabPtr->m_bits & Tablerec::TR_RowGCI)
137  {
138  Tuple_header* ptr = 0;
139  gci_pos = Uint32(ptr->get_mm_gci(regTabPtr) - (Uint32*)ptr);
140  gci_val = 0;
141  }
142  while (pos + nextTuple <= Fix_page::DATA_WORDS)
143  {
144  regPagePtr->m_data[pos] = (prev << 16) | (pos + nextTuple);
145  regPagePtr->m_data[pos + 1] = Fix_page::FREE_RECORD;
146  regPagePtr->m_data[pos + gci_pos] = gci_val;
147  prev = pos;
148  pos += nextTuple;
149  cnt ++;
150  }
151 
152  regPagePtr->m_data[prev] |= 0xFFFF;
153  regPagePtr->next_free_index= 0;
154  regPagePtr->free_space= cnt;
155  regPagePtr->m_page_header.m_page_type = File_formats::PT_Tup_fixsize_page;
156 }//Dbtup::convertThPage()
157 
158 Uint32
159 Dbtup::alloc_tuple_from_page(Fragrecord* const regFragPtr,
160  Fix_page* const regPagePtr)
161 {
162  ndbassert(regPagePtr->free_space);
163  Uint32 idx= regPagePtr->alloc_record();
164  if(regPagePtr->free_space == 0)
165  {
166  jam();
167 /* ---------------------------------------------------------------- */
168 /* THIS WAS THE LAST TUPLE HEADER IN THIS PAGE. REMOVE IT FROM*/
169 /* THE TUPLE HEADER FREE LIST OR TH COPY FREE LIST. ALSO SET */
170 /* A PROPER PAGE STATE. */
171 /* */
172 /* WE ALSO HAVE TO INSERT AN UNDO LOG ENTRY TO ENSURE PAGE */
173 /* ARE MAINTAINED EVEN AFTER A SYSTEM CRASH. */
174 /* ---------------------------------------------------------------- */
175  ndbrequire(regPagePtr->page_state == ZTH_MM_FREE);
176  LocalDLFifoList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
177  free_pages.remove((Page*)regPagePtr);
178  regPagePtr->page_state = ZTH_MM_FULL;
179  }
180 
181  return idx;
182 }//Dbtup::getThAtPage()
183 
184 
185 void Dbtup::free_fix_rec(Fragrecord* regFragPtr,
186  Tablerec* regTabPtr,
187  Local_key* key,
188  Fix_page* regPagePtr)
189 {
190  Uint32 free= regPagePtr->free_record(key->m_page_idx);
191  PagePtr pagePtr = { (Page*)regPagePtr, key->m_page_no };
192 
193  if(free == 1)
194  {
195  jam();
196  LocalDLFifoList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
197  ndbrequire(regPagePtr->page_state == ZTH_MM_FULL);
198  regPagePtr->page_state = ZTH_MM_FREE;
199  free_pages.addLast(pagePtr);
200  }
201  else if (free ==
202  (Fix_page::DATA_WORDS / regTabPtr->m_offsets[MM].m_fix_header_size))
203  {
204  jam();
205  Uint32 page_no = pagePtr.p->frag_page_id;
206  LocalDLFifoList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
207  free_pages.remove(pagePtr);
208  releaseFragPage(regFragPtr, page_no, pagePtr);
209  }
210 }//Dbtup::freeTh()
211 
212 Uint32*
213 Dbtup::alloc_fix_rowid(Uint32 * err,
214  Fragrecord* regFragPtr,
215  Tablerec* regTabPtr,
216  Local_key* key,
217  Uint32 * out_frag_page_id)
218 {
219  Uint32 page_no = key->m_page_no;
220  Uint32 idx= key->m_page_idx;
221 
222  PagePtr pagePtr;
223  if ((pagePtr.i = allocFragPage(err, regTabPtr, regFragPtr, page_no)) == RNIL)
224  {
225  return 0;
226  }
227 
228  c_page_pool.getPtr(pagePtr);
229  Uint32 state = pagePtr.p->page_state;
230  LocalDLFifoList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
231  switch(state){
232  case ZTH_MM_FREE:
233  if (((Fix_page*)pagePtr.p)->alloc_record(idx) != idx)
234  {
235  * err = ZROWID_ALLOCATED;
236  return 0;
237  }
238 
239  if(pagePtr.p->free_space == 0)
240  {
241  jam();
242  pagePtr.p->page_state = ZTH_MM_FULL;
243  free_pages.remove(pagePtr);
244  }
245 
246  *out_frag_page_id= page_no;
247  key->m_page_no = pagePtr.i;
248  key->m_page_idx = idx;
249  return pagePtr.p->m_data + idx;
250  case ZTH_MM_FULL:
251  * err = ZROWID_ALLOCATED;
252  return 0;
253  default:
254  ndbrequire(false);
255  }
256  return 0; /* purify: deadcode */
257 }