testSuperPool.cpp 6.26 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
#if 0
make -f Makefile -f - testSuperPool <<'_eof_'
testSuperPool: testSuperPool.cpp libkernel.a
	$(CXXCOMPILE) -o $@ $@.cpp libkernel.a -L../../common/util/.libs -lgeneral
_eof_
exit $?
#endif

/* Copyright (C) 2003 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; either version 2 of the License, or
   (at your option) any later version.

   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "SuperPool.hpp"
#include <NdbOut.hpp>

template <Uint32 sz>
struct A {
  Uint32 a[sz];
  void fill() {
    Uint32 c = 0;
    for (Uint32 i = 0; i + 1 < sz; i++) {
      a[i] = random();
      c = (c << 1) ^ a[i];
    }
    a[sz - 1] = c;
  }
  void check() {
    Uint32 c = 0;
    for (Uint32 i = 0; i + 1 < sz; i++) {
      c = (c << 1) ^ a[i];
    }
    assert(a[sz - 1] == c);
  }
};

static Uint32
urandom(Uint32 n)
{
  return (Uint32)random() % n;
}

static Uint32
random_coprime(Uint32 n)
{
  Uint32 prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 };
  Uint32 count = sizeof(prime) / sizeof(prime[0]);
  while (1) {
    Uint32 i = urandom(count);
    if (n % prime[i] != 0)
      return prime[i];
  }
}

static int
cmpPtrI(const void* a, const void* b)
{
  Ptr<const void> u = *(Ptr<const void>*)a;
  Ptr<const void> v = *(Ptr<const void>*)b;
  return u.i < v.i ? -1 : u.i > v.i ? +1 : 0;
}

static int
cmpPtrP(const void* a, const void* b)
{
  Ptr<const void> u = *(Ptr<const void>*)a;
  Ptr<const void> v = *(Ptr<const void>*)b;
  return u.p < v.p ? -1 : u.p > v.p ? +1 : 0;
}

static Uint32 loopcount = 3;

84 85 86
template <class T>
static void
sp_test(GroupPool& gp)
unknown's avatar
unknown committed
87
{
88 89 90
  SuperPool& sp = gp.m_superPool;
  RecordPool<T> rp(gp);
  assert(gp.m_totPages == gp.m_freeList.m_pageCount);
unknown's avatar
unknown committed
91
  SuperPool::RecInfo& ri = rp.m_recInfo;
92 93
  Uint32 pageCount = sp.m_totPages;
  Uint32 perPage = rp.m_recInfo.m_maxPerPage;
unknown's avatar
unknown committed
94 95 96 97
  Uint32 perPool = perPage * pageCount;
  ndbout << "pages=" << pageCount << " perpage=" << perPage << " perpool=" << perPool << endl;
  Ptr<T>* ptrList = new Ptr<T> [perPool];
  memset(ptrList, 0x1f, perPool * sizeof(Ptr<T>));
98 99
  Uint32 verify = 1000;
  Uint32 useCount;
unknown's avatar
unknown committed
100 101 102 103 104 105 106
  Uint32 loop;
  for (loop = 0; loop < loopcount; loop++) {
    ndbout << "loop " << loop << endl;
    Uint32 i, j;
    // seize all
    ndbout << "seize all" << endl;
    for (i = 0; i < perPool + 1; i++) {
107 108
      if (verify == 0 || urandom(perPool) < verify)
        sp.verify(ri);
unknown's avatar
unknown committed
109 110 111 112 113 114 115 116 117 118 119 120
      j = i;
      Ptr<T> ptr1 = { 0, RNIL };
      if (! rp.seize(ptr1))
        break;
      ptr1.p->fill();
      ptr1.p->check();
      Ptr<T> ptr2 = { 0, ptr1.i };
      rp.getPtr(ptr2);
      assert(ptr1.i == ptr2.i && ptr1.p == ptr2.p);
      ptrList[j] = ptr1;
    }
    sp.verify(ri);
121 122 123 124
    ndbout << "seized " << i << endl;
    assert(i == perPool);
    useCount = sp.getRecUseCount(ri);
    assert(useCount == perPool);
unknown's avatar
unknown committed
125
    // check duplicates
126
    ndbout << "check dups" << endl;
unknown's avatar
unknown committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
    {
      Ptr<T>* ptrList2 = new Ptr<T> [perPool];
      memcpy(ptrList2, ptrList, perPool * sizeof(Ptr<T>));
      qsort(ptrList2, perPool, sizeof(Ptr<T>), cmpPtrI);
      for (i = 1; i < perPool; i++)
        assert(ptrList2[i - 1].i != ptrList2[i].i);
      qsort(ptrList2, perPool, sizeof(Ptr<T>), cmpPtrP);
      for (i = 1; i < perPool; i++)
        assert(ptrList2[i - 1].p != ptrList2[i].p);
      delete [] ptrList2;
    }
    // release all in various orders
    ndbout << "release all" << endl;
    Uint32 coprime = random_coprime(perPool);
    for (i = 0; i < perPool; i++) {
142 143
      if (verify == 0 || urandom(perPool) < verify)
        sp.verify(ri);
unknown's avatar
unknown committed
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
      switch (loop % 3) {
      case 0:   // ascending
        j = i;
        break;
      case 1:   // descending
        j = perPool - 1 - i;
        break;
      case 2:   // pseudo-random
        j = (coprime * i) % perPool;
        break;
      }
      Ptr<T>& ptr = ptrList[j];
      assert(ptr.i != RNIL && ptr.p != 0);
      ptr.p->check();
      rp.release(ptr);
      assert(ptr.i == RNIL && ptr.p == 0);
    }
    sp.verify(ri);
162 163
    useCount = sp.getRecUseCount(ri);
    assert(useCount == 0);
unknown's avatar
unknown committed
164 165 166
    // seize/release at random
    ndbout << "seize/release at random" << endl;
    for (i = 0; i < loopcount * perPool; i++) {
167 168
      if (verify == 0 || urandom(perPool) < verify)
        sp.verify(ri);
unknown's avatar
unknown committed
169 170 171
      j = urandom(perPool);
      Ptr<T>& ptr = ptrList[j];
      if (ptr.i == RNIL) {
172 173
        if (rp.seize(ptr))
          ptr.p->fill();
unknown's avatar
unknown committed
174 175 176 177 178
      } else {
        ptr.p->check();
        rp.release(ptr);
      }
    }
179
    ndbout << "used " << ri.m_useCount << endl;
unknown's avatar
unknown committed
180 181 182 183
    sp.verify(ri);
    // release all
    ndbout << "release all" << endl;
    for (i = 0; i < perPool; i++) {
184 185
      if (verify == 0 || urandom(perPool) < verify)
        sp.verify(ri);
unknown's avatar
unknown committed
186 187 188 189 190 191 192 193
      j = i;
      Ptr<T>& ptr = ptrList[j];
      if (ptr.i != RNIL) {
        ptr.p->check();
        rp.release(ptr);
      }
    }
    sp.verify(ri);
194 195
    useCount = sp.getRecUseCount(ri);
    assert(useCount == 0);
unknown's avatar
unknown committed
196 197 198 199 200 201
  }
  // done
  delete [] ptrList;
}

static Uint32 pageSize = 32768;
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
static Uint32 pageBits = 17;

const Uint32 sz1 = 3;
const Uint32 sz2 = 4;
const Uint32 sz3 = 53;
const Uint32 sz4 = 424;
const Uint32 sz5 = 5353;

typedef A<sz1> T1;
typedef A<sz2> T2;
typedef A<sz3> T3;
typedef A<sz4> T4;
typedef A<sz5> T5;

template static void sp_test<T1>(GroupPool& sp);
template static void sp_test<T2>(GroupPool& sp);
template static void sp_test<T3>(GroupPool& sp);
template static void sp_test<T4>(GroupPool& sp);
template static void sp_test<T5>(GroupPool& sp);
unknown's avatar
unknown committed
221 222 223 224 225

int
main()
{
  HeapPool sp(pageSize, pageBits);
226 227 228
  sp.setInitPages(7);
  sp.setMaxPages(7);
  if (! sp.allocMemory())
unknown's avatar
unknown committed
229
    assert(false);
230
  GroupPool gp(sp);
unknown's avatar
unknown committed
231 232 233
  Uint16 s = (Uint16)getpid();
  srandom(s);
  ndbout << "rand " << s << endl;
234 235 236 237 238 239 240 241
  int count = 0;
  while (++count <= 1) {
    sp_test<T1>(gp);
    sp_test<T2>(gp);
    sp_test<T3>(gp);
    sp_test<T4>(gp);
    sp_test<T5>(gp);
  }
unknown's avatar
unknown committed
242 243
  return 0;
}