mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / ndb / src / kernel / blocks / dbtup / test_varpage.cpp
blob63b1c497958bfdc492da3c43bcdde106041cf757
1 /* Copyright (c) 2005, 2006 MySQL AB
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16 #include <ndb_global.h>
17 #include "tuppage.hpp"
18 #include <Vector.hpp>
20 struct Record
22 Uint32 idx;
23 Uint32 size;
24 Uint32* data;
27 NdbOut&
28 operator <<(NdbOut& out, const Record& rec)
30 out << "[ idx: " << rec.idx << " sz: " << rec.size << " ]";
31 return out;
34 #define TRACE(x) x
36 static
37 bool
38 cmp(const Uint32 *p1, const Uint32 *p2, Uint32 words)
40 if(memcmp(p1, p2, 4*words) == 0)
41 return true;
43 for(Uint32 i = 0; i<words; i++)
44 printf(" %.8x", p1[i]);
45 printf("\n");
47 for(Uint32 i = 0; i<words; i++)
48 printf(" %.8x", p2[i]);
49 printf("\n");
51 return false;
54 static
55 void
56 do_test(int loops, int dist[5])
58 fprintf(stderr, "do_test(%d, [ %d %d %d %d %d ])\n",
59 loops,
60 dist[0],
61 dist[1],
62 dist[2],
63 dist[3],
64 dist[4]);
65 int allocated= 0;
66 Record records[8192];
68 Tup_varsize_page page, tmp;
69 page.init();
71 for(int i = 0; i<loops; i++)
73 assert(page.high_index + page.insert_pos <= page.DATA_WORDS);
75 for(int j = 0; j<allocated; j++)
77 Record rec= records[j];
78 Uint32* ptr= page.get_ptr(rec.idx);
79 Uint32 pos = page.get_ptr(rec.idx) - page.m_data;
80 if (page.get_entry_len(rec.idx) != rec.size)
82 ndbout << "INVALID LEN " << j << " " << rec << " pos: " << pos << endl;
83 ndbout << page << endl;
84 abort();
87 if(!cmp(ptr, rec.data, rec.size))
89 ndbout << "FAILED " << j << " " << rec << " pos: " << pos << endl;
90 ndbout << page << endl;
91 abort();
95 loop:
96 int op;
97 int rnd= rand() % 100;
98 for(op= 0; op<5; op++)
99 if(rnd < dist[op])
100 break;
102 if(allocated == 0)
103 op= 0;
104 if(page.free_space <= 2 && op == 0) goto loop;
106 switch(op){
107 case 0: // Alloc
109 Record rec;
110 rec.size= 1 + (rand() % (page.free_space-1));
111 rec.data = new Uint32[rec.size];
112 for(Uint32 i= 0; i<rec.size; i++)
114 rec.data[i] = rand();
116 ndbout << "Alloc hi: " << page.high_index << " (" <<
117 ((rnd < 30) ? "any" :
118 (rnd < 60) ? "dir" :
119 (rnd < 80) ? "exp" : "fail") << ") ";
120 ndbout << rec.size << flush;
121 if (rnd < 30)
123 rec.idx= page.alloc_record(rec.size, &tmp, 0);
125 else if (rnd < 60)
127 // Alloc with id, from directory
128 Vector<Uint32> free;
129 for(Uint32 i = page.high_index - 1; i > 0; i--)
131 if (page.get_index_word(i) & page.FREE)
133 free.push_back(i);
134 if (free.size() > 100)
135 break;
138 if (free.size())
140 rec.idx = free[rand() % free.size()];
141 if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx)
143 abort();
146 else
148 rec.idx = page.high_index;
149 if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx)
151 if (rec.size + 1 != page.free_space)
152 abort();
153 delete [] rec.data;
154 ndbout_c(" FAIL");
155 break;
159 else if(rnd < 80)
161 // Alloc with id, outside of directory
162 rec.idx = page.high_index + (rand() % (page.free_space - rec.size));
163 if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx)
165 abort();
168 else
170 rec.idx = page.high_index + (page.free_space - rec.size) + 1;
171 if (page.alloc_record(rec.idx, rec.size, &tmp) == rec.idx)
173 abort();
175 delete [] rec.data;
176 ndbout_c(" FAIL");
177 break;
180 Uint32 pos = page.get_ptr(rec.idx) - page.m_data;
181 ndbout << " -> " << rec.idx
182 << " pos: " << pos << endl;
183 Uint32* ptr= page.get_ptr(rec.idx);
184 memcpy(ptr, rec.data, 4*rec.size);
185 records[allocated++] = rec;
186 break;
188 case 1: // Free
190 int no= rand() % allocated;
191 Record rec= records[no];
192 Uint32 pos = page.get_ptr(rec.idx) - page.m_data;
193 ndbout << "Free hi: " << page.high_index << " no: " << no << " idx: " << rec.idx << " pos: " << pos << endl;
194 Uint32* ptr= page.get_ptr(rec.idx);
195 assert(page.get_entry_len(rec.idx) == rec.size);
196 cmp(ptr, rec.data, rec.size);
197 delete[] rec.data;
198 page.free_record(rec.idx, 0);
200 for (unsigned k = no; k + 1 < allocated; k++)
201 records[k] = records[k+1];
202 allocated--;
204 break;
206 case 2: // Reorg
207 ndbout << "Reorg" << endl;
208 page.reorg(&tmp);
209 break;
210 case 3:
212 Uint32 free = page.free_space;
213 if (free <= 2)
215 goto shrink;
217 free /= 2;
218 int no = rand() % allocated;
219 Record rec= records[no];
220 ndbout << "Expand no: " << no << " idx: " << rec.idx
221 << " add: " << free << " reorg: "
222 << !page.is_space_behind_entry(rec.idx, free)
223 << endl;
224 if (!page.is_space_behind_entry(rec.idx, free))
226 Uint32 buffer[8192];
227 Uint32 len = page.get_entry_len(rec.idx);
228 memcpy(buffer, page.get_ptr(rec.idx), 4*len);
229 page.set_entry_len(rec.idx, 0);
230 page.free_space += len;
231 page.reorg(&tmp);
232 memcpy(page.get_free_space_ptr(), buffer, 4*len);
233 page.set_entry_offset(rec.idx, page.insert_pos);
234 free += len;
235 records[no].size = 0;
238 page.grow_entry(rec.idx, free);
239 records[no].size += free;
240 Uint32 *ptr = page.get_ptr(rec.idx);
241 Uint32 *new_data = new Uint32[records[no].size];
242 for(Uint32 i= 0; i<records[no].size; i++)
244 ptr[i] = new_data[i] = rand();
246 delete []rec.data;
247 records[no].data = new_data;
248 break;
250 case 4:
252 shrink:
253 int no = rand() % allocated;
254 Record rec = records[no];
255 Uint32 sz = rec.size / 2 + 1;
256 ndbout << "Shrink no: " << no << " idx: " << rec.idx << " remove: "
257 << (rec.size - sz) << endl;
258 page.shrink_entry(rec.idx, sz);
259 records[no].size = sz;
260 break;
265 ndbout << page << endl;
269 main(int argc, char **argv)
271 ndb_init();
273 if (argc > 1)
275 time_t seed = time(0);
276 srand(seed);
277 fprintf(stderr, "srand(%d)\n", seed);
279 // alloc, free, reorg, grow, shrink
281 int t1[] = { 10, 60, 70, 85, 100 };
282 int t2[] = { 30, 60, 70, 85, 100 };
283 int t3[] = { 50, 60, 70, 85, 100 };
285 do_test(10000, t1);
286 do_test(10000, t2);
287 do_test(10000, t3);
289 return 0;
292 template class Vector<Record>;
294 // hp3750
295 struct Signal { Signal(); int foo; };
296 Signal::Signal(){}