00001 /* Copyright (C) 2003 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 #define DBTUP_C 00018 #include "Dbtup.hpp" 00019 #include <RefConvert.hpp> 00020 #include <ndb_limits.h> 00021 #include <pc.hpp> 00022 00023 #define ljam() { jamLine(6000 + __LINE__); } 00024 #define ljamEntry() { jamEntryLine(6000 + __LINE__); } 00025 00026 // 00027 // Fixed Allocator 00028 // This module is used to allocate and free fixed size tuples from the 00029 // set of pages attached to a fragment. The fixed size is preset per 00030 // fragment and their can only be one such value per fragment in the 00031 // current implementation. 00032 // 00033 // Public methods 00034 // bool 00035 // alloc_fix_rec(Fragrecord* const regFragPtr, # In 00036 // Tablerec* const regTabPtr, # In 00037 // Uint32 pageType, # In 00038 // Signal* signal, # In 00039 // Uint32& pageOffset, # Out 00040 // PagePtr& pagePtr) # In/Out 00041 // This method allocates a fixed size and the pagePtr is a reference 00042 // to the page and pageOffset is the offset in the page of the tuple. 00043 // 00044 // freeTh() 00045 // This method is used to free a tuple header in normal transaction 00046 // handling. 00047 // 00048 // getThAtPageSr() 00049 // This method is used to allocate a tuple on a set page as part of 00050 // undo log execution. 00051 // 00052 // 00053 // Private methods 00054 // getThAtPage() 00055 // This method gets a tuple from a page with free tuples. 00056 // 00057 // convertThPage() 00058 // Convert an empty page into a page of free tuples in a linked list. 00059 // 00060 // getEmptyPageTh() 00061 // A page recently taken from the set of empty pages on the fragment is 00062 // is made part of the set of free pages with fixed size tuples in the 00063 // fragment. 00064 // 00065 Uint32* 00066 Dbtup::alloc_fix_rec(Fragrecord* const regFragPtr, 00067 Tablerec* const regTabPtr, 00068 Local_key* key, 00069 Uint32 * out_frag_page_id) 00070 { 00071 /* ---------------------------------------------------------------- */ 00072 /* EITHER NORMAL PAGE REQUESTED OR ALLOCATION FROM COPY PAGE */ 00073 /* FAILED. TRY ALLOCATING FROM NORMAL PAGE. */ 00074 /* ---------------------------------------------------------------- */ 00075 PagePtr pagePtr; 00076 pagePtr.i = regFragPtr->thFreeFirst.firstItem; 00077 if (pagePtr.i == RNIL) { 00078 /* ---------------------------------------------------------------- */ 00079 // No prepared tuple header page with free entries exists. 00080 /* ---------------------------------------------------------------- */ 00081 pagePtr.i = getEmptyPage(regFragPtr); 00082 if (pagePtr.i != RNIL) { 00083 ljam(); 00084 /* ---------------------------------------------------------------- */ 00085 // We found empty pages on the fragment. Allocate an empty page and 00086 // convert it into a tuple header page and put it in thFreeFirst-list. 00087 /* ---------------------------------------------------------------- */ 00088 c_page_pool.getPtr(pagePtr); 00089 00090 ndbassert(pagePtr.p->page_state == ZEMPTY_MM); 00091 00092 convertThPage((Fix_page*)pagePtr.p, regTabPtr, MM); 00093 00094 pagePtr.p->page_state = ZTH_MM_FREE; 00095 00096 LocalDLList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst); 00097 free_pages.add(pagePtr); 00098 } else { 00099 ljam(); 00100 /* ---------------------------------------------------------------- */ 00101 /* THERE ARE NO EMPTY PAGES. MEMORY CAN NOT BE ALLOCATED. */ 00102 /* ---------------------------------------------------------------- */ 00103 return 0; 00104 } 00105 } else { 00106 ljam(); 00107 /* ---------------------------------------------------------------- */ 00108 /* THIS SHOULD BE THE COMMON PATH THROUGH THE CODE, FREE */ 00109 /* COPY PAGE EXISTED. */ 00110 /* ---------------------------------------------------------------- */ 00111 c_page_pool.getPtr(pagePtr); 00112 } 00113 00114 Uint32 page_offset= alloc_tuple_from_page(regFragPtr, (Fix_page*)pagePtr.p); 00115 00116 *out_frag_page_id= pagePtr.p->frag_page_id; 00117 key->m_page_no = pagePtr.i; 00118 key->m_page_idx = page_offset; 00119 return pagePtr.p->m_data + page_offset; 00120 } 00121 00122 void Dbtup::convertThPage(Fix_page* regPagePtr, 00123 Tablerec* regTabPtr, 00124 Uint32 mm) 00125 { 00126 Uint32 nextTuple = regTabPtr->m_offsets[mm].m_fix_header_size; 00127 Uint32 endOfList; 00128 /* 00129 ASSUMES AT LEAST ONE TUPLE HEADER FITS AND THEREFORE NO HANDLING 00130 OF ZERO AS EXTREME CASE 00131 */ 00132 Uint32 cnt= 0; 00133 Uint32 pos= 0; 00134 Uint32 prev = 0xFFFF; 00135 #ifdef VM_TRACE 00136 memset(regPagePtr->m_data, 0xF1, 4*Fix_page::DATA_WORDS); 00137 #endif 00138 Uint32 gci_pos = 2; 00139 Uint32 gci_val = 0xF1F1F1F1; 00140 if (regTabPtr->m_bits & Tablerec::TR_RowGCI) 00141 { 00142 Tuple_header* ptr = 0; 00143 gci_pos = ptr->get_mm_gci(regTabPtr) - (Uint32*)ptr; 00144 gci_val = 0; 00145 } 00146 while (pos + nextTuple <= Fix_page::DATA_WORDS) 00147 { 00148 regPagePtr->m_data[pos] = (prev << 16) | (pos + nextTuple); 00149 regPagePtr->m_data[pos + 1] = Fix_page::FREE_RECORD; 00150 regPagePtr->m_data[pos + gci_pos] = gci_val; 00151 prev = pos; 00152 pos += nextTuple; 00153 cnt ++; 00154 } 00155 00156 regPagePtr->m_data[prev] |= 0xFFFF; 00157 regPagePtr->next_free_index= 0; 00158 regPagePtr->free_space= cnt; 00159 regPagePtr->m_page_header.m_page_type = File_formats::PT_Tup_fixsize_page; 00160 }//Dbtup::convertThPage() 00161 00162 Uint32 00163 Dbtup::alloc_tuple_from_page(Fragrecord* const regFragPtr, 00164 Fix_page* const regPagePtr) 00165 { 00166 ndbassert(regPagePtr->free_space); 00167 Uint32 idx= regPagePtr->alloc_record(); 00168 if(regPagePtr->free_space == 0) 00169 { 00170 jam(); 00171 /* ---------------------------------------------------------------- */ 00172 /* THIS WAS THE LAST TUPLE HEADER IN THIS PAGE. REMOVE IT FROM*/ 00173 /* THE TUPLE HEADER FREE LIST OR TH COPY FREE LIST. ALSO SET */ 00174 /* A PROPER PAGE STATE. */ 00175 /* */ 00176 /* WE ALSO HAVE TO INSERT AN UNDO LOG ENTRY TO ENSURE PAGE */ 00177 /* ARE MAINTAINED EVEN AFTER A SYSTEM CRASH. */ 00178 /* ---------------------------------------------------------------- */ 00179 ndbrequire(regPagePtr->page_state == ZTH_MM_FREE); 00180 LocalDLList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst); 00181 free_pages.remove((Page*)regPagePtr); 00182 regPagePtr->page_state = ZTH_MM_FULL; 00183 } 00184 00185 return idx; 00186 }//Dbtup::getThAtPage() 00187 00188 00189 void Dbtup::free_fix_rec(Fragrecord* regFragPtr, 00190 Tablerec* regTabPtr, 00191 Local_key* key, 00192 Fix_page* regPagePtr) 00193 { 00194 Uint32 free= regPagePtr->free_record(key->m_page_idx); 00195 00196 if(free == 1) 00197 { 00198 ljam(); 00199 PagePtr pagePtr = { (Page*)regPagePtr, key->m_page_no }; 00200 LocalDLList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst); 00201 ndbrequire(regPagePtr->page_state == ZTH_MM_FULL); 00202 regPagePtr->page_state = ZTH_MM_FREE; 00203 free_pages.add(pagePtr); 00204 } 00205 }//Dbtup::freeTh() 00206 00207 00208 int 00209 Dbtup::alloc_page(Tablerec* tabPtrP, Fragrecord* fragPtrP, 00210 PagePtr * ret, Uint32 page_no) 00211 { 00212 Uint32 pages = fragPtrP->noOfPages; 00213 00214 if (page_no >= pages) 00215 { 00216 Uint32 start = pages; 00217 while(page_no >= pages) 00218 pages += (pages >> 3) + (pages >> 4) + 2; 00219 allocFragPages(fragPtrP, pages - start); 00220 if (page_no >= (pages = fragPtrP->noOfPages)) 00221 { 00222 terrorCode = ZMEM_NOMEM_ERROR; 00223 return 1; 00224 } 00225 } 00226 00227 PagePtr pagePtr; 00228 c_page_pool.getPtr(pagePtr, getRealpid(fragPtrP, page_no)); 00229 00230 LocalDLList<Page> alloc_pages(c_page_pool, fragPtrP->emptyPrimPage); 00231 LocalDLList<Page> free_pages(c_page_pool, fragPtrP->thFreeFirst); 00232 if (pagePtr.p->page_state == ZEMPTY_MM) 00233 { 00234 convertThPage((Fix_page*)pagePtr.p, tabPtrP, MM); 00235 pagePtr.p->page_state = ZTH_MM_FREE; 00236 alloc_pages.remove(pagePtr); 00237 free_pages.add(pagePtr); 00238 } 00239 00240 *ret = pagePtr; 00241 return 0; 00242 } 00243 00244 Uint32* 00245 Dbtup::alloc_fix_rowid(Fragrecord* regFragPtr, 00246 Tablerec* regTabPtr, 00247 Local_key* key, 00248 Uint32 * out_frag_page_id) 00249 { 00250 Uint32 page_no = key->m_page_no; 00251 Uint32 idx= key->m_page_idx; 00252 00253 PagePtr pagePtr; 00254 if (alloc_page(regTabPtr, regFragPtr, &pagePtr, page_no)) 00255 { 00256 terrorCode = ZMEM_NOMEM_ERROR; 00257 return 0; 00258 } 00259 00260 Uint32 state = pagePtr.p->page_state; 00261 LocalDLList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst); 00262 switch(state){ 00263 case ZTH_MM_FREE: 00264 if (((Fix_page*)pagePtr.p)->alloc_record(idx) != idx) 00265 { 00266 terrorCode = ZROWID_ALLOCATED; 00267 return 0; 00268 } 00269 00270 if(pagePtr.p->free_space == 0) 00271 { 00272 jam(); 00273 pagePtr.p->page_state = ZTH_MM_FULL; 00274 free_pages.remove(pagePtr); 00275 } 00276 00277 *out_frag_page_id= page_no; 00278 key->m_page_no = pagePtr.i; 00279 key->m_page_idx = idx; 00280 return pagePtr.p->m_data + idx; 00281 case ZTH_MM_FULL: 00282 terrorCode = ZROWID_ALLOCATED; 00283 return 0; 00284 case ZEMPTY_MM: 00285 ndbrequire(false); 00286 } 00287 }
1.4.7

