mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / ndb / test / ndbapi / testBitfield.cpp
blob9ba355a0b7310cd407fce1480a9a41abc6b8c421
1 /* Copyright (C) 2004, 2008 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 Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 #include <ndb_global.h>
17 #include <ndb_opts.h>
18 #include <NDBT.hpp>
19 #include <NdbApi.hpp>
20 #include <HugoTransactions.hpp>
21 #include <Bitmask.hpp>
22 #include <Vector.hpp>
24 static const char* _dbname = "TEST_DB";
25 static int g_loops = 7;
28 NDB_STD_OPTS_VARS;
30 static struct my_option my_long_options[] =
32 NDB_STD_OPTS("ndb_desc"),
33 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
36 static void usage()
38 ndb_std_print_version();
40 #if 0
41 static my_bool
42 get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
43 const char *argument)
45 return ndb_std_get_one_option(optid, opt, argument ? argument :
46 "d:t:O,/tmp/testBitfield.trace");
48 #endif
50 static const NdbDictionary::Table* create_random_table(Ndb*);
51 static int transactions(Ndb*, const NdbDictionary::Table* tab);
52 static int unique_indexes(Ndb*, const NdbDictionary::Table* tab);
53 static int ordered_indexes(Ndb*, const NdbDictionary::Table* tab);
54 static int node_restart(Ndb*, const NdbDictionary::Table* tab);
55 static int system_restart(Ndb*, const NdbDictionary::Table* tab);
56 static int testBitmask();
58 int
59 main(int argc, char** argv){
60 NDB_INIT(argv[0]);
61 const char *load_default_groups[]= { "mysql_cluster",0 };
62 load_defaults("my",load_default_groups,&argc,&argv);
63 int ho_error;
65 if ((ho_error=handle_options(&argc, &argv, my_long_options,
66 ndb_std_get_one_option)))
67 return NDBT_ProgramExit(NDBT_WRONGARGS);
69 int res = NDBT_FAILED;
71 /* Run cluster-independent tests */
72 for (int i=0; i<(10*g_loops); i++)
74 if (NDBT_OK != (res= testBitmask()))
75 return NDBT_ProgramExit(res);
78 Ndb_cluster_connection con(opt_connect_str);
79 if(con.connect(12, 5, 1))
81 return NDBT_ProgramExit(NDBT_FAILED);
85 Ndb* pNdb;
86 pNdb = new Ndb(&con, _dbname);
87 pNdb->init();
88 while (pNdb->waitUntilReady() != 0);
90 NdbDictionary::Dictionary * dict = pNdb->getDictionary();
92 const NdbDictionary::Table* pTab = 0;
93 for (int i = 0; i < (argc ? argc : g_loops) ; i++)
95 res = NDBT_FAILED;
96 if(argc == 0)
98 pTab = create_random_table(pNdb);
100 else
102 dict->dropTable(argv[i]);
103 NDBT_Tables::createTable(pNdb, argv[i]);
104 pTab = dict->getTable(argv[i]);
107 if (pTab == 0)
109 ndbout << "Failed to create table" << endl;
110 ndbout << dict->getNdbError() << endl;
111 break;
114 if(transactions(pNdb, pTab))
115 break;
117 if(unique_indexes(pNdb, pTab))
118 break;
120 if(ordered_indexes(pNdb, pTab))
121 break;
123 if(node_restart(pNdb, pTab))
124 break;
126 if(system_restart(pNdb, pTab))
127 break;
129 dict->dropTable(pTab->getName());
130 res = NDBT_OK;
133 if(res != NDBT_OK && pTab)
135 dict->dropTable(pTab->getName());
138 delete pNdb;
139 return NDBT_ProgramExit(res);
142 static
143 const NdbDictionary::Table*
144 create_random_table(Ndb* pNdb)
146 do {
147 NdbDictionary::Table tab;
148 Uint32 cols = 1 + (rand() % (NDB_MAX_ATTRIBUTES_IN_TABLE - 1));
149 Uint32 length = 4090;
151 BaseString name;
152 name.assfmt("TAB_%d", rand() & 65535);
153 tab.setName(name.c_str());
154 for(Uint32 i = 0; i<cols && length > 2; i++)
156 NdbDictionary::Column col;
157 name.assfmt("COL_%d", i);
158 col.setName(name.c_str());
159 if(i == 0 || i == 1)
161 col.setType(NdbDictionary::Column::Unsigned);
162 col.setLength(1);
163 col.setNullable(false);
164 col.setPrimaryKey(i == 0);
165 tab.addColumn(col);
166 continue;
169 col.setType(NdbDictionary::Column::Bit);
171 Uint32 len = 1 + (rand() % (length - 1));
172 col.setLength(len); length -= len;
173 int nullable = (rand() >> 16) & 1;
174 col.setNullable(nullable); length -= nullable;
175 col.setPrimaryKey(false);
176 tab.addColumn(col);
179 pNdb->getDictionary()->dropTable(tab.getName());
180 if(pNdb->getDictionary()->createTable(tab) == 0)
182 ndbout << (NDBT_Table&)tab << endl;
183 return pNdb->getDictionary()->getTable(tab.getName());
185 } while(0);
186 return 0;
189 static
191 transactions(Ndb* pNdb, const NdbDictionary::Table* tab)
193 int i = 0;
194 HugoTransactions trans(* tab);
195 i |= trans.loadTable(pNdb, 1000);
196 i |= trans.pkReadRecords(pNdb, 1000, 13);
197 i |= trans.scanReadRecords(pNdb, 1000, 25);
198 i |= trans.pkUpdateRecords(pNdb, 1000, 37);
199 i |= trans.scanUpdateRecords(pNdb, 1000, 25);
200 i |= trans.pkDelRecords(pNdb, 500, 23);
201 i |= trans.clearTable(pNdb);
202 return i;
205 static
206 int
207 unique_indexes(Ndb* pNdb, const NdbDictionary::Table* tab)
209 return 0;
212 static
213 int
214 ordered_indexes(Ndb* pNdb, const NdbDictionary::Table* tab)
216 return 0;
219 static
220 int
221 node_restart(Ndb* pNdb, const NdbDictionary::Table* tab)
223 return 0;
226 static
227 int
228 system_restart(Ndb* pNdb, const NdbDictionary::Table* tab)
230 return 0;
233 /* Note : folowing classes test functionality of storage/ndb/src/common/util/Bitmask.cpp
234 * and were originally defined there.
235 * Set BITMASK_DEBUG to 1 to get more test debugging info.
237 #define BITMASK_DEBUG 0
239 static
240 bool cmp(const Uint32 b1[], const Uint32 b2[], Uint32 len)
242 Uint32 sz32 = (len + 31) >> 5;
243 for(Uint32 i = 0; i<len; i++)
245 if(BitmaskImpl::get(sz32, b1, i) ^ BitmaskImpl::get(sz32, b2, i))
246 return false;
248 return true;
251 static
252 void print(const Uint32 src[], Uint32 len, Uint32 pos = 0)
254 printf("b'");
255 for(unsigned i = 0; i<len; i++)
257 if(BitmaskImpl::get((pos + len + 31) >> 5, src, i+pos))
258 printf("1");
259 else
260 printf("0");
261 if((i & 31) == 31)
262 printf(" ");
266 static int lrand()
268 return rand();
271 static
272 void rand(Uint32 dst[], Uint32 len)
274 for(Uint32 i = 0; i<len; i++)
275 BitmaskImpl::set((len + 31) >> 5, dst, i, (lrand() % 1000) > 500);
278 static
279 int checkNoTramplingGetSetField(const Uint32 totalTests)
281 const Uint32 numWords= 67;
282 const Uint32 maxBitsToCopy= (numWords * 32);
283 Uint32 sourceBuf[numWords];
284 Uint32 targetBuf[numWords];
286 ndbout << "Testing : Bitmask NoTrampling\n";
288 memset(sourceBuf, 0x00, (numWords*4));
290 for (Uint32 test=0; test<totalTests; test++)
292 /* Always copy at least 1 bit */
293 Uint32 srcStart= rand() % (maxBitsToCopy -1);
294 Uint32 length= (rand() % ((maxBitsToCopy -1) - srcStart)) + 1;
296 if (BITMASK_DEBUG)
297 ndbout << "Testing start %u, length %u \n"
298 << srcStart
299 << length;
300 // Set target to all ones.
301 memset(targetBuf, 0xff, (numWords*4));
303 BitmaskImpl::getField(numWords, sourceBuf, srcStart, length, targetBuf);
305 // Check that there is no trampling
306 Uint32 firstUntrampledWord= (length + 31)/32;
308 for (Uint32 word=0; word< numWords; word++)
310 Uint32 targetWord= targetBuf[word];
311 if (BITMASK_DEBUG)
312 ndbout << "word=%d, targetWord=%u, firstUntrampledWord..=%u"
313 << word << targetWord << firstUntrampledWord;
315 if (! (word < firstUntrampledWord) ?
316 (targetWord == 0) :
317 (targetWord == 0xffffffff))
319 ndbout << "Notrampling getField failed for srcStart "
320 << srcStart
321 << " length " << length
322 << " at word " << word << "\n";
323 ndbout << "word=%d, targetWord=%u, firstUntrampledWord..=%u"
324 << word << targetWord << firstUntrampledWord;
325 return -1;
330 /* Set target back to all ones. */
331 memset(targetBuf, 0xff, (numWords*4));
333 BitmaskImpl::setField(numWords, targetBuf, srcStart, length, sourceBuf);
335 /* Check we've got all ones, with zeros only where expected */
336 for (Uint32 word=0; word< numWords; word++)
338 Uint32 targetWord= targetBuf[word];
340 for (Uint32 bit=0; bit< 32; bit++)
342 Uint32 bitNum= (word << 5) + bit;
343 bool expectedValue= !((bitNum >= srcStart) &&
344 (bitNum < (srcStart + length)));
345 bool actualValue= (((targetWord >> bit) & 1) == 1);
346 if (BITMASK_DEBUG)
347 ndbout << "bitNum=%u expectedValue=%u, actual value=%u"
348 << bitNum << expectedValue << actualValue;
350 if (actualValue != expectedValue)
352 ndbout << "Notrampling setField failed for srcStart "
353 << srcStart
354 << " length " << length
355 << " at word " << word << " bit " << bit << "\n";
356 ndbout << "bitNum=%u expectedValue=%u, actual value=%u"
357 << bitNum << expectedValue << actualValue;
358 return -1;
365 return 0;
368 static
369 int simple(int pos, int size)
371 ndbout << "Testing : Bitmask simple pos: " << pos << " size: " << size << "\n";
372 Vector<Uint32> _mask;
373 Vector<Uint32> _src;
374 Vector<Uint32> _dst;
375 Uint32 sz32 = (size + pos + 32) >> 5;
376 const Uint32 sz = 4 * sz32;
378 Uint32 zero = 0;
379 _mask.fill(sz32+1, zero);
380 _src.fill(sz32+1, zero);
381 _dst.fill(sz32+1, zero);
383 Uint32 * src = _src.getBase();
384 Uint32 * dst = _dst.getBase();
385 Uint32 * mask = _mask.getBase();
387 memset(src, 0x0, sz);
388 memset(dst, 0x0, sz);
389 memset(mask, 0xFF, sz);
390 rand(src, size);
391 BitmaskImpl::setField(sz32, mask, pos, size, src);
392 BitmaskImpl::getField(sz32, mask, pos, size, dst);
393 if (BITMASK_DEBUG)
395 printf("src: "); print(src, size+31); printf("\n");
396 printf("msk: "); print(mask, (sz32 << 5) + 31); printf("\n");
397 printf("dst: "); print(dst, size+31); printf("\n");
399 return (cmp(src, dst, size+31)?0 : -1);
402 struct Alloc
404 Uint32 pos;
405 Uint32 size;
406 Vector<Uint32> data;
409 static
411 testRanges(Uint32 bitmask_size)
413 Vector<Alloc> alloc_list;
414 bitmask_size = (bitmask_size + 31) & ~31;
415 Uint32 sz32 = (bitmask_size >> 5);
416 Vector<Uint32> alloc_mask;
417 Vector<Uint32> test_mask;
419 ndbout_c("Testing : Bitmask ranges for bitmask of size %d", bitmask_size);
420 Uint32 zero = 0;
421 alloc_mask.fill(sz32, zero);
422 test_mask.fill(sz32, zero);
424 /* Loop a number of times, setting and clearing bits in the mask
425 * and tracking the modifications in a separate structure.
426 * Check that both structures remain in sync
428 for(int i = 0; i<5000; i++)
430 Vector<Uint32> tmp;
431 tmp.fill(sz32, zero);
433 Uint32 pos = lrand() % (bitmask_size - 1);
434 Uint32 free = 0;
435 if(BitmaskImpl::get(sz32, alloc_mask.getBase(), pos))
437 // Bit was allocated
438 // 1) Look up allocation
439 // 2) Check data
440 // 3) free it
441 size_t j;
442 Uint32 min, max;
443 for(j = 0; j<alloc_list.size(); j++)
445 min = alloc_list[j].pos;
446 max = min + alloc_list[j].size;
447 if(pos >= min && pos < max)
449 break;
452 if (! ((pos >= min) && (pos < max)))
454 printf("Failed with pos %u, min %u, max %u\n",
455 pos, min, max);
456 return -1;
458 BitmaskImpl::getField(sz32, test_mask.getBase(), min, max-min,
459 tmp.getBase());
460 if(BITMASK_DEBUG)
462 printf("freeing [ %d %d ]", min, max);
463 printf("- mask: ");
464 print(tmp.getBase(), max - min);
466 printf(" save: ");
467 size_t k;
468 Alloc& a = alloc_list[j];
469 for(k = 0; k<a.data.size(); k++)
470 printf("%.8x ", a.data[k]);
471 printf("\n");
473 if(!cmp(tmp.getBase(), alloc_list[j].data.getBase(), max - min))
475 return -1;
477 while(min < max)
478 BitmaskImpl::clear(sz32, alloc_mask.getBase(), min++);
479 alloc_list.erase(j);
481 else
483 Vector<Uint32> tmp;
484 tmp.fill(sz32, zero);
486 // Bit was free
487 // 1) Check how much space is avaiable
488 // 2) Create new allocation of lrandom size
489 // 3) Fill data with lrandom data
490 // 4) Update alloc mask
491 while(pos+free < bitmask_size &&
492 !BitmaskImpl::get(sz32, alloc_mask.getBase(), pos+free))
493 free++;
495 Uint32 sz =
496 (free <= 64 && ((lrand() % 100) > 80)) ? free : (lrand() % free);
497 sz = sz ? sz : 1;
498 sz = pos + sz == bitmask_size ? sz - 1 : sz;
499 Alloc a;
500 a.pos = pos;
501 a.size = sz;
502 a.data.fill(((sz+31)>> 5)-1, zero);
503 if(BITMASK_DEBUG)
504 printf("pos %d -> alloc [ %d %d ]", pos, pos, pos+sz);
505 for(size_t j = 0; j<sz; j++)
507 BitmaskImpl::set(sz32, alloc_mask.getBase(), pos+j);
508 if((lrand() % 1000) > 500)
509 BitmaskImpl::set((sz + 31) >> 5, a.data.getBase(), j);
511 if(BITMASK_DEBUG)
513 printf("- mask: ");
514 print(a.data.getBase(), sz);
515 printf("\n");
517 BitmaskImpl::setField(sz32, test_mask.getBase(), pos, sz,
518 a.data.getBase());
519 alloc_list.push_back(a);
523 #define NDB_BM_SUPPORT_RANGE
524 #ifdef NDB_BM_SUPPORT_RANGE
525 for(Uint32 i = 0; i<1000; i++)
527 Uint32 sz32 = 10+rand() % 100;
528 Uint32 zero = 0;
529 Vector<Uint32> map;
530 map.fill(sz32, zero);
532 Uint32 sz = 32 * sz32;
533 Uint32 start = (rand() % sz);
534 Uint32 stop = start + ((rand() % (sz - start)) & 0xFFFFFFFF);
536 Vector<Uint32> check;
537 check.fill(sz32, zero);
539 /* Verify range setting method works correctly */
540 for(Uint32 j = 0; j<sz; j++)
542 bool expect = (j >= start && j<stop);
543 if(expect)
544 BitmaskImpl::set(sz32, check.getBase(), j);
547 BitmaskImpl::set_range(sz32, map.getBase(), start, stop);
548 if (!BitmaskImpl::equal(sz32, map.getBase(), check.getBase()))
550 ndbout_c(" FAIL 1 sz: %d [ %d %d ]", sz, start, stop);
551 printf("check: ");
552 for(Uint32 j = 0; j<sz32; j++)
553 printf("%.8x ", check[j]);
554 printf("\n");
556 printf("map : ");
557 for(Uint32 j = 0; j<sz32; j++)
558 printf("%.8x ", map[j]);
559 printf("\n");
560 return -1;
563 map.clear();
564 check.clear();
566 /* Verify range clearing method works correctly */
567 Uint32 one = ~(Uint32)0;
568 map.fill(sz32, one);
569 check.fill(sz32, one);
571 for(Uint32 j = 0; j<sz; j++)
573 bool expect = (j >= start && j<stop);
574 if(expect)
575 BitmaskImpl::clear(sz32, check.getBase(), j);
578 BitmaskImpl::clear_range(sz32, map.getBase(), start, stop);
579 if (!BitmaskImpl::equal(sz32, map.getBase(), check.getBase()))
581 ndbout_c(" FAIL 2 sz: %d [ %d %d ]", sz, start, stop);
582 printf("check: ");
583 for(Uint32 j = 0; j<sz32; j++)
584 printf("%.8x ", check[j]);
585 printf("\n");
587 printf("map : ");
588 for(Uint32 j = 0; j<sz32; j++)
589 printf("%.8x ", map[j]);
590 printf("\n");
591 return -1;
594 #endif
596 return 0;
599 static
601 testBitmask()
603 /* Some testcases from storage/ndb/src/common/util/Bitmask.cpp */
604 int res= 0;
606 if ((res= checkNoTramplingGetSetField(100 /* totalTests */)) != 0)
607 return res;
609 if ((res= simple(rand() % 33, // position
610 (rand() % 63)+1) // size
611 ) != 0)
612 return res;
614 if ((res= testRanges(1+(rand() % 1000) // bitmask size
615 )) != 0)
616 return res;
618 return 0;
621 template class Vector<Alloc>;
622 template class Vector<Uint32>;