#At file:///C:/Work/bzr/Merge/mysql-6.0-falcon-team/
2865 Kevin Lewis 2008-10-15
Bug#39672 - Using Bitmap::nextSet() failed after searching
from last bit cleard and crossing multiples of 1024.
To show the problem, I added a unit test that can be
activated by "SET GLOBAL FALCON_DEBUG_TRACE=64". The unit
test contains 4 different tests that print "** Error" when
something goes wrong.
modified:
storage/falcon/Bitmap.cpp
storage/falcon/Database.cpp
storage/falcon/Database.h
=== modified file 'storage/falcon/Bitmap.cpp'
--- a/storage/falcon/Bitmap.cpp 2008-06-19 15:09:45 +0000
+++ b/storage/falcon/Bitmap.cpp 2008-10-16 01:04:03 +0000
@@ -19,6 +19,7 @@
#include <memory.h>
#include "Engine.h"
+#include "Log.h"
#include "Bitmap.h"
#ifndef FALCONDB
@@ -207,7 +208,7 @@ int32 Bitmap::nextSet(int32 start)
uint indexes[6];
decompose (start, indexes);
- void **vectors [5];
+ void **vectors [5];
vectors [level] = vector;
int index;
@@ -244,7 +245,8 @@ int32 Bitmap::nextSet(int32 start)
void **vec = vectors [lvl];
for (index = indexes[lvl]; index < BITMAP_VECTOR_SIZE && !vec [index]; ++index)
- ;
+ for (int n = 0; n < lvl; ++n)
+ indexes[n] = 0;
if (index < BITMAP_VECTOR_SIZE)
{
@@ -702,3 +704,116 @@ bool Bitmap::setSafe(int32 bitNumber)
return true;
}
+
+void Bitmap::unitTest(void)
+{
+ int bitNumber;
+ Bitmap *tester = new Bitmap;
+
+ // Set numbers incremented by random amounts.
+ // Check that what is set is set.
+ // Clear sequentially searching from zero.
+ // Check that what was cleared is not still set.
+ Log::log("\nBitmap Test #1\n");
+
+ for (bitNumber = 0; bitNumber < 20000; bitNumber += rand() % 200)
+ {
+ Log::log("Setting bit %d\n", bitNumber);
+ tester->set(bitNumber);
+ }
+
+ for (int bitNumber = 0; (bitNumber = tester->nextSet(0)) >= 0;)
+ {
+ if (!tester->isSet(bitNumber))
+ Log::log("** Error - %d should be set\n", bitNumber);
+
+ Log::log("Clearing bit %d\n", bitNumber);
+ tester->clear(bitNumber);
+
+ if (tester->isSet(bitNumber))
+ Log::log("** Error - %d is still set\n", bitNumber);
+ }
+
+ for (bitNumber = 0; (bitNumber = tester->nextSet(bitNumber + 1)) >= 0;)
+ Log::log("** Error - bit %d is still set\n", bitNumber);
+
+ tester->clear();
+
+ // Set numbers incremented by large random amounts.
+ // Clear bits after searching from last bit cleard.
+ // Check that all bits are cleared.
+ Log::log("\nBitmap Test #2\n");
+
+ for (bitNumber = 0; bitNumber < 2000000; bitNumber += rand() % 20000)
+ {
+ Log::log("Setting bit %d\n", bitNumber);
+ tester->set(bitNumber);
+ }
+
+ for (int bitNumber = 0; (bitNumber = tester->nextSet(bitNumber)) >= 0;)
+ {
+ Log::log("Clearing bit %d\n", bitNumber);
+ tester->clear(bitNumber);
+ }
+
+ for (bitNumber = 0; (bitNumber = tester->nextSet(bitNumber + 1)) >= 0;)
+ Log::log("** Error - bit %d is still set\n", bitNumber);
+
+ tester->clear();
+
+ // Set numbers incremented by larger random amounts.
+ // Clear bits after searching from random locations.
+ // Finish clearing after searching from zero.
+ // Check that all bits are cleared.
+ Log::log("\nBitmap Test #3\n");
+
+ for (bitNumber = 0; bitNumber < 2000000; bitNumber += rand() % 20000)
+ {
+ Log::log("Setting bit %d\n", bitNumber);
+ tester->set(bitNumber);
+ }
+
+ for (int bitNumber = 0; (bitNumber = tester->nextSet( ((int32) rand() * (int32) rand()) % 1800000)) >= 0;)
+ {
+ Log::log("Clearing bit %d\n", bitNumber);
+ tester->clear(bitNumber);
+ }
+
+ for (int bitNumber = 0; (bitNumber = tester->nextSet(0)) >= 0;)
+ {
+ Log::log("Clearing bit %d\n", bitNumber);
+ tester->clear(bitNumber);
+ }
+
+ for (bitNumber = 0; (bitNumber = tester->nextSet(bitNumber + 1)) >= 0;)
+ Log::log("** Error - bit %d is still set\n", bitNumber);
+
+ tester->clear();
+
+ // Set specific numbers around 1024 and 2048.
+ // Clear bits after searching from last bit cleared.
+ // Check that all bits are cleared.
+ Log::log("\nBitmap Test #4\n");
+ for (bitNumber = 1020; bitNumber <= 1040; bitNumber += 1)
+ {
+ Log::log("Setting bit %d\n", bitNumber);
+ tester->set(bitNumber);
+ }
+
+ for (bitNumber = 2040; bitNumber <= 2060; bitNumber += 1) // rand() % 1000)
+ {
+ Log::log("Setting bit %d\n", bitNumber);
+ tester->set(bitNumber);
+ }
+
+ for (bitNumber = 0; (bitNumber = tester->nextSet(bitNumber)) >= 0;)
+ {
+ Log::log("Clearing bit %d\n", bitNumber);
+ tester->clear(bitNumber);
+ }
+
+ for (bitNumber = 0; (bitNumber = tester->nextSet(bitNumber + 1)) >= 0;)
+ Log::log("** Error - bit %d is still set \n", bitNumber);
+
+ tester->clear();
+}
=== modified file 'storage/falcon/Database.cpp'
--- a/storage/falcon/Database.cpp 2008-10-13 21:02:24 +0000
+++ b/storage/falcon/Database.cpp 2008-10-16 01:04:03 +0000
@@ -2501,6 +2501,9 @@ void Database::debugTrace(void)
if (falcon_debug_trace & FALC0N_FREEZE)
Synchronize::freezeSystem();
+ if (falcon_debug_trace & FALC0N_TEST_BITMAP)
+ Bitmap::unitTest();
+
falcon_debug_trace = 0;
#endif
}
=== modified file 'storage/falcon/Database.h'
--- a/storage/falcon/Database.h 2008-09-03 21:49:18 +0000
+++ b/storage/falcon/Database.h 2008-10-16 01:04:03 +0000
@@ -46,6 +46,7 @@ static const int FALC0N_SYNC_OBJECTS =
static const int FALC0N_FREEZE = 8;
static const int FALC0N_REPORT_WRITES = 16;
static const int FALC0N_SYNC_HANDLER = 32;
+static const int FALC0N_TEST_BITMAP = 64;
#define TABLE_HASH_SIZE 101
@@ -305,7 +306,7 @@ public:
int noSchedule;
int pendingIOErrorCode;
uint32 serialLogBlockSize;
-
+
volatile INTERLOCK_TYPE currentGeneration;
uint64 recordMemoryMax;
uint64 recordScavengeThreshold;