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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
c50598bd
Commit
c50598bd
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-merge
parents
2401f86c
79e8f3e4
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
2366 additions
and
658 deletions
+2366
-658
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
+1
-1
storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
+18
-0
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
+176
-0
storage/ndb/test/include/dbutil.hpp
storage/ndb/test/include/dbutil.hpp
+0
-97
storage/ndb/test/ndbapi/Makefile.am
storage/ndb/test/ndbapi/Makefile.am
+8
-1
storage/ndb/test/ndbapi/acrt/NdbRepStress.cpp
storage/ndb/test/ndbapi/acrt/NdbRepStress.cpp
+478
-0
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
+677
-0
storage/ndb/test/src/Makefile.am
storage/ndb/test/src/Makefile.am
+3
-3
storage/ndb/test/src/dbutil.cpp
storage/ndb/test/src/dbutil.cpp
+0
-176
No files found.
storage/ndb/include/util/Bitmask.hpp
View file @
c50598bd
...
...
@@ -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/transporter/TCP_Transporter.cpp
View file @
c50598bd
...
...
@@ -317,22 +317,32 @@ TCP_Transporter::doSend() {
// Empty the SendBuffers
bool
sent_any
=
true
;
while
(
m_sendBuffer
.
dataSize
>
0
)
{
const
char
*
const
sendPtr
=
m_sendBuffer
.
sendPtr
;
const
Uint32
sizeToSend
=
m_sendBuffer
.
sendDataSize
;
if
(
sizeToSend
>
0
){
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 @
c50598bd
...
...
@@ -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/src/kernel/blocks/ERROR_codes.txt
View file @
c50598bd
...
...
@@ -11,7 +11,7 @@ Next CMVMI 9000
Next BACKUP 10038
Next DBUTIL 11002
Next DBTUX 12008
Next SUMA 1303
4
Next SUMA 1303
6
TESTING NODE FAILURE, ARBITRATION
---------------------------------
...
...
storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
View file @
c50598bd
...
...
@@ -619,6 +619,24 @@ Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr)
if
(
lcp
&&
lcp_list
!=
RNIL
)
goto
found_lcp_keep
;
switch
(
pos
.
m_get
){
case
ScanPos
:
:
Get_next_tuple
:
case
ScanPos
:
:
Get_next_tuple_fs
:
jam
();
key
.
m_page_idx
+=
size
;
// fall through
case
ScanPos
:
:
Get_tuple
:
case
ScanPos
:
:
Get_tuple_fs
:
jam
();
/**
* We need to refetch page after timeslice
*/
pos
.
m_get
=
ScanPos
::
Get_page
;
break
;
default:
break
;
}
while
(
true
)
{
switch
(
pos
.
m_get
)
{
case
ScanPos
:
:
Get_next_page
:
...
...
storage/ndb/src/kernel/blocks/suma/Suma.cpp
View file @
c50598bd
...
...
@@ -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 @
c50598bd
/* 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
0 → 100755
View file @
c50598bd
/* Copyright (C) 2007 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 */
// dbutil.h: interface for the database utilities class.
// Supplies a database to the test application
#ifndef DBUTIL_HPP
#define DBUTIL_HPP
#include <NDBT.hpp>
#include <BaseString.hpp>
#include <Properties.hpp>
#include <Vector.hpp>
#include <mysql.h>
//#define DEBUG
#define DIE_UNLESS(expr) \
((void) ((expr) ? 0 : (Die(__FILE__, __LINE__, #expr), 0)))
#define DIE(expr) \
Die(__FILE__, __LINE__, #expr)
#define myerror(msg) printError(msg)
#define mysterror(stmt, msg) printStError(stmt, msg)
#define CheckStmt(stmt) \
{ \
if ( stmt == 0) \
myerror(NULL); \
DIE_UNLESS(stmt != 0); \
}
#define check_execute(stmt, r) \
{ \
if (r) \
mysterror(stmt, NULL); \
DIE_UNLESS(r == 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
class
DbUtil
{
public:
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
,
const
char
*
password
,
unsigned
int
portIn
,
const
char
*
sockIn
,
bool
transactional
);
const
char
*
getDbName
()
{
return
m_dbname
.
c_str
();};
const
char
*
getUser
()
{
return
m_user
.
c_str
();};
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
(
m_mysql
);};
const
char
*
getError
();
MYSQL
*
getMysql
(){
return
m_mysql
;};
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
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
;
BaseString
m_host
;
// Computer to connect to
BaseString
m_user
;
// MySQL User
BaseString
m_pass
;
// MySQL User Password
BaseString
m_dbname
;
// Database to use
BaseString
m_socket
;
// MySQL Server Unix Socket
BaseString
m_default_file
;
BaseString
m_default_group
;
unsigned
int
m_port
;
// MySQL Server port
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
);};
void
setHost
(
const
char
*
system
){
m_host
.
assign
(
system
);};
void
setPort
(
unsigned
int
portIn
){
m_port
=
portIn
;};
void
setSocket
(
const
char
*
sockIn
){
m_socket
.
assign
(
sockIn
);};
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/include/dbutil.hpp
deleted
100755 → 0
View file @
2401f86c
// dbutil.h: interface for the database utilities class.
//////////////////////////////////////////////////////////////////////
// Supplies a database to the test application
//////////////////////////////////////////////////////////////////////
#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 <mysql.h>
//include "rand.h"
#include <stdlib.h>
//#define DEBUG
#define DIE_UNLESS(expr) \
((void) ((expr) ? 0 : (Die(__FILE__, __LINE__, #expr), 0)))
#define DIE(expr) \
Die(__FILE__, __LINE__, #expr)
#define myerror(msg) PrintError(msg)
#define mysterror(stmt, msg) PrintStError(stmt, msg)
#define CheckStmt(stmt) \
{ \
if ( stmt == 0) \
myerror(NULL); \
DIE_UNLESS(stmt != 0); \
}
#define check_execute(stmt, r) \
{ \
if (r) \
mysterror(stmt, NULL); \
DIE_UNLESS(r == 0);\
}
#define TRUE 1
#define FALSE 0
class
dbutil
{
public:
dbutil
(
const
char
*
databaseName
);
~
dbutil
();
void
DatabaseLogin
(
const
char
*
system
,
const
char
*
usr
,
const
char
*
password
,
unsigned
int
portIn
,
const
char
*
sockIn
,
bool
transactional
);
char
*
GetDbName
(){
return
dbs
;};
char
*
GetUser
(){
return
user
;};
char
*
GetPassword
(){
return
pass
;};
char
*
GetHost
(){
return
host
;};
char
*
GetSocket
(){
return
socket
;};
const
char
*
GetServerType
(){
return
mysql_get_server_info
(
myDbHandel
);};
MYSQL
*
GetDbHandel
(){
return
myDbHandel
;};
MYSQL_STMT
*
STDCALL
MysqlSimplePrepare
(
const
char
*
query
);
int
Select_DB
();
int
Do_Query
(
char
*
stm
);
const
char
*
GetError
();
int
GetErrorNumber
();
unsigned
long
SelectCountTable
(
const
char
*
table
);
private:
//Connect variables
char
*
databaseName
;
//hold results file name
char
host
[
256
];
// Computer to connect to
char
user
[
256
];
// MySQL User
char
pass
[
256
];
// MySQL User Password
char
dbs
[
256
];
// Database to use (TPCB)
unsigned
int
port
;
// MySQL Server port
char
socket
[
256
];
// MySQL Server Unix Socket
MYSQL
*
myDbHandel
;
void
DatabaseLogout
();
void
SetDbName
(
const
char
*
name
){
strcpy
((
char
*
)
dbs
,
name
);};
void
SetUser
(
const
char
*
userName
){
strcpy
((
char
*
)
user
,
userName
);};
void
SetPassword
(
const
char
*
password
){
strcpy
((
char
*
)
pass
,
password
);};
void
SetHost
(
const
char
*
system
){
strcpy
((
char
*
)
host
,
system
);};
void
SetPort
(
unsigned
int
portIn
){
port
=
portIn
;};
void
SetSocket
(
const
char
*
sockIn
){
strcpy
((
char
*
)
socket
,
sockIn
);};
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 @
c50598bd
...
...
@@ -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/acrt/NdbRepStress.cpp
0 → 100644
View file @
c50598bd
/* 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_Test.hpp>
#include <NDBT_ReturnCodes.h>
#include <HugoTransactions.hpp>
#include <UtilTransactions.hpp>
#include <DbUtil.hpp>
#include <mysql.h>
/*
Will include restart testing in future phases
#include <NdbRestarter.hpp>
#include <NdbRestarts.hpp>
*/
/**** TOOL SECTION ****/
static
uint
urandom
()
{
uint
r
=
(
uint
)
random
();
return
r
;
}
static
uint
urandom
(
uint
m
)
{
if
(
m
==
0
)
return
NDBT_OK
;
uint
r
=
urandom
();
r
=
r
%
m
;
return
r
;
}
#define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb()
/*
*/
int
syncSlaveWithMaster
()
{
/*
We need to look at the MAX epoch of the
mysql.ndb_binlog_index table so we will
know when the slave has caught up
*/
MYSQL_RES
*
result
;
MYSQL_ROW
row
;
unsigned
int
masterEpoch
=
0
;
unsigned
int
slaveEpoch
=
0
;
unsigned
int
slaveEpochOld
=
0
;
int
maxLoops
=
100
;
int
loopCnt
=
0
;
//Create a DbUtil object for the master
DbUtil
master
(
"mysql"
,
""
);
//Login to Master
if
(
!
master
.
connect
())
{
return
NDBT_FAILED
;
}
//Get max epoch from master
if
(
master
.
doQuery
(
"SELECT MAX(epoch) FROM mysql.ndb_binlog_index"
))
{
return
NDBT_FAILED
;
}
result
=
mysql_use_result
(
master
.
getMysql
());
row
=
mysql_fetch_row
(
result
);
masterEpoch
=
atoi
(
row
[
0
]);
mysql_free_result
(
result
);
/*
Now we will pull current epoch from slave. If not the
same as master, we will continue to retrieve the epoch
and compare until it matches or we reach the max loops
allowed.
*/
//Create a dbutil object for the slave
DbUtil
slave
(
"mysql"
,
".slave"
);
//Login to slave
if
(
!
slave
.
connect
())
{
return
NDBT_FAILED
;
}
while
(
slaveEpoch
!=
masterEpoch
&&
loopCnt
<
maxLoops
)
{
if
(
slave
.
doQuery
(
"SELECT epoch FROM mysql.ndb_apply_status"
))
{
return
NDBT_FAILED
;
}
result
=
mysql_use_result
(
slave
.
getMysql
());
row
=
mysql_fetch_row
(
result
);
slaveEpoch
=
atoi
(
row
[
0
]);
mysql_free_result
(
result
);
if
(
slaveEpoch
!=
slaveEpochOld
)
{
slaveEpochOld
=
slaveEpoch
;
if
(
loopCnt
>
0
)
loopCnt
--
;
sleep
(
3
);
}
else
{
sleep
(
1
);
loopCnt
++
;
}
}
if
(
slaveEpoch
!=
masterEpoch
)
{
g_err
<<
"Slave not in sync with master!"
<<
endl
;
return
NDBT_FAILED
;
}
return
NDBT_OK
;
}
int
verifySlaveLoad
(
BaseString
*
table
)
{
BaseString
sqlStm
;
BaseString
db
;
MYSQL_RES
*
result
;
MYSQL_ROW
row
;
unsigned
int
masterCount
=
0
;
unsigned
int
slaveCount
=
0
;
db
.
assign
(
"TEST_DB"
);
sqlStm
.
assfmt
(
"SELECT COUNT(*) FROM %s"
,
table
);
//First thing to do is sync slave
if
(
syncSlaveWithMaster
())
{
g_err
<<
"Verify Load -> Syncing with slave failed"
<<
endl
;
return
NDBT_FAILED
;
}
//Now that slave is sync we can verify load
DbUtil
master
(
db
.
c_str
(),
" "
);
//Login to Master
if
(
!
master
.
connect
())
{
return
NDBT_FAILED
;
}
if
(
master
.
doQuery
(
sqlStm
.
c_str
()))
{
return
NDBT_FAILED
;
}
result
=
mysql_use_result
(
master
.
getMysql
());
row
=
mysql_fetch_row
(
result
);
masterCount
=
atoi
(
row
[
0
]);
mysql_free_result
(
result
);
//Create a DB Object for slave
DbUtil
slave
(
db
.
c_str
(),
".slave"
);
//Login to slave
if
(
!
slave
.
connect
())
{
return
NDBT_FAILED
;
}
if
(
slave
.
doQuery
(
sqlStm
.
c_str
()))
{
return
NDBT_FAILED
;
}
result
=
mysql_use_result
(
slave
.
getMysql
());
row
=
mysql_fetch_row
(
result
);
slaveCount
=
atoi
(
row
[
0
]);
mysql_free_result
(
result
);
if
(
slaveCount
!=
masterCount
)
{
g_err
<<
"Verify Load -> Slave Count != Master Count "
<<
endl
;
return
NDBT_FAILED
;
}
return
NDBT_OK
;
}
int
createTEST_DB
(
NDBT_Context
*
ctx
,
NDBT_Step
*
step
)
{
BaseString
cdb
;
cdb
.
assign
(
"TEST_DB"
);
//Create a dbutil object
DbUtil
master
(
"mysql"
,
""
);
if
(
master
.
connect
())
{
if
(
master
.
createDb
(
cdb
)
==
NDBT_OK
)
{
return
NDBT_OK
;
}
}
return
NDBT_FAILED
;
}
int
dropTEST_DB
(
NDBT_Context
*
ctx
,
NDBT_Step
*
step
)
{
//Create an SQL Object
DbUtil
master
(
"mysql"
,
""
);
//Login to Master
if
(
!
master
.
connect
())
{
return
NDBT_FAILED
;
}
if
(
master
.
doQuery
(
"DROP DATABASE TEST_DB"
)
!=
NDBT_OK
)
{
return
NDBT_FAILED
;
}
if
(
syncSlaveWithMaster
()
!=
NDBT_OK
)
{
g_err
<<
"Drop DB -> Syncing with slave failed"
<<
endl
;
return
NDBT_FAILED
;
}
return
NDBT_OK
;
}
int
verifySlave
(
BaseString
&
sqlStm
,
BaseString
&
db
)
{
MYSQL_RES
*
resource
;
MYSQL_ROW
row
;
float
masterSum
;
float
slaveSum
;
//Create SQL Objects
DbUtil
master
(
db
.
c_str
(),
""
);
DbUtil
slave
(
db
.
c_str
(),
".slave"
);
if
(
syncSlaveWithMaster
()
!=
NDBT_OK
)
{
g_err
<<
"Verify Slave rep1 -> Syncing with slave failed"
<<
endl
;
return
NDBT_FAILED
;
}
//Login to Master
if
(
!
master
.
connect
())
{
return
NDBT_FAILED
;
}
if
(
master
.
doQuery
(
sqlStm
.
c_str
())
!=
NDBT_OK
)
{
return
NDBT_FAILED
;
}
resource
=
mysql_use_result
(
master
.
getMysql
());
row
=
mysql_fetch_row
(
resource
);
masterSum
=
atoi
(
row
[
0
]);
mysql_free_result
(
resource
);
//Login to slave
if
(
!
slave
.
connect
())
{
return
NDBT_FAILED
;
}
if
(
slave
.
doQuery
(
sqlStm
.
c_str
())
!=
NDBT_OK
)
{
return
NDBT_FAILED
;
}
resource
=
mysql_use_result
(
slave
.
getMysql
());
row
=
mysql_fetch_row
(
resource
);
slaveSum
=
atoi
(
row
[
0
]);
mysql_free_result
(
resource
);
if
(
masterSum
!=
slaveSum
)
{
g_err
<<
"VerifySlave -> masterSum != slaveSum..."
<<
endl
;
return
NDBT_FAILED
;
}
return
NDBT_OK
;
}
/**** Test Section ****/
int
createDB
(
NDBT_Context
*
ctx
,
NDBT_Step
*
step
)
{
BaseString
cdb
;
cdb
.
assign
(
"TEST_DB"
);
//Create a dbutil object
DbUtil
master
(
"mysql"
,
""
);
if
(
master
.
connect
())
{
if
(
master
.
createDb
(
cdb
)
==
NDBT_OK
)
{
return
NDBT_OK
;
}
}
return
NDBT_FAILED
;
}
int
createTable_rep1
(
NDBT_Context
*
ctx
,
NDBT_Step
*
step
)
{
BaseString
table
;
BaseString
db
;
table
.
assign
(
"rep1"
);
db
.
assign
(
"TEST_DB"
);
//Ensure slave is up and ready
if
(
syncSlaveWithMaster
()
!=
NDBT_OK
)
{
g_err
<<
"Create Table -> Syncing with slave failed"
<<
endl
;
return
NDBT_FAILED
;
}
//Create an SQL Object
DbUtil
master
(
db
.
c_str
(),
""
);
//Login to Master
if
(
!
master
.
connect
())
{
return
NDBT_FAILED
;
}
if
(
master
.
doQuery
(
"CREATE TABLE rep1 (c1 MEDIUMINT NOT NULL AUTO_INCREMENT,"
" c2 FLOAT, c3 CHAR(5), c4 bit(8), c5 FLOAT, c6 INT,"
" c7 INT, PRIMARY KEY (c1))ENGINE=NDB"
))
{
return
NDBT_FAILED
;
}
ctx
->
setProperty
(
"TABLES"
,
table
.
c_str
());
HugoTransactions
hugoTrans
(
*
ctx
->
getTab
());
if
(
hugoTrans
.
loadTable
(
GETNDB
(
step
),
ctx
->
getNumRecords
(),
1
,
true
,
0
)
!=
NDBT_OK
)
{
g_err
<<
"Create Table -> Load failed!"
<<
endl
;
return
NDBT_FAILED
;
}
if
(
verifySlaveLoad
(
&
table
)
!=
NDBT_OK
)
{
g_err
<<
"Create Table -> Failed on verify slave load!"
<<
endl
;
return
NDBT_FAILED
;
}
//else everything is okay
return
NDBT_OK
;
}
int
stressNDB_rep1
(
NDBT_Context
*
ctx
,
NDBT_Step
*
step
)
{
const
NdbDictionary
::
Table
*
table
=
ctx
->
getTab
();
HugoTransactions
hugoTrans
(
*
table
);
while
(
!
ctx
->
isTestStopped
())
{
if
(
hugoTrans
.
pkUpdateRecords
(
GETNDB
(
step
),
ctx
->
getNumRecords
(),
1
,
30
)
!=
0
)
{
g_err
<<
"pkUpdate Failed!"
<<
endl
;
return
NDBT_FAILED
;
}
if
(
hugoTrans
.
scanUpdateRecords
(
GETNDB
(
step
),
ctx
->
getNumRecords
(),
1
,
30
)
!=
0
)
{
g_err
<<
"scanUpdate Failed!"
<<
endl
;
return
NDBT_FAILED
;
}
}
return
NDBT_OK
;
}
int
stressSQL_rep1
(
NDBT_Context
*
ctx
,
NDBT_Step
*
step
)
{
BaseString
sqlStm
;
DbUtil
master
(
"TEST_DB"
,
""
);
int
loops
=
ctx
->
getNumLoops
();
uint
record
=
0
;
//Login to Master
if
(
!
master
.
connect
())
{
ctx
->
stopTest
();
return
NDBT_FAILED
;
}
for
(
int
j
=
0
;
loops
==
0
||
j
<
loops
;
j
++
)
{
record
=
urandom
(
ctx
->
getNumRecords
());
sqlStm
.
assfmt
(
"UPDATE TEST_DB.rep1 SET c2 = 33.3221 where c1 = %u"
,
record
);
if
(
master
.
doQuery
(
sqlStm
.
c_str
()))
{
return
NDBT_FAILED
;
}
}
ctx
->
stopTest
();
return
NDBT_OK
;
}
int
verifySlave_rep1
(
NDBT_Context
*
ctx
,
NDBT_Step
*
step
)
{
BaseString
sql
;
BaseString
db
;
sql
.
assign
(
"SELECT SUM(c3) FROM rep1"
);
db
.
assign
(
"TEST_DB"
);
if
(
verifySlave
(
sql
,
db
)
!=
NDBT_OK
)
return
NDBT_FAILED
;
return
NDBT_OK
;
}
/* TOOLS LIST
syncSlaveWithMaster()
{ensures slave is at same epoch as master}
verifySlaveLoad(BaseString *table)
{ensures slave table has same record count as master}
createTEST_DB()
{Creates TEST_DB database on master}
dropTEST_DB()
{Drops TEST_DB database on master}
verifySlave(BaseString& sql, BaseSting& db)
{The SQL statement must sum a column and will verify
that the sum of the column is equal on master & slave}
*/
NDBT_TESTSUITE
(
NdbRepStress
);
TESTCASE
(
"PHASE_I_Stress"
,
"Basic Replication Stressing"
)
{
INITIALIZER
(
createDB
);
INITIALIZER
(
createTable_rep1
);
STEP
(
stressNDB_rep1
);
STEP
(
stressSQL_rep1
);
FINALIZER
(
verifySlave_rep1
);
FINALIZER
(
dropTEST_DB
);
}
NDBT_TESTSUITE_END
(
NdbRepStress
);
int
main
(
int
argc
,
const
char
**
argv
){
ndb_init
();
NdbRepStress
.
setCreateAllTables
(
true
);
return
NdbRepStress
.
execute
(
argc
,
argv
);
}
storage/ndb/test/ndbapi/testBitfield.cpp
View file @
c50598bd
...
...
@@ -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 @
c50598bd
/* 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 @
c50598bd
...
...
@@ -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 @
c50598bd
...
...
@@ -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 @
c50598bd
/* 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
0 → 100755
View file @
c50598bd
/* 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 */
/* DbUtil.cpp: implementation of the database utilities class.*/
#include "DbUtil.hpp"
#include <NdbSleep.h>
/* Constructors */
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
)
{
const
char
*
env
=
getenv
(
"MYSQL_HOME"
);
if
(
env
&&
strlen
(
env
))
{
m_default_file
.
assfmt
(
"%s/my.cnf"
,
env
);
}
if
(
_suffix
!=
NULL
){
m_default_group
.
assfmt
(
"client%s"
,
_suffix
);
}
else
{
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
;
}
bool
DbUtil
::
waitConnected
(
int
timeout
)
{
timeout
*=
10
;
while
(
!
isConnected
()){
if
(
timeout
--
==
0
)
return
false
;
NdbSleep_MilliSleep
(
100
);
}
return
true
;
}
void
DbUtil
::
disconnect
(){
if
(
m_mysql
!=
NULL
){
if
(
m_free_mysql
)
mysql_close
(
m_mysql
);
m_mysql
=
NULL
;
}
m_connected
=
false
;
}
/* Destructor */
DbUtil
::~
DbUtil
()
{
disconnect
();
}
/* Database Login */
void
DbUtil
::
databaseLogin
(
const
char
*
system
,
const
char
*
usr
,
const
char
*
password
,
unsigned
int
portIn
,
const
char
*
sockIn
,
bool
transactional
)
{
if
(
!
(
m_mysql
=
mysql_init
(
NULL
)))
{
myerror
(
"DB Login-> mysql_init() failed"
);
exit
(
DBU_FAILED
);
}
setUser
(
usr
);
setHost
(
system
);
setPassword
(
password
);
setPort
(
portIn
);
setSocket
(
sockIn
);
if
(
!
(
mysql_real_connect
(
m_mysql
,
m_host
.
c_str
(),
m_user
.
c_str
(),
m_pass
.
c_str
(),
"test"
,
m_port
,
m_socket
.
c_str
(),
0
)))
{
myerror
(
"connection failed"
);
mysql_close
(
m_mysql
);
exit
(
DBU_FAILED
);
}
m_mysql
->
reconnect
=
TRUE
;
/* set AUTOCOMMIT */
if
(
!
transactional
)
mysql_autocommit
(
m_mysql
,
TRUE
);
else
mysql_autocommit
(
m_mysql
,
FALSE
);
#ifdef DEBUG
printf
(
"
\n\t
Connected to MySQL server version: %s (%lu)
\n\n
"
,
mysql_get_server_info
(
m_mysql
),
(
unsigned
long
)
mysql_get_server_version
(
m_mysql
));
#endif
selectDb
();
}
/* Database Connect */
int
DbUtil
::
connect
()
{
if
(
!
(
m_mysql
=
mysql_init
(
NULL
)))
{
myerror
(
"DB connect-> mysql_init() failed"
);
return
DBU_FAILED
;
}
/* Load connection parameters file and group */
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
;
}
/*
Connect, read settings from my.cnf
NOTE! user and password can be stored there as well
*/
if
(
mysql_real_connect
(
m_mysql
,
NULL
,
"root"
,
""
,
m_dbname
.
c_str
(),
0
,
NULL
,
0
)
==
NULL
)
{
myerror
(
"connection failed"
);
mysql_close
(
m_mysql
);
return
DBU_FAILED
;
}
selectDb
();
m_connected
=
true
;
return
DBU_OK
;
}
/* Database Logout */
void
DbUtil
::
databaseLogout
()
{
if
(
m_mysql
){
#ifdef DEBUG
printf
(
"
\n\t
Closing the MySQL database connection ...
\n\n
"
);
#endif
mysql_close
(
m_mysql
);
}
}
/* Prepare MySQL Statements Cont */
MYSQL_STMT
*
STDCALL
DbUtil
::
mysqlSimplePrepare
(
const
char
*
query
)
{
#ifdef DEBUG
printf
(
"Inside DbUtil::mysqlSimplePrepare
\n
"
);
#endif
int
m_res
=
DBU_OK
;
MYSQL_STMT
*
my_stmt
=
mysql_stmt_init
(
this
->
getMysql
());
if
(
my_stmt
&&
(
m_res
=
mysql_stmt_prepare
(
my_stmt
,
query
,
strlen
(
query
)))){
this
->
printStError
(
my_stmt
,
"Prepare Statement Failed"
);
mysql_stmt_close
(
my_stmt
);
exit
(
DBU_FAILED
);
}
return
my_stmt
;
}
/* Close MySQL Statements Handle */
void
DbUtil
::
mysqlCloseStmHandle
(
MYSQL_STMT
*
my_stmt
)
{
mysql_stmt_close
(
my_stmt
);
}
/* Error Printing */
void
DbUtil
::
printError
(
const
char
*
msg
)
{
if
(
m_mysql
&&
mysql_errno
(
m_mysql
))
{
if
(
m_mysql
->
server_version
)
printf
(
"
\n
[MySQL-%s]"
,
m_mysql
->
server_version
);
else
printf
(
"
\n
[MySQL]"
);
printf
(
"[%d] %s
\n
"
,
getErrorNumber
(),
getError
());
}
else
if
(
msg
)
printf
(
" [MySQL] %s
\n
"
,
msg
);
}
void
DbUtil
::
printStError
(
MYSQL_STMT
*
stmt
,
const
char
*
msg
)
{
if
(
stmt
&&
mysql_stmt_errno
(
stmt
))
{
if
(
m_mysql
&&
m_mysql
->
server_version
)
printf
(
"
\n
[MySQL-%s]"
,
m_mysql
->
server_version
);
else
printf
(
"
\n
[MySQL]"
);
printf
(
"[%d] %s
\n
"
,
mysql_stmt_errno
(
stmt
),
mysql_stmt_error
(
stmt
));
}
else
if
(
msg
)
printf
(
"[MySQL] %s
\n
"
,
msg
);
}
/* Select which database to use */
int
DbUtil
::
selectDb
()
{
if
((
getDbName
())
!=
NULL
)
{
if
(
mysql_select_db
(
m_mysql
,
this
->
getDbName
()))
{
printError
(
"mysql_select_db failed"
);
return
DBU_FAILED
;
}
return
DBU_OK
;
}
printError
(
"getDbName() == NULL"
);
return
DBU_FAILED
;
}
int
DbUtil
::
selectDb
(
const
char
*
m_db
)
{
{
if
(
mysql_select_db
(
m_mysql
,
m_db
))
{
printError
(
"mysql_select_db failed"
);
return
DBU_FAILED
;
}
return
DBU_OK
;
}
}
int
DbUtil
::
createDb
(
BaseString
&
m_db
)
{
BaseString
stm
;
{
if
(
mysql_select_db
(
m_mysql
,
m_db
.
c_str
())
==
DBU_OK
)
{
stm
.
assfmt
(
"DROP DATABASE %s"
,
m_db
.
c_str
());
if
(
doQuery
(
m_db
.
c_str
())
==
DBU_FAILED
)
return
DBU_FAILED
;
}
stm
.
assfmt
(
"CREATE DATABASE %s"
,
m_db
.
c_str
());
if
(
doQuery
(
m_db
.
c_str
())
==
DBU_FAILED
)
return
DBU_FAILED
;
return
DBU_OK
;
}
}
/* Count Table Rows */
unsigned
long
DbUtil
::
selectCountTable
(
const
char
*
table
)
{
BaseString
query
;
SqlResultSet
result
;
query
.
assfmt
(
"select count(*) as count from %s"
,
table
);
if
(
!
doQuery
(
query
,
result
))
{
printError
(
"select count(*) failed"
);
return
-
1
;
}
return
result
.
columnAsInt
(
"count"
);
}
/* 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
)))
{
g_err
<<
"Failed to prepare: "
<<
mysql_error
(
m_mysql
)
<<
endl
;
return
false
;
}
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
*
DbUtil
::
getError
()
{
return
mysql_error
(
this
->
getMysql
());
}
/* Return MySQL Error Number */
int
DbUtil
::
getErrorNumber
()
{
return
mysql_errno
(
this
->
getMysql
());
}
/* DIE */
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 @
c50598bd
...
...
@@ -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
...
...
storage/ndb/test/src/dbutil.cpp
deleted
100755 → 0
View file @
2401f86c
// dbutil.cpp: implementation of the database utilities class.
//
//////////////////////////////////////////////////////////////////////
#include "dbutil.hpp"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
dbutil
::
dbutil
(
const
char
*
dbname
)
{
memset
(
host
,
' '
,
sizeof
(
host
));
memset
(
user
,
' '
,
sizeof
(
pass
));
memset
(
dbs
,
' '
,
sizeof
(
dbs
));
port
=
0
;
memset
(
socket
,
' '
,
sizeof
(
socket
));
this
->
SetDbName
(
dbname
);
}
dbutil
::~
dbutil
()
{
this
->
DatabaseLogout
();
}
//////////////////////////////////////////////////////////////////////
// Database Login
//////////////////////////////////////////////////////////////////////
void
dbutil
::
DatabaseLogin
(
const
char
*
system
,
const
char
*
usr
,
const
char
*
password
,
unsigned
int
portIn
,
const
char
*
sockIn
,
bool
transactional
){
if
(
!
(
myDbHandel
=
mysql_init
(
NULL
))){
myerror
(
"mysql_init() failed"
);
exit
(
1
);
}
this
->
SetUser
(
usr
);
this
->
SetHost
(
system
);
this
->
SetPassword
(
password
);
this
->
SetPort
(
portIn
);
this
->
SetSocket
(
sockIn
);
if
(
!
(
mysql_real_connect
(
myDbHandel
,
host
,
user
,
pass
,
"test"
,
port
,
socket
,
0
))){
myerror
(
"connection failed"
);
mysql_close
(
myDbHandel
);
fprintf
(
stdout
,
"
\n
Check the connection options using --help or -?
\n
"
);
exit
(
1
);
}
myDbHandel
->
reconnect
=
1
;
/* set AUTOCOMMIT */
if
(
!
transactional
){
mysql_autocommit
(
myDbHandel
,
TRUE
);
}
else
{
mysql_autocommit
(
myDbHandel
,
FALSE
);
}
fprintf
(
stdout
,
"
\n\t
Connected to MySQL server version: %s (%lu)
\n\n
"
,
mysql_get_server_info
(
myDbHandel
),
(
unsigned
long
)
mysql_get_server_version
(
myDbHandel
));
}
//////////////////////////////////////////////////////////////////////
// Database Logout
//////////////////////////////////////////////////////////////////////
void
dbutil
::
DatabaseLogout
(){
if
(
myDbHandel
){
fprintf
(
stdout
,
"
\n\t
Closing the MySQL database connection ...
\n\n
"
);
mysql_close
(
myDbHandel
);
}
}
//////////////////////////////////////////////////////////////////////
// Prepare MySQL Statements Cont
//////////////////////////////////////////////////////////////////////
MYSQL_STMT
*
STDCALL
dbutil
::
MysqlSimplePrepare
(
const
char
*
query
){
#ifdef DEBUG
printf
(
"Inside dbutil::MysqlSimplePrepare
\n
"
);
#endif
int
result
=
0
;
MYSQL_STMT
*
my_stmt
=
mysql_stmt_init
(
this
->
GetDbHandel
());
if
(
my_stmt
&&
(
result
=
mysql_stmt_prepare
(
my_stmt
,
query
,
strlen
(
query
)))){
printf
(
"res = %s
\n
"
,
mysql_stmt_error
(
my_stmt
));
mysql_stmt_close
(
my_stmt
);
return
0
;
}
return
my_stmt
;
}
//////////////////////////////////////////////////////////////////////
// Error Printing
//////////////////////////////////////////////////////////////////////
void
dbutil
::
PrintError
(
const
char
*
msg
){
if
(
this
->
GetDbHandel
()
&&
mysql_errno
(
this
->
GetDbHandel
())){
if
(
this
->
GetDbHandel
()
->
server_version
){
fprintf
(
stdout
,
"
\n
[MySQL-%s]"
,
this
->
GetDbHandel
()
->
server_version
);
}
else
fprintf
(
stdout
,
"
\n
[MySQL]"
);
fprintf
(
stdout
,
"[%d] %s
\n
"
,
mysql_errno
(
this
->
GetDbHandel
()),
mysql_error
(
this
->
GetDbHandel
()));
}
else
if
(
msg
)
fprintf
(
stderr
,
" [MySQL] %s
\n
"
,
msg
);
}
void
dbutil
::
PrintStError
(
MYSQL_STMT
*
stmt
,
const
char
*
msg
)
{
if
(
stmt
&&
mysql_stmt_errno
(
stmt
))
{
if
(
this
->
GetDbHandel
()
&&
this
->
GetDbHandel
()
->
server_version
)
fprintf
(
stdout
,
"
\n
[MySQL-%s]"
,
this
->
GetDbHandel
()
->
server_version
);
else
fprintf
(
stdout
,
"
\n
[MySQL]"
);
fprintf
(
stdout
,
"[%d] %s
\n
"
,
mysql_stmt_errno
(
stmt
),
mysql_stmt_error
(
stmt
));
}
else
if
(
msg
)
fprintf
(
stderr
,
" [MySQL] %s
\n
"
,
msg
);
}
/////////////////////////////////////////////////////
int
dbutil
::
Select_DB
()
{
return
mysql_select_db
(
this
->
GetDbHandel
(),
this
->
GetDbName
());
}
////////////////////////////////////////////////////
int
dbutil
::
Do_Query
(
char
*
stm
)
{
return
mysql_query
(
this
->
GetDbHandel
(),
stm
);
}
////////////////////////////////////////////////////
const
char
*
dbutil
::
GetError
()
{
return
mysql_error
(
this
->
GetDbHandel
());
}
////////////////////////////////////////////////////
int
dbutil
::
GetErrorNumber
()
{
return
mysql_errno
(
this
->
GetDbHandel
());
}
////////////////////////////////////////////////////
unsigned
long
dbutil
::
SelectCountTable
(
const
char
*
table
)
{
unsigned
long
count
=
0
;
MYSQL_RES
*
result
;
char
query
[
1024
];
MYSQL_ROW
row
;
sprintf
(
query
,
"select count(*) from `%s`"
,
table
);
if
(
mysql_query
(
this
->
GetDbHandel
(),
query
)
||
!
(
result
=
mysql_store_result
(
this
->
GetDbHandel
())))
{
printf
(
"error
\n
"
);
return
1
;
}
row
=
mysql_fetch_row
(
result
);
count
=
(
ulong
)
strtoull
(
row
[
0
],
(
char
**
)
0
,
10
);
mysql_free_result
(
result
);
return
count
;
}
void
dbutil
::
Die
(
const
char
*
file
,
int
line
,
const
char
*
expr
){
fprintf
(
stderr
,
"%s:%d: check failed: '%s'
\n
"
,
file
,
line
,
expr
);
abort
();
}
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