18 #include <ndb_global.h> 
   19 #include "tuppage.hpp" 
   39   Uint32 page_idx = next_free_index;
 
   40   assert(page_idx + 1 < DATA_WORDS);
 
   42   Uint32 prev = m_data[page_idx] >> 16;
 
   43   Uint32 next = m_data[page_idx] & 0xFFFF;
 
   45   assert(prev == 0xFFFF);
 
   46   assert(m_data[page_idx + 1] == FREE_RECORD);
 
   48   m_data[page_idx + 1] = 0;
 
   51     assert(free_space > 1);
 
   52     Uint32 nextP = m_data[next];
 
   53     assert((nextP >> 16) == page_idx);
 
   54     m_data[next] = 0xFFFF0000 | (nextP & 0xFFFF);
 
   58     assert(free_space == 1);
 
   61   next_free_index = next;
 
   69   assert(page_idx + 1 < DATA_WORDS);
 
   70   if (likely(free_space && m_data[page_idx + 1] == FREE_RECORD))
 
   72     Uint32 prev = m_data[page_idx] >> 16;
 
   73     Uint32 next = m_data[page_idx] & 0xFFFF;
 
   75     assert(prev != 0xFFFF || (next_free_index == page_idx));
 
   78       next_free_index = next;
 
   82       Uint32 prevP = m_data[prev];
 
   83       m_data[prev] = (prevP & 0xFFFF0000) | next;
 
   88       Uint32 nextP = m_data[next];
 
   89       m_data[next] = (prev << 16) | (nextP & 0xFFFF);
 
   92     m_data[page_idx + 1] = 0;
 
   99 Tup_fixsize_page::free_record(Uint32 page_idx)
 
  101   Uint32 next = next_free_index;
 
  103   assert(page_idx + 1 < DATA_WORDS);
 
  104   assert(m_data[page_idx + 1] != FREE_RECORD);
 
  108     assert(free_space == 0);
 
  113     assert(next + 1 < DATA_WORDS);
 
  114     Uint32 nextP = m_data[next];
 
  115     assert((nextP >> 16) == 0xFFFF);
 
  116     m_data[next] = (page_idx << 16) | (nextP & 0xFFFF);
 
  117     assert(m_data[next + 1] == FREE_RECORD);
 
  120   next_free_index = page_idx;
 
  121   m_data[page_idx] = 0xFFFF0000 | next;
 
  122   m_data[page_idx + 1] = FREE_RECORD;
 
  128 Tup_varsize_page::init()
 
  130   free_space= DATA_WORDS - 1;
 
  133   next_free_index= END_OF_FREE_LIST;
 
  134   m_page_header.m_page_type = File_formats::PT_Tup_varsize_page;
 
  142   Uint32 free = free_space;
 
  143   Uint32 largest_size= DATA_WORDS - (insert_pos + high_index);
 
  144   Uint32 free_list = next_free_index;
 
  146   if (page_idx < high_index)
 
  148     Uint32 *ptr = get_index_ptr(page_idx);
 
  151     if (unlikely((free < alloc_size) || ! (word & FREE)))
 
  156     if (alloc_size >= largest_size)
 
  166     Uint32 next = (word & NEXT_MASK) >> NEXT_SHIFT;
 
  167     Uint32 prev = (word & PREV_MASK) >> PREV_SHIFT;
 
  169     if (next != END_OF_FREE_LIST)
 
  171       Uint32 * next_ptr = get_index_ptr(next);
 
  172       Uint32 next_word = * next_ptr;
 
  173       * next_ptr = (next_word & ~PREV_MASK) | (prev << PREV_SHIFT);
 
  176     if (prev != END_OF_FREE_LIST)
 
  178       Uint32 * prev_ptr = get_index_ptr(prev);
 
  179       Uint32 prev_word = * prev_ptr;
 
  180       * prev_ptr = (prev_word & ~NEXT_MASK) | (next << NEXT_SHIFT);
 
  184       assert(next_free_index == page_idx);
 
  185       next_free_index = next;
 
  188     * ptr = insert_pos + (alloc_size << LEN_SHIFT);
 
  196     Uint32 hi = high_index;
 
  197     Uint32 expand = (page_idx + 1 - hi);
 
  198     Uint32 
size = alloc_size + expand;
 
  199     if (unlikely(size > free))
 
  204     if (size >= largest_size)
 
  214     Uint32 *ptr = m_data + DATA_WORDS - hi;
 
  217       * ptr = insert_pos + (alloc_size << LEN_SHIFT);
 
  221       if (free_list != END_OF_FREE_LIST)
 
  223         Uint32 * prev_ptr = get_index_ptr(free_list);
 
  224         Uint32 prev_word = * prev_ptr;
 
  225         * prev_ptr = (prev_word & ~PREV_MASK) | (hi << PREV_SHIFT);
 
  228       for (; hi < page_idx;)
 
  230         * ptr-- = FREE | (free_list << NEXT_SHIFT) | ((hi+1) << PREV_SHIFT);
 
  234       * ptr++ = insert_pos + (alloc_size << LEN_SHIFT);
 
  235       * ptr = ((* ptr) & ~PREV_MASK) | (END_OF_FREE_LIST << PREV_SHIFT);
 
  237       next_free_index = hi - 1;
 
  244   insert_pos += alloc_size;
 
  253   assert(free_space >= alloc_size);
 
  254   Uint32 largest_size= DATA_WORDS - (insert_pos + high_index);
 
  255   if (alloc_size >= largest_size) {
 
  262     largest_size= DATA_WORDS - (insert_pos + high_index);
 
  264   assert(largest_size > alloc_size);
 
  267   if (next_free_index == END_OF_FREE_LIST) {
 
  272     page_idx= high_index++;
 
  276     page_idx= next_free_index;
 
  277     assert((get_index_word(page_idx) & FREE) == FREE);
 
  278     assert(((get_index_word(page_idx) & PREV_MASK) >> PREV_SHIFT) == 
 
  280     next_free_index= (get_index_word(page_idx) & NEXT_MASK) >> NEXT_SHIFT;
 
  281     assert(next_free_index);
 
  282     if (next_free_index != END_OF_FREE_LIST)
 
  284       Uint32 *ptr = get_index_ptr(next_free_index);
 
  286       * ptr = (word & ~PREV_MASK) | (END_OF_FREE_LIST << PREV_SHIFT);
 
  290   assert(chain == 0 || chain == CHAIN);
 
  291   * get_index_ptr(page_idx) = insert_pos + chain + (alloc_size << LEN_SHIFT);
 
  293   insert_pos += alloc_size;
 
  294   free_space -= alloc_size;
 
  303   Uint32 *index_ptr= get_index_ptr(page_idx);
 
  304   Uint32 index_word= * index_ptr;
 
  305   Uint32 entry_pos= (index_word & POS_MASK) >> POS_SHIFT;
 
  306   Uint32 entry_len= (index_word & LEN_MASK) >> LEN_SHIFT;
 
  307   assert(chain == 0 || chain == CHAIN);
 
  308   assert((index_word & CHAIN) == chain);
 
  310   memset(m_data + entry_pos, 0xF2, 4*entry_len);
 
  312   if (page_idx + 1 == high_index) {
 
  321     if (next_free_index != END_OF_FREE_LIST)
 
  323       Uint32 *ptr = get_index_ptr(next_free_index);
 
  325       assert(((word & PREV_MASK) >> PREV_SHIFT) == END_OF_FREE_LIST);
 
  326       * ptr = (word & ~PREV_MASK) | (page_idx << PREV_SHIFT);
 
  328     * index_ptr= FREE | next_free_index | (END_OF_FREE_LIST << PREV_SHIFT);
 
  329     next_free_index= page_idx;
 
  330     assert(next_free_index);
 
  333   free_space+= entry_len;
 
  335   insert_pos -= (entry_pos + entry_len == insert_pos ? entry_len : 0);
 
  344   Uint32 *end= m_data + DATA_WORDS;
 
  349   for(index_ptr++; index_ptr < end; index_ptr++)
 
  350     if((* index_ptr) & FREE)
 
  360     next_free_index = END_OF_FREE_LIST;
 
  364   Uint32 next= END_OF_FREE_LIST;
 
  366   Uint32 *prev_ptr = &dummy;
 
  367   for(index_ptr++; index_ptr < end; index_ptr++)
 
  369     if ((* index_ptr) & FREE)
 
  371       * index_ptr= FREE | next;
 
  372       next= Uint32(end - index_ptr);
 
  373       * prev_ptr |= (next << PREV_SHIFT);
 
  374       prev_ptr = index_ptr;
 
  378   * prev_ptr |= (END_OF_FREE_LIST << PREV_SHIFT);
 
  382   next_free_index= next;
 
  383   assert(next_free_index);
 
  389   Uint32 new_insert_pos= 0;
 
  390   Uint32 old_insert_pos= insert_pos;
 
  393   memcpy(copy_page->m_data, m_data, 4*old_insert_pos);
 
  394   assert(high_index > 0);
 
  395   Uint32* index_ptr= get_index_ptr(high_index-1);
 
  396   Uint32 *end_of_page= m_data + DATA_WORDS;
 
  397   for (; index_ptr < end_of_page; index_ptr++)
 
  399     Uint32 index_word= * index_ptr;
 
  400     Uint32 entry_len= (index_word & LEN_MASK) >> LEN_SHIFT;
 
  401     if (!(index_word & FREE) && entry_len) 
 
  407       Uint32 entry_pos= (index_word & POS_MASK) >> POS_SHIFT;
 
  408       assert(entry_pos + entry_len <= old_insert_pos);
 
  409       assert(new_insert_pos + entry_len <= old_insert_pos);
 
  410       * index_ptr= (new_insert_pos << POS_SHIFT) + (index_word & ~POS_MASK);
 
  411       memcpy(m_data+new_insert_pos, copy_page->m_data+entry_pos, 4*entry_len);
 
  413       new_insert_pos += entry_len;
 
  416   insert_pos= new_insert_pos;
 
  422   out << 
"[ Varpage " << &page << 
": free: " << page.free_space
 
  423       << 
" (" << (page.DATA_WORDS - (page.insert_pos + page.high_index + 1)) << 
")" 
  424       << 
" insert_pos: " << page.insert_pos 
 
  425       << 
" high_index: " << page.high_index
 
  426       << 
" index: " << flush;
 
  428   const Uint32 *index_ptr= page.m_data+page.DATA_WORDS-1;
 
  429   for(Uint32 
i = 1; 
i<page.high_index; 
i++, index_ptr--)
 
  432     if(! (*index_ptr & page.FREE))
 
  433       out << 
" pos: " << ((* index_ptr & page.POS_MASK) >> page.POS_SHIFT)
 
  434           << 
" len: " << ((* index_ptr & page.LEN_MASK) >> page.LEN_SHIFT)
 
  435           << ((* index_ptr & page.CHAIN) ? 
" CHAIN " : 
" ") 
 
  438       out << 
" FREE ]" << flush;
 
  441   out << 
" free list: " << flush;
 
  442   Uint32 next= page.next_free_index;
 
  443   while(next != page.END_OF_FREE_LIST)
 
  445     out << next << 
" " << flush;
 
  446     next= ((* (page.m_data+page.DATA_WORDS-next)) & page.NEXT_MASK) >> page.NEXT_SHIFT;
 
  455   out << 
"[ Fixpage " << &page 
 
  456       << 
": frag_page: " << page.frag_page_id 
 
  457       << 
" page_no: " << page.m_page_no 
 
  458       << 
" file_no: " << page.m_file_no
 
  459       << 
" table: " << page.m_table_id
 
  460       << 
" fragment: " << page.m_fragment_id 
 
  461       << 
" uncommitted_used_space: " << page.uncommitted_used_space 
 
  462       << 
" free: " << page.free_space;
 
  464   out << 
" free list: " << hex << page.next_free_index << 
" " << flush;
 
  466   Uint32 startTuple = page.next_free_index >> 16;
 
  468   Uint32 next= startTuple;
 
  469   while((next & 0xFFFF) != 0xFFFF)
 
  472     out << dec << 
"(" << (next & 0xFFFF) << 
" " << hex << next << 
") " << flush;
 
  473     assert(page.m_data[(next & 0xFFFF) + 1] == Dbtup::Tuple_header::FREE);
 
  474     next= * (page.m_data + ( next & 0xFFFF ));
 
  476   assert(cnt == page.free_space);