/* Copyright (C) 2006 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "tuppage.hpp" #include struct Record { Uint32 idx; Uint32 size; Uint32* data; }; NdbOut& operator <<(NdbOut& out, const Record& rec) { out << "[ idx: " << rec.idx << " sz: " << rec.size << " ]"; return out; } #define TRACE(x) x static bool cmp(const Uint32 *p1, const Uint32 *p2, Uint32 words) { if(memcmp(p1, p2, 4*words) == 0) return true; for(Uint32 i = 0; i free; for(Uint32 i = page.high_index - 1; i > 0; i--) { if (page.get_index_word(i) & page.FREE) { free.push_back(i); if (free.size() > 100) break; } } if (free.size()) { rec.idx = free[rand() % free.size()]; if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx) { abort(); } } else { rec.idx = page.high_index; if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx) { if (rec.size + 1 != page.free_space) abort(); delete [] rec.data; ndbout_c(" FAIL"); break; } } } else if(rnd < 80) { // Alloc with id, outside of directory rec.idx = page.high_index + (rand() % (page.free_space - rec.size)); if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx) { abort(); } } else { rec.idx = page.high_index + (page.free_space - rec.size) + 1; if (page.alloc_record(rec.idx, rec.size, &tmp) == rec.idx) { abort(); } delete [] rec.data; ndbout_c(" FAIL"); break; } Uint32 pos = page.get_ptr(rec.idx) - page.m_data; ndbout << " -> " << rec.idx << " pos: " << pos << endl; Uint32* ptr= page.get_ptr(rec.idx); memcpy(ptr, rec.data, 4*rec.size); records[allocated++] = rec; break; } case 1: // Free { int no= rand() % allocated; Record rec= records[no]; Uint32 pos = page.get_ptr(rec.idx) - page.m_data; ndbout << "Free hi: " << page.high_index << " no: " << no << " idx: " << rec.idx << " pos: " << pos << endl; Uint32* ptr= page.get_ptr(rec.idx); assert(page.get_entry_len(rec.idx) == rec.size); cmp(ptr, rec.data, rec.size); delete[] rec.data; page.free_record(rec.idx, 0); for (unsigned k = no; k + 1 < allocated; k++) records[k] = records[k+1]; allocated--; break; } case 2: // Reorg ndbout << "Reorg" << endl; page.reorg(&tmp); break; case 3: { Uint32 free = page.free_space; if (free <= 2) { goto shrink; } free /= 2; int no = rand() % allocated; Record rec= records[no]; ndbout << "Expand no: " << no << " idx: " << rec.idx << " add: " << free << " reorg: " << !page.is_space_behind_entry(rec.idx, free) << endl; if (!page.is_space_behind_entry(rec.idx, free)) { Uint32 buffer[8192]; Uint32 len = page.get_entry_len(rec.idx); memcpy(buffer, page.get_ptr(rec.idx), 4*len); page.set_entry_len(rec.idx, 0); page.free_space += len; page.reorg(&tmp); memcpy(page.get_free_space_ptr(), buffer, 4*len); page.set_entry_offset(rec.idx, page.insert_pos); free += len; records[no].size = 0; } page.grow_entry(rec.idx, free); records[no].size += free; Uint32 *ptr = page.get_ptr(rec.idx); Uint32 *new_data = new Uint32[records[no].size]; for(Uint32 i= 0; i 1) { time_t seed = time(0); srand(seed); fprintf(stderr, "srand(%d)\n", seed); } // alloc, free, reorg, grow, shrink int t1[] = { 10, 60, 70, 85, 100 }; int t2[] = { 30, 60, 70, 85, 100 }; int t3[] = { 50, 60, 70, 85, 100 }; do_test(10000, t1); do_test(10000, t2); do_test(10000, t3); return 0; } template class Vector; // hp3750 struct Signal { Signal(); int foo; }; Signal::Signal(){}