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"
28 operator <<(NdbOut
& out
, const Record
& rec
)
30 out
<< "[ idx: " << rec
.idx
<< " sz: " << rec
.size
<< " ]";
38 cmp(const Uint32
*p1
, const Uint32
*p2
, Uint32 words
)
40 if(memcmp(p1
, p2
, 4*words
) == 0)
43 for(Uint32 i
= 0; i
<words
; i
++)
44 printf(" %.8x", p1
[i
]);
47 for(Uint32 i
= 0; i
<words
; i
++)
48 printf(" %.8x", p2
[i
]);
56 do_test(int loops
, int dist
[5])
58 fprintf(stderr
, "do_test(%d, [ %d %d %d %d %d ])\n",
68 Tup_varsize_page page
, tmp
;
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
;
87 if(!cmp(ptr
, rec
.data
, rec
.size
))
89 ndbout
<< "FAILED " << j
<< " " << rec
<< " pos: " << pos
<< endl
;
90 ndbout
<< page
<< endl
;
97 int rnd
= rand() % 100;
98 for(op
= 0; op
<5; op
++)
104 if(page
.free_space
<= 2 && op
== 0) goto loop
;
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" :
119 (rnd
< 80) ? "exp" : "fail") << ") ";
120 ndbout
<< rec
.size
<< flush
;
123 rec
.idx
= page
.alloc_record(rec
.size
, &tmp
, 0);
127 // Alloc with id, from directory
129 for(Uint32 i
= page
.high_index
- 1; i
> 0; i
--)
131 if (page
.get_index_word(i
) & page
.FREE
)
134 if (free
.size() > 100)
140 rec
.idx
= free
[rand() % free
.size()];
141 if (page
.alloc_record(rec
.idx
, rec
.size
, &tmp
) != rec
.idx
)
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
)
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
)
170 rec
.idx
= page
.high_index
+ (page
.free_space
- rec
.size
) + 1;
171 if (page
.alloc_record(rec
.idx
, rec
.size
, &tmp
) == rec
.idx
)
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
;
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
);
198 page
.free_record(rec
.idx
, 0);
200 for (unsigned k
= no
; k
+ 1 < allocated
; k
++)
201 records
[k
] = records
[k
+1];
207 ndbout
<< "Reorg" << endl
;
212 Uint32 free
= page
.free_space
;
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
)
224 if (!page
.is_space_behind_entry(rec
.idx
, free
))
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
;
232 memcpy(page
.get_free_space_ptr(), buffer
, 4*len
);
233 page
.set_entry_offset(rec
.idx
, page
.insert_pos
);
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();
247 records
[no
].data
= new_data
;
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
;
265 ndbout
<< page
<< endl
;
269 main(int argc
, char **argv
)
275 time_t seed
= time(0);
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 };
292 template class Vector
<Record
>;
295 struct Signal
{ Signal(); int foo
; };