00001 #if 0 00002 make -f Makefile -f - testSuperPool <<'_eof_' 00003 testSuperPool: testSuperPool.cpp libkernel.a LinearPool.hpp 00004 $(CXXCOMPILE) -o $@ $@.cpp libkernel.a -L../../common/util/.libs -lgeneral 00005 _eof_ 00006 exit $? 00007 #endif 00008 00009 /* Copyright (C) 2003 MySQL AB 00010 00011 This program is free software; you can redistribute it and/or modify 00012 it under the terms of the GNU General Public License as published by 00013 the Free Software Foundation; either version 2 of the License, or 00014 (at your option) any later version. 00015 00016 This program is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 GNU General Public License for more details. 00020 00021 You should have received a copy of the GNU General Public License 00022 along with this program; if not, write to the Free Software 00023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00024 00025 #include "SuperPool.hpp" 00026 #include "LinearPool.hpp" 00027 #include <NdbOut.hpp> 00028 00029 template <Uint32 sz> 00030 struct A { 00031 Uint32 a[sz]; 00032 void fill() { 00033 Uint32 c = 0; 00034 for (Uint32 i = 0; i + 1 < sz; i++) { 00035 a[i] = random(); 00036 c = (c << 1) ^ a[i]; 00037 } 00038 a[sz - 1] = c; 00039 } 00040 void check() { 00041 Uint32 c = 0; 00042 for (Uint32 i = 0; i + 1 < sz; i++) { 00043 c = (c << 1) ^ a[i]; 00044 } 00045 assert(a[sz - 1] == c); 00046 } 00047 }; 00048 00049 static Uint32 00050 urandom(Uint32 n) 00051 { 00052 return (Uint32)random() % n; 00053 } 00054 00055 static Uint32 00056 random_coprime(Uint32 n) 00057 { 00058 Uint32 prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 }; 00059 Uint32 count = sizeof(prime) / sizeof(prime[0]); 00060 assert(n != 0); 00061 while (1) { 00062 Uint32 i = urandom(count); 00063 if (n % prime[i] != 0) 00064 return prime[i]; 00065 } 00066 } 00067 00068 static int 00069 cmpPtrI(const void* a, const void* b) 00070 { 00071 Ptr<const void> u = *(Ptr<const void>*)a; 00072 Ptr<const void> v = *(Ptr<const void>*)b; 00073 return u.i < v.i ? -1 : u.i > v.i ? +1 : 0; 00074 } 00075 00076 static int 00077 cmpPtrP(const void* a, const void* b) 00078 { 00079 Ptr<const void> u = *(Ptr<const void>*)a; 00080 Ptr<const void> v = *(Ptr<const void>*)b; 00081 return u.p < v.p ? -1 : u.p > v.p ? +1 : 0; 00082 } 00083 00084 static Uint32 loopcount = 3; 00085 00086 template <class T> 00087 static void 00088 sp_test(GroupPool& gp) 00089 { 00090 SuperPool& sp = gp.m_superPool; 00091 RecordPool<T> rp(gp); 00092 assert(gp.m_totPages == gp.m_freeList.m_pageCount); 00093 SuperPool::RecInfo& ri = rp.m_recInfo; 00094 Uint32 pageCount = sp.m_totPages; 00095 Uint32 perPage = rp.m_recInfo.m_maxPerPage; 00096 Uint32 perPool = perPage * pageCount; 00097 ndbout << "pages=" << pageCount << " perpage=" << perPage << " perpool=" << perPool << endl; 00098 Ptr<T>* ptrList = new Ptr<T> [perPool]; 00099 memset(ptrList, 0x1f, perPool * sizeof(Ptr<T>)); 00100 Uint32 verify = 1000; 00101 Uint32 useCount; 00102 Uint32 loop; 00103 for (loop = 0; loop < loopcount; loop++) { 00104 ndbout << "loop " << loop << endl; 00105 Uint32 i, j; 00106 // seize all 00107 ndbout << "seize all" << endl; 00108 for (i = 0; i < perPool + 1; i++) { 00109 if (verify == 0 || urandom(perPool) < verify) 00110 sp.verify(ri); 00111 j = i; 00112 Ptr<T> ptr1 = { 0, RNIL }; 00113 if (! rp.seize(ptr1)) 00114 break; 00115 ptr1.p->fill(); 00116 ptr1.p->check(); 00117 Ptr<T> ptr2 = { 0, ptr1.i }; 00118 rp.getPtr(ptr2); 00119 assert(ptr1.i == ptr2.i && ptr1.p == ptr2.p); 00120 ptrList[j] = ptr1; 00121 } 00122 sp.verify(ri); 00123 ndbout << "seized " << i << endl; 00124 assert(i == perPool); 00125 useCount = sp.getRecUseCount(ri); 00126 assert(useCount == perPool); 00127 // check duplicates 00128 ndbout << "check dups" << endl; 00129 { 00130 Ptr<T>* ptrList2 = new Ptr<T> [perPool]; 00131 memcpy(ptrList2, ptrList, perPool * sizeof(Ptr<T>)); 00132 qsort(ptrList2, perPool, sizeof(Ptr<T>), cmpPtrI); 00133 for (i = 1; i < perPool; i++) 00134 assert(ptrList2[i - 1].i != ptrList2[i].i); 00135 qsort(ptrList2, perPool, sizeof(Ptr<T>), cmpPtrP); 00136 for (i = 1; i < perPool; i++) 00137 assert(ptrList2[i - 1].p != ptrList2[i].p); 00138 delete [] ptrList2; 00139 } 00140 // release all in various orders 00141 ndbout << "release all" << endl; 00142 Uint32 coprime = random_coprime(perPool); 00143 for (i = 0; i < perPool; i++) { 00144 if (verify == 0 || urandom(perPool) < verify) 00145 sp.verify(ri); 00146 switch (loop % 3) { 00147 case 0: // ascending 00148 j = i; 00149 break; 00150 case 1: // descending 00151 j = perPool - 1 - i; 00152 break; 00153 case 2: // pseudo-random 00154 j = (coprime * i) % perPool; 00155 break; 00156 } 00157 Ptr<T>& ptr = ptrList[j]; 00158 assert(ptr.i != RNIL && ptr.p != 0); 00159 ptr.p->check(); 00160 rp.release(ptr); 00161 assert(ptr.i == RNIL && ptr.p == 0); 00162 } 00163 sp.verify(ri); 00164 useCount = sp.getRecUseCount(ri); 00165 assert(useCount == 0); 00166 // seize/release at random 00167 ndbout << "seize/release at random" << endl; 00168 for (i = 0; i < loopcount * perPool; i++) { 00169 if (verify == 0 || urandom(perPool) < verify) 00170 sp.verify(ri); 00171 j = urandom(perPool); 00172 Ptr<T>& ptr = ptrList[j]; 00173 if (ptr.i == RNIL) { 00174 if (rp.seize(ptr)) 00175 ptr.p->fill(); 00176 } else { 00177 ptr.p->check(); 00178 rp.release(ptr); 00179 } 00180 } 00181 ndbout << "used " << ri.m_useCount << endl; 00182 sp.verify(ri); 00183 // release all 00184 ndbout << "release all" << endl; 00185 for (i = 0; i < perPool; i++) { 00186 if (verify == 0 || urandom(perPool) < verify) 00187 sp.verify(ri); 00188 j = i; 00189 Ptr<T>& ptr = ptrList[j]; 00190 if (ptr.i != RNIL) { 00191 ptr.p->check(); 00192 rp.release(ptr); 00193 } 00194 } 00195 sp.verify(ri); 00196 useCount = sp.getRecUseCount(ri); 00197 assert(useCount == 0); 00198 } 00199 // done 00200 delete [] ptrList; 00201 } 00202 00203 template <class T> 00204 static void 00205 lp_test(GroupPool& gp) 00206 { 00207 SuperPool& sp = gp.m_superPool; 00208 LinearPool<T, 5> lp(gp); 00209 ndbout << "linear pool test" << endl; 00210 Ptr<T> ptr; 00211 Uint32 loop; 00212 for (loop = 0; loop < loopcount; loop++) { 00213 int count = 0; 00214 while (1) { 00215 bool ret = lp.seize(ptr); 00216 lp.verify(); 00217 if (! ret) 00218 break; 00219 assert(ptr.i == count); 00220 Ptr<T> ptr2; 00221 ptr2.i = ptr.i; 00222 ptr2.p = 0; 00223 lp.getPtr(ptr2); 00224 assert(ptr.p == ptr2.p); 00225 count++; 00226 } 00227 assert(count != 0); 00228 ndbout << "seized " << count << endl; 00229 switch (loop % 3) { 00230 case 0: 00231 { 00232 int n = 0; 00233 while (n < count) { 00234 ptr.i = n; 00235 lp.release(ptr); 00236 lp.verify(); 00237 n++; 00238 } 00239 ndbout << "released in order" << endl; 00240 } 00241 break; 00242 case 1: 00243 { 00244 int n = count; 00245 while (n > 0) { 00246 n--; 00247 ptr.i = n; 00248 lp.release(ptr); 00249 lp.verify(); 00250 } 00251 ndbout << "released in reverse" << endl; 00252 } 00253 break; 00254 default: 00255 { 00256 int coprime = random_coprime(count); 00257 int n = 0; 00258 while (n < count) { 00259 int m = (coprime * n) % count; 00260 ptr.i = m; 00261 lp.release(ptr); 00262 lp.verify(); 00263 n++; 00264 } 00265 ndbout << "released at random" << endl; 00266 } 00267 break; 00268 } 00269 { Uint32 cnt = lp.count(); assert(cnt == 0); } 00270 // seize_index test 00271 char *used = new char [10 * count]; 00272 memset(used, false, sizeof(used)); 00273 Uint32 i, ns = 0, nr = 0; 00274 for (i = 0; i < count; i++) { 00275 Uint32 index = urandom(10 * count); 00276 if (used[index]) { 00277 ptr.i = index; 00278 lp.release(ptr); 00279 lp.verify(); 00280 nr++; 00281 } else { 00282 int i = lp.seize_index(ptr, index); 00283 assert(i >= 0); 00284 lp.verify(); 00285 if (i == 0) // no space 00286 continue; 00287 assert(ptr.i == index); 00288 Ptr<T> ptr2; 00289 ptr2.i = ptr.i; 00290 ptr2.p = 0; 00291 lp.getPtr(ptr2); 00292 assert(ptr.p == ptr2.p); 00293 ns++; 00294 } 00295 used[index] = ! used[index]; 00296 } 00297 ndbout << "random sparse seize " << ns << " release " << nr << endl; 00298 nr = 0; 00299 for (i = 0; i < 10 * count; i++) { 00300 if (used[i]) { 00301 ptr.i = i; 00302 lp.release(ptr); 00303 lp.verify(); 00304 used[i] = false; 00305 nr++; 00306 } 00307 } 00308 ndbout << "released " << nr << endl; 00309 { Uint32 cnt = lp.count(); assert(cnt == 0); } 00310 } 00311 } 00312 00313 static Uint32 pageSize = 32768; 00314 static Uint32 pageBits = 17; 00315 00316 const Uint32 sz1 = 3; 00317 const Uint32 sz2 = 4; 00318 const Uint32 sz3 = 53; 00319 const Uint32 sz4 = 424; 00320 const Uint32 sz5 = 5353; 00321 00322 typedef A<sz1> T1; 00323 typedef A<sz2> T2; 00324 typedef A<sz3> T3; 00325 typedef A<sz4> T4; 00326 typedef A<sz5> T5; 00327 00328 template static void sp_test<T1>(GroupPool& sp); 00329 template static void sp_test<T2>(GroupPool& sp); 00330 template static void sp_test<T3>(GroupPool& sp); 00331 template static void sp_test<T4>(GroupPool& sp); 00332 template static void sp_test<T5>(GroupPool& sp); 00333 // 00334 template static void lp_test<T3>(GroupPool& sp); 00335 00336 int 00337 main(int argc, char** argv) 00338 { 00339 if (argc > 1 && strncmp(argv[1], "-l", 2) == 0) 00340 loopcount = atoi(argv[1] + 2); 00341 HeapPool sp(pageSize, pageBits); 00342 sp.setInitPages(7); 00343 sp.setMaxPages(7); 00344 if (! sp.allocMemory()) 00345 assert(false); 00346 GroupPool gp(sp); 00347 Uint16 s = (Uint16)getpid(); 00348 srandom(s); 00349 ndbout << "rand " << s << endl; 00350 int count; 00351 count = 0; 00352 while (++count <= 0) { // change to 1 to find new bug 00353 sp_test<T1>(gp); 00354 sp_test<T2>(gp); 00355 sp_test<T3>(gp); 00356 sp_test<T4>(gp); 00357 sp_test<T5>(gp); 00358 } 00359 count = 0; 00360 while (++count <= 1) { 00361 lp_test<T3>(gp); 00362 } 00363 return 0; 00364 }
1.4.7

