Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
47f379d2
Commit
47f379d2
authored
Jan 23, 2008
by
jonas@perch.ndb.mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge perch.ndb.mysql.com:/home/jonas/src/51-telco-gca
into perch.ndb.mysql.com:/home/jonas/src/51-ndb
parents
ddf645b1
94378f91
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
465 additions
and
373 deletions
+465
-373
storage/ndb/include/util/Bitmask.hpp
storage/ndb/include/util/Bitmask.hpp
+9
-1
storage/ndb/src/common/util/Bitmask.cpp
storage/ndb/src/common/util/Bitmask.cpp
+52
-368
storage/ndb/test/ndbapi/testBitfield.cpp
storage/ndb/test/ndbapi/testBitfield.cpp
+404
-4
No files found.
storage/ndb/include/util/Bitmask.hpp
View file @
47f379d2
...
...
@@ -139,6 +139,7 @@ public:
/**
* setField - Set bitfield at given position and length (max 32 bits)
* Note : length == 0 not supported.
*/
static
void
setField
(
unsigned
size
,
Uint32
data
[],
unsigned
pos
,
unsigned
len
,
Uint32
val
);
...
...
@@ -146,6 +147,7 @@ public:
/**
* getField - Get bitfield at given position and length
* Note : length == 0 not supported.
*/
static
void
getField
(
unsigned
size
,
const
Uint32
data
[],
unsigned
pos
,
unsigned
len
,
Uint32
dst
[]);
...
...
@@ -918,6 +920,9 @@ BitmaskImpl::getField(unsigned size, const Uint32 src[],
unsigned
pos
,
unsigned
len
,
Uint32
dst
[])
{
assert
(
pos
+
len
<=
(
size
<<
5
));
assert
(
len
!=
0
);
if
(
len
==
0
)
return
;
src
+=
(
pos
>>
5
);
Uint32
offset
=
pos
&
31
;
...
...
@@ -937,6 +942,9 @@ BitmaskImpl::setField(unsigned size, Uint32 dst[],
unsigned
pos
,
unsigned
len
,
const
Uint32
src
[])
{
assert
(
pos
+
len
<=
(
size
<<
5
));
assert
(
len
!=
0
);
if
(
len
==
0
)
return
;
dst
+=
(
pos
>>
5
);
Uint32
offset
=
pos
&
31
;
...
...
storage/ndb/src/common/util/Bitmask.cpp
View file @
47f379d2
...
...
@@ -20,13 +20,38 @@ void
BitmaskImpl
::
getFieldImpl
(
const
Uint32
src
[],
unsigned
shiftL
,
unsigned
len
,
Uint32
dst
[])
{
/* Copy whole words of src to dst, shifting src left
* by shiftL. Undefined bits of the last written dst word
* should be zeroed.
*/
assert
(
shiftL
<
32
);
unsigned
shiftR
=
32
-
shiftL
;
unsigned
undefined
=
shiftL
?
~
0
:
0
;
/* Merge first word with previously set bits if there's a shift */
*
dst
=
shiftL
?
*
dst
:
0
;
/* Treat the zero-shift case separately to avoid
* trampling or reading past the end of src
*/
if
(
shiftL
==
0
)
{
while
(
len
>=
32
)
{
*
dst
++
=
*
src
++
;
len
-=
32
;
}
if
(
len
!=
0
)
{
/* Last word has some bits set */
Uint32
mask
=
((
1
<<
len
)
-
1
);
// 0000111
*
dst
=
(
*
src
)
&
mask
;
}
}
else
// shiftL !=0, need to build each word from two words shifted
{
while
(
len
>=
32
)
{
*
dst
++
|=
(
*
src
)
<<
shiftL
;
...
...
@@ -34,15 +59,21 @@ BitmaskImpl::getFieldImpl(const Uint32 src[],
len
-=
32
;
}
if
(
len
<
shiftR
)
/* Have space for shiftR more bits in the current dst word
* is that enough?
*/
if
(
len
<=
shiftR
)
{
/* Fit the remaining bits in the current dst word */
*
dst
|=
((
*
src
)
&
((
1
<<
len
)
-
1
))
<<
shiftL
;
}
else
{
/* Need to write to two dst words */
*
dst
++
|=
((
*
src
)
<<
shiftL
);
*
dst
=
((
*
src
)
>>
shiftR
)
&
((
1
<<
(
len
-
shiftR
))
-
1
)
&
undefined
;
}
}
}
void
...
...
@@ -64,370 +95,23 @@ BitmaskImpl::setFieldImpl(Uint32 dst[],
len
-=
32
;
}
/* Copy last bits */
Uint32
mask
=
((
1
<<
len
)
-
1
);
*
dst
=
(
*
dst
&
~
mask
);
if
(
len
<
shiftR
)
if
(
len
<
=
shiftR
)
{
/* Remaining bits fit in current word */
*
dst
|=
((
*
src
++
)
>>
shiftL
)
&
mask
;
}
else
{
/* Remaining bits update 2 words */
*
dst
|=
((
*
src
++
)
>>
shiftL
);
*
dst
|=
((
*
src
)
&
((
1
<<
(
len
-
shiftR
))
-
1
))
<<
shiftR
;
}
}
#ifdef __TEST_BITMASK__
static
void
print
(
const
Uint32
src
[],
Uint32
len
,
Uint32
pos
=
0
)
{
printf
(
"b'"
);
for
(
unsigned
i
=
0
;
i
<
len
;
i
++
)
{
if
(
BitmaskImpl
::
get
((
pos
+
len
+
31
)
>>
5
,
src
,
i
+
pos
))
printf
(
"1"
);
else
printf
(
"0"
);
if
((
i
&
31
)
==
31
)
printf
(
" "
);
}
}
#define DEBUG 0
#include <Vector.hpp>
static
void
do_test
(
int
bitmask_size
);
int
main
(
int
argc
,
char
**
argv
)
{
int
loops
=
argc
>
1
?
atoi
(
argv
[
1
])
:
1000
;
int
max_size
=
argc
>
2
?
atoi
(
argv
[
2
])
:
1000
;
for
(
int
i
=
0
;
i
<
loops
;
i
++
)
do_test
(
1
+
(
rand
()
%
max_size
));
}
struct
Alloc
{
Uint32
pos
;
Uint32
size
;
Vector
<
Uint32
>
data
;
};
static
void
require
(
bool
b
)
{
if
(
!
b
)
abort
();
}
static
bool
cmp
(
const
Uint32
b1
[],
const
Uint32
b2
[],
Uint32
len
)
{
Uint32
sz32
=
(
len
+
31
)
>>
5
;
for
(
int
i
=
0
;
i
<
len
;
i
++
)
{
if
(
BitmaskImpl
::
get
(
sz32
,
b1
,
i
)
^
BitmaskImpl
::
get
(
sz32
,
b2
,
i
))
return
false
;
}
return
true
;
}
static
int
val_pos
=
0
;
static
int
val
[]
=
{
384
,
241
,
32
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
241
};
static
int
lrand
()
{
#if 0
return val[val_pos++];
#else
return
rand
();
#endif
}
static
void
rand
(
Uint32
dst
[],
Uint32
len
)
{
for
(
int
i
=
0
;
i
<
len
;
i
++
)
BitmaskImpl
::
set
((
len
+
31
)
>>
5
,
dst
,
i
,
(
lrand
()
%
1000
)
>
500
);
}
static
void
simple
(
int
pos
,
int
size
)
{
ndbout_c
(
"simple pos: %d size: %d"
,
pos
,
size
);
Vector
<
Uint32
>
_mask
;
Vector
<
Uint32
>
_src
;
Vector
<
Uint32
>
_dst
;
Uint32
sz32
=
(
size
+
pos
+
32
)
>>
5
;
const
Uint32
sz
=
4
*
sz32
;
Uint32
zero
=
0
;
_mask
.
fill
(
sz32
+
1
,
zero
);
_src
.
fill
(
sz32
+
1
,
zero
);
_dst
.
fill
(
sz32
+
1
,
zero
);
Uint32
*
src
=
_src
.
getBase
();
Uint32
*
dst
=
_dst
.
getBase
();
Uint32
*
mask
=
_mask
.
getBase
();
memset
(
src
,
0x0
,
sz
);
memset
(
dst
,
0x0
,
sz
);
memset
(
mask
,
0xFF
,
sz
);
rand
(
src
,
size
);
BitmaskImpl
::
setField
(
sz32
,
mask
,
pos
,
size
,
src
);
BitmaskImpl
::
getField
(
sz32
,
mask
,
pos
,
size
,
dst
);
printf
(
"src: "
);
print
(
src
,
size
+
31
);
printf
(
"
\n
"
);
printf
(
"msk: "
);
print
(
mask
,
(
sz32
<<
5
)
+
31
);
printf
(
"
\n
"
);
printf
(
"dst: "
);
print
(
dst
,
size
+
31
);
printf
(
"
\n
"
);
require
(
cmp
(
src
,
dst
,
size
+
31
));
};
static
void
simple2
(
int
size
,
int
loops
)
{
ndbout_c
(
"simple2 %d - "
,
size
);
Vector
<
Uint32
>
_mask
;
Vector
<
Uint32
>
_src
;
Vector
<
Uint32
>
_dst
;
Uint32
sz32
=
(
size
+
32
)
>>
5
;
Uint32
sz
=
sz32
<<
2
;
Uint32
zero
=
0
;
_mask
.
fill
(
sz32
+
1
,
zero
);
_src
.
fill
(
sz32
+
1
,
zero
);
_dst
.
fill
(
sz32
+
1
,
zero
);
Uint32
*
src
=
_src
.
getBase
();
Uint32
*
dst
=
_dst
.
getBase
();
Uint32
*
mask
=
_mask
.
getBase
();
Vector
<
Uint32
>
save
;
for
(
int
i
=
0
;
i
<
loops
;
i
++
)
{
memset
(
mask
,
0xFF
,
sz
);
memset
(
dst
,
0xFF
,
sz
);
int
len
;
int
pos
=
0
;
while
(
pos
+
1
<
size
)
{
memset
(
src
,
0xFF
,
sz
);
while
(
!
(
len
=
rand
()
%
(
size
-
pos
)));
BitmaskImpl
::
setField
(
sz32
,
mask
,
pos
,
len
,
src
);
if
(
memcmp
(
dst
,
mask
,
sz
))
{
ndbout_c
(
"pos: %d len: %d"
,
pos
,
len
);
print
(
mask
,
size
);
abort
();
}
printf
(
"[ %d %d ]"
,
pos
,
len
);
save
.
push_back
(
pos
);
save
.
push_back
(
len
);
pos
+=
len
;
}
for
(
int
j
=
0
;
j
<
save
.
size
();
)
{
pos
=
save
[
j
++
];
len
=
save
[
j
++
];
memset
(
src
,
0xFF
,
sz
);
BitmaskImpl
::
getField
(
sz32
,
mask
,
pos
,
len
,
src
);
if
(
memcmp
(
dst
,
src
,
sz
))
{
ndbout_c
(
"pos: %d len: %d"
,
pos
,
len
);
printf
(
"src: "
);
print
(
src
,
size
);
printf
(
"
\n
"
);
printf
(
"dst: "
);
print
(
dst
,
size
);
printf
(
"
\n
"
);
printf
(
"msk: "
);
print
(
mask
,
size
);
printf
(
"
\n
"
);
abort
();
}
}
ndbout_c
(
""
);
}
}
static
void
do_test
(
int
bitmask_size
)
{
#if 1
simple
(
rand
()
%
33
,
(
rand
()
%
63
)
+
1
);
//#else
Vector
<
Alloc
>
alloc_list
;
bitmask_size
=
(
bitmask_size
+
31
)
&
~
31
;
Uint32
sz32
=
(
bitmask_size
>>
5
);
Vector
<
Uint32
>
alloc_mask
;
Vector
<
Uint32
>
test_mask
;
ndbout_c
(
"Testing bitmask of size %d"
,
bitmask_size
);
Uint32
zero
=
0
;
alloc_mask
.
fill
(
sz32
,
zero
);
test_mask
.
fill
(
sz32
,
zero
);
for
(
int
i
=
0
;
i
<
5000
;
i
++
)
{
Vector
<
Uint32
>
tmp
;
tmp
.
fill
(
sz32
,
zero
);
int
pos
=
lrand
()
%
(
bitmask_size
-
1
);
int
free
=
0
;
if
(
BitmaskImpl
::
get
(
sz32
,
alloc_mask
.
getBase
(),
pos
))
{
// Bit was allocated
// 1) Look up allocation
// 2) Check data
// 3) free it
size_t
j
;
int
min
,
max
;
for
(
j
=
0
;
j
<
alloc_list
.
size
();
j
++
)
{
min
=
alloc_list
[
j
].
pos
;
max
=
min
+
alloc_list
[
j
].
size
;
if
(
pos
>=
min
&&
pos
<
max
)
{
break
;
}
}
require
(
pos
>=
min
&&
pos
<
max
);
BitmaskImpl
::
getField
(
sz32
,
test_mask
.
getBase
(),
min
,
max
-
min
,
tmp
.
getBase
());
if
(
DEBUG
)
{
printf
(
"freeing [ %d %d ]"
,
min
,
max
);
printf
(
"- mask: "
);
print
(
tmp
.
getBase
(),
max
-
min
);
printf
(
" save: "
);
size_t
k
;
Alloc
&
a
=
alloc_list
[
j
];
for
(
k
=
0
;
k
<
a
.
data
.
size
();
k
++
)
printf
(
"%.8x "
,
a
.
data
[
k
]);
printf
(
"
\n
"
);
}
int
bytes
=
(
max
-
min
+
7
)
>>
3
;
if
(
!
cmp
(
tmp
.
getBase
(),
alloc_list
[
j
].
data
.
getBase
(),
max
-
min
))
{
abort
();
}
while
(
min
<
max
)
BitmaskImpl
::
clear
(
sz32
,
alloc_mask
.
getBase
(),
min
++
);
alloc_list
.
erase
(
j
);
}
else
{
Vector
<
Uint32
>
tmp
;
tmp
.
fill
(
sz32
,
zero
);
// Bit was free
// 1) Check how much space is avaiable
// 2) Create new allocation of lrandom size
// 3) Fill data with lrandom data
// 4) Update alloc mask
while
(
pos
+
free
<
bitmask_size
&&
!
BitmaskImpl
::
get
(
sz32
,
alloc_mask
.
getBase
(),
pos
+
free
))
free
++
;
Uint32
sz
=
(
free
<=
64
&&
((
lrand
()
%
100
)
>
80
))
?
free
:
(
lrand
()
%
free
);
sz
=
sz
?
sz
:
1
;
sz
=
pos
+
sz
==
bitmask_size
?
sz
-
1
:
sz
;
Alloc
a
;
a
.
pos
=
pos
;
a
.
size
=
sz
;
a
.
data
.
fill
(((
sz
+
31
)
>>
5
)
-
1
,
zero
);
if
(
DEBUG
)
printf
(
"pos %d -> alloc [ %d %d ]"
,
pos
,
pos
,
pos
+
sz
);
for
(
size_t
j
=
0
;
j
<
sz
;
j
++
)
{
BitmaskImpl
::
set
(
sz32
,
alloc_mask
.
getBase
(),
pos
+
j
);
if
((
lrand
()
%
1000
)
>
500
)
BitmaskImpl
::
set
((
sz
+
31
)
>>
5
,
a
.
data
.
getBase
(),
j
);
}
if
(
DEBUG
)
{
printf
(
"- mask: "
);
print
(
a
.
data
.
getBase
(),
sz
);
printf
(
"
\n
"
);
}
BitmaskImpl
::
setField
(
sz32
,
test_mask
.
getBase
(),
pos
,
sz
,
a
.
data
.
getBase
());
alloc_list
.
push_back
(
a
);
}
}
for
(
Uint32
i
=
0
;
i
<
1000
;
i
++
)
{
Uint32
sz32
=
10
+
rand
()
%
100
;
Uint32
zero
=
0
;
Vector
<
Uint32
>
map
;
map
.
fill
(
sz32
,
zero
);
Uint32
sz
=
32
*
sz32
;
Uint32
start
=
(
rand
()
%
sz
);
Uint32
stop
=
start
+
((
rand
()
%
(
sz
-
start
))
&
0xFFFFFFFF
);
Vector
<
Uint32
>
check
;
check
.
fill
(
sz32
,
zero
);
for
(
Uint32
j
=
0
;
j
<
sz
;
j
++
)
{
bool
expect
=
(
j
>=
start
&&
j
<
stop
);
if
(
expect
)
BitmaskImpl
::
set
(
sz32
,
check
.
getBase
(),
j
);
}
BitmaskImpl
::
set
(
sz32
,
map
.
getBase
(),
start
,
stop
);
if
(
!
BitmaskImpl
::
equal
(
sz32
,
map
.
getBase
(),
check
.
getBase
()))
{
ndbout_c
(
" FAIL sz: %d [ %d %d ]"
,
sz
,
start
,
stop
);
printf
(
"check: "
);
for
(
Uint32
j
=
0
;
j
<
sz32
;
j
++
)
printf
(
"%.8x "
,
check
[
j
]);
printf
(
"
\n
"
);
printf
(
"map : "
);
for
(
Uint32
j
=
0
;
j
<
sz32
;
j
++
)
printf
(
"%.8x "
,
map
[
j
]);
printf
(
"
\n
"
);
abort
();
}
map
.
clear
();
check
.
clear
();
Uint32
one
=
~
(
Uint32
)
0
;
map
.
fill
(
sz32
,
one
);
check
.
fill
(
sz32
,
one
);
for
(
Uint32
j
=
0
;
j
<
sz
;
j
++
)
{
bool
expect
=
(
j
>=
start
&&
j
<
stop
);
if
(
expect
)
BitmaskImpl
::
clear
(
sz32
,
check
.
getBase
(),
j
);
}
BitmaskImpl
::
clear
(
sz32
,
map
.
getBase
(),
start
,
stop
);
if
(
!
BitmaskImpl
::
equal
(
sz32
,
map
.
getBase
(),
check
.
getBase
()))
{
ndbout_c
(
" FAIL sz: %d [ %d %d ]"
,
sz
,
start
,
stop
);
printf
(
"check: "
);
for
(
Uint32
j
=
0
;
j
<
sz32
;
j
++
)
printf
(
"%.8x "
,
check
[
j
]);
printf
(
"
\n
"
);
printf
(
"map : "
);
for
(
Uint32
j
=
0
;
j
<
sz32
;
j
++
)
printf
(
"%.8x "
,
map
[
j
]);
printf
(
"
\n
"
);
abort
();
}
}
#endif
}
template
class
Vector
<
Alloc
>;
template
class
Vector
<
Uint32
>;
#endif
/* Bitmask testcase code moved from here to
* storage/ndb/test/ndbapi/testBitfield.cpp
* to get coverage from automated testing
*/
storage/ndb/test/ndbapi/testBitfield.cpp
View file @
47f379d2
...
...
@@ -4,6 +4,8 @@
#include <NDBT.hpp>
#include <NdbApi.hpp>
#include <HugoTransactions.hpp>
#include <Bitmask.hpp>
#include <Vector.hpp>
static
const
char
*
_dbname
=
"TEST_DB"
;
static
int
g_loops
=
7
;
...
...
@@ -37,6 +39,7 @@ static int unique_indexes(Ndb*, const NdbDictionary::Table* tab);
static
int
ordered_indexes
(
Ndb
*
,
const
NdbDictionary
::
Table
*
tab
);
static
int
node_restart
(
Ndb
*
,
const
NdbDictionary
::
Table
*
tab
);
static
int
system_restart
(
Ndb
*
,
const
NdbDictionary
::
Table
*
tab
);
static
int
testBitmask
();
int
main
(
int
argc
,
char
**
argv
){
...
...
@@ -49,6 +52,15 @@ main(int argc, char** argv){
ndb_std_get_one_option
)))
return
NDBT_ProgramExit
(
NDBT_WRONGARGS
);
int
res
=
NDBT_FAILED
;
/* Run cluster-independent tests */
for
(
int
i
=
0
;
i
<
(
10
*
g_loops
);
i
++
)
{
if
(
NDBT_OK
!=
(
res
=
testBitmask
()))
return
NDBT_ProgramExit
(
res
);
}
Ndb_cluster_connection
con
(
opt_connect_str
);
if
(
con
.
connect
(
12
,
5
,
1
))
{
...
...
@@ -60,7 +72,6 @@ main(int argc, char** argv){
pNdb
=
new
Ndb
(
&
con
,
_dbname
);
pNdb
->
init
();
while
(
pNdb
->
waitUntilReady
()
!=
0
);
int
res
=
NDBT_FAILED
;
NdbDictionary
::
Dictionary
*
dict
=
pNdb
->
getDictionary
();
...
...
@@ -121,14 +132,12 @@ create_random_table(Ndb* pNdb)
do
{
NdbDictionary
::
Table
tab
;
Uint32
cols
=
1
+
(
rand
()
%
(
NDB_MAX_ATTRIBUTES_IN_TABLE
-
1
));
Uint32
keys
=
NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY
;
Uint32
length
=
4090
;
Uint32
key_size
=
NDB_MAX_KEYSIZE_IN_WORDS
;
BaseString
name
;
name
.
assfmt
(
"TAB_%d"
,
rand
()
&
65535
);
tab
.
setName
(
name
.
c_str
());
for
(
int
i
=
0
;
i
<
cols
&&
length
>
2
;
i
++
)
for
(
Uint32
i
=
0
;
i
<
cols
&&
length
>
2
;
i
++
)
{
NdbDictionary
::
Column
col
;
name
.
assfmt
(
"COL_%d"
,
i
);
...
...
@@ -206,3 +215,394 @@ system_restart(Ndb* pNdb, const NdbDictionary::Table* tab)
{
return
0
;
}
/* Note : folowing classes test functionality of storage/ndb/src/common/util/Bitmask.cpp
* and were originally defined there.
* Set BITMASK_DEBUG to 1 to get more test debugging info.
*/
#define BITMASK_DEBUG 0
static
bool
cmp
(
const
Uint32
b1
[],
const
Uint32
b2
[],
Uint32
len
)
{
Uint32
sz32
=
(
len
+
31
)
>>
5
;
for
(
Uint32
i
=
0
;
i
<
len
;
i
++
)
{
if
(
BitmaskImpl
::
get
(
sz32
,
b1
,
i
)
^
BitmaskImpl
::
get
(
sz32
,
b2
,
i
))
return
false
;
}
return
true
;
}
static
void
print
(
const
Uint32
src
[],
Uint32
len
,
Uint32
pos
=
0
)
{
printf
(
"b'"
);
for
(
unsigned
i
=
0
;
i
<
len
;
i
++
)
{
if
(
BitmaskImpl
::
get
((
pos
+
len
+
31
)
>>
5
,
src
,
i
+
pos
))
printf
(
"1"
);
else
printf
(
"0"
);
if
((
i
&
31
)
==
31
)
printf
(
" "
);
}
}
static
int
lrand
()
{
return
rand
();
}
static
void
rand
(
Uint32
dst
[],
Uint32
len
)
{
for
(
Uint32
i
=
0
;
i
<
len
;
i
++
)
BitmaskImpl
::
set
((
len
+
31
)
>>
5
,
dst
,
i
,
(
lrand
()
%
1000
)
>
500
);
}
static
int
checkNoTramplingGetSetField
(
const
Uint32
totalTests
)
{
const
Uint32
numWords
=
67
;
const
Uint32
maxBitsToCopy
=
(
numWords
*
32
);
Uint32
sourceBuf
[
numWords
];
Uint32
targetBuf
[
numWords
];
ndbout
<<
"Testing : Bitmask NoTrampling
\n
"
;
memset
(
sourceBuf
,
0x00
,
(
numWords
*
4
));
for
(
Uint32
test
=
0
;
test
<
totalTests
;
test
++
)
{
/* Always copy at least 1 bit */
Uint32
srcStart
=
rand
()
%
(
maxBitsToCopy
-
1
);
Uint32
length
=
(
rand
()
%
((
maxBitsToCopy
-
1
)
-
srcStart
))
+
1
;
if
(
BITMASK_DEBUG
)
ndbout
<<
"Testing start %u, length %u
\n
"
<<
srcStart
<<
length
;
// Set target to all ones.
memset
(
targetBuf
,
0xff
,
(
numWords
*
4
));
BitmaskImpl
::
getField
(
numWords
,
sourceBuf
,
srcStart
,
length
,
targetBuf
);
// Check that there is no trampling
Uint32
firstUntrampledWord
=
(
length
+
31
)
/
32
;
for
(
Uint32
word
=
0
;
word
<
numWords
;
word
++
)
{
Uint32
targetWord
=
targetBuf
[
word
];
if
(
BITMASK_DEBUG
)
ndbout
<<
"word=%d, targetWord=%u, firstUntrampledWord..=%u"
<<
word
<<
targetWord
<<
firstUntrampledWord
;
if
(
!
(
word
<
firstUntrampledWord
)
?
(
targetWord
==
0
)
:
(
targetWord
==
0xffffffff
))
{
ndbout
<<
"Notrampling getField failed for srcStart "
<<
srcStart
<<
" length "
<<
length
<<
" at word "
<<
word
<<
"
\n
"
;
ndbout
<<
"word=%d, targetWord=%u, firstUntrampledWord..=%u"
<<
word
<<
targetWord
<<
firstUntrampledWord
;
return
-
1
;
}
}
/* Set target back to all ones. */
memset
(
targetBuf
,
0xff
,
(
numWords
*
4
));
BitmaskImpl
::
setField
(
numWords
,
targetBuf
,
srcStart
,
length
,
sourceBuf
);
/* Check we've got all ones, with zeros only where expected */
for
(
Uint32
word
=
0
;
word
<
numWords
;
word
++
)
{
Uint32
targetWord
=
targetBuf
[
word
];
for
(
Uint32
bit
=
0
;
bit
<
32
;
bit
++
)
{
Uint32
bitNum
=
(
word
<<
5
)
+
bit
;
bool
expectedValue
=
!
((
bitNum
>=
srcStart
)
&&
(
bitNum
<
(
srcStart
+
length
)));
bool
actualValue
=
(((
targetWord
>>
bit
)
&
1
)
==
1
);
if
(
BITMASK_DEBUG
)
ndbout
<<
"bitNum=%u expectedValue=%u, actual value=%u"
<<
bitNum
<<
expectedValue
<<
actualValue
;
if
(
actualValue
!=
expectedValue
)
{
ndbout
<<
"Notrampling setField failed for srcStart "
<<
srcStart
<<
" length "
<<
length
<<
" at word "
<<
word
<<
" bit "
<<
bit
<<
"
\n
"
;
ndbout
<<
"bitNum=%u expectedValue=%u, actual value=%u"
<<
bitNum
<<
expectedValue
<<
actualValue
;
return
-
1
;
}
}
}
}
return
0
;
}
static
int
simple
(
int
pos
,
int
size
)
{
ndbout
<<
"Testing : Bitmask simple pos: "
<<
pos
<<
" size: "
<<
size
<<
"
\n
"
;
Vector
<
Uint32
>
_mask
;
Vector
<
Uint32
>
_src
;
Vector
<
Uint32
>
_dst
;
Uint32
sz32
=
(
size
+
pos
+
32
)
>>
5
;
const
Uint32
sz
=
4
*
sz32
;
Uint32
zero
=
0
;
_mask
.
fill
(
sz32
+
1
,
zero
);
_src
.
fill
(
sz32
+
1
,
zero
);
_dst
.
fill
(
sz32
+
1
,
zero
);
Uint32
*
src
=
_src
.
getBase
();
Uint32
*
dst
=
_dst
.
getBase
();
Uint32
*
mask
=
_mask
.
getBase
();
memset
(
src
,
0x0
,
sz
);
memset
(
dst
,
0x0
,
sz
);
memset
(
mask
,
0xFF
,
sz
);
rand
(
src
,
size
);
BitmaskImpl
::
setField
(
sz32
,
mask
,
pos
,
size
,
src
);
BitmaskImpl
::
getField
(
sz32
,
mask
,
pos
,
size
,
dst
);
if
(
BITMASK_DEBUG
)
{
printf
(
"src: "
);
print
(
src
,
size
+
31
);
printf
(
"
\n
"
);
printf
(
"msk: "
);
print
(
mask
,
(
sz32
<<
5
)
+
31
);
printf
(
"
\n
"
);
printf
(
"dst: "
);
print
(
dst
,
size
+
31
);
printf
(
"
\n
"
);
}
return
(
cmp
(
src
,
dst
,
size
+
31
)
?
0
:
-
1
);
};
struct
Alloc
{
Uint32
pos
;
Uint32
size
;
Vector
<
Uint32
>
data
;
};
static
int
testRanges
(
Uint32
bitmask_size
)
{
Vector
<
Alloc
>
alloc_list
;
bitmask_size
=
(
bitmask_size
+
31
)
&
~
31
;
Uint32
sz32
=
(
bitmask_size
>>
5
);
Vector
<
Uint32
>
alloc_mask
;
Vector
<
Uint32
>
test_mask
;
ndbout_c
(
"Testing : Bitmask ranges for bitmask of size %d"
,
bitmask_size
);
Uint32
zero
=
0
;
alloc_mask
.
fill
(
sz32
,
zero
);
test_mask
.
fill
(
sz32
,
zero
);
/* Loop a number of times, setting and clearing bits in the mask
* and tracking the modifications in a separate structure.
* Check that both structures remain in sync
*/
for
(
int
i
=
0
;
i
<
5000
;
i
++
)
{
Vector
<
Uint32
>
tmp
;
tmp
.
fill
(
sz32
,
zero
);
Uint32
pos
=
lrand
()
%
(
bitmask_size
-
1
);
Uint32
free
=
0
;
if
(
BitmaskImpl
::
get
(
sz32
,
alloc_mask
.
getBase
(),
pos
))
{
// Bit was allocated
// 1) Look up allocation
// 2) Check data
// 3) free it
size_t
j
;
Uint32
min
,
max
;
for
(
j
=
0
;
j
<
alloc_list
.
size
();
j
++
)
{
min
=
alloc_list
[
j
].
pos
;
max
=
min
+
alloc_list
[
j
].
size
;
if
(
pos
>=
min
&&
pos
<
max
)
{
break
;
}
}
if
(
!
((
pos
>=
min
)
&&
(
pos
<
max
)))
{
printf
(
"Failed with pos %u, min %u, max %u
\n
"
,
pos
,
min
,
max
);
return
-
1
;
}
BitmaskImpl
::
getField
(
sz32
,
test_mask
.
getBase
(),
min
,
max
-
min
,
tmp
.
getBase
());
if
(
BITMASK_DEBUG
)
{
printf
(
"freeing [ %d %d ]"
,
min
,
max
);
printf
(
"- mask: "
);
print
(
tmp
.
getBase
(),
max
-
min
);
printf
(
" save: "
);
size_t
k
;
Alloc
&
a
=
alloc_list
[
j
];
for
(
k
=
0
;
k
<
a
.
data
.
size
();
k
++
)
printf
(
"%.8x "
,
a
.
data
[
k
]);
printf
(
"
\n
"
);
}
if
(
!
cmp
(
tmp
.
getBase
(),
alloc_list
[
j
].
data
.
getBase
(),
max
-
min
))
{
return
-
1
;
}
while
(
min
<
max
)
BitmaskImpl
::
clear
(
sz32
,
alloc_mask
.
getBase
(),
min
++
);
alloc_list
.
erase
(
j
);
}
else
{
Vector
<
Uint32
>
tmp
;
tmp
.
fill
(
sz32
,
zero
);
// Bit was free
// 1) Check how much space is avaiable
// 2) Create new allocation of lrandom size
// 3) Fill data with lrandom data
// 4) Update alloc mask
while
(
pos
+
free
<
bitmask_size
&&
!
BitmaskImpl
::
get
(
sz32
,
alloc_mask
.
getBase
(),
pos
+
free
))
free
++
;
Uint32
sz
=
(
free
<=
64
&&
((
lrand
()
%
100
)
>
80
))
?
free
:
(
lrand
()
%
free
);
sz
=
sz
?
sz
:
1
;
sz
=
pos
+
sz
==
bitmask_size
?
sz
-
1
:
sz
;
Alloc
a
;
a
.
pos
=
pos
;
a
.
size
=
sz
;
a
.
data
.
fill
(((
sz
+
31
)
>>
5
)
-
1
,
zero
);
if
(
BITMASK_DEBUG
)
printf
(
"pos %d -> alloc [ %d %d ]"
,
pos
,
pos
,
pos
+
sz
);
for
(
size_t
j
=
0
;
j
<
sz
;
j
++
)
{
BitmaskImpl
::
set
(
sz32
,
alloc_mask
.
getBase
(),
pos
+
j
);
if
((
lrand
()
%
1000
)
>
500
)
BitmaskImpl
::
set
((
sz
+
31
)
>>
5
,
a
.
data
.
getBase
(),
j
);
}
if
(
BITMASK_DEBUG
)
{
printf
(
"- mask: "
);
print
(
a
.
data
.
getBase
(),
sz
);
printf
(
"
\n
"
);
}
BitmaskImpl
::
setField
(
sz32
,
test_mask
.
getBase
(),
pos
,
sz
,
a
.
data
.
getBase
());
alloc_list
.
push_back
(
a
);
}
}
#define NDB_BM_SUPPORT_RANGE
#ifdef NDB_BM_SUPPORT_RANGE
for
(
Uint32
i
=
0
;
i
<
1000
;
i
++
)
{
Uint32
sz32
=
10
+
rand
()
%
100
;
Uint32
zero
=
0
;
Vector
<
Uint32
>
map
;
map
.
fill
(
sz32
,
zero
);
Uint32
sz
=
32
*
sz32
;
Uint32
start
=
(
rand
()
%
sz
);
Uint32
stop
=
start
+
((
rand
()
%
(
sz
-
start
))
&
0xFFFFFFFF
);
Vector
<
Uint32
>
check
;
check
.
fill
(
sz32
,
zero
);
/* Verify range setting method works correctly */
for
(
Uint32
j
=
0
;
j
<
sz
;
j
++
)
{
bool
expect
=
(
j
>=
start
&&
j
<
stop
);
if
(
expect
)
BitmaskImpl
::
set
(
sz32
,
check
.
getBase
(),
j
);
}
BitmaskImpl
::
set_range
(
sz32
,
map
.
getBase
(),
start
,
stop
);
if
(
!
BitmaskImpl
::
equal
(
sz32
,
map
.
getBase
(),
check
.
getBase
()))
{
ndbout_c
(
" FAIL 1 sz: %d [ %d %d ]"
,
sz
,
start
,
stop
);
printf
(
"check: "
);
for
(
Uint32
j
=
0
;
j
<
sz32
;
j
++
)
printf
(
"%.8x "
,
check
[
j
]);
printf
(
"
\n
"
);
printf
(
"map : "
);
for
(
Uint32
j
=
0
;
j
<
sz32
;
j
++
)
printf
(
"%.8x "
,
map
[
j
]);
printf
(
"
\n
"
);
return
-
1
;
}
map
.
clear
();
check
.
clear
();
/* Verify range clearing method works correctly */
Uint32
one
=
~
(
Uint32
)
0
;
map
.
fill
(
sz32
,
one
);
check
.
fill
(
sz32
,
one
);
for
(
Uint32
j
=
0
;
j
<
sz
;
j
++
)
{
bool
expect
=
(
j
>=
start
&&
j
<
stop
);
if
(
expect
)
BitmaskImpl
::
clear
(
sz32
,
check
.
getBase
(),
j
);
}
BitmaskImpl
::
clear_range
(
sz32
,
map
.
getBase
(),
start
,
stop
);
if
(
!
BitmaskImpl
::
equal
(
sz32
,
map
.
getBase
(),
check
.
getBase
()))
{
ndbout_c
(
" FAIL 2 sz: %d [ %d %d ]"
,
sz
,
start
,
stop
);
printf
(
"check: "
);
for
(
Uint32
j
=
0
;
j
<
sz32
;
j
++
)
printf
(
"%.8x "
,
check
[
j
]);
printf
(
"
\n
"
);
printf
(
"map : "
);
for
(
Uint32
j
=
0
;
j
<
sz32
;
j
++
)
printf
(
"%.8x "
,
map
[
j
]);
printf
(
"
\n
"
);
return
-
1
;
}
}
#endif
return
0
;
}
static
int
testBitmask
()
{
/* Some testcases from storage/ndb/src/common/util/Bitmask.cpp */
int
res
=
0
;
if
((
res
=
checkNoTramplingGetSetField
(
100
/* totalTests */
))
!=
0
)
return
res
;
if
((
res
=
simple
(
rand
()
%
33
,
// position
(
rand
()
%
63
)
+
1
)
// size
)
!=
0
)
return
res
;
if
((
res
=
testRanges
(
1
+
(
rand
()
%
1000
)
// bitmask size
))
!=
0
)
return
res
;
return
0
;
}
template
class
Vector
<
Alloc
>;
template
class
Vector
<
Uint32
>;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment