MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
testSuperPool.cpp
1 #if 0
2 make -f Makefile -f - testSuperPool <<'_eof_'
3 testSuperPool: testSuperPool.cpp libkernel.a LinearPool.hpp
4  $(CXXCOMPILE) -o $@ $@.cpp libkernel.a -L../../common/util/.libs -lgeneral
5 _eof_
6 exit $?
7 #endif
8 
9 /*
10  Copyright (C) 2005, 2006 MySQL AB
11  All rights reserved. Use is subject to license terms.
12 
13  This program is free software; you can redistribute it and/or modify
14  it under the terms of the GNU General Public License as published by
15  the Free Software Foundation; version 2 of the License.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 */
26 
27 #include "SuperPool.hpp"
28 #include "LinearPool.hpp"
29 #include <NdbOut.hpp>
30 
31 template <Uint32 sz>
32 struct A {
33  Uint32 a[sz];
34  void fill() {
35  Uint32 c = 0;
36  for (Uint32 i = 0; i + 1 < sz; i++) {
37  a[i] = random();
38  c = (c << 1) ^ a[i];
39  }
40  a[sz - 1] = c;
41  }
42  void check() {
43  Uint32 c = 0;
44  for (Uint32 i = 0; i + 1 < sz; i++) {
45  c = (c << 1) ^ a[i];
46  }
47  assert(a[sz - 1] == c);
48  }
49 };
50 
51 static Uint32
52 urandom(Uint32 n)
53 {
54  return (Uint32)random() % n;
55 }
56 
57 static Uint32
58 random_coprime(Uint32 n)
59 {
60  Uint32 prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 };
61  Uint32 count = sizeof(prime) / sizeof(prime[0]);
62  assert(n != 0);
63  while (1) {
64  Uint32 i = urandom(count);
65  if (n % prime[i] != 0)
66  return prime[i];
67  }
68 }
69 
70 static int
71 cmpPtrI(const void* a, const void* b)
72 {
75  return u.i < v.i ? -1 : u.i > v.i ? +1 : 0;
76 }
77 
78 static int
79 cmpPtrP(const void* a, const void* b)
80 {
83  return u.p < v.p ? -1 : u.p > v.p ? +1 : 0;
84 }
85 
86 static Uint32 loopcount = 3;
87 
88 template <class T>
89 static void
90 sp_test(GroupPool& gp)
91 {
92  SuperPool& sp = gp.m_superPool;
93  RecordPool<T> rp(gp);
94  assert(gp.m_totPages == gp.m_freeList.m_pageCount);
95  SuperPool::RecInfo& ri = rp.m_recInfo;
96  Uint32 pageCount = sp.m_totPages;
97  Uint32 perPage = rp.m_recInfo.m_maxPerPage;
98  Uint32 perPool = perPage * pageCount;
99  ndbout << "pages=" << pageCount << " perpage=" << perPage << " perpool=" << perPool << endl;
100  Ptr<T>* ptrList = new Ptr<T> [perPool];
101  memset(ptrList, 0x1f, perPool * sizeof(Ptr<T>));
102  Uint32 verify = 1000;
103  Uint32 useCount;
104  Uint32 loop;
105  for (loop = 0; loop < loopcount; loop++) {
106  ndbout << "loop " << loop << endl;
107  Uint32 i, j;
108  // seize all
109  ndbout << "seize all" << endl;
110  for (i = 0; i < perPool + 1; i++) {
111  if (verify == 0 || urandom(perPool) < verify)
112  sp.verify(ri);
113  j = i;
114  Ptr<T> ptr1 = { 0, RNIL };
115  if (! rp.seize(ptr1))
116  break;
117  ptr1.p->fill();
118  ptr1.p->check();
119  Ptr<T> ptr2 = { 0, ptr1.i };
120  rp.getPtr(ptr2);
121  assert(ptr1.i == ptr2.i && ptr1.p == ptr2.p);
122  ptrList[j] = ptr1;
123  }
124  sp.verify(ri);
125  ndbout << "seized " << i << endl;
126  assert(i == perPool);
127  useCount = sp.getRecUseCount(ri);
128  assert(useCount == perPool);
129  // check duplicates
130  ndbout << "check dups" << endl;
131  {
132  Ptr<T>* ptrList2 = new Ptr<T> [perPool];
133  memcpy(ptrList2, ptrList, perPool * sizeof(Ptr<T>));
134  qsort(ptrList2, perPool, sizeof(Ptr<T>), cmpPtrI);
135  for (i = 1; i < perPool; i++)
136  assert(ptrList2[i - 1].i != ptrList2[i].i);
137  qsort(ptrList2, perPool, sizeof(Ptr<T>), cmpPtrP);
138  for (i = 1; i < perPool; i++)
139  assert(ptrList2[i - 1].p != ptrList2[i].p);
140  delete [] ptrList2;
141  }
142  // release all in various orders
143  ndbout << "release all" << endl;
144  Uint32 coprime = random_coprime(perPool);
145  for (i = 0; i < perPool; i++) {
146  if (verify == 0 || urandom(perPool) < verify)
147  sp.verify(ri);
148  switch (loop % 3) {
149  case 0: // ascending
150  j = i;
151  break;
152  case 1: // descending
153  j = perPool - 1 - i;
154  break;
155  case 2: // pseudo-random
156  j = (coprime * i) % perPool;
157  break;
158  }
159  Ptr<T>& ptr = ptrList[j];
160  assert(ptr.i != RNIL && ptr.p != 0);
161  ptr.p->check();
162  rp.release(ptr);
163  assert(ptr.i == RNIL && ptr.p == 0);
164  }
165  sp.verify(ri);
166  useCount = sp.getRecUseCount(ri);
167  assert(useCount == 0);
168  // seize/release at random
169  ndbout << "seize/release at random" << endl;
170  for (i = 0; i < loopcount * perPool; i++) {
171  if (verify == 0 || urandom(perPool) < verify)
172  sp.verify(ri);
173  j = urandom(perPool);
174  Ptr<T>& ptr = ptrList[j];
175  if (ptr.i == RNIL) {
176  if (rp.seize(ptr))
177  ptr.p->fill();
178  } else {
179  ptr.p->check();
180  rp.release(ptr);
181  }
182  }
183  ndbout << "used " << ri.m_useCount << endl;
184  sp.verify(ri);
185  // release all
186  ndbout << "release all" << endl;
187  for (i = 0; i < perPool; i++) {
188  if (verify == 0 || urandom(perPool) < verify)
189  sp.verify(ri);
190  j = i;
191  Ptr<T>& ptr = ptrList[j];
192  if (ptr.i != RNIL) {
193  ptr.p->check();
194  rp.release(ptr);
195  }
196  }
197  sp.verify(ri);
198  useCount = sp.getRecUseCount(ri);
199  assert(useCount == 0);
200  }
201  // done
202  delete [] ptrList;
203 }
204 
205 template <class T>
206 static void
207 lp_test(GroupPool& gp)
208 {
209  SuperPool& sp = gp.m_superPool;
210  LinearPool<T, 5> lp(gp);
211  ndbout << "linear pool test" << endl;
212  Ptr<T> ptr;
213  Uint32 loop;
214  for (loop = 0; loop < loopcount; loop++) {
215  int count = 0;
216  while (1) {
217  bool ret = lp.seize(ptr);
218  lp.verify();
219  if (! ret)
220  break;
221  assert(ptr.i == count);
222  Ptr<T> ptr2;
223  ptr2.i = ptr.i;
224  ptr2.p = 0;
225  lp.getPtr(ptr2);
226  assert(ptr.p == ptr2.p);
227  count++;
228  }
229  assert(count != 0);
230  ndbout << "seized " << count << endl;
231  switch (loop % 3) {
232  case 0:
233  {
234  int n = 0;
235  while (n < count) {
236  ptr.i = n;
237  lp.release(ptr);
238  lp.verify();
239  n++;
240  }
241  ndbout << "released in order" << endl;
242  }
243  break;
244  case 1:
245  {
246  int n = count;
247  while (n > 0) {
248  n--;
249  ptr.i = n;
250  lp.release(ptr);
251  lp.verify();
252  }
253  ndbout << "released in reverse" << endl;
254  }
255  break;
256  default:
257  {
258  int coprime = random_coprime(count);
259  int n = 0;
260  while (n < count) {
261  int m = (coprime * n) % count;
262  ptr.i = m;
263  lp.release(ptr);
264  lp.verify();
265  n++;
266  }
267  ndbout << "released at random" << endl;
268  }
269  break;
270  }
271  { Uint32 cnt = lp.count(); assert(cnt == 0); }
272  // seize_index test
273  char *used = new char [10 * count];
274  memset(used, false, sizeof(used));
275  Uint32 i, ns = 0, nr = 0;
276  for (i = 0; i < count; i++) {
277  Uint32 index = urandom(10 * count);
278  if (used[index]) {
279  ptr.i = index;
280  lp.release(ptr);
281  lp.verify();
282  nr++;
283  } else {
284  int i = lp.seize_index(ptr, index);
285  assert(i >= 0);
286  lp.verify();
287  if (i == 0) // no space
288  continue;
289  assert(ptr.i == index);
290  Ptr<T> ptr2;
291  ptr2.i = ptr.i;
292  ptr2.p = 0;
293  lp.getPtr(ptr2);
294  assert(ptr.p == ptr2.p);
295  ns++;
296  }
297  used[index] = ! used[index];
298  }
299  ndbout << "random sparse seize " << ns << " release " << nr << endl;
300  nr = 0;
301  for (i = 0; i < 10 * count; i++) {
302  if (used[i]) {
303  ptr.i = i;
304  lp.release(ptr);
305  lp.verify();
306  used[i] = false;
307  nr++;
308  }
309  }
310  ndbout << "released " << nr << endl;
311  { Uint32 cnt = lp.count(); assert(cnt == 0); }
312  }
313 }
314 
315 static Uint32 pageSize = 32768;
316 static Uint32 pageBits = 17;
317 
318 const Uint32 sz1 = 3;
319 const Uint32 sz2 = 4;
320 const Uint32 sz3 = 53;
321 const Uint32 sz4 = 424;
322 const Uint32 sz5 = 5353;
323 
324 typedef A<sz1> T1;
325 typedef A<sz2> T2;
326 typedef A<sz3> T3;
327 typedef A<sz4> T4;
328 typedef A<sz5> T5;
329 
330 template static void sp_test<T1>(GroupPool& sp);
331 template static void sp_test<T2>(GroupPool& sp);
332 template static void sp_test<T3>(GroupPool& sp);
333 template static void sp_test<T4>(GroupPool& sp);
334 template static void sp_test<T5>(GroupPool& sp);
335 //
336 template static void lp_test<T3>(GroupPool& sp);
337 
338 int
339 main(int argc, char** argv)
340 {
341  if (argc > 1 && strncmp(argv[1], "-l", 2) == 0)
342  loopcount = atoi(argv[1] + 2);
343  HeapPool sp(pageSize, pageBits);
344  sp.setInitPages(7);
345  sp.setMaxPages(7);
346  if (! sp.allocMemory())
347  assert(false);
348  GroupPool gp(sp);
349  Uint16 s = (Uint16)getpid();
350  srandom(s);
351  ndbout << "rand " << s << endl;
352  int count;
353  count = 0;
354  while (++count <= 0) { // change to 1 to find new bug
355  sp_test<T1>(gp);
356  sp_test<T2>(gp);
357  sp_test<T3>(gp);
358  sp_test<T4>(gp);
359  sp_test<T5>(gp);
360  }
361  count = 0;
362  while (++count <= 1) {
363  lp_test<T3>(gp);
364  }
365  return 0;
366 }