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
f02562b7
Commit
f02562b7
authored
Jan 23, 2008
by
tomas@whalegate.ndb.mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge whalegate.ndb.mysql.com:/home/tomas/cge-5.1
into whalegate.ndb.mysql.com:/home/tomas/mysql-5.1-new-ndb-bj
parents
4b0d36cc
79e8f3e4
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1532 additions
and
514 deletions
+1532
-514
storage/ndb/include/util/Bitmask.hpp
storage/ndb/include/util/Bitmask.hpp
+9
-1
storage/ndb/src/common/transporter/TCP_Transporter.cpp
storage/ndb/src/common/transporter/TCP_Transporter.cpp
+16
-6
storage/ndb/src/common/util/Bitmask.cpp
storage/ndb/src/common/util/Bitmask.cpp
+52
-368
storage/ndb/src/kernel/blocks/ERROR_codes.txt
storage/ndb/src/kernel/blocks/ERROR_codes.txt
+2
-1
storage/ndb/src/kernel/blocks/suma/Suma.cpp
storage/ndb/src/kernel/blocks/suma/Suma.cpp
+15
-1
storage/ndb/test/include/AtrtClient.hpp
storage/ndb/test/include/AtrtClient.hpp
+56
-0
storage/ndb/test/include/DbUtil.hpp
storage/ndb/test/include/DbUtil.hpp
+71
-26
storage/ndb/test/ndbapi/Makefile.am
storage/ndb/test/ndbapi/Makefile.am
+8
-1
storage/ndb/test/ndbapi/testBitfield.cpp
storage/ndb/test/ndbapi/testBitfield.cpp
+404
-4
storage/ndb/test/ndbapi/testNDBT.cpp
storage/ndb/test/ndbapi/testNDBT.cpp
+173
-0
storage/ndb/test/ndbapi/test_event.cpp
storage/ndb/test/ndbapi/test_event.cpp
+61
-0
storage/ndb/test/run-test/daily-basic-tests.txt
storage/ndb/test/run-test/daily-basic-tests.txt
+4
-0
storage/ndb/test/src/AtrtClient.cpp
storage/ndb/test/src/AtrtClient.cpp
+215
-0
storage/ndb/test/src/DbUtil.cpp
storage/ndb/test/src/DbUtil.cpp
+443
-103
storage/ndb/test/src/Makefile.am
storage/ndb/test/src/Makefile.am
+3
-3
No files found.
storage/ndb/include/util/Bitmask.hpp
View file @
f02562b7
...
...
@@ -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,7 +920,10 @@ 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
;
*
dst
=
(
*
src
>>
offset
)
&
(
len
>=
32
?
~
0
:
(
1
<<
len
)
-
1
);
...
...
@@ -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/transporter/TCP_Transporter.cpp
View file @
f02562b7
...
...
@@ -317,22 +317,32 @@ TCP_Transporter::doSend() {
// Empty the SendBuffers
const
char
*
const
sendPtr
=
m_sendBuffer
.
sendPtr
;
const
Uint32
sizeToSend
=
m_sendBuffer
.
sendDataSize
;
if
(
sizeToSend
>
0
){
bool
sent_any
=
true
;
while
(
m_sendBuffer
.
dataSize
>
0
)
{
const
char
*
const
sendPtr
=
m_sendBuffer
.
sendPtr
;
const
Uint32
sizeToSend
=
m_sendBuffer
.
sendDataSize
;
const
int
nBytesSent
=
send
(
theSocket
,
sendPtr
,
sizeToSend
,
0
);
if
(
nBytesSent
>
0
)
{
if
(
nBytesSent
>
0
)
{
sent_any
=
true
;
m_sendBuffer
.
bytesSent
(
nBytesSent
);
sendCount
++
;
sendSize
+=
nBytesSent
;
if
(
sendCount
==
reportFreq
){
if
(
sendCount
==
reportFreq
)
{
reportSendLen
(
get_callback_obj
(),
remoteNodeId
,
sendCount
,
sendSize
);
sendCount
=
0
;
sendSize
=
0
;
}
}
else
{
}
else
{
if
(
nBytesSent
<
0
&&
InetErrno
==
EAGAIN
&&
sent_any
)
break
;
// Send failed
#if defined DEBUG_TRANSPORTER
g_eventLogger
.
error
(
"Send Failure(disconnect==%d) to node = %d nBytesSent = %d "
...
...
storage/ndb/src/common/util/Bitmask.cpp
View file @
f02562b7
...
...
@@ -20,28 +20,59 @@ 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
;
while
(
len
>=
32
)
{
*
dst
++
|=
(
*
src
)
<<
shiftL
;
*
dst
=
((
*
src
++
)
>>
shiftR
)
&
undefined
;
len
-=
32
;
}
if
(
len
<
shiftR
)
/* Treat the zero-shift case separately to avoid
* trampling or reading past the end of src
*/
if
(
shiftL
==
0
)
{
*
dst
|=
((
*
src
)
&
((
1
<<
len
)
-
1
))
<<
shiftL
;
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
else
// shiftL !=0, need to build each word from two words shifted
{
*
dst
++
|=
((
*
src
)
<<
shiftL
);
*
dst
=
((
*
src
)
>>
shiftR
)
&
((
1
<<
(
len
-
shiftR
))
-
1
)
&
undefined
;
while
(
len
>=
32
)
{
*
dst
++
|=
(
*
src
)
<<
shiftL
;
*
dst
=
((
*
src
++
)
>>
shiftR
)
&
undefined
;
len
-=
32
;
}
/* 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
;
}
}
}
...
...
@@ -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/src/kernel/blocks/ERROR_codes.txt
View file @
f02562b7
...
...
@@ -11,9 +11,10 @@ Next CMVMI 9000
Next BACKUP 10038
Next DBUTIL 11002
Next DBTUX 12008
Next SUMA 13034
Next SUMA 13036
Next LGMAN 15001
Next TSMAN 16001
Next SUMA 13034
TESTING NODE FAILURE, ARBITRATION
---------------------------------
...
...
storage/ndb/src/kernel/blocks/suma/Suma.cpp
View file @
f02562b7
...
...
@@ -4908,6 +4908,21 @@ Suma::release_gci(Signal* signal, Uint32 buck, Uint32 gci)
if
(
gci
>=
head
.
m_max_gci
)
{
jam
();
if
(
ERROR_INSERTED
(
13034
))
{
jam
();
SET_ERROR_INSERT_VALUE
(
13035
);
return
;
}
if
(
ERROR_INSERTED
(
13035
))
{
CLEAR_ERROR_INSERT_VALUE
;
NodeReceiverGroup
rg
(
CMVMI
,
c_nodes_in_nodegroup_mask
);
rg
.
m_nodes
.
clear
(
getOwnNodeId
());
signal
->
theData
[
0
]
=
9999
;
sendSignal
(
rg
,
GSN_NDB_TAMPER
,
signal
,
1
,
JBA
);
return
;
}
head
.
m_page_pos
=
0
;
head
.
m_max_gci
=
gci
;
head
.
m_last_gci
=
0
;
...
...
@@ -4979,7 +4994,6 @@ Suma::start_resend(Signal* signal, Uint32 buck)
if
(
min
>
max
)
{
ndbrequire
(
pos
.
m_page_pos
<=
2
);
ndbrequire
(
pos
.
m_page_id
==
bucket
->
m_buffer_tail
);
m_active_buckets
.
set
(
buck
);
m_gcp_complete_rep_count
++
;
...
...
storage/ndb/test/include/AtrtClient.hpp
0 → 100644
View file @
f02562b7
/* 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; version 2 of the License.
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 */
#ifndef ATRT_CLIENT_HPP
#define ATRT_CLIENT_HPP
#include <DbUtil.hpp>
class
AtrtClient
:
public
DbUtil
{
public:
enum
AtrtCommandType
{
ATCT_CHANGE_VERSION
=
1
,
ATCT_RESET_PROC
=
2
};
AtrtClient
(
const
char
*
_user
=
"root"
,
const
char
*
_password
=
""
,
const
char
*
_suffix
=
".1.atrt"
);
AtrtClient
(
MYSQL
*
);
~
AtrtClient
();
// Command functions
bool
changeVersion
(
int
process_id
,
const
char
*
process_args
);
bool
resetProc
(
int
process_id
);
// Query functions
bool
getConnectString
(
int
cluster_id
,
SqlResultSet
&
result
);
bool
getClusters
(
SqlResultSet
&
result
);
bool
getMgmds
(
int
cluster_id
,
SqlResultSet
&
result
);
bool
getNdbds
(
int
cluster_id
,
SqlResultSet
&
result
);
private:
int
writeCommand
(
AtrtCommandType
_type
,
const
Properties
&
args
);
bool
readCommand
(
uint
command_id
,
SqlResultSet
&
result
);
bool
doCommand
(
AtrtCommandType
_type
,
const
Properties
&
args
);
};
#endif
storage/ndb/test/include/DbUtil.hpp
View file @
f02562b7
...
...
@@ -19,17 +19,11 @@
#ifndef DBUTIL_HPP
#define DBUTIL_HPP
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <NDBT.hpp>
#include <BaseString.hpp>
#include <Properties.hpp>
#include <Vector.hpp>
#include <mysql.h>
//include "rand.h"
#include <stdlib.h>
#include "BaseString.hpp"
#include "NDBT.hpp"
//#define DEBUG
#define DIE_UNLESS(expr) \
...
...
@@ -52,8 +46,41 @@ if (r) \
DIE_UNLESS(r == 0);\
}
#define DBU_TRUE 1
#define DBU_FALSE 0
class
SqlResultSet
:
public
Properties
{
public:
// Get row with number
bool
get_row
(
int
row_num
);
// Load next row
bool
next
(
void
);
// Reset iterator
void
reset
(
void
);
// Remove current row from resultset
void
remove
();
SqlResultSet
();
~
SqlResultSet
();
const
char
*
column
(
const
char
*
col_name
);
uint
columnAsInt
(
const
char
*
col_name
);
uint
insertId
();
uint
affectedRows
();
uint
numRows
(
void
);
uint
mysqlErrno
();
const
char
*
mysqlError
();
const
char
*
mysqlSqlstate
();
private:
uint
get_int
(
const
char
*
name
);
const
char
*
get_string
(
const
char
*
name
);
const
Properties
*
m_curr_row
;
uint
m_curr_row_num
;
};
#define DBU_FAILED 1
#define DBU_OK 0
...
...
@@ -61,11 +88,23 @@ class DbUtil
{
public:
/* Deprecated, see DbUtil(dbname, suffix) */
DbUtil
(
const
char
*
databaseName
);
DbUtil
(
const
char
*
dbname
,
const
char
*
suffix
=
NULL
);
DbUtil
(
MYSQL
*
mysql
);
DbUtil
(
const
char
*
dbname
=
"mysql"
,
const
char
*
user
=
"root"
,
const
char
*
pass
=
""
,
const
char
*
suffix
=
NULL
);
~
DbUtil
();
bool
doQuery
(
const
char
*
query
);
bool
doQuery
(
const
char
*
query
,
SqlResultSet
&
result
);
bool
doQuery
(
const
char
*
query
,
const
Properties
&
args
,
SqlResultSet
&
result
);
bool
doQuery
(
BaseString
&
str
);
bool
doQuery
(
BaseString
&
str
,
SqlResultSet
&
result
);
bool
doQuery
(
BaseString
&
str
,
const
Properties
&
args
,
SqlResultSet
&
result
);
bool
waitConnected
(
int
timeout
);
/* Deprecated, see connect() */
void
databaseLogin
(
const
char
*
system
,
const
char
*
usr
,
...
...
@@ -79,25 +118,35 @@ public:
const
char
*
getPassword
(){
return
m_pass
.
c_str
();};
const
char
*
getHost
()
{
return
m_host
.
c_str
();};
const
char
*
getSocket
()
{
return
m_socket
.
c_str
();};
const
char
*
getServerType
(){
return
mysql_get_server_info
(
mysql
);};
const
char
*
getServerType
(){
return
mysql_get_server_info
(
m
_m
ysql
);};
const
char
*
getError
();
MYSQL
*
getMysql
(){
return
mysql
;};
MYSQL
*
getMysql
(){
return
m
_m
ysql
;};
MYSQL_STMT
*
STDCALL
mysqlSimplePrepare
(
const
char
*
query
);
void
databaseLogout
();
void
mysqlCloseStmHandle
(
MYSQL_STMT
*
my_stmt
);
int
connect
();
void
disconnect
();
int
selectDb
();
int
selectDb
(
const
char
*
);
int
createDb
(
BaseString
&
);
int
doQuery
(
BaseString
&
);
int
doQuery
(
const
char
*
);
int
getErrorNumber
();
unsigned
long
selectCountTable
(
const
char
*
table
);
protected:
bool
runQuery
(
const
char
*
query
,
const
Properties
&
args
,
SqlResultSet
&
rows
);
bool
isConnected
();
MYSQL
*
m_mysql
;
bool
m_free_mysql
;
/* Don't free mysql* if allocated elsewhere */
private:
bool
m_connected
;
...
...
@@ -107,15 +156,11 @@ private:
BaseString
m_pass
;
// MySQL User Password
BaseString
m_dbname
;
// Database to use
BaseString
m_socket
;
// MySQL Server Unix Socket
BaseString
default_file
;
BaseString
default_group
;
BaseString
m_
default_file
;
BaseString
m_
default_group
;
unsigned
int
m_port
;
// MySQL Server port
MYSQL
*
mysql
;
MYSQL_RES
*
m_result
;
MYSQL_ROW
m_row
;
void
setDbName
(
const
char
*
name
){
m_dbname
.
assign
(
name
);};
void
setUser
(
const
char
*
user_name
){
m_user
.
assign
(
user_name
);};
void
setPassword
(
const
char
*
password
){
m_pass
.
assign
(
password
);};
...
...
@@ -125,7 +170,7 @@ private:
void
printError
(
const
char
*
msg
);
void
printStError
(
MYSQL_STMT
*
stmt
,
const
char
*
msg
);
void
die
(
const
char
*
file
,
int
line
,
const
char
*
expr
);
// stop program
};
#endif
storage/ndb/test/ndbapi/Makefile.am
View file @
f02562b7
...
...
@@ -52,7 +52,9 @@ testBitfield \
DbCreate DbAsyncGenerator
\
testSRBank
\
test_event_merge
\
testIndexStat
testIndexStat
\
testNDBT
\
NdbRepStress
EXTRA_PROGRAMS
=
\
test_event
\
...
...
@@ -98,7 +100,10 @@ ndbapi_slow_select_SOURCES = slow_select.cpp
testReadPerf_SOURCES
=
testReadPerf.cpp
testLcp_SOURCES
=
testLcp.cpp
testPartitioning_SOURCES
=
testPartitioning.cpp
testNDBT_SOURCES
=
testNDBT.cpp
testNDBT_LDADD
=
$(LDADD)
$(top_srcdir)
/libmysql_r/libmysqlclient_r.la
testBitfield_SOURCES
=
testBitfield.cpp
NdbRepStress_SOURCES
=
acrt/NdbRepStress.cpp
DbCreate_SOURCES
=
bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
DbAsyncGenerator_SOURCES
=
bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
testSRBank_SOURCES
=
testSRBank.cpp
...
...
@@ -115,8 +120,10 @@ include $(top_srcdir)/storage/ndb/config/type_ndbapitest.mk.am
##testIndex_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
##testSystemRestart_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
##testTransactions_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
NdbRepStress_INCLUDES
=
$(INCLUDES)
-I
$(top_srcdir)
/ndb/test/include
-I
$(top_srcdir)
/include
testBackup_LDADD
=
$(LDADD)
bank/libbank.a
testSRBank_LDADD
=
bank/libbank.a
$(LDADD)
NdbRepStress_LDADD
=
$(LDADD)
$(top_builddir)
/libmysql_r/libmysqlclient_r.la
# Don't update the files from bitkeeper
%
::
SCCS/s.%
...
...
storage/ndb/test/ndbapi/testBitfield.cpp
View file @
f02562b7
...
...
@@ -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
>;
storage/ndb/test/ndbapi/testNDBT.cpp
0 → 100644
View file @
f02562b7
/* 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; version 2 of the License.
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 <NDBT.hpp>
#include <NDBT_Test.hpp>
#include <DbUtil.hpp>
#include <AtrtClient.hpp>
int
runTestAtrtClient
(
NDBT_Context
*
ctx
,
NDBT_Step
*
step
){
AtrtClient
atrt
;
SqlResultSet
clusters
;
if
(
!
atrt
.
getClusters
(
clusters
))
return
NDBT_FAILED
;
int
i
=
0
;
while
(
clusters
.
next
())
{
ndbout
<<
clusters
.
column
(
"name"
)
<<
endl
;
if
(
i
++
==
1
){
ndbout
<<
"removing: "
<<
clusters
.
column
(
"name"
)
<<
endl
;
clusters
.
remove
();
}
}
clusters
.
reset
();
while
(
clusters
.
next
())
{
ndbout
<<
clusters
.
column
(
"name"
)
<<
endl
;
}
return
NDBT_OK
;
}
int
runTestDbUtil
(
NDBT_Context
*
ctx
,
NDBT_Step
*
step
){
DbUtil
sql
;
{
// Select all rows from mysql.user
SqlResultSet
result
;
if
(
!
sql
.
doQuery
(
"SELECT * FROM mysql.user"
,
result
))
return
NDBT_FAILED
;
// result.print();
while
(
result
.
next
())
{
ndbout
<<
result
.
column
(
"host"
)
<<
", "
<<
result
.
column
(
"uSer"
)
<<
", "
<<
result
.
columnAsInt
(
"max_updates"
)
<<
", "
<<
endl
;
}
result
.
reset
();
while
(
result
.
next
())
{
ndbout
<<
result
.
column
(
"host"
)
<<
endl
;
}
}
{
// No column name, query should fail
Properties
args
;
SqlResultSet
result
;
if
(
sql
.
doQuery
(
"SELECT * FROM mysql.user WHERE name=?"
,
args
,
result
))
return
NDBT_FAILED
;
result
.
print
();
}
{
// Select nonexisiting rows from mysql.user
Properties
args
;
SqlResultSet
result
;
args
.
put
(
"0"
,
"no_such_host"
);
if
(
!
sql
.
doQuery
(
"SELECT * FROM mysql.user WHERE host=?"
,
args
,
result
))
return
NDBT_FAILED
;
ndbout
<<
"no rows"
<<
endl
;
result
.
print
();
// Change args to an find one row
args
.
clear
();
args
.
put
(
"0"
,
"localhost"
);
if
(
!
sql
.
doQuery
(
"SELECT host, user FROM mysql.user WHERE host=?"
,
args
,
result
))
return
NDBT_FAILED
;
result
.
print
();
}
{
if
(
!
sql
.
doQuery
(
"CREATE TABLE sql_client_test (a int, b varchar(255))"
))
return
NDBT_FAILED
;
if
(
!
sql
.
doQuery
(
"INSERT INTO sql_client_test VALUES(1, 'hello'), (2, 'bye')"
))
return
NDBT_FAILED
;
// Select all rows from sql_client_test
SqlResultSet
result
;
if
(
!
sql
.
doQuery
(
"SELECT * FROM sql_client_test"
,
result
))
return
NDBT_FAILED
;
// result.print();
while
(
result
.
next
())
{
}
// Select second row from sql_client_test
Properties
args
;
args
.
put
(
"0"
,
2
);
if
(
!
sql
.
doQuery
(
"SELECT * FROM sql_client_test WHERE a=?"
,
args
,
result
))
return
NDBT_FAILED
;
result
.
print
();
result
.
reset
();
while
(
result
.
next
())
{
ndbout
<<
"a: "
<<
result
.
columnAsInt
(
"a"
)
<<
endl
;
ndbout
<<
"b: "
<<
result
.
column
(
"b"
)
<<
endl
;
if
(
result
.
columnAsInt
(
"a"
)
!=
2
){
ndbout
<<
"hepp1"
<<
endl
;
return
NDBT_FAILED
;
}
if
(
strcmp
(
result
.
column
(
"b"
),
"bye"
)){
ndbout
<<
"hepp2"
<<
endl
;
return
NDBT_FAILED
;
}
}
if
(
sql
.
selectCountTable
(
"sql_client_test"
)
!=
2
)
{
ndbout
<<
"Got wrong count"
<<
endl
;
return
NDBT_FAILED
;
}
if
(
!
sql
.
doQuery
(
"DROP TABLE sql_client_test"
))
return
NDBT_FAILED
;
}
return
NDBT_OK
;
}
NDBT_TESTSUITE
(
testNDBT
);
TESTCASE
(
"AtrtClient"
,
"Test AtrtClient class"
){
INITIALIZER
(
runTestAtrtClient
);
}
TESTCASE
(
"DbUtil"
,
"Test DbUtil class"
){
INITIALIZER
(
runTestDbUtil
);
}
NDBT_TESTSUITE_END
(
testNDBT
);
int
main
(
int
argc
,
const
char
**
argv
){
ndb_init
();
return
testNDBT
.
execute
(
argc
,
argv
);
}
storage/ndb/test/ndbapi/test_event.cpp
View file @
f02562b7
...
...
@@ -1838,6 +1838,61 @@ runBug31701(NDBT_Context* ctx, NDBT_Step* step)
return
NDBT_OK
;
}
int
runBug33793
(
NDBT_Context
*
ctx
,
NDBT_Step
*
step
)
{
int
result
=
NDBT_OK
;
int
loops
=
ctx
->
getNumLoops
();
NdbRestarter
restarter
;
if
(
restarter
.
getNumDbNodes
()
<
2
){
ctx
->
stopTest
();
return
NDBT_OK
;
}
// This should really wait for applier to start...10s is likely enough
NdbSleep_SecSleep
(
10
);
while
(
loops
--
&&
ctx
->
isTestStopped
()
==
false
)
{
int
nodeId
=
restarter
.
getDbNodeId
(
rand
()
%
restarter
.
getNumDbNodes
());
int
nodecount
=
0
;
int
nodes
[
255
];
printf
(
"nodeid: %u : victims: "
,
nodeId
);
for
(
int
i
=
0
;
i
<
restarter
.
getNumDbNodes
();
i
++
)
{
int
id
=
restarter
.
getDbNodeId
(
i
);
if
(
id
==
nodeId
)
continue
;
if
(
restarter
.
getNodeGroup
(
id
)
==
restarter
.
getNodeGroup
(
nodeId
))
{
nodes
[
nodecount
++
]
=
id
;
printf
(
"%u "
,
id
);
int
val2
[]
=
{
DumpStateOrd
::
CmvmiSetRestartOnErrorInsert
,
1
};
if
(
restarter
.
dumpStateOneNode
(
id
,
val2
,
2
))
return
NDBT_FAILED
;
}
}
printf
(
"
\n
"
);
fflush
(
stdout
);
restarter
.
insertErrorInNode
(
nodeId
,
13034
);
if
(
restarter
.
waitNodesNoStart
(
nodes
,
nodecount
))
return
NDBT_FAILED
;
if
(
restarter
.
startNodes
(
nodes
,
nodecount
))
return
NDBT_FAILED
;
if
(
restarter
.
waitClusterStarted
())
return
NDBT_FAILED
;
}
ctx
->
stopTest
();
return
NDBT_OK
;
}
NDBT_TESTSUITE
(
test_event
);
TESTCASE
(
"BasicEventOperation"
,
"Verify that we can listen to Events"
...
...
@@ -1975,6 +2030,12 @@ TESTCASE("Bug31701", ""){
FINALIZER
(
runDropEvent
);
FINALIZER
(
runDropShadowTable
);
}
TESTCASE
(
"Bug33793"
,
""
){
INITIALIZER
(
runCreateEvent
);
STEP
(
runEventListenerUntilStopped
);
STEP
(
runBug33793
);
FINALIZER
(
runDropEvent
);
}
NDBT_TESTSUITE_END
(
test_event
);
int
main
(
int
argc
,
const
char
**
argv
){
...
...
storage/ndb/test/run-test/daily-basic-tests.txt
View file @
f02562b7
...
...
@@ -1046,3 +1046,7 @@ max-time: 300
cmd: testSystemRestart
args: -n Bug22696 T1
max-time: 300
cmd: test_event
args: -n Bug33793 T1
storage/ndb/test/src/AtrtClient.cpp
0 → 100644
View file @
f02562b7
/* Copyright (C) 2008 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; version 2 of the License.
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 <AtrtClient.hpp>
#include <NDBT_Output.hpp>
#include <NdbSleep.h>
AtrtClient
::
AtrtClient
(
const
char
*
_user
,
const
char
*
_password
,
const
char
*
_group_suffix
)
:
DbUtil
(
_user
,
_password
,
_group_suffix
)
{
}
AtrtClient
::
AtrtClient
(
MYSQL
*
mysql
)
:
DbUtil
(
mysql
)
{
}
AtrtClient
::~
AtrtClient
(){
}
int
AtrtClient
::
writeCommand
(
AtrtCommandType
_type
,
const
Properties
&
args
){
if
(
!
isConnected
())
return
false
;
BaseString
sql
;
sql
.
assfmt
(
"INSERT command ( "
);
const
char
*
name
;
{
Properties
::
Iterator
iter
(
&
args
);
while
((
name
=
iter
.
next
())){
sql
.
appfmt
(
"%s, "
,
name
);
}
}
sql
.
appfmt
(
" state, cmd) VALUES ("
);
{
Properties
::
Iterator
iter
(
&
args
);
while
((
name
=
iter
.
next
())){
PropertiesType
t
;
Uint32
val_i
;
BaseString
val_s
;
args
.
getTypeOf
(
name
,
&
t
);
switch
(
t
)
{
case
PropertiesType_Uint32
:
args
.
get
(
name
,
&
val_i
);
sql
.
appfmt
(
"%d, "
,
val_i
);
break
;
case
PropertiesType_char
:
args
.
get
(
name
,
val_s
);
sql
.
appfmt
(
"'%s', "
,
val_s
.
c_str
());
break
;
default:
assert
(
false
);
break
;
}
}
}
sql
.
appfmt
(
"'new', %d)"
,
_type
);
if
(
!
doQuery
(
sql
)){
return
-
1
;
}
return
mysql_insert_id
(
m_mysql
);
}
bool
AtrtClient
::
readCommand
(
uint
command_id
,
SqlResultSet
&
result
){
Properties
args
;
args
.
put
(
"0"
,
command_id
);
return
runQuery
(
"SELECT * FROM command WHERE id = ?"
,
args
,
result
);
}
bool
AtrtClient
::
doCommand
(
AtrtCommandType
type
,
const
Properties
&
args
){
int
running_timeout
=
10
;
int
total_timeout
=
120
;
int
commandId
=
writeCommand
(
type
,
args
);
if
(
commandId
==
-
1
){
g_err
<<
"Failed to write command"
<<
endl
;
return
false
;
}
while
(
true
){
SqlResultSet
result
;
if
(
!
readCommand
(
commandId
,
result
))
{
result
.
print
();
g_err
<<
"Failed to read command "
<<
commandId
<<
endl
;
return
false
;
}
// Get first row
result
.
next
();
// Check if command has completed
BaseString
state
(
result
.
column
(
"state"
));
if
(
state
==
"done"
)
{
return
true
;
}
if
(
state
==
"new"
){
if
(
!
running_timeout
--
){
g_err
<<
"Timeout while waiting for command "
<<
commandId
<<
" to start run"
<<
endl
;
return
false
;
}
}
else
if
(
!
total_timeout
--
){
g_err
<<
"Timeout while waiting for result of command "
<<
commandId
<<
endl
;
return
false
;
}
NdbSleep_SecSleep
(
1
);
}
return
false
;
}
bool
AtrtClient
::
changeVersion
(
int
process_id
,
const
char
*
process_args
){
Properties
args
;
args
.
put
(
"process_id"
,
process_id
);
args
.
put
(
"process_args"
,
process_args
);
return
doCommand
(
ATCT_CHANGE_VERSION
,
args
);
}
bool
AtrtClient
::
resetProc
(
int
process_id
){
Properties
args
;
args
.
put
(
"process_id"
,
process_id
);
return
doCommand
(
ATCT_RESET_PROC
,
args
);
}
bool
AtrtClient
::
getConnectString
(
int
cluster_id
,
SqlResultSet
&
result
){
Properties
args
;
args
.
put
(
"0"
,
cluster_id
);
return
doQuery
(
"SELECT value as connectstring "
\
"FROM cluster c, process p, host h, options o "
\
"WHERE c.id=p.cluster_id AND p.host_id=h.id AND "
\
"p.id=o.process_id AND c.id=? AND "
\
"o.name='--ndb-connectstring=' AND type='ndb_mgmd'"
,
args
,
result
);
}
bool
AtrtClient
::
getClusters
(
SqlResultSet
&
result
){
Properties
args
;
return
runQuery
(
"SELECT id, name FROM cluster WHERE name != '.atrt'"
,
args
,
result
);
}
bool
AtrtClient
::
getMgmds
(
int
cluster_id
,
SqlResultSet
&
result
){
Properties
args
;
args
.
put
(
"0"
,
cluster_id
);
return
runQuery
(
"SELECT * FROM process WHERE cluster_id=? and type='ndb_mgmd'"
,
args
,
result
);
}
bool
AtrtClient
::
getNdbds
(
int
cluster_id
,
SqlResultSet
&
result
){
Properties
args
;
args
.
put
(
"0"
,
cluster_id
);
return
runQuery
(
"SELECT * FROM process WHERE cluster_id=? and type='ndbd'"
,
args
,
result
);
}
storage/ndb/test/src/DbUtil.cpp
View file @
f02562b7
/* Copyright (C) 200
7
MySQL AB
/* Copyright (C) 200
8
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
...
...
@@ -16,43 +16,89 @@
/* DbUtil.cpp: implementation of the database utilities class.*/
#include "DbUtil.hpp"
#include <NdbSleep.h>
/* Constructors */
DbUtil
::
DbUtil
(
const
char
*
dbname
)
{
m_port
=
0
;
m_connected
=
false
;
this
->
setDbName
(
dbname
);
}
/* Constructors */
DbUtil
::
DbUtil
(
const
char
*
dbname
,
const
char
*
suffix
)
DbUtil
::
DbUtil
(
const
char
*
_dbname
,
const
char
*
_user
,
const
char
*
_password
,
const
char
*
_suffix
)
:
m_connected
(
false
),
m_dbname
(
_dbname
),
m_mysql
(
NULL
),
m_free_mysql
(
true
)
{
this
->
setDbName
(
dbname
);
m_connected
=
false
;
const
char
*
env
=
getenv
(
"MYSQL_HOME"
);
if
(
env
&&
strlen
(
env
))
{
default_file
.
assfmt
(
"%s/my.cnf"
,
env
);
m_
default_file
.
assfmt
(
"%s/my.cnf"
,
env
);
}
if
(
suffix
!=
NULL
){
default_group
.
assfmt
(
"client%s"
,
suffix
);
if
(
_
suffix
!=
NULL
){
m_default_group
.
assfmt
(
"client%s"
,
_
suffix
);
}
else
{
default_group
.
assign
(
"client.1.master"
);
m_default_group
.
assign
(
"client.1.master"
);
}
ndbout
<<
"default_file: "
<<
m_default_file
.
c_str
()
<<
endl
;
ndbout
<<
"default_group: "
<<
m_default_group
.
c_str
()
<<
endl
;
m_user
.
assign
(
_user
);
m_pass
.
assign
(
_password
);
}
DbUtil
::
DbUtil
(
MYSQL
*
mysql
)
:
m_connected
(
true
),
m_mysql
(
mysql
),
m_free_mysql
(
false
)
{
}
bool
DbUtil
::
isConnected
(){
if
(
m_connected
==
true
)
{
assert
(
m_mysql
);
return
true
;
}
return
connect
()
==
0
;
}
ndbout
<<
"default_file: "
<<
default_file
.
c_str
()
<<
endl
;
ndbout
<<
"default_group: "
<<
default_group
.
c_str
()
<<
endl
;
bool
DbUtil
::
waitConnected
(
int
timeout
)
{
timeout
*=
10
;
while
(
!
isConnected
()){
if
(
timeout
--
==
0
)
return
false
;
NdbSleep_MilliSleep
(
100
);
}
return
true
;
}
/* Destructor*/
void
DbUtil
::
disconnect
(){
if
(
m_mysql
!=
NULL
){
if
(
m_free_mysql
)
mysql_close
(
m_mysql
);
m_mysql
=
NULL
;
}
m_connected
=
false
;
}
/* Destructor */
DbUtil
::~
DbUtil
()
{
this
->
databaseLogou
t
();
disconnec
t
();
}
/* Database Login */
...
...
@@ -62,18 +108,18 @@ DbUtil::databaseLogin(const char* system, const char* usr,
const
char
*
password
,
unsigned
int
portIn
,
const
char
*
sockIn
,
bool
transactional
)
{
if
(
!
(
mysql
=
mysql_init
(
NULL
)))
if
(
!
(
m
_m
ysql
=
mysql_init
(
NULL
)))
{
myerror
(
"DB Login-> mysql_init() failed"
);
exit
(
DBU_FAILED
);
}
this
->
setUser
(
usr
);
this
->
setHost
(
system
);
this
->
setPassword
(
password
);
this
->
setPort
(
portIn
);
this
->
setSocket
(
sockIn
);
setUser
(
usr
);
setHost
(
system
);
setPassword
(
password
);
setPort
(
portIn
);
setSocket
(
sockIn
);
if
(
!
(
mysql_real_connect
(
mysql
,
if
(
!
(
mysql_real_connect
(
m
_m
ysql
,
m_host
.
c_str
(),
m_user
.
c_str
(),
m_pass
.
c_str
(),
...
...
@@ -82,40 +128,40 @@ DbUtil::databaseLogin(const char* system, const char* usr,
m_socket
.
c_str
(),
0
)))
{
myerror
(
"connection failed"
);
mysql_close
(
mysql
);
mysql_close
(
m
_m
ysql
);
exit
(
DBU_FAILED
);
}
m
ysql
->
reconnect
=
DBU_
TRUE
;
m
_mysql
->
reconnect
=
TRUE
;
/* set AUTOCOMMIT */
if
(
!
transactional
)
mysql_autocommit
(
m
ysql
,
DBU_
TRUE
);
mysql_autocommit
(
m
_mysql
,
TRUE
);
else
mysql_autocommit
(
m
ysql
,
DBU_
FALSE
);
mysql_autocommit
(
m
_mysql
,
FALSE
);
#ifdef DEBUG
printf
(
"
\n\t
Connected to MySQL server version: %s (%lu)
\n\n
"
,
mysql_get_server_info
(
mysql
),
(
unsigned
long
)
mysql_get_server_version
(
mysql
));
mysql_get_server_info
(
m
_m
ysql
),
(
unsigned
long
)
mysql_get_server_version
(
m
_m
ysql
));
#endif
this
->
selectDb
();
selectDb
();
}
/* Database Connect */
int
int
DbUtil
::
connect
()
{
if
(
!
(
mysql
=
mysql_init
(
NULL
)))
if
(
!
(
m
_m
ysql
=
mysql_init
(
NULL
)))
{
myerror
(
"DB connect-> mysql_init() failed"
);
return
DBU_FAILED
;
}
/* Load connection parameters file and group */
if
(
mysql_options
(
m
ysql
,
MYSQL_READ_DEFAULT_FILE
,
default_file
.
c_str
())
||
mysql_options
(
m
ysql
,
MYSQL_READ_DEFAULT_GROUP
,
default_group
.
c_str
()))
if
(
mysql_options
(
m
_mysql
,
MYSQL_READ_DEFAULT_FILE
,
m_
default_file
.
c_str
())
||
mysql_options
(
m
_mysql
,
MYSQL_READ_DEFAULT_GROUP
,
m_
default_group
.
c_str
()))
{
myerror
(
"DB Connect -> mysql_options failed"
);
return
DBU_FAILED
;
...
...
@@ -126,14 +172,14 @@ DbUtil::connect()
NOTE! user and password can be stored there as well
*/
if
(
mysql_real_connect
(
mysql
,
NULL
,
"root"
,
""
,
m_dbname
.
c_str
(),
if
(
mysql_real_connect
(
m
_m
ysql
,
NULL
,
"root"
,
""
,
m_dbname
.
c_str
(),
0
,
NULL
,
0
)
==
NULL
)
{
myerror
(
"connection failed"
);
mysql_close
(
mysql
);
mysql_close
(
m
_m
ysql
);
return
DBU_FAILED
;
}
this
->
selectDb
();
selectDb
();
m_connected
=
true
;
return
DBU_OK
;
}
...
...
@@ -141,14 +187,14 @@ DbUtil::connect()
/* Database Logout */
void
void
DbUtil
::
databaseLogout
()
{
if
(
mysql
){
if
(
m
_m
ysql
){
#ifdef DEBUG
printf
(
"
\n\t
Closing the MySQL database connection ...
\n\n
"
);
#endif
mysql_close
(
mysql
);
mysql_close
(
m
_m
ysql
);
}
}
...
...
@@ -181,28 +227,28 @@ DbUtil::mysqlCloseStmHandle(MYSQL_STMT *my_stmt)
/* Error Printing */
void
void
DbUtil
::
printError
(
const
char
*
msg
)
{
if
(
this
->
getMysql
()
&&
mysql_errno
(
this
->
getMysql
()
))
if
(
m_mysql
&&
mysql_errno
(
m_mysql
))
{
if
(
this
->
getMysql
()
->
server_version
)
printf
(
"
\n
[MySQL-%s]"
,
this
->
getMysql
()
->
server_version
);
if
(
m_mysql
->
server_version
)
printf
(
"
\n
[MySQL-%s]"
,
m_mysql
->
server_version
);
else
printf
(
"
\n
[MySQL]"
);
printf
(
"[%d] %s
\n
"
,
this
->
getErrorNumber
(),
this
->
getError
());
printf
(
"[%d] %s
\n
"
,
getErrorNumber
(),
getError
());
}
else
if
(
msg
)
printf
(
" [MySQL] %s
\n
"
,
msg
);
}
void
void
DbUtil
::
printStError
(
MYSQL_STMT
*
stmt
,
const
char
*
msg
)
{
if
(
stmt
&&
mysql_stmt_errno
(
stmt
))
{
if
(
this
->
getMysql
()
&&
this
->
getMysql
()
->
server_version
)
printf
(
"
\n
[MySQL-%s]"
,
this
->
getMysql
()
->
server_version
);
if
(
m_mysql
&&
m_mysql
->
server_version
)
printf
(
"
\n
[MySQL-%s]"
,
m_mysql
->
server_version
);
else
printf
(
"
\n
[MySQL]"
);
...
...
@@ -215,19 +261,19 @@ DbUtil::printStError(MYSQL_STMT *stmt, const char *msg)
/* Select which database to use */
int
int
DbUtil
::
selectDb
()
{
if
((
this
->
getDbName
())
!=
NULL
)
if
((
getDbName
())
!=
NULL
)
{
if
(
mysql_select_db
(
this
->
getMysql
()
,
this
->
getDbName
()))
if
(
mysql_select_db
(
m_mysql
,
this
->
getDbName
()))
{
this
->
printError
(
"mysql_select_db failed"
);
printError
(
"mysql_select_db failed"
);
return
DBU_FAILED
;
}
return
DBU_OK
;
}
this
->
printError
(
"getDbName() == NULL"
);
printError
(
"getDbName() == NULL"
);
return
DBU_FAILED
;
}
...
...
@@ -235,9 +281,9 @@ int
DbUtil
::
selectDb
(
const
char
*
m_db
)
{
{
if
(
mysql_select_db
(
this
->
getMysql
()
,
m_db
))
if
(
mysql_select_db
(
m_mysql
,
m_db
))
{
this
->
printError
(
"mysql_select_db failed"
);
printError
(
"mysql_select_db failed"
);
return
DBU_FAILED
;
}
return
DBU_OK
;
...
...
@@ -249,89 +295,383 @@ DbUtil::createDb(BaseString& m_db)
{
BaseString
stm
;
{
if
(
mysql_select_db
(
this
->
getMysql
()
,
m_db
.
c_str
())
==
DBU_OK
)
if
(
mysql_select_db
(
m_mysql
,
m_db
.
c_str
())
==
DBU_OK
)
{
stm
.
assfmt
(
"DROP DATABASE %s"
,
m_db
.
c_str
());
if
(
this
->
doQuery
(
m_db
.
c_str
())
==
DBU_FAILED
)
if
(
doQuery
(
m_db
.
c_str
())
==
DBU_FAILED
)
return
DBU_FAILED
;
}
stm
.
assfmt
(
"CREATE DATABASE %s"
,
m_db
.
c_str
());
if
(
this
->
doQuery
(
m_db
.
c_str
())
==
DBU_FAILED
)
if
(
doQuery
(
m_db
.
c_str
())
==
DBU_FAILED
)
return
DBU_FAILED
;
return
DBU_OK
;
}
}
/* Run Simple Queries */
int
DbUtil
::
doQuery
(
BaseString
&
str
)
/* Count Table Rows */
unsigned
long
DbUtil
::
selectCountTable
(
const
char
*
table
)
{
if
(
mysql_query
(
this
->
getMysql
(),
str
.
c_str
()))
{
this
->
printError
(
str
.
c_str
());
return
DBU_FAILED
;
BaseString
query
;
SqlResultSet
result
;
query
.
assfmt
(
"select count(*) as count from %s"
,
table
);
if
(
!
doQuery
(
query
,
result
))
{
printError
(
"select count(*) failed"
);
return
-
1
;
}
return
DBU_OK
;
return
result
.
columnAsInt
(
"count"
)
;
}
int
DbUtil
::
doQuery
(
const
char
*
stm
)
{
if
(
mysql_query
(
this
->
getMysql
(),
stm
))
/* Run Simple Queries */
static
bool
is_int_type
(
enum_field_types
type
){
switch
(
type
){
case
MYSQL_TYPE_TINY
:
case
MYSQL_TYPE_SHORT
:
case
MYSQL_TYPE_LONGLONG
:
case
MYSQL_TYPE_INT24
:
case
MYSQL_TYPE_LONG
:
case
MYSQL_TYPE_ENUM
:
return
true
;
default:
return
false
;
}
return
false
;
}
bool
DbUtil
::
runQuery
(
const
char
*
sql
,
const
Properties
&
args
,
SqlResultSet
&
rows
){
rows
.
clear
();
if
(
!
isConnected
())
return
false
;
g_debug
<<
"runQuery: "
<<
endl
<<
" sql: '"
<<
sql
<<
"'"
<<
endl
;
MYSQL_STMT
*
stmt
=
mysql_stmt_init
(
m_mysql
);
if
(
mysql_stmt_prepare
(
stmt
,
sql
,
strlen
(
sql
)))
{
this
->
printError
(
stm
)
;
return
DBU_FAILED
;
g_err
<<
"Failed to prepare: "
<<
mysql_error
(
m_mysql
)
<<
endl
;
return
false
;
}
return
DBU_OK
;
uint
params
=
mysql_stmt_param_count
(
stmt
);
MYSQL_BIND
bind_param
[
params
];
bzero
(
bind_param
,
sizeof
(
bind_param
));
for
(
uint
i
=
0
;
i
<
mysql_stmt_param_count
(
stmt
);
i
++
)
{
BaseString
name
;
name
.
assfmt
(
"%d"
,
i
);
// Parameters are named 0, 1, 2...
if
(
!
args
.
contains
(
name
.
c_str
()))
{
g_err
<<
"param "
<<
i
<<
" missing"
<<
endl
;
assert
(
false
);
}
PropertiesType
t
;
Uint32
val_i
;
const
char
*
val_s
;
args
.
getTypeOf
(
name
.
c_str
(),
&
t
);
switch
(
t
)
{
case
PropertiesType_Uint32
:
args
.
get
(
name
.
c_str
(),
&
val_i
);
bind_param
[
i
].
buffer_type
=
MYSQL_TYPE_LONG
;
bind_param
[
i
].
buffer
=
(
char
*
)
&
val_i
;
g_debug
<<
" param"
<<
name
.
c_str
()
<<
": "
<<
val_i
<<
endl
;
break
;
case
PropertiesType_char
:
args
.
get
(
name
.
c_str
(),
&
val_s
);
bind_param
[
i
].
buffer_type
=
MYSQL_TYPE_STRING
;
bind_param
[
i
].
buffer
=
(
char
*
)
val_s
;
bind_param
[
i
].
buffer_length
=
strlen
(
val_s
);
g_debug
<<
" param"
<<
name
.
c_str
()
<<
": "
<<
val_s
<<
endl
;
break
;
default:
assert
(
false
);
break
;
}
}
if
(
mysql_stmt_bind_param
(
stmt
,
bind_param
))
{
g_err
<<
"Failed to bind param: "
<<
mysql_error
(
m_mysql
)
<<
endl
;
mysql_stmt_close
(
stmt
);
return
false
;
}
if
(
mysql_stmt_execute
(
stmt
))
{
g_err
<<
"Failed to execute: "
<<
mysql_error
(
m_mysql
)
<<
endl
;
mysql_stmt_close
(
stmt
);
return
false
;
}
/*
Update max_length, making it possible to know how big
buffers to allocate
*/
my_bool
one
=
1
;
mysql_stmt_attr_set
(
stmt
,
STMT_ATTR_UPDATE_MAX_LENGTH
,
(
void
*
)
&
one
);
if
(
mysql_stmt_store_result
(
stmt
))
{
g_err
<<
"Failed to store result: "
<<
mysql_error
(
m_mysql
)
<<
endl
;
mysql_stmt_close
(
stmt
);
return
false
;
}
uint
row
=
0
;
MYSQL_RES
*
res
=
mysql_stmt_result_metadata
(
stmt
);
if
(
res
!=
NULL
)
{
MYSQL_FIELD
*
fields
=
mysql_fetch_fields
(
res
);
uint
num_fields
=
mysql_num_fields
(
res
);
MYSQL_BIND
bind_result
[
num_fields
];
bzero
(
bind_result
,
sizeof
(
bind_result
));
for
(
uint
i
=
0
;
i
<
num_fields
;
i
++
)
{
if
(
is_int_type
(
fields
[
i
].
type
)){
bind_result
[
i
].
buffer_type
=
MYSQL_TYPE_LONG
;
bind_result
[
i
].
buffer
=
malloc
(
sizeof
(
int
));
}
else
{
uint
max_length
=
fields
[
i
].
max_length
+
1
;
bind_result
[
i
].
buffer_type
=
MYSQL_TYPE_STRING
;
bind_result
[
i
].
buffer
=
malloc
(
max_length
);
bind_result
[
i
].
buffer_length
=
max_length
;
}
}
if
(
mysql_stmt_bind_result
(
stmt
,
bind_result
)){
g_err
<<
"Failed to bind result: "
<<
mysql_error
(
m_mysql
)
<<
endl
;
mysql_stmt_close
(
stmt
);
return
false
;
}
while
(
mysql_stmt_fetch
(
stmt
)
!=
MYSQL_NO_DATA
)
{
Properties
curr
(
true
);
for
(
uint
i
=
0
;
i
<
num_fields
;
i
++
){
if
(
is_int_type
(
fields
[
i
].
type
))
curr
.
put
(
fields
[
i
].
name
,
*
(
int
*
)
bind_result
[
i
].
buffer
);
else
curr
.
put
(
fields
[
i
].
name
,
(
char
*
)
bind_result
[
i
].
buffer
);
}
rows
.
put
(
"row"
,
row
++
,
&
curr
);
}
mysql_free_result
(
res
);
for
(
uint
i
=
0
;
i
<
num_fields
;
i
++
)
free
(
bind_result
[
i
].
buffer
);
}
// Save stats in result set
rows
.
put
(
"rows"
,
row
);
rows
.
put
(
"affected_rows"
,
mysql_affected_rows
(
m_mysql
));
rows
.
put
(
"mysql_errno"
,
mysql_errno
(
m_mysql
));
rows
.
put
(
"mysql_error"
,
mysql_error
(
m_mysql
));
rows
.
put
(
"mysql_sqlstate"
,
mysql_sqlstate
(
m_mysql
));
rows
.
put
(
"insert_id"
,
mysql_insert_id
(
m_mysql
));
mysql_stmt_close
(
stmt
);
return
true
;
}
bool
DbUtil
::
doQuery
(
const
char
*
query
){
const
Properties
args
;
SqlResultSet
result
;
return
doQuery
(
query
,
args
,
result
);
}
bool
DbUtil
::
doQuery
(
const
char
*
query
,
SqlResultSet
&
result
){
Properties
args
;
return
doQuery
(
query
,
args
,
result
);
}
bool
DbUtil
::
doQuery
(
const
char
*
query
,
const
Properties
&
args
,
SqlResultSet
&
result
){
if
(
!
runQuery
(
query
,
args
,
result
))
return
false
;
result
.
get_row
(
0
);
// Load first row
return
true
;
}
bool
DbUtil
::
doQuery
(
BaseString
&
str
){
return
doQuery
(
str
.
c_str
());
}
bool
DbUtil
::
doQuery
(
BaseString
&
str
,
SqlResultSet
&
result
){
return
doQuery
(
str
.
c_str
(),
result
);
}
bool
DbUtil
::
doQuery
(
BaseString
&
str
,
const
Properties
&
args
,
SqlResultSet
&
result
){
return
doQuery
(
str
.
c_str
(),
args
,
result
);
}
/* Return MySQL Error String */
const
char
*
const
char
*
DbUtil
::
getError
()
{
return
mysql_error
(
this
->
getMysql
());
}
/* Ret
ru
n MySQL Error Number */
/* Ret
ur
n MySQL Error Number */
int
int
DbUtil
::
getErrorNumber
()
{
return
mysql_errno
(
this
->
getMysql
());
}
/* Count Table Rows */
unsigned
long
DbUtil
::
selectCountTable
(
const
char
*
table
)
{
unsigned
long
m_count
=
0
;
BaseString
m_query
;
m_query
.
assfmt
(
"select count(*) from %s"
,
table
);
if
(
mysql_query
(
this
->
getMysql
(),
m_query
.
c_str
())
||
!
(
m_result
=
mysql_store_result
(
this
->
getMysql
())))
{
this
->
printError
(
"selectCountTable
\n
"
);
return
DBU_FAILED
;
}
m_row
=
mysql_fetch_row
(
m_result
);
m_count
=
(
ulong
)
strtoull
(
m_row
[
0
],
(
char
**
)
0
,
10
);
mysql_free_result
(
m_result
);
return
m_count
;
}
/* DIE */
void
void
DbUtil
::
die
(
const
char
*
file
,
int
line
,
const
char
*
expr
)
{
printf
(
"%s:%d: check failed: '%s'
\n
"
,
file
,
line
,
expr
);
abort
();
}
/* SqlResultSet */
bool
SqlResultSet
::
get_row
(
int
row_num
){
if
(
!
get
(
"row"
,
row_num
,
&
m_curr_row
)){
return
false
;
}
return
true
;
}
bool
SqlResultSet
::
next
(
void
){
return
get_row
(
++
m_curr_row_num
);
}
// Reset iterator
void
SqlResultSet
::
reset
(
void
){
m_curr_row_num
=
-
1
;
m_curr_row
=
0
;
}
// Remove row from resultset
void
SqlResultSet
::
remove
(){
BaseString
row_name
;
row_name
.
assfmt
(
"row_%d"
,
m_curr_row_num
);
Properties
::
remove
(
row_name
.
c_str
());
}
SqlResultSet
::
SqlResultSet
()
:
m_curr_row
(
0
),
m_curr_row_num
(
-
1
){
}
SqlResultSet
::~
SqlResultSet
(){
}
const
char
*
SqlResultSet
::
column
(
const
char
*
col_name
){
const
char
*
value
;
if
(
!
m_curr_row
){
g_err
<<
"ERROR: SqlResultSet::column("
<<
col_name
<<
")"
<<
endl
<<
"There is no row loaded, call next() before "
<<
"acessing the column values"
<<
endl
;
assert
(
m_curr_row
);
}
if
(
!
m_curr_row
->
get
(
col_name
,
&
value
))
return
NULL
;
return
value
;
}
uint
SqlResultSet
::
columnAsInt
(
const
char
*
col_name
){
uint
value
;
if
(
!
m_curr_row
){
g_err
<<
"ERROR: SqlResultSet::columnAsInt("
<<
col_name
<<
")"
<<
endl
<<
"There is no row loaded, call next() before "
<<
"acessing the column values"
<<
endl
;
assert
(
m_curr_row
);
}
if
(
!
m_curr_row
->
get
(
col_name
,
&
value
))
return
(
uint
)
-
1
;
return
value
;
}
uint
SqlResultSet
::
insertId
(){
return
get_int
(
"insert_id"
);
}
uint
SqlResultSet
::
affectedRows
(){
return
get_int
(
"affected_rows"
);
}
uint
SqlResultSet
::
numRows
(
void
){
return
get_int
(
"rows"
);
}
uint
SqlResultSet
::
mysqlErrno
(
void
){
return
get_int
(
"mysql_errno"
);
}
const
char
*
SqlResultSet
::
mysqlError
(
void
){
return
get_string
(
"mysql_error"
);
}
const
char
*
SqlResultSet
::
mysqlSqlstate
(
void
){
return
get_string
(
"mysql_sqlstate"
);
}
uint
SqlResultSet
::
get_int
(
const
char
*
name
){
uint
value
;
get
(
name
,
&
value
);
return
value
;
}
const
char
*
SqlResultSet
::
get_string
(
const
char
*
name
){
const
char
*
value
;
get
(
name
,
&
value
);
return
value
;
}
/* EOF */
storage/ndb/test/src/Makefile.am
View file @
f02562b7
...
...
@@ -23,10 +23,10 @@ libNDBT_a_SOURCES = \
HugoAsynchTransactions.cpp UtilTransactions.cpp
\
NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp
\
NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp
\
NdbSchemaCon.cpp NdbSchemaOp.cpp getarg.c
\
CpcClient.cpp NdbMixRestarter.cpp NDBT_Thread.cpp
dbu
til.cpp
NdbSchemaCon.cpp NdbSchemaOp.cpp getarg.c
AtrtClient.cpp
\
CpcClient.cpp NdbMixRestarter.cpp NDBT_Thread.cpp
DbU
til.cpp
INCLUDES_LOC
=
-I
$(top_srcdir)
/storage/ndb/src/common/mgmcommon
-I
$(top_srcdir)
/storage/ndb/include/mgmcommon
-I
$(top_srcdir)
/storage/ndb/include/kernel
-I
$(top_srcdir)
/storage/ndb/src/mgmapi
INCLUDES_LOC
=
-I
$(top_srcdir)
/storage/ndb/src/common/mgmcommon
-I
$(top_srcdir)
/storage/ndb/include/mgmcommon
-I
$(top_srcdir)
/storage/ndb/include/kernel
-I
$(top_srcdir)
/storage/ndb/src/mgmapi
-I
$(top_srcdir)
/include
include
$(top_srcdir)/storage/ndb/config/common.mk.am
include
$(top_srcdir)/storage/ndb/config/type_ndbapitest.mk.am
...
...
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