Merge branch '5.5' into 10.1
This commit is contained in:
commit
23c6fb3e62
@ -32,7 +32,7 @@
|
|||||||
** master/autocommit code by Brian Aker <brian@tangent.org>
|
** master/autocommit code by Brian Aker <brian@tangent.org>
|
||||||
** SSL by
|
** SSL by
|
||||||
** Andrei Errapart <andreie@no.spam.ee>
|
** Andrei Errapart <andreie@no.spam.ee>
|
||||||
** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee>
|
** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee>
|
||||||
** XML by Gary Huntress <ghuntress@mediaone.net> 10/10/01, cleaned up
|
** XML by Gary Huntress <ghuntress@mediaone.net> 10/10/01, cleaned up
|
||||||
** and adapted to mysqldump 05/11/01 by Jani Tolonen
|
** and adapted to mysqldump 05/11/01 by Jani Tolonen
|
||||||
** Added --single-transaction option 06/06/2002 by Peter Zaitsev
|
** Added --single-transaction option 06/06/2002 by Peter Zaitsev
|
||||||
|
@ -55,7 +55,7 @@ typedef struct st_queue {
|
|||||||
#define queue_top(queue) ((queue)->root[1])
|
#define queue_top(queue) ((queue)->root[1])
|
||||||
#define queue_element(queue,index) ((queue)->root[index])
|
#define queue_element(queue,index) ((queue)->root[index])
|
||||||
#define queue_end(queue) ((queue)->root[(queue)->elements])
|
#define queue_end(queue) ((queue)->root[(queue)->elements])
|
||||||
#define queue_replace_top(queue) _downheap(queue, 1, (queue)->root[1])
|
#define queue_replace_top(queue) _downheap(queue, 1)
|
||||||
#define queue_set_cmp_arg(queue, set_arg) (queue)->first_cmp_arg= set_arg
|
#define queue_set_cmp_arg(queue, set_arg) (queue)->first_cmp_arg= set_arg
|
||||||
#define queue_set_max_at_top(queue, set_arg) \
|
#define queue_set_max_at_top(queue, set_arg) \
|
||||||
(queue)->max_at_top= set_arg ? -1 : 1
|
(queue)->max_at_top= set_arg ? -1 : 1
|
||||||
@ -63,23 +63,23 @@ typedef struct st_queue {
|
|||||||
typedef int (*queue_compare)(void *,uchar *, uchar *);
|
typedef int (*queue_compare)(void *,uchar *, uchar *);
|
||||||
|
|
||||||
int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
|
int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
|
||||||
pbool max_at_top, queue_compare compare,
|
my_bool max_at_top, queue_compare compare,
|
||||||
void *first_cmp_arg, uint offset_to_queue_pos,
|
void *first_cmp_arg, uint offset_to_queue_pos,
|
||||||
uint auto_extent);
|
uint auto_extent);
|
||||||
int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
|
int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
|
||||||
pbool max_at_top, queue_compare compare,
|
my_bool max_at_top, queue_compare compare,
|
||||||
void *first_cmp_arg, uint offset_to_queue_pos,
|
void *first_cmp_arg, uint offset_to_queue_pos,
|
||||||
uint auto_extent);
|
uint auto_extent);
|
||||||
int resize_queue(QUEUE *queue, uint max_elements);
|
int resize_queue(QUEUE *queue, uint max_elements);
|
||||||
void delete_queue(QUEUE *queue);
|
void delete_queue(QUEUE *queue);
|
||||||
void queue_insert(QUEUE *queue,uchar *element);
|
void queue_insert(QUEUE *queue, uchar *element);
|
||||||
int queue_insert_safe(QUEUE *queue, uchar *element);
|
int queue_insert_safe(QUEUE *queue, uchar *element);
|
||||||
uchar *queue_remove(QUEUE *queue,uint idx);
|
uchar *queue_remove(QUEUE *queue,uint idx);
|
||||||
void queue_replace(QUEUE *queue,uint idx);
|
void queue_replace(QUEUE *queue,uint idx);
|
||||||
|
|
||||||
#define queue_remove_all(queue) { (queue)->elements= 0; }
|
#define queue_remove_all(queue) { (queue)->elements= 0; }
|
||||||
#define queue_is_full(queue) (queue->elements == queue->max_elements)
|
#define queue_is_full(queue) (queue->elements == queue->max_elements)
|
||||||
void _downheap(QUEUE *queue, uint idx, uchar *element);
|
void _downheap(QUEUE *queue, uint idx);
|
||||||
void queue_fix(QUEUE *queue);
|
void queue_fix(QUEUE *queue);
|
||||||
#define is_queue_inited(queue) ((queue)->root != 0)
|
#define is_queue_inited(queue) ((queue)->root != 0)
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ int main(int argc, const char** argv )
|
|||||||
} else {
|
} else {
|
||||||
if (strcmp(arg, "--verbose") == 0)
|
if (strcmp(arg, "--verbose") == 0)
|
||||||
verbose++;
|
verbose++;
|
||||||
else if (strncmp(arg, "--parent-pid", 10) == 0)
|
else if (strncmp(arg, "--parent-pid", 12) == 0)
|
||||||
{
|
{
|
||||||
/* Override parent_pid with a value provided by user */
|
/* Override parent_pid with a value provided by user */
|
||||||
const char* start;
|
const char* start;
|
||||||
|
@ -281,7 +281,7 @@ my $current_config_name; # The currently running config file template
|
|||||||
our @opt_experimentals;
|
our @opt_experimentals;
|
||||||
our $experimental_test_cases= [];
|
our $experimental_test_cases= [];
|
||||||
|
|
||||||
my $baseport;
|
our $baseport;
|
||||||
# $opt_build_thread may later be set from $opt_port_base
|
# $opt_build_thread may later be set from $opt_port_base
|
||||||
my $opt_build_thread= $ENV{'MTR_BUILD_THREAD'} || "auto";
|
my $opt_build_thread= $ENV{'MTR_BUILD_THREAD'} || "auto";
|
||||||
my $opt_port_base= $ENV{'MTR_PORT_BASE'} || "auto";
|
my $opt_port_base= $ENV{'MTR_PORT_BASE'} || "auto";
|
||||||
|
@ -62,9 +62,10 @@ sub skip_combinations {
|
|||||||
sub ipv6_ok() {
|
sub ipv6_ok() {
|
||||||
use Socket;
|
use Socket;
|
||||||
return 0 unless socket my $sock, PF_INET6, SOCK_STREAM, getprotobyname('tcp');
|
return 0 unless socket my $sock, PF_INET6, SOCK_STREAM, getprotobyname('tcp');
|
||||||
|
$!="";
|
||||||
# eval{}, if there's no Socket::sockaddr_in6 at all, old Perl installation
|
# eval{}, if there's no Socket::sockaddr_in6 at all, old Perl installation
|
||||||
eval { connect $sock, sockaddr_in6(7, Socket::IN6ADDR_LOOPBACK) };
|
eval { bind $sock, sockaddr_in6($::baseport, Socket::IN6ADDR_LOOPBACK) };
|
||||||
return $@ eq "";
|
return $@ eq "" && $! eq ""
|
||||||
}
|
}
|
||||||
$skip{'include/check_ipv6.inc'} = 'No IPv6' unless ipv6_ok();
|
$skip{'include/check_ipv6.inc'} = 'No IPv6' unless ipv6_ok();
|
||||||
|
|
||||||
|
@ -65,5 +65,20 @@ include/diff_tables.inc [master:t1,slave:t1]
|
|||||||
# comments
|
# comments
|
||||||
SELECT c1 FROM /*!999999 t1 WHEREN;
|
SELECT c1 FROM /*!999999 t1 WHEREN;
|
||||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '/*!999999 t1 WHEREN' at line 1
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '/*!999999 t1 WHEREN' at line 1
|
||||||
|
insert t1 values (/*!50505 1 /* foo */ */ + 2);
|
||||||
|
insert t1 values (/*!999999 10 /* foo */ */ + 20);
|
||||||
|
include/show_binlog_events.inc
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
|
master-bin.000001 # Query # # use `test`; insert t1 values (/*!50505 1 /* foo */ */ + 2)
|
||||||
|
master-bin.000001 # Query # # COMMIT
|
||||||
|
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
|
master-bin.000001 # Query # # use `test`; insert t1 values (/* 999999 10 (* foo *) */ + 20)
|
||||||
|
master-bin.000001 # Query # # COMMIT
|
||||||
|
select * from t1;
|
||||||
|
c1
|
||||||
|
62
|
||||||
|
3
|
||||||
|
20
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
include/rpl_end.inc
|
include/rpl_end.inc
|
||||||
|
16
mysql-test/suite/rpl/r/rpl_fail_register.result
Normal file
16
mysql-test/suite/rpl/r/rpl_fail_register.result
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
include/master-slave.inc
|
||||||
|
[connection master]
|
||||||
|
set @old_dbug=@@global.debug_dbug;
|
||||||
|
set global debug_dbug='d,fail_com_register_slave';
|
||||||
|
stop slave;
|
||||||
|
reset slave;
|
||||||
|
include/wait_for_slave_to_stop.inc
|
||||||
|
start slave;
|
||||||
|
stop slave;
|
||||||
|
include/wait_for_slave_to_stop.inc
|
||||||
|
set global debug_dbug=@old_dbug;
|
||||||
|
kill DUMP_THREAD;
|
||||||
|
show slave hosts;
|
||||||
|
Server_id Host Port Master_id
|
||||||
|
start slave;
|
||||||
|
include/rpl_end.inc
|
@ -68,7 +68,17 @@ sync_slave_with_master;
|
|||||||
--echo # comments
|
--echo # comments
|
||||||
--connection master
|
--connection master
|
||||||
--error 1064
|
--error 1064
|
||||||
SELECT c1 FROM /*!999999 t1 WHEREN;
|
SELECT c1 FROM /*!999999 t1 WHEREN; #*/
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#28388217 - SERVER CAN FAIL WHILE REPLICATING CONDITIONAL COMMENTS
|
||||||
|
#
|
||||||
|
insert t1 values (/*!50505 1 /* foo */ */ + 2);
|
||||||
|
insert t1 values (/*!999999 10 /* foo */ */ + 20);
|
||||||
|
source include/show_binlog_events.inc;
|
||||||
|
sync_slave_with_master;
|
||||||
|
select * from t1;
|
||||||
|
connection master;
|
||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
--source include/rpl_end.inc
|
--source include/rpl_end.inc
|
||||||
|
33
mysql-test/suite/rpl/t/rpl_fail_register.test
Normal file
33
mysql-test/suite/rpl/t/rpl_fail_register.test
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
source include/have_debug.inc;
|
||||||
|
source include/have_binlog_format_mixed.inc;
|
||||||
|
source include/master-slave.inc;
|
||||||
|
|
||||||
|
connection slave;
|
||||||
|
|
||||||
|
set @old_dbug=@@global.debug_dbug;
|
||||||
|
set global debug_dbug='d,fail_com_register_slave';
|
||||||
|
|
||||||
|
stop slave;
|
||||||
|
reset slave;
|
||||||
|
source include/wait_for_slave_to_stop.inc;
|
||||||
|
start slave;
|
||||||
|
stop slave;
|
||||||
|
source include/wait_for_slave_to_stop.inc;
|
||||||
|
set global debug_dbug=@old_dbug;
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
|
||||||
|
### why is that needed?
|
||||||
|
let $id=`SELECT id from information_schema.processlist where command='Binlog Dump'`;
|
||||||
|
if ($id) {
|
||||||
|
replace_result $id DUMP_THREAD;
|
||||||
|
eval kill $id;
|
||||||
|
let $wait_condition= SELECT count(*)=0 from information_schema.processlist where command='Binlog Dump';
|
||||||
|
source include/wait_condition.inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
show slave hosts;
|
||||||
|
|
||||||
|
connection slave;
|
||||||
|
start slave;
|
||||||
|
source include/rpl_end.inc;
|
169
mysys/queues.c
169
mysys/queues.c
@ -70,10 +70,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
|
int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
|
||||||
pbool max_at_top, int (*compare) (void *, uchar *, uchar *),
|
my_bool max_at_top, int (*compare) (void *, uchar *, uchar *),
|
||||||
void *first_cmp_arg, uint offset_to_queue_pos,
|
void *first_cmp_arg, uint offset_to_queue_pos,
|
||||||
uint auto_extent)
|
uint auto_extent)
|
||||||
|
|
||||||
{
|
{
|
||||||
DBUG_ENTER("init_queue");
|
DBUG_ENTER("init_queue");
|
||||||
if ((queue->root= (uchar **) my_malloc((max_elements + 1) * sizeof(void*),
|
if ((queue->root= (uchar **) my_malloc((max_elements + 1) * sizeof(void*),
|
||||||
@ -109,7 +108,7 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
|
int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
|
||||||
pbool max_at_top, int (*compare) (void *, uchar *, uchar *),
|
my_bool max_at_top, int (*compare) (void *, uchar *, uchar *),
|
||||||
void *first_cmp_arg, uint offset_to_queue_pos,
|
void *first_cmp_arg, uint offset_to_queue_pos,
|
||||||
uint auto_extent)
|
uint auto_extent)
|
||||||
{
|
{
|
||||||
@ -182,6 +181,28 @@ void delete_queue(QUEUE *queue)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void insert_at(QUEUE *queue, uchar *element, uint idx)
|
||||||
|
{
|
||||||
|
uint next_index, offset_to_key= queue->offset_to_key;
|
||||||
|
uint offset_to_queue_pos= queue->offset_to_queue_pos;
|
||||||
|
/* max_at_top swaps the comparison if we want to order by desc */
|
||||||
|
while ((next_index= idx >> 1) > 0 &&
|
||||||
|
queue->compare(queue->first_cmp_arg,
|
||||||
|
element + offset_to_key,
|
||||||
|
queue->root[next_index] + offset_to_key) *
|
||||||
|
queue->max_at_top < 0)
|
||||||
|
{
|
||||||
|
queue->root[idx]= queue->root[next_index];
|
||||||
|
if (offset_to_queue_pos)
|
||||||
|
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
||||||
|
idx= next_index;
|
||||||
|
}
|
||||||
|
queue->root[idx]= element;
|
||||||
|
if (offset_to_queue_pos)
|
||||||
|
(*(uint*) (element + offset_to_queue_pos-1))= idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Insert element in queue
|
Insert element in queue
|
||||||
|
|
||||||
@ -191,28 +212,10 @@ void delete_queue(QUEUE *queue)
|
|||||||
element Element to insert
|
element Element to insert
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void queue_insert(register QUEUE *queue, uchar *element)
|
void queue_insert(QUEUE *queue, uchar *element)
|
||||||
{
|
{
|
||||||
reg2 uint idx, next;
|
|
||||||
uint offset_to_queue_pos= queue->offset_to_queue_pos;
|
|
||||||
DBUG_ASSERT(queue->elements < queue->max_elements);
|
DBUG_ASSERT(queue->elements < queue->max_elements);
|
||||||
|
insert_at(queue, element, ++queue->elements);
|
||||||
idx= ++queue->elements;
|
|
||||||
/* max_at_top swaps the comparison if we want to order by desc */
|
|
||||||
while (idx > 1 &&
|
|
||||||
(queue->compare(queue->first_cmp_arg,
|
|
||||||
element + queue->offset_to_key,
|
|
||||||
queue->root[(next= idx >> 1)] +
|
|
||||||
queue->offset_to_key) * queue->max_at_top) < 0)
|
|
||||||
{
|
|
||||||
queue->root[idx]= queue->root[next];
|
|
||||||
if (offset_to_queue_pos)
|
|
||||||
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
|
||||||
idx= next;
|
|
||||||
}
|
|
||||||
queue->root[idx]= element;
|
|
||||||
if (offset_to_queue_pos)
|
|
||||||
(*(uint*) (element+ offset_to_queue_pos-1))= idx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -230,7 +233,7 @@ void queue_insert(register QUEUE *queue, uchar *element)
|
|||||||
2 auto_extend is 0; No insertion done
|
2 auto_extend is 0; No insertion done
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int queue_insert_safe(register QUEUE *queue, uchar *element)
|
int queue_insert_safe(QUEUE *queue, uchar *element)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (queue->elements == queue->max_elements)
|
if (queue->elements == queue->max_elements)
|
||||||
@ -240,7 +243,7 @@ int queue_insert_safe(register QUEUE *queue, uchar *element)
|
|||||||
if (resize_queue(queue, queue->max_elements + queue->auto_extent))
|
if (resize_queue(queue, queue->max_elements + queue->auto_extent))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_insert(queue, element);
|
queue_insert(queue, element);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -259,81 +262,55 @@ int queue_insert_safe(register QUEUE *queue, uchar *element)
|
|||||||
pointer to removed element
|
pointer to removed element
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uchar *queue_remove(register QUEUE *queue, uint idx)
|
uchar *queue_remove(QUEUE *queue, uint idx)
|
||||||
{
|
{
|
||||||
uchar *element;
|
uchar *element;
|
||||||
DBUG_ASSERT(idx >= 1 && idx <= queue->elements);
|
DBUG_ASSERT(idx >= 1);
|
||||||
|
DBUG_ASSERT(idx <= queue->elements);
|
||||||
element= queue->root[idx];
|
element= queue->root[idx];
|
||||||
_downheap(queue, idx, queue->root[queue->elements--]);
|
queue->root[idx]= queue->root[queue->elements--];
|
||||||
|
queue_replace(queue, idx);
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Add element to fixed position and update heap
|
Restores the heap property from idx down the heap
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
_downheap()
|
_downheap()
|
||||||
queue Queue to use
|
queue Queue to use
|
||||||
idx Index of element to change
|
idx Index of element to change
|
||||||
element Element to store at 'idx'
|
|
||||||
|
|
||||||
NOTE
|
|
||||||
This only works if element is >= all elements <= start_idx
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void _downheap(register QUEUE *queue, uint start_idx, uchar *element)
|
void _downheap(QUEUE *queue, uint idx)
|
||||||
{
|
{
|
||||||
uint elements,half_queue,offset_to_key, next_index, offset_to_queue_pos;
|
uchar *element= queue->root[idx];
|
||||||
register uint idx= start_idx;
|
uint next_index,
|
||||||
my_bool first= TRUE;
|
elements= queue->elements,
|
||||||
|
half_queue= elements >> 1,
|
||||||
offset_to_key=queue->offset_to_key;
|
offset_to_key= queue->offset_to_key,
|
||||||
offset_to_queue_pos= queue->offset_to_queue_pos;
|
offset_to_queue_pos= queue->offset_to_queue_pos;
|
||||||
half_queue= (elements= queue->elements) >> 1;
|
|
||||||
|
|
||||||
while (idx <= half_queue)
|
while (idx <= half_queue)
|
||||||
{
|
{
|
||||||
next_index=idx+idx;
|
next_index= idx+idx;
|
||||||
if (next_index < elements &&
|
if (next_index < elements &&
|
||||||
(queue->compare(queue->first_cmp_arg,
|
(queue->compare(queue->first_cmp_arg,
|
||||||
queue->root[next_index]+offset_to_key,
|
queue->root[next_index]+offset_to_key,
|
||||||
queue->root[next_index+1]+offset_to_key) *
|
queue->root[next_index+1]+offset_to_key) *
|
||||||
queue->max_at_top) > 0)
|
queue->max_at_top) > 0)
|
||||||
next_index++;
|
next_index++;
|
||||||
if (first &&
|
if ((queue->compare(queue->first_cmp_arg,
|
||||||
(((queue->compare(queue->first_cmp_arg,
|
queue->root[next_index]+offset_to_key,
|
||||||
queue->root[next_index]+offset_to_key,
|
element+offset_to_key) * queue->max_at_top) >= 0)
|
||||||
element+offset_to_key) * queue->max_at_top) >= 0)))
|
break;
|
||||||
{
|
|
||||||
queue->root[idx]= element;
|
|
||||||
if (offset_to_queue_pos)
|
|
||||||
(*(uint*) (element + offset_to_queue_pos-1))= idx;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
first= FALSE;
|
|
||||||
queue->root[idx]= queue->root[next_index];
|
|
||||||
if (offset_to_queue_pos)
|
|
||||||
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
|
||||||
idx=next_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Insert the element into the right position. This is the same code
|
|
||||||
as we have in queue_insert()
|
|
||||||
*/
|
|
||||||
while ((next_index= (idx >> 1)) > start_idx &&
|
|
||||||
queue->compare(queue->first_cmp_arg,
|
|
||||||
element+offset_to_key,
|
|
||||||
queue->root[next_index]+offset_to_key)*
|
|
||||||
queue->max_at_top < 0)
|
|
||||||
{
|
|
||||||
queue->root[idx]= queue->root[next_index];
|
queue->root[idx]= queue->root[next_index];
|
||||||
if (offset_to_queue_pos)
|
if (offset_to_queue_pos)
|
||||||
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
||||||
idx= next_index;
|
idx= next_index;
|
||||||
}
|
}
|
||||||
queue->root[idx]= element;
|
queue->root[idx]=element;
|
||||||
if (offset_to_queue_pos)
|
if (offset_to_queue_pos)
|
||||||
(*(uint*) (element + offset_to_queue_pos-1))= idx;
|
(*(uint*) (element + offset_to_queue_pos-1))= idx;
|
||||||
}
|
}
|
||||||
@ -351,7 +328,7 @@ void queue_fix(QUEUE *queue)
|
|||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
for (i= queue->elements >> 1; i > 0; i--)
|
for (i= queue->elements >> 1; i > 0; i--)
|
||||||
_downheap(queue, i, queue_element(queue, i));
|
_downheap(queue, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -362,13 +339,47 @@ void queue_fix(QUEUE *queue)
|
|||||||
queue_replace()
|
queue_replace()
|
||||||
queue Queue to use
|
queue Queue to use
|
||||||
idx Index of element to change
|
idx Index of element to change
|
||||||
element Element to store at 'idx'
|
|
||||||
|
NOTE
|
||||||
|
optimized for the case when the new position is close to the end of the
|
||||||
|
heap (typical for queue_remove() replacements).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void queue_replace(QUEUE *queue, uint idx)
|
void queue_replace(QUEUE *queue, uint idx)
|
||||||
{
|
{
|
||||||
uchar *element= queue->root[idx];
|
uchar *element= queue->root[idx];
|
||||||
DBUG_ASSERT(idx >= 1 && idx <= queue->elements);
|
uint next_index,
|
||||||
queue_remove(queue, idx);
|
elements= queue->elements,
|
||||||
queue_insert(queue, element);
|
half_queue= elements>>1,
|
||||||
|
offset_to_key= queue->offset_to_key,
|
||||||
|
offset_to_queue_pos= queue->offset_to_queue_pos;
|
||||||
|
my_bool first= TRUE;
|
||||||
|
|
||||||
|
while (idx <= half_queue)
|
||||||
|
{
|
||||||
|
next_index= idx + idx;
|
||||||
|
if (next_index < elements &&
|
||||||
|
queue->compare(queue->first_cmp_arg,
|
||||||
|
queue->root[next_index]+offset_to_key,
|
||||||
|
queue->root[next_index+1]+offset_to_key) *
|
||||||
|
queue->max_at_top > 0)
|
||||||
|
next_index++;
|
||||||
|
if (first &&
|
||||||
|
queue->compare(queue->first_cmp_arg,
|
||||||
|
queue->root[next_index]+offset_to_key,
|
||||||
|
element+offset_to_key) * queue->max_at_top >= 0)
|
||||||
|
{
|
||||||
|
queue->root[idx]= element;
|
||||||
|
if (offset_to_queue_pos)
|
||||||
|
(*(uint*) (element + offset_to_queue_pos-1))= idx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
first= FALSE;
|
||||||
|
queue->root[idx]= queue->root[next_index];
|
||||||
|
if (offset_to_queue_pos)
|
||||||
|
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
||||||
|
idx=next_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_at(queue, element, idx);
|
||||||
}
|
}
|
||||||
|
@ -1403,9 +1403,23 @@ unpack_fields(MYSQL *mysql, MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
|
|||||||
{
|
{
|
||||||
if (field - result >= (my_ptrdiff_t)fields)
|
if (field - result >= (my_ptrdiff_t)fields)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If any of the row->data[] below is NULL, it can result in a
|
||||||
|
crash. Error out early as it indicates a malformed packet.
|
||||||
|
For data[0], data[1] and data[5], strmake_root will handle
|
||||||
|
NULL values.
|
||||||
|
*/
|
||||||
|
if (!row->data[2] || !row->data[3] || !row->data[4])
|
||||||
|
{
|
||||||
|
free_rows(data);
|
||||||
|
set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
cli_fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5);
|
cli_fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5);
|
||||||
field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]);
|
field->org_table= field->table= strmake_root(alloc,(char*) row->data[0], lengths[0]);
|
||||||
field->name= strdup_root(alloc,(char*) row->data[1]);
|
field->name= strmake_root(alloc,(char*) row->data[1], lengths[1]);
|
||||||
field->length= (uint) uint3korr(row->data[2]);
|
field->length= (uint) uint3korr(row->data[2]);
|
||||||
field->type= (enum enum_field_types) (uchar) row->data[3][0];
|
field->type= (enum enum_field_types) (uchar) row->data[3][0];
|
||||||
|
|
||||||
@ -1430,7 +1444,7 @@ unpack_fields(MYSQL *mysql, MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
|
|||||||
field->flags|= NUM_FLAG;
|
field->flags|= NUM_FLAG;
|
||||||
if (default_value && row->data[5])
|
if (default_value && row->data[5])
|
||||||
{
|
{
|
||||||
field->def=strdup_root(alloc,(char*) row->data[5]);
|
field->def= strmake_root(alloc,(char*) row->data[5], lengths[5]);
|
||||||
field->def_length= lengths[5];
|
field->def_length= lengths[5];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Copyright (c) 2006, 2013, Oracle and/or its affiliates.
|
/* Copyright (c) 2006, 2019, Oracle and/or its affiliates.
|
||||||
|
Copyright (c) 2009, 2020, MariaDB Corporation
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -507,6 +508,7 @@ Event_scheduler::run(THD *thd)
|
|||||||
DBUG_PRINT("info", ("job_data is NULL, the thread was killed"));
|
DBUG_PRINT("info", ("job_data is NULL, the thread was killed"));
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("state=%s", scheduler_states_names[state].str));
|
DBUG_PRINT("info", ("state=%s", scheduler_states_names[state].str));
|
||||||
|
free_root(thd->mem_root, MYF(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK_DATA();
|
LOCK_DATA();
|
||||||
|
@ -358,9 +358,8 @@ QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index,
|
|||||||
uint mrr_buf_size, MEM_ROOT *alloc);
|
uint mrr_buf_size, MEM_ROOT *alloc);
|
||||||
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
|
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
|
||||||
bool index_read_must_be_used,
|
bool index_read_must_be_used,
|
||||||
bool update_tbl_stats,
|
bool for_range_access,
|
||||||
double read_time,
|
double read_time);
|
||||||
bool ror_scans_required);
|
|
||||||
static
|
static
|
||||||
TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree,
|
TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree,
|
||||||
double read_time);
|
double read_time);
|
||||||
@ -2599,7 +2598,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
|||||||
|
|
||||||
/* Get best 'range' plan and prepare data for making other plans */
|
/* Get best 'range' plan and prepare data for making other plans */
|
||||||
if ((range_trp= get_key_scans_params(¶m, tree, FALSE, TRUE,
|
if ((range_trp= get_key_scans_params(¶m, tree, FALSE, TRUE,
|
||||||
best_read_time, FALSE)))
|
best_read_time)))
|
||||||
{
|
{
|
||||||
best_trp= range_trp;
|
best_trp= range_trp;
|
||||||
best_read_time= best_trp->read_cost;
|
best_read_time= best_trp->read_cost;
|
||||||
@ -4686,7 +4685,6 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
|
|||||||
double roru_index_costs;
|
double roru_index_costs;
|
||||||
ha_rows roru_total_records;
|
ha_rows roru_total_records;
|
||||||
double roru_intersect_part= 1.0;
|
double roru_intersect_part= 1.0;
|
||||||
bool only_ror_scans_required= FALSE;
|
|
||||||
DBUG_ENTER("get_best_disjunct_quick");
|
DBUG_ENTER("get_best_disjunct_quick");
|
||||||
DBUG_PRINT("info", ("Full table scan cost: %g", read_time));
|
DBUG_PRINT("info", ("Full table scan cost: %g", read_time));
|
||||||
|
|
||||||
@ -4713,8 +4711,6 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
|
|||||||
n_child_scans)))
|
n_child_scans)))
|
||||||
DBUG_RETURN(NULL);
|
DBUG_RETURN(NULL);
|
||||||
|
|
||||||
only_ror_scans_required= !optimizer_flag(param->thd,
|
|
||||||
OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION);
|
|
||||||
/*
|
/*
|
||||||
Collect best 'range' scan for each of disjuncts, and, while doing so,
|
Collect best 'range' scan for each of disjuncts, and, while doing so,
|
||||||
analyze possibility of ROR scans. Also calculate some values needed by
|
analyze possibility of ROR scans. Also calculate some values needed by
|
||||||
@ -4727,8 +4723,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
|
|||||||
DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map,
|
DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map,
|
||||||
"tree in SEL_IMERGE"););
|
"tree in SEL_IMERGE"););
|
||||||
if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE,
|
if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE,
|
||||||
read_time,
|
read_time)))
|
||||||
only_ror_scans_required)))
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
One of index scans in this index_merge is more expensive than entire
|
One of index scans in this index_merge is more expensive than entire
|
||||||
@ -5048,9 +5043,12 @@ TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge,
|
|||||||
a random order
|
a random order
|
||||||
2. the functions that estimate the cost of a range scan and an
|
2. the functions that estimate the cost of a range scan and an
|
||||||
index merge retrievals are not well calibrated
|
index merge retrievals are not well calibrated
|
||||||
|
|
||||||
|
As the best range access has been already chosen it does not
|
||||||
|
make sense to evaluate the one obtained from a degenerated
|
||||||
|
index merge.
|
||||||
*/
|
*/
|
||||||
trp= get_key_scans_params(param, *imerge->trees, FALSE, TRUE,
|
trp= 0;
|
||||||
read_time, FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(trp);
|
DBUG_RETURN(trp);
|
||||||
@ -6777,9 +6775,9 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
|
|||||||
tree make range select for this SEL_TREE
|
tree make range select for this SEL_TREE
|
||||||
index_read_must_be_used if TRUE, assume 'index only' option will be set
|
index_read_must_be_used if TRUE, assume 'index only' option will be set
|
||||||
(except for clustered PK indexes)
|
(except for clustered PK indexes)
|
||||||
|
for_range_access if TRUE the function is called to get the best range
|
||||||
|
plan for range access, not for index merge access
|
||||||
read_time don't create read plans with cost > read_time.
|
read_time don't create read plans with cost > read_time.
|
||||||
only_ror_scans_required set to TRUE when we are only interested
|
|
||||||
in ROR scan
|
|
||||||
RETURN
|
RETURN
|
||||||
Best range read plan
|
Best range read plan
|
||||||
NULL if no plan found or error occurred
|
NULL if no plan found or error occurred
|
||||||
@ -6787,9 +6785,8 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
|
|||||||
|
|
||||||
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
|
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
|
||||||
bool index_read_must_be_used,
|
bool index_read_must_be_used,
|
||||||
bool update_tbl_stats,
|
bool for_range_access,
|
||||||
double read_time,
|
double read_time)
|
||||||
bool only_ror_scans_required)
|
|
||||||
{
|
{
|
||||||
uint idx, best_idx;
|
uint idx, best_idx;
|
||||||
SEL_ARG *key_to_read= NULL;
|
SEL_ARG *key_to_read= NULL;
|
||||||
@ -6834,10 +6831,11 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
|
|||||||
(bool) param->table->covering_keys.is_set(keynr);
|
(bool) param->table->covering_keys.is_set(keynr);
|
||||||
|
|
||||||
found_records= check_quick_select(param, idx, read_index_only, key,
|
found_records= check_quick_select(param, idx, read_index_only, key,
|
||||||
update_tbl_stats, &mrr_flags,
|
for_range_access, &mrr_flags,
|
||||||
&buf_size, &cost);
|
&buf_size, &cost);
|
||||||
|
|
||||||
if (only_ror_scans_required && !param->is_ror_scan)
|
if (!for_range_access && !param->is_ror_scan &&
|
||||||
|
!optimizer_flag(param->thd,OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION))
|
||||||
{
|
{
|
||||||
/* The scan is not a ROR-scan, just skip it */
|
/* The scan is not a ROR-scan, just skip it */
|
||||||
continue;
|
continue;
|
||||||
|
@ -4304,6 +4304,7 @@ connected:
|
|||||||
goto err;
|
goto err;
|
||||||
goto connected;
|
goto connected;
|
||||||
}
|
}
|
||||||
|
DBUG_EXECUTE_IF("fail_com_register_slave", goto err;);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_PRINT("info",("Starting reading binary log from master"));
|
DBUG_PRINT("info",("Starting reading binary log from master"));
|
||||||
|
@ -71,6 +71,7 @@
|
|||||||
#ifdef HAVE_SYS_SYSCALL_H
|
#ifdef HAVE_SYS_SYSCALL_H
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include "repl_failsafe.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following is used to initialise Table_ident with a internal
|
The following is used to initialise Table_ident with a internal
|
||||||
@ -1593,6 +1594,7 @@ THD::~THD()
|
|||||||
if (rgi_slave)
|
if (rgi_slave)
|
||||||
rgi_slave->cleanup_after_session();
|
rgi_slave->cleanup_after_session();
|
||||||
my_free(semisync_info);
|
my_free(semisync_info);
|
||||||
|
unregister_slave(this, true, true);
|
||||||
#endif
|
#endif
|
||||||
main_lex.free_set_stmt_mem_root();
|
main_lex.free_set_stmt_mem_root();
|
||||||
free_root(&main_mem_root, MYF(0));
|
free_root(&main_mem_root, MYF(0));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
|
/* Copyright (c) 2000, 2019, Oracle and/or its affiliates.
|
||||||
Copyright (c) 2009, 2018, MariaDB Corporation
|
Copyright (c) 2009, 2020, MariaDB Corporation
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -1181,17 +1181,27 @@ static inline uint int_token(const char *str,uint length)
|
|||||||
*/
|
*/
|
||||||
bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted)
|
bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted)
|
||||||
{
|
{
|
||||||
|
// only one level of nested comments are allowed
|
||||||
|
DBUG_ASSERT(remaining_recursions_permitted == 0 ||
|
||||||
|
remaining_recursions_permitted == 1);
|
||||||
uchar c;
|
uchar c;
|
||||||
while (! lip->eof())
|
while (! lip->eof())
|
||||||
{
|
{
|
||||||
c= lip->yyGet();
|
c= lip->yyGet();
|
||||||
|
|
||||||
if (remaining_recursions_permitted > 0)
|
if (remaining_recursions_permitted == 1)
|
||||||
{
|
{
|
||||||
if ((c == '/') && (lip->yyPeek() == '*'))
|
if ((c == '/') && (lip->yyPeek() == '*'))
|
||||||
{
|
{
|
||||||
|
lip->yyUnput('('); // Replace nested "/*..." with "(*..."
|
||||||
|
lip->yySkip(); // and skip "("
|
||||||
|
|
||||||
lip->yySkip(); /* Eat asterisk */
|
lip->yySkip(); /* Eat asterisk */
|
||||||
consume_comment(lip, remaining_recursions_permitted-1);
|
if (consume_comment(lip, 0))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
lip->yyUnput(')'); // Replace "...*/" with "...*)"
|
||||||
|
lip->yySkip(); // and skip ")"
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1739,7 +1739,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
general_log_print(thd, command, "Log: '%s' Pos: %lu", name, pos);
|
general_log_print(thd, command, "Log: '%s' Pos: %lu", name, pos);
|
||||||
if (nlen < FN_REFLEN)
|
if (nlen < FN_REFLEN)
|
||||||
mysql_binlog_send(thd, thd->strmake(name, nlen), (my_off_t)pos, flags);
|
mysql_binlog_send(thd, thd->strmake(name, nlen), (my_off_t)pos, flags);
|
||||||
unregister_slave(thd,1,1);
|
|
||||||
/* fake COM_QUIT -- if we get here, the thread needs to terminate */
|
/* fake COM_QUIT -- if we get here, the thread needs to terminate */
|
||||||
error = TRUE;
|
error = TRUE;
|
||||||
break;
|
break;
|
||||||
|
@ -170,9 +170,9 @@ if (NOT CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
|||||||
set_cflags_if_supported(-Wcast-align)
|
set_cflags_if_supported(-Wcast-align)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
## always want these in debug builds
|
## never want these
|
||||||
set(CMAKE_C_FLAGS_DEBUG "-Wall -Werror ${CMAKE_C_FLAGS_DEBUG}")
|
set(CMAKE_C_FLAGS "-Wno-error ${CMAKE_C_FLAGS}")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -Werror ${CMAKE_CXX_FLAGS_DEBUG}")
|
set(CMAKE_CXX_FLAGS "-Wno-error ${CMAKE_CXX_FLAGS}")
|
||||||
|
|
||||||
# pick language dialect
|
# pick language dialect
|
||||||
set(CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS}")
|
set(CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS}")
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
MY_ADD_TESTS(bitmap base64 my_atomic my_rdtsc lf my_malloc my_getopt dynstring
|
MY_ADD_TESTS(bitmap base64 my_atomic my_rdtsc lf my_malloc my_getopt dynstring
|
||||||
aes
|
aes
|
||||||
LINK_LIBRARIES mysys)
|
queues LINK_LIBRARIES mysys)
|
||||||
MY_ADD_TESTS(my_vsnprintf LINK_LIBRARIES strings mysys)
|
MY_ADD_TESTS(my_vsnprintf LINK_LIBRARIES strings mysys)
|
||||||
|
|
||||||
ADD_DEFINITIONS(${SSL_DEFINES})
|
ADD_DEFINITIONS(${SSL_DEFINES})
|
||||||
|
139
unittest/mysys/queues-t.c
Normal file
139
unittest/mysys/queues-t.c
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/* Copyright (c) 2020, MariaDB Corporation
|
||||||
|
|
||||||
|
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||||
|
|
||||||
|
#include <my_global.h>
|
||||||
|
#include <my_sys.h>
|
||||||
|
#include <queues.h>
|
||||||
|
#include <my_rnd.h>
|
||||||
|
#include "tap.h"
|
||||||
|
|
||||||
|
int cmp(void *arg __attribute__((unused)), uchar *a, uchar *b)
|
||||||
|
{
|
||||||
|
return *a < *b ? -1 : *a > *b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define rnd(R) ((uint)(my_rnd(R) * INT_MAX32))
|
||||||
|
|
||||||
|
#define el(Q,I) ((uint)*queue_element(Q, I))
|
||||||
|
|
||||||
|
my_bool verbose;
|
||||||
|
|
||||||
|
my_bool check_queue(QUEUE *queue)
|
||||||
|
{
|
||||||
|
char b[1024]={0}, *s, *e=b+sizeof(b)-2;
|
||||||
|
my_bool ok=1;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
s= b + my_snprintf(b, e-b, "%x", el(queue, 1));
|
||||||
|
for (i=2; i <= queue->elements; i++)
|
||||||
|
{
|
||||||
|
s+= my_snprintf(s, e-s, ", %x", el(queue, i));
|
||||||
|
ok &= el(queue, i) <= el(queue, i>>1);
|
||||||
|
}
|
||||||
|
if (!ok || verbose)
|
||||||
|
diag("%s", b);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc __attribute__((unused)), char *argv[])
|
||||||
|
{
|
||||||
|
QUEUE q, *queue=&q;
|
||||||
|
MY_INIT(argv[0]);
|
||||||
|
plan(19);
|
||||||
|
|
||||||
|
verbose=1;
|
||||||
|
|
||||||
|
init_queue(queue, 256, 0, 1, cmp, NULL, 0, 0);
|
||||||
|
queue_insert(queue, (uchar*)"\x99");
|
||||||
|
queue_insert(queue, (uchar*)"\x19");
|
||||||
|
queue_insert(queue, (uchar*)"\x36");
|
||||||
|
queue_insert(queue, (uchar*)"\x17");
|
||||||
|
queue_insert(queue, (uchar*)"\x12");
|
||||||
|
queue_insert(queue, (uchar*)"\x05");
|
||||||
|
queue_insert(queue, (uchar*)"\x25");
|
||||||
|
queue_insert(queue, (uchar*)"\x09");
|
||||||
|
queue_insert(queue, (uchar*)"\x15");
|
||||||
|
queue_insert(queue, (uchar*)"\x06");
|
||||||
|
queue_insert(queue, (uchar*)"\x11");
|
||||||
|
queue_insert(queue, (uchar*)"\x01");
|
||||||
|
queue_insert(queue, (uchar*)"\x04");
|
||||||
|
queue_insert(queue, (uchar*)"\x13");
|
||||||
|
queue_insert(queue, (uchar*)"\x24");
|
||||||
|
ok(check_queue(queue), "after insert");
|
||||||
|
queue_remove(queue, 5);
|
||||||
|
ok(check_queue(queue), "after remove 5th");
|
||||||
|
|
||||||
|
queue_element(queue, 1) = (uchar*)"\x01";
|
||||||
|
queue_element(queue, 2) = (uchar*)"\x10";
|
||||||
|
queue_element(queue, 3) = (uchar*)"\x04";
|
||||||
|
queue_element(queue, 4) = (uchar*)"\x09";
|
||||||
|
queue_element(queue, 5) = (uchar*)"\x13";
|
||||||
|
queue_element(queue, 6) = (uchar*)"\x03";
|
||||||
|
queue_element(queue, 7) = (uchar*)"\x08";
|
||||||
|
queue_element(queue, 8) = (uchar*)"\x07";
|
||||||
|
queue_element(queue, 9) = (uchar*)"\x06";
|
||||||
|
queue_element(queue,10) = (uchar*)"\x12";
|
||||||
|
queue_element(queue,11) = (uchar*)"\x05";
|
||||||
|
queue_element(queue,12) = (uchar*)"\x02";
|
||||||
|
queue_element(queue,13) = (uchar*)"\x11";
|
||||||
|
queue->elements= 13;
|
||||||
|
ok(!check_queue(queue), "manually filled (queue property violated)");
|
||||||
|
|
||||||
|
queue_fix(queue);
|
||||||
|
ok(check_queue(queue), "fixed");
|
||||||
|
|
||||||
|
ok(*queue_remove_top(queue) == 0x13, "remove top 13");
|
||||||
|
ok(*queue_remove_top(queue) == 0x12, "remove top 12");
|
||||||
|
ok(*queue_remove_top(queue) == 0x11, "remove top 11");
|
||||||
|
ok(*queue_remove_top(queue) == 0x10, "remove top 10");
|
||||||
|
ok(*queue_remove_top(queue) == 0x09, "remove top 9");
|
||||||
|
ok(*queue_remove_top(queue) == 0x08, "remove top 8");
|
||||||
|
ok(*queue_remove_top(queue) == 0x07, "remove top 7");
|
||||||
|
ok(*queue_remove_top(queue) == 0x06, "remove top 6");
|
||||||
|
ok(*queue_remove_top(queue) == 0x05, "remove top 5");
|
||||||
|
ok(*queue_remove_top(queue) == 0x04, "remove top 4");
|
||||||
|
ok(*queue_remove_top(queue) == 0x03, "remove top 3");
|
||||||
|
ok(*queue_remove_top(queue) == 0x02, "remove top 2");
|
||||||
|
ok(*queue_remove_top(queue) == 0x01, "remove top 1");
|
||||||
|
|
||||||
|
/* random test */
|
||||||
|
{
|
||||||
|
int i, res;
|
||||||
|
struct my_rnd_struct rand;
|
||||||
|
my_rnd_init(&rand, (ulong)(intptr)&i, (ulong)(intptr)argv);
|
||||||
|
verbose=0;
|
||||||
|
|
||||||
|
for (res= i=1; i <= 250; i++)
|
||||||
|
{
|
||||||
|
uchar *s=alloca(2);
|
||||||
|
*s= rnd(&rand) % 251;
|
||||||
|
queue_insert(queue, s);
|
||||||
|
res &= check_queue(queue);
|
||||||
|
}
|
||||||
|
ok(res, "inserted 250");
|
||||||
|
|
||||||
|
while (queue->elements)
|
||||||
|
{
|
||||||
|
queue_remove(queue, (rnd(&rand) % queue->elements) + 1);
|
||||||
|
res &= check_queue(queue);
|
||||||
|
}
|
||||||
|
ok(res, "removed 250");
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_queue(queue);
|
||||||
|
my_end(0);
|
||||||
|
return exit_status();
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user