~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/src/kernel/vm/RWPool.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2003 MySQL AB
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
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 */
 
15
 
 
16
#include "RWPool.hpp"
 
17
#include <ndbd_exit_codes.h>
 
18
#include <NdbOut.hpp>
 
19
 
 
20
#define REC_NIL GLOBAL_PAGE_SIZE_WORDS
 
21
 
 
22
RWPool::RWPool() 
 
23
{
 
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;
 
28
}
 
29
 
 
30
void
 
31
RWPool::init(const Record_info& ri, const Pool_context& pc)
 
32
{
 
33
  m_ctx = pc;
 
34
  m_record_info = ri;
 
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);
 
40
}
 
41
 
 
42
bool
 
43
RWPool::seize(Ptr<void>& ptr)
 
44
{
 
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))
 
50
  {
 
51
seize_free:
 
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];
 
58
    return true;
 
59
  }
 
60
  else if (pos + size < RWPage::RWPAGE_WORDS)
 
61
  {
 
62
seize_first:
 
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;
 
68
    return true;
 
69
  }
 
70
 
 
71
  if (m_current_page)
 
72
  {
 
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;
 
78
  }
 
79
 
 
80
  if (m_first_free_page != RNIL)
 
81
  {
 
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)
 
89
    {
 
90
      (m_memroot + m_first_free_page)->m_prev_page = RNIL;
 
91
    }
 
92
    goto seize_free;
 
93
  }
 
94
 
 
95
  m_current_ref_count = 0;
 
96
  
 
97
  RWPage* page;
 
98
  Uint32 page_no = RNIL;
 
99
  if ((page = (RWPage*)m_ctx.alloc_page(m_record_info.m_type_id, &page_no)))
 
100
  {
 
101
    pos = 0;
 
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;
 
106
    goto seize_first;
 
107
  }
 
108
 
 
109
  m_current_page = 0;
 
110
  m_current_page_no = RNIL;
 
111
  m_current_pos = RWPage::RWPAGE_WORDS;
 
112
  m_current_first_free = REC_NIL;
 
113
  
 
114
  return false;
 
115
}
 
116
 
 
117
void
 
118
RWPool::release(Ptr<void> ptr)
 
119
{
 
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);
 
124
  
 
125
  if (likely(magic_val == ~(Uint32)m_record_info.m_type_id))
 
126
  {
 
127
    * (record_ptr + m_record_info.m_offset_magic) = 0;
 
128
    if (cur_page == ptr_page)
 
129
    {
 
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;
 
134
      return;
 
135
    }
 
136
 
 
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;
 
141
 
 
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;
 
145
    
 
146
    if (ff == REC_NIL)
 
147
    {
 
148
      /**
 
149
       * It was full...add to free page list
 
150
       */
 
151
      Uint32 ffp = m_first_free_page;
 
152
      if (ffp != RNIL)
 
153
      {
 
154
        RWPage* next = (m_memroot + ffp);
 
155
        assert(next->m_prev_page == RNIL);
 
156
        next->m_prev_page = ptr_page;
 
157
      }
 
158
      page->m_next_page = ffp;
 
159
      page->m_prev_page = RNIL;
 
160
      m_first_free_page = ptr_page;
 
161
      return;
 
162
    }
 
163
    else if(ref_cnt == 1)
 
164
    {
 
165
      /**
 
166
       * It's now empty...release it
 
167
       */
 
168
      Uint32 prev = page->m_prev_page;
 
169
      Uint32 next = page->m_next_page;
 
170
      if (prev != RNIL)
 
171
      {
 
172
        (m_memroot + prev)->m_next_page = next;
 
173
      }
 
174
      else
 
175
      {
 
176
        assert(m_first_free_page == ptr_page);
 
177
        m_first_free_page = next;
 
178
      }
 
179
      
 
180
      if (next != RNIL)
 
181
      {
 
182
        (m_memroot + next)->m_prev_page = prev;
 
183
      }
 
184
      m_ctx.release_page(m_record_info.m_type_id, ptr_page);
 
185
      return;
 
186
    }
 
187
    return;
 
188
  }
 
189
  handle_invalid_release(ptr);
 
190
}
 
191
 
 
192
void
 
193
RWPool::handle_invalid_release(Ptr<void> ptr)
 
194
{
 
195
  char buf[255];
 
196
 
 
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;
 
201
  
 
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,
 
206
           m_memroot,
 
207
           (m_memroot+pageI)->m_type_id);
 
208
  
 
209
  m_ctx.handleAbort(NDBD_EXIT_PRGERR, buf);
 
210
}
 
211
 
 
212
void
 
213
RWPool::handle_invalid_get_ptr(Uint32 ptrI)
 
214
{
 
215
  char buf[255];
 
216
 
 
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;
 
220
  
 
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,
 
225
           m_memroot,
 
226
           (m_memroot+pageI)->m_type_id);
 
227
  
 
228
  m_ctx.handleAbort(NDBD_EXIT_PRGERR, buf);
 
229
}