Improved speed of thr_alarm from O(N) to O(1). thr_alarm is used to handle timeouts and kill of connections.

Fixed compiler warnings.
queues.h and queues.c are now based on the UNIREG code and thus made BSD.
Fix code to use new queue() interface. This mostly affects how you access elements in the queue.
If USE_NET_CLEAR is not set, don't clear connection from unexpected characters. This should give a speed up when doing a lot of fast queries.
Fixed some code in ma_ft_boolean_search.c that had not made it from myisam/ft_boolean_search.c


include/queues.h:
  Use UNIREG code base (BSD)
  Changed init_queue() to take all initialization arguments.
  New interface to access elements in queue
include/thr_alarm.h:
  Changed to use time_t instead of ulong (portability)
  Added index_in_queue, to be able to remove random element from queue in O(1)
mysys/queues.c:
  Use UNIREG code base (BSD)
  init_queue() and reinit_queue() now takes more initialization arguments. (No need for init_queue_ex() anymore)
  Now one can tell queue_insert() to store in the element a pointer to where element is in queue. This allows one to remove elements from queue in O(1) instead of O(N)
mysys/thr_alarm.c:
  Use new option in queue() to allow fast removal of elements.
  Do less inside LOCK_alarm mutex.
  This should give a major speed up of thr_alarm usage when there is many threads
sql/create_options.cc:
  Fixed wrong printf
sql/event_queue.cc:
  Use new queue interface()
sql/filesort.cc:
  Use new queue interface()
sql/ha_partition.cc:
  Use new queue interface()
sql/ha_partition.h:
  Fixed compiler warning
sql/item_cmpfunc.cc:
  Fixed compiler warning
sql/item_subselect.cc:
  Use new queue interface()
  Removed not used variable
sql/net_serv.cc:
  If USE_NET_CLEAR is not set, don't clear connection from unexpected characters.
  This should give a speed up when doing a lot of fast queries at the disadvantage that if there is a bug in the client protocol the connection will be dropped instead of being unnoticed.
sql/opt_range.cc:
  Use new queue interface()
  Fixed compiler warnings
sql/uniques.cc:
  Use new queue interface()
storage/maria/ma_ft_boolean_search.c:
  Copy code from myisam/ft_boolean_search.c
  Use new queue interface()
storage/maria/ma_ft_nlq_search.c:
  Use new queue interface()
storage/maria/ma_sort.c:
  Use new queue interface()
storage/maria/maria_pack.c:
  Use new queue interface()
  Use queue_fix() instead of own loop to fix queue.
storage/myisam/ft_boolean_search.c:
  Use new queue interface()
storage/myisam/ft_nlq_search.c:
  Use new queue interface()
storage/myisam/mi_test_all.sh:
  Remove temporary file from last run
storage/myisam/myisampack.c:
  Use new queue interface()
  Use queue_fix() instead of own loop to fix queue.
storage/myisam/sort.c:
  Use new queue interface()
storage/myisammrg/myrg_queue.c:
  Use new queue interface()
storage/myisammrg/myrg_rnext.c:
  Use new queue interface()
storage/myisammrg/myrg_rnext_same.c:
  Use new queue interface()
storage/myisammrg/myrg_rprev.c:
  Use new queue interface()
This commit is contained in:
Michael Widenius 2010-07-16 10:33:01 +03:00
parent ceb5468fd8
commit ecbcddc03d
28 changed files with 405 additions and 754 deletions

View File

@ -1940,3 +1940,4 @@ sql/client_plugin.c
*.dgcov *.dgcov
libmysqld/create_options.cc libmysqld/create_options.cc
storage/pbxt/bin/xtstat storage/pbxt/bin/xtstat
libmysqld/sql_expression_cache.cc

View File

@ -1,23 +1,31 @@
/* Copyright (C) 2000 MySQL AB /* Copyright (C) 2010 Monty Program Ab
All Rights reserved
This program is free software; you can redistribute it and/or modify Redistribution and use in source and binary forms, with or without
it under the terms of the GNU General Public License as published by modification, are permitted provided that the following conditions are met:
the Free Software Foundation; version 2 of the License. * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the following disclaimer
in the documentation and/or other materials provided with the
distribution.
This program is distributed in the hope that it will be useful, THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
but WITHOUT ANY WARRANTY; without even the implied warranty of "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
GNU General Public License for more details. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
<COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
You should have received a copy of the GNU General Public License SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
along with this program; if not, write to the Free Software LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* /*
Code for generell handling of priority Queues. Code for generell handling of priority Queues.
Implemention of queues from "Algoritms in C" by Robert Sedgewick. Implemention of queues from "Algoritms in C" by Robert Sedgewick.
Copyright Monty Program KB.
By monty.
*/ */
#ifndef _queues_h #ifndef _queues_h
@ -31,30 +39,34 @@ typedef struct st_queue {
void *first_cmp_arg; void *first_cmp_arg;
uint elements; uint elements;
uint max_elements; uint max_elements;
uint offset_to_key; /* compare is done on element+offset */ uint offset_to_key; /* compare is done on element+offset */
uint offset_to_queue_pos; /* If we want to store position in element */
uint auto_extent;
int max_at_top; /* Normally 1, set to -1 if queue_top gives max */ int max_at_top; /* Normally 1, set to -1 if queue_top gives max */
int (*compare)(void *, uchar *,uchar *); int (*compare)(void *, uchar *,uchar *);
uint auto_extent;
} QUEUE; } QUEUE;
#define queue_first_element(queue) 1
#define queue_last_element(queue) (queue)->elements
#define queue_top(queue) ((queue)->root[1]) #define queue_top(queue) ((queue)->root[1])
#define queue_element(queue,index) ((queue)->root[index+1]) #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_replaced(queue) _downheap(queue,1) #define queue_replace(queue, idx) _downheap(queue, idx, (queue)->root[idx])
#define queue_replace_top(queue) _downheap(queue, 1, (queue)->root[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
#define queue_remove_top(queue_arg) queue_remove((queue_arg), queue_first_element(queue_arg))
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, pbool max_at_top, queue_compare compare,
void *first_cmp_arg); void *first_cmp_arg, uint offset_to_queue_pos,
int init_queue_ex(QUEUE *queue,uint max_elements,uint offset_to_key, uint auto_extent);
pbool max_at_top, queue_compare compare,
void *first_cmp_arg, 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, pbool max_at_top, queue_compare compare,
void *first_cmp_arg); void *first_cmp_arg, uint offset_to_queue_pos,
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);
@ -62,7 +74,7 @@ int queue_insert_safe(QUEUE *queue, uchar *element);
uchar *queue_remove(QUEUE *queue,uint idx); uchar *queue_remove(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); void _downheap(QUEUE *queue, uint idx, uchar *element);
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)

View File

@ -34,7 +34,7 @@ extern "C" {
typedef struct st_alarm_info typedef struct st_alarm_info
{ {
ulong next_alarm_time; time_t next_alarm_time;
uint active_alarms; uint active_alarms;
uint max_used_alarms; uint max_used_alarms;
} ALARM_INFO; } ALARM_INFO;
@ -78,10 +78,11 @@ typedef int thr_alarm_entry;
typedef thr_alarm_entry* thr_alarm_t; typedef thr_alarm_entry* thr_alarm_t;
typedef struct st_alarm { typedef struct st_alarm {
ulong expire_time; time_t expire_time;
thr_alarm_entry alarmed; /* set when alarm is due */ thr_alarm_entry alarmed; /* set when alarm is due */
pthread_t thread; pthread_t thread;
my_thread_id thread_id; my_thread_id thread_id;
uint index_in_queue;
my_bool malloced; my_bool malloced;
} ALARM; } ALARM;

View File

@ -1,25 +1,42 @@
/* Copyright (C) 2000, 2005 MySQL AB /* Copyright (C) 2010 Monty Program Ab
All Rights reserved
This program is free software; you can redistribute it and/or modify Redistribution and use in source and binary forms, with or without
it under the terms of the GNU General Public License as published by modification, are permitted provided that the following conditions are met:
the Free Software Foundation; version 2 of the License. * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the following disclaimer
in the documentation and/or other materials provided with the
distribution.
This program is distributed in the hope that it will be useful, THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
but WITHOUT ANY WARRANTY; without even the implied warranty of "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
GNU General Public License for more details. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
<COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
You should have received a copy of the GNU General Public License SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
along with this program; if not, write to the Free Software LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* /*
This code originates from the Unireg project.
Code for generell handling of priority Queues. Code for generell handling of priority Queues.
Implemention of queues from "Algoritms in C" by Robert Sedgewick. Implemention of queues from "Algoritms in C" by Robert Sedgewick.
An optimisation of _downheap suggested in Exercise 7.51 in "Data
Structures & Algorithms in C++" by Mark Allen Weiss, Second Edition The queue can optionally store the position in queue in the element
was implemented by Mikael Ronstrom 2005. Also the O(N) algorithm that is in the queue. This allows one to remove any element from the queue
of queue_fix was implemented. in O(1) time.
Optimisation of _downheap() and queue_fix() is inspired by code done
by Mikael Ronström, based on an optimisation of _downheap from
Exercise 7.51 in "Data Structures & Algorithms in C++" by Mark Allen
Weiss, Second Edition.
*/ */
#include "mysys_priv.h" #include "mysys_priv.h"
@ -39,47 +56,8 @@
max_at_top Set to 1 if you want biggest element on top. max_at_top Set to 1 if you want biggest element on top.
compare Compare function for elements, takes 3 arguments. compare Compare function for elements, takes 3 arguments.
first_cmp_arg First argument to compare function first_cmp_arg First argument to compare function
offset_to_queue_pos If <> 0, then offset+1 in element to store position
NOTES in queue (for fast delete of element in queue)
Will allocate max_element pointers for queue array
RETURN
0 ok
1 Could not allocate memory
*/
int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
pbool max_at_top, int (*compare) (void *, uchar *, uchar *),
void *first_cmp_arg)
{
DBUG_ENTER("init_queue");
if ((queue->root= (uchar **) my_malloc((max_elements+1)*sizeof(void*),
MYF(MY_WME))) == 0)
DBUG_RETURN(1);
queue->elements=0;
queue->compare=compare;
queue->first_cmp_arg=first_cmp_arg;
queue->max_elements=max_elements;
queue->offset_to_key=offset_to_key;
queue_set_max_at_top(queue, max_at_top);
DBUG_RETURN(0);
}
/*
Init queue, uses init_queue internally for init work but also accepts
auto_extent as parameter
SYNOPSIS
init_queue_ex()
queue Queue to initialise
max_elements Max elements that will be put in queue
offset_to_key Offset to key in element stored in queue
Used when sending pointers to compare function
max_at_top Set to 1 if you want biggest element on top.
compare Compare function for elements, takes 3 arguments.
first_cmp_arg First argument to compare function
auto_extent When the queue is full and there is insert operation auto_extent When the queue is full and there is insert operation
extend the queue. extend the queue.
@ -91,33 +69,35 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
1 Could not allocate memory 1 Could not allocate memory
*/ */
int init_queue_ex(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 *), pbool max_at_top, int (*compare) (void *, uchar *, uchar *),
void *first_cmp_arg, uint auto_extent) void *first_cmp_arg, uint offset_to_queue_pos,
uint auto_extent)
{ {
int ret; DBUG_ENTER("init_queue");
DBUG_ENTER("init_queue_ex"); if ((queue->root= (uchar **) my_malloc((max_elements + 1) * sizeof(void*),
MYF(MY_WME))) == 0)
if ((ret= init_queue(queue, max_elements, offset_to_key, max_at_top, compare, DBUG_RETURN(1);
first_cmp_arg))) queue->elements= 0;
DBUG_RETURN(ret); queue->compare= compare;
queue->first_cmp_arg= first_cmp_arg;
queue->auto_extent= auto_extent; queue->max_elements= max_elements;
queue->offset_to_key= offset_to_key;
queue->offset_to_queue_pos= offset_to_queue_pos;
queue->auto_extent= auto_extent;
queue_set_max_at_top(queue, max_at_top);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/* /*
Reinitialize queue for other usage Reinitialize queue for other usage
SYNOPSIS SYNOPSIS
reinit_queue() reinit_queue()
queue Queue to initialise queue Queue to initialise
max_elements Max elements that will be put in queue For rest of arguments, see init_queue() above
offset_to_key Offset to key in element stored in queue
Used when sending pointers to compare function
max_at_top Set to 1 if you want biggest element on top.
compare Compare function for elements, takes 3 arguments.
first_cmp_arg First argument to compare function
NOTES NOTES
This will delete all elements from the queue. If you don't want this, This will delete all elements from the queue. If you don't want this,
@ -125,21 +105,23 @@ int init_queue_ex(QUEUE *queue, uint max_elements, uint offset_to_key,
RETURN RETURN
0 ok 0 ok
EE_OUTOFMEMORY Wrong max_elements 1 Wrong max_elements; Queue has old size
*/ */
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 *), pbool max_at_top, int (*compare) (void *, uchar *, uchar *),
void *first_cmp_arg) void *first_cmp_arg, uint offset_to_queue_pos,
uint auto_extent)
{ {
DBUG_ENTER("reinit_queue"); DBUG_ENTER("reinit_queue");
queue->elements=0; queue->elements= 0;
queue->compare=compare; queue->compare= compare;
queue->first_cmp_arg=first_cmp_arg; queue->first_cmp_arg= first_cmp_arg;
queue->offset_to_key=offset_to_key; queue->offset_to_key= offset_to_key;
queue->offset_to_queue_pos= offset_to_queue_pos;
queue->auto_extent= auto_extent;
queue_set_max_at_top(queue, max_at_top); queue_set_max_at_top(queue, max_at_top);
resize_queue(queue, max_elements); DBUG_RETURN(resize_queue(queue, max_elements));
DBUG_RETURN(0);
} }
@ -167,8 +149,8 @@ int resize_queue(QUEUE *queue, uint max_elements)
if (queue->max_elements == max_elements) if (queue->max_elements == max_elements)
DBUG_RETURN(0); DBUG_RETURN(0);
if ((new_root= (uchar **) my_realloc((void *)queue->root, if ((new_root= (uchar **) my_realloc((void *)queue->root,
(max_elements+1)*sizeof(void*), (max_elements + 1)* sizeof(void*),
MYF(MY_WME))) == 0) MYF(MY_WME))) == 0)
DBUG_RETURN(1); DBUG_RETURN(1);
set_if_smaller(queue->elements, max_elements); set_if_smaller(queue->elements, max_elements);
queue->max_elements= max_elements; queue->max_elements= max_elements;
@ -197,39 +179,58 @@ void delete_queue(QUEUE *queue)
if (queue->root) if (queue->root)
{ {
my_free((uchar*) queue->root,MYF(0)); my_free((uchar*) queue->root,MYF(0));
queue->root=0; queue->root=0; /* Allow multiple calls */
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/* Code for insert, search and delete of elements */ /*
Insert element in queue
SYNOPSIS
queue_insert()
queue Queue to use
element Element to insert
*/
void queue_insert(register QUEUE *queue, uchar *element) void queue_insert(register QUEUE *queue, uchar *element)
{ {
reg2 uint idx, next; 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);
queue->root[0]= element;
idx= ++queue->elements; idx= ++queue->elements;
/* max_at_top swaps the comparison if we want to order by desc */ /* max_at_top swaps the comparison if we want to order by desc */
while ((queue->compare(queue->first_cmp_arg, while (idx > 1 &&
(queue->compare(queue->first_cmp_arg,
element + queue->offset_to_key, element + queue->offset_to_key,
queue->root[(next= idx >> 1)] + queue->root[(next= idx >> 1)] +
queue->offset_to_key) * queue->max_at_top) < 0) queue->offset_to_key) * queue->max_at_top) < 0)
{ {
queue->root[idx]= queue->root[next]; queue->root[idx]= queue->root[next];
if (offset_to_queue_pos)
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
idx= next; idx= next;
} }
queue->root[idx]= element; queue->root[idx]= element;
if (offset_to_queue_pos)
(*(uint*) (element+ offset_to_queue_pos-1))= idx;
} }
/* /*
Does safe insert. If no more space left on the queue resize it. Like queue_insert, but resize queue if queue is full
Return codes:
0 - OK SYNOPSIS
1 - Cannot allocate more memory queue_insert_safe()
2 - auto_extend is 0, the operation would queue Queue to use
element Element to insert
RETURN
0 OK
1 Cannot allocate more memory
2 auto_extend is 0; No insertion done
*/ */
int queue_insert_safe(register QUEUE *queue, uchar *element) int queue_insert_safe(register QUEUE *queue, uchar *element)
@ -239,7 +240,7 @@ int queue_insert_safe(register QUEUE *queue, uchar *element)
{ {
if (!queue->auto_extent) if (!queue->auto_extent)
return 2; return 2;
else if (resize_queue(queue, queue->max_elements + queue->auto_extent)) if (resize_queue(queue, queue->max_elements + queue->auto_extent))
return 1; return 1;
} }
@ -248,40 +249,48 @@ int queue_insert_safe(register QUEUE *queue, uchar *element)
} }
/* Remove item from queue */ /*
/* Returns pointer to removed element */ Remove item from queue
SYNOPSIS
queue_remove()
queue Queue to use
element Index of element to remove.
First element in queue is 'queue_first_element(queue)'
RETURN
pointer to removed element
*/
uchar *queue_remove(register QUEUE *queue, uint idx) uchar *queue_remove(register QUEUE *queue, uint idx)
{ {
uchar *element; uchar *element;
DBUG_ASSERT(idx < queue->max_elements); DBUG_ASSERT(idx >= 1 && idx <= queue->elements);
element= queue->root[++idx]; /* Intern index starts from 1 */ element= queue->root[idx];
queue->root[idx]= queue->root[queue->elements--]; _downheap(queue, idx, queue->root[queue->elements--]);
_downheap(queue, idx);
return element; return element;
} }
/* Fix when element on top has been replaced */
#ifndef queue_replaced /*
void queue_replaced(QUEUE *queue) Add element to fixed position and update heap
SYNOPSIS
_downheap()
queue Queue to use
idx Index of element to change
element Element to store at 'idx'
*/
void _downheap(register QUEUE *queue, uint start_idx, uchar *element)
{ {
_downheap(queue,1); uint elements,half_queue,offset_to_key, next_index, offset_to_queue_pos;
} register uint idx= start_idx;
#endif
#ifndef OLD_VERSION
void _downheap(register QUEUE *queue, uint idx)
{
uchar *element;
uint elements,half_queue,offset_to_key, next_index;
my_bool first= TRUE; my_bool first= TRUE;
uint start_idx= idx;
offset_to_key=queue->offset_to_key; offset_to_key=queue->offset_to_key;
element=queue->root[idx]; offset_to_queue_pos= queue->offset_to_queue_pos;
half_queue=(elements=queue->elements) >> 1; half_queue= (elements= queue->elements) >> 1;
while (idx <= half_queue) while (idx <= half_queue)
{ {
@ -298,393 +307,49 @@ void _downheap(register QUEUE *queue, uint idx)
element+offset_to_key) * queue->max_at_top) >= 0))) element+offset_to_key) * queue->max_at_top) >= 0)))
{ {
queue->root[idx]= element; queue->root[idx]= element;
if (offset_to_queue_pos)
(*(uint*) (element + offset_to_queue_pos-1))= idx;
return; return;
} }
queue->root[idx]=queue->root[next_index];
idx=next_index;
first= FALSE; first= FALSE;
} queue->root[idx]= queue->root[next_index];
if (offset_to_queue_pos)
next_index= idx >> 1; (*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
while (next_index > start_idx)
{
if ((queue->compare(queue->first_cmp_arg,
queue->root[next_index]+offset_to_key,
element+offset_to_key) *
queue->max_at_top) < 0)
break;
queue->root[idx]=queue->root[next_index];
idx=next_index; idx=next_index;
next_index= idx >> 1;
} }
queue->root[idx]=element;
}
#else
/* /*
The old _downheap version is kept for comparisons with the benchmark Insert the element into the right position. This is the same code
suit or new benchmarks anyone wants to run for comparisons. as we have in queue_insert()
*/ */
/* Fix heap when index have changed */ while ((next_index= (idx >> 1)) > start_idx &&
void _downheap(register QUEUE *queue, uint idx) queue->compare(queue->first_cmp_arg,
{ element+offset_to_key,
uchar *element; queue->root[next_index]+offset_to_key)*
uint elements,half_queue,next_index,offset_to_key; queue->max_at_top < 0)
offset_to_key=queue->offset_to_key;
element=queue->root[idx];
half_queue=(elements=queue->elements) >> 1;
while (idx <= half_queue)
{ {
next_index=idx+idx; queue->root[idx]= queue->root[next_index];
if (next_index < elements && if (offset_to_queue_pos)
(queue->compare(queue->first_cmp_arg, (*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
queue->root[next_index]+offset_to_key, idx= next_index;
queue->root[next_index+1]+offset_to_key) *
queue->max_at_top) > 0)
next_index++;
if ((queue->compare(queue->first_cmp_arg,
queue->root[next_index]+offset_to_key,
element+offset_to_key) * queue->max_at_top) >= 0)
break;
queue->root[idx]=queue->root[next_index];
idx=next_index;
} }
queue->root[idx]=element; queue->root[idx]= element;
if (offset_to_queue_pos)
(*(uint*) (element + offset_to_queue_pos-1))= idx;
} }
#endif
/* /*
Fix heap when every element was changed. Fix heap when every element was changed.
SYNOPSIS
queue_fix()
queue Queue to use
*/ */
void queue_fix(QUEUE *queue) 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); _downheap(queue, i, queue_element(queue, i));
} }
#ifdef MAIN
/*
A test program for the priority queue implementation.
It can also be used to benchmark changes of the implementation
Build by doing the following in the directory mysys
make test_priority_queue
./test_priority_queue
Written by Mikael Ronström, 2005
*/
static uint num_array[1025];
static uint tot_no_parts= 0;
static uint tot_no_loops= 0;
static uint expected_part= 0;
static uint expected_num= 0;
static bool max_ind= 0;
static bool fix_used= 0;
static ulonglong start_time= 0;
static bool is_divisible_by(uint num, uint divisor)
{
uint quotient= num / divisor;
if (quotient * divisor == num)
return TRUE;
return FALSE;
}
void calculate_next()
{
uint part= expected_part, num= expected_num;
uint no_parts= tot_no_parts;
if (max_ind)
{
do
{
while (++part <= no_parts)
{
if (is_divisible_by(num, part) &&
(num <= ((1 << 21) + part)))
{
expected_part= part;
expected_num= num;
return;
}
}
part= 0;
} while (--num);
}
else
{
do
{
while (--part > 0)
{
if (is_divisible_by(num, part))
{
expected_part= part;
expected_num= num;
return;
}
}
part= no_parts + 1;
} while (++num);
}
}
void calculate_end_next(uint part)
{
uint no_parts= tot_no_parts, num;
num_array[part]= 0;
if (max_ind)
{
expected_num= 0;
for (part= no_parts; part > 0 ; part--)
{
if (num_array[part])
{
num= num_array[part] & 0x3FFFFF;
if (num >= expected_num)
{
expected_num= num;
expected_part= part;
}
}
}
if (expected_num == 0)
expected_part= 0;
}
else
{
expected_num= 0xFFFFFFFF;
for (part= 1; part <= no_parts; part++)
{
if (num_array[part])
{
num= num_array[part] & 0x3FFFFF;
if (num <= expected_num)
{
expected_num= num;
expected_part= part;
}
}
}
if (expected_num == 0xFFFFFFFF)
expected_part= 0;
}
return;
}
static int test_compare(void *null_arg, uchar *a, uchar *b)
{
uint a_num= (*(uint*)a) & 0x3FFFFF;
uint b_num= (*(uint*)b) & 0x3FFFFF;
uint a_part, b_part;
if (a_num > b_num)
return +1;
if (a_num < b_num)
return -1;
a_part= (*(uint*)a) >> 22;
b_part= (*(uint*)b) >> 22;
if (a_part < b_part)
return +1;
if (a_part > b_part)
return -1;
return 0;
}
bool check_num(uint num_part)
{
uint part= num_part >> 22;
uint num= num_part & 0x3FFFFF;
if (part == expected_part)
if (num == expected_num)
return FALSE;
printf("Expect part %u Expect num 0x%x got part %u num 0x%x max_ind %u fix_used %u \n",
expected_part, expected_num, part, num, max_ind, fix_used);
return TRUE;
}
void perform_insert(QUEUE *queue)
{
uint i= 1, no_parts= tot_no_parts;
uint backward_start= 0;
expected_part= 1;
expected_num= 1;
if (max_ind)
backward_start= 1 << 21;
do
{
uint num= (i + backward_start);
if (max_ind)
{
while (!is_divisible_by(num, i))
num--;
if (max_ind && (num > expected_num ||
(num == expected_num && i < expected_part)))
{
expected_num= num;
expected_part= i;
}
}
num_array[i]= num + (i << 22);
if (fix_used)
queue_element(queue, i-1)= (uchar*)&num_array[i];
else
queue_insert(queue, (uchar*)&num_array[i]);
} while (++i <= no_parts);
if (fix_used)
{
queue->elements= no_parts;
queue_fix(queue);
}
}
bool perform_ins_del(QUEUE *queue, bool max_ind)
{
uint i= 0, no_loops= tot_no_loops, j= tot_no_parts;
do
{
uint num_part= *(uint*)queue_top(queue);
uint part= num_part >> 22;
if (check_num(num_part))
return TRUE;
if (j++ >= no_loops)
{
calculate_end_next(part);
queue_remove(queue, (uint) 0);
}
else
{
calculate_next();
if (max_ind)
num_array[part]-= part;
else
num_array[part]+= part;
queue_top(queue)= (uchar*)&num_array[part];
queue_replaced(queue);
}
} while (++i < no_loops);
return FALSE;
}
bool do_test(uint no_parts, uint l_max_ind, bool l_fix_used)
{
QUEUE queue;
bool result;
max_ind= l_max_ind;
fix_used= l_fix_used;
init_queue(&queue, no_parts, 0, max_ind, test_compare, NULL);
tot_no_parts= no_parts;
tot_no_loops= 1024;
perform_insert(&queue);
if ((result= perform_ins_del(&queue, max_ind)))
delete_queue(&queue);
if (result)
{
printf("Error\n");
return TRUE;
}
return FALSE;
}
static void start_measurement()
{
start_time= my_getsystime();
}
static void stop_measurement()
{
ulonglong stop_time= my_getsystime();
uint time_in_micros;
stop_time-= start_time;
stop_time/= 10; /* Convert to microseconds */
time_in_micros= (uint)stop_time;
printf("Time expired is %u microseconds \n", time_in_micros);
}
static void benchmark_test()
{
QUEUE queue_real;
QUEUE *queue= &queue_real;
uint i, add;
fix_used= TRUE;
max_ind= FALSE;
tot_no_parts= 1024;
init_queue(queue, tot_no_parts, 0, max_ind, test_compare, NULL);
/*
First benchmark whether queue_fix is faster than using queue_insert
for sizes of 16 partitions.
*/
for (tot_no_parts= 2, add=2; tot_no_parts < 128;
tot_no_parts+= add, add++)
{
printf("Start benchmark queue_fix, tot_no_parts= %u \n", tot_no_parts);
start_measurement();
for (i= 0; i < 128; i++)
{
perform_insert(queue);
queue_remove_all(queue);
}
stop_measurement();
fix_used= FALSE;
printf("Start benchmark queue_insert\n");
start_measurement();
for (i= 0; i < 128; i++)
{
perform_insert(queue);
queue_remove_all(queue);
}
stop_measurement();
}
/*
Now benchmark insertion and deletion of 16400 elements.
Used in consecutive runs this shows whether the optimised _downheap
is faster than the standard implementation.
*/
printf("Start benchmarking _downheap \n");
start_measurement();
perform_insert(queue);
for (i= 0; i < 65536; i++)
{
uint num, part;
num= *(uint*)queue_top(queue);
num+= 16;
part= num >> 22;
num_array[part]= num;
queue_top(queue)= (uchar*)&num_array[part];
queue_replaced(queue);
}
for (i= 0; i < 16; i++)
queue_remove(queue, (uint) 0);
queue_remove_all(queue);
stop_measurement();
}
int main()
{
int i, add= 1;
for (i= 1; i < 1024; i+=add, add++)
{
printf("Start test for priority queue of size %u\n", i);
if (do_test(i, 0, 1))
return -1;
if (do_test(i, 1, 1))
return -1;
if (do_test(i, 0, 0))
return -1;
if (do_test(i, 1, 0))
return -1;
}
benchmark_test();
printf("OK\n");
return 0;
}
#endif

View File

@ -41,6 +41,19 @@ volatile my_bool alarm_thread_running= 0;
time_t next_alarm_expire_time= ~ (time_t) 0; time_t next_alarm_expire_time= ~ (time_t) 0;
static sig_handler process_alarm_part2(int sig); static sig_handler process_alarm_part2(int sig);
#ifdef DBUG_OFF
#define reset_index_in_queue(alarm_data)
#else
#define reset_index_in_queue(alarm_data) alarm_data->index_in_queue= 0;
#endif /* DBUG_OFF */
#ifndef USE_ONE_SIGNAL_HAND
#define one_signal_hand_sigmask(A,B,C) pthread_sigmask((A), (B), (C))
#else
#define one_signal_hand_sigmask(A,B,C)
#endif
#if !defined(__WIN__) #if !defined(__WIN__)
static pthread_mutex_t LOCK_alarm; static pthread_mutex_t LOCK_alarm;
@ -72,8 +85,8 @@ void init_thr_alarm(uint max_alarms)
DBUG_ENTER("init_thr_alarm"); DBUG_ENTER("init_thr_alarm");
alarm_aborted=0; alarm_aborted=0;
next_alarm_expire_time= ~ (time_t) 0; next_alarm_expire_time= ~ (time_t) 0;
init_queue(&alarm_queue,max_alarms+1,offsetof(ALARM,expire_time),0, init_queue(&alarm_queue, max_alarms+1, offsetof(ALARM,expire_time), 0,
compare_ulong,NullS); compare_ulong, NullS, offsetof(ALARM, index_in_queue)+1, 0);
sigfillset(&full_signal_set); /* Neaded to block signals */ sigfillset(&full_signal_set); /* Neaded to block signals */
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
pthread_cond_init(&COND_alarm,NULL); pthread_cond_init(&COND_alarm,NULL);
@ -151,7 +164,7 @@ void resize_thr_alarm(uint max_alarms)
my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
{ {
time_t now; time_t now, next;
#ifndef USE_ONE_SIGNAL_HAND #ifndef USE_ONE_SIGNAL_HAND
sigset_t old_mask; sigset_t old_mask;
#endif #endif
@ -161,79 +174,68 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
DBUG_PRINT("enter",("thread: %s sec: %d",my_thread_name(),sec)); DBUG_PRINT("enter",("thread: %s sec: %d",my_thread_name(),sec));
now= my_time(0); now= my_time(0);
#ifndef USE_ONE_SIGNAL_HAND if (!alarm_data)
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); {
#endif if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME))))
goto abort_no_unlock;
alarm_data->malloced= 1;
}
else
alarm_data->malloced= 0;
next= now + sec;
alarm_data->expire_time= next;
alarm_data->alarmed= 0;
alarm_data->thread= current_my_thread_var->pthread_self;
alarm_data->thread_id= current_my_thread_var->id;
one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */
if (alarm_aborted > 0) if (unlikely(alarm_aborted))
{ /* No signal thread */ { /* No signal thread */
DBUG_PRINT("info", ("alarm aborted")); DBUG_PRINT("info", ("alarm aborted"));
*alrm= 0; /* No alarm */ if (alarm_aborted > 0)
pthread_mutex_unlock(&LOCK_alarm); goto abort;
#ifndef USE_ONE_SIGNAL_HAND
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
#endif
DBUG_RETURN(1);
}
if (alarm_aborted < 0)
sec= 1; /* Abort mode */ sec= 1; /* Abort mode */
}
if (alarm_queue.elements >= max_used_alarms) if (alarm_queue.elements >= max_used_alarms)
{ {
if (alarm_queue.elements == alarm_queue.max_elements) if (alarm_queue.elements == alarm_queue.max_elements)
{ {
DBUG_PRINT("info", ("alarm queue full")); DBUG_PRINT("info", ("alarm queue full"));
fprintf(stderr,"Warning: thr_alarm queue is full\n"); fprintf(stderr,"Warning: thr_alarm queue is full\n");
*alrm= 0; /* No alarm */ goto abort;
pthread_mutex_unlock(&LOCK_alarm);
#ifndef USE_ONE_SIGNAL_HAND
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
#endif
DBUG_RETURN(1);
} }
max_used_alarms=alarm_queue.elements+1; max_used_alarms=alarm_queue.elements+1;
} }
reschedule= (ulong) next_alarm_expire_time > (ulong) now + sec; reschedule= (ulong) next_alarm_expire_time > (ulong) next;
if (!alarm_data)
{
if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME))))
{
DBUG_PRINT("info", ("failed my_malloc()"));
*alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
#ifndef USE_ONE_SIGNAL_HAND
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
#endif
DBUG_RETURN(1);
}
alarm_data->malloced=1;
}
else
alarm_data->malloced=0;
alarm_data->expire_time=now+sec;
alarm_data->alarmed=0;
alarm_data->thread= current_my_thread_var->pthread_self;
alarm_data->thread_id= current_my_thread_var->id;
queue_insert(&alarm_queue,(uchar*) alarm_data); queue_insert(&alarm_queue,(uchar*) alarm_data);
assert(alarm_data->index_in_queue > 0);
/* Reschedule alarm if the current one has more than sec left */ /* Reschedule alarm if the current one has more than sec left */
if (reschedule) if (unlikely(reschedule))
{ {
DBUG_PRINT("info", ("reschedule")); DBUG_PRINT("info", ("reschedule"));
if (pthread_equal(pthread_self(),alarm_thread)) if (pthread_equal(pthread_self(),alarm_thread))
{ {
alarm(sec); /* purecov: inspected */ alarm(sec); /* purecov: inspected */
next_alarm_expire_time= now + sec; next_alarm_expire_time= next;
} }
else else
reschedule_alarms(); /* Reschedule alarms */ reschedule_alarms(); /* Reschedule alarms */
} }
pthread_mutex_unlock(&LOCK_alarm); pthread_mutex_unlock(&LOCK_alarm);
#ifndef USE_ONE_SIGNAL_HAND one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
#endif
(*alrm)= &alarm_data->alarmed; (*alrm)= &alarm_data->alarmed;
DBUG_RETURN(0); DBUG_RETURN(0);
abort:
if (alarm_data->malloced)
my_free(alarm_data, MYF(0));
pthread_mutex_unlock(&LOCK_alarm);
one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL);
abort_no_unlock:
*alrm= 0; /* No alarm */
DBUG_RETURN(1);
} }
@ -247,41 +249,18 @@ void thr_end_alarm(thr_alarm_t *alarmed)
#ifndef USE_ONE_SIGNAL_HAND #ifndef USE_ONE_SIGNAL_HAND
sigset_t old_mask; sigset_t old_mask;
#endif #endif
uint i, found=0;
DBUG_ENTER("thr_end_alarm"); DBUG_ENTER("thr_end_alarm");
#ifndef USE_ONE_SIGNAL_HAND one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
#endif
pthread_mutex_lock(&LOCK_alarm);
alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed)); alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed));
for (i=0 ; i < alarm_queue.elements ; i++) pthread_mutex_lock(&LOCK_alarm);
{ DBUG_ASSERT(alarm_data->index_in_queue != 0);
if ((ALARM*) queue_element(&alarm_queue,i) == alarm_data) DBUG_ASSERT(queue_element(&alarm_queue, alarm_data->index_in_queue) ==
{ alarm_data);
queue_remove(&alarm_queue,i),MYF(0); queue_remove(&alarm_queue, alarm_data->index_in_queue);
if (alarm_data->malloced)
my_free((uchar*) alarm_data,MYF(0));
found++;
#ifdef DBUG_OFF
break;
#endif
}
}
DBUG_ASSERT(!*alarmed || found == 1);
if (!found)
{
if (*alarmed)
fprintf(stderr,"Warning: Didn't find alarm 0x%lx in queue of %d alarms\n",
(long) *alarmed, alarm_queue.elements);
DBUG_PRINT("warning",("Didn't find alarm 0x%lx in queue\n",
(long) *alarmed));
}
pthread_mutex_unlock(&LOCK_alarm); pthread_mutex_unlock(&LOCK_alarm);
#ifndef USE_ONE_SIGNAL_HAND one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL); reset_index_in_queue(alarm_data);
#endif
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -344,12 +323,13 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
#if defined(MAIN) && !defined(__bsdi__) #if defined(MAIN) && !defined(__bsdi__)
printf("process_alarm\n"); fflush(stdout); printf("process_alarm\n"); fflush(stdout);
#endif #endif
if (alarm_queue.elements) if (likely(alarm_queue.elements))
{ {
if (alarm_aborted) if (unlikely(alarm_aborted))
{ {
uint i; uint i;
for (i=0 ; i < alarm_queue.elements ;) for (i= queue_first_element(&alarm_queue) ;
i <= queue_last_element(&alarm_queue) ;)
{ {
alarm_data=(ALARM*) queue_element(&alarm_queue,i); alarm_data=(ALARM*) queue_element(&alarm_queue,i);
alarm_data->alarmed=1; /* Info to thread */ alarm_data->alarmed=1; /* Info to thread */
@ -360,6 +340,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
printf("Warning: pthread_kill couldn't find thread!!!\n"); printf("Warning: pthread_kill couldn't find thread!!!\n");
#endif #endif
queue_remove(&alarm_queue,i); /* No thread. Remove alarm */ queue_remove(&alarm_queue,i); /* No thread. Remove alarm */
reset_index_in_queue(alarm_data);
} }
else else
i++; /* Signal next thread */ i++; /* Signal next thread */
@ -371,8 +352,8 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
} }
else else
{ {
ulong now=(ulong) my_time(0); time_t now= my_time(0);
ulong next=now+10-(now%10); time_t next= now+10-(now%10);
while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now) while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now)
{ {
alarm_data->alarmed=1; /* Info to thread */ alarm_data->alarmed=1; /* Info to thread */
@ -382,15 +363,16 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
{ {
#ifdef MAIN #ifdef MAIN
printf("Warning: pthread_kill couldn't find thread!!!\n"); printf("Warning: pthread_kill couldn't find thread!!!\n");
#endif #endif /* MAIN */
queue_remove(&alarm_queue,0); /* No thread. Remove alarm */ queue_remove_top(&alarm_queue); /* No thread. Remove alarm */
reset_index_in_queue(alarm_data);
if (!alarm_queue.elements) if (!alarm_queue.elements)
break; break;
} }
else else
{ {
alarm_data->expire_time=next; alarm_data->expire_time=next;
queue_replaced(&alarm_queue); queue_replace_top(&alarm_queue);
} }
} }
#ifndef USE_ALARM_THREAD #ifndef USE_ALARM_THREAD
@ -486,13 +468,15 @@ void thr_alarm_kill(my_thread_id thread_id)
if (alarm_aborted) if (alarm_aborted)
return; return;
pthread_mutex_lock(&LOCK_alarm); pthread_mutex_lock(&LOCK_alarm);
for (i=0 ; i < alarm_queue.elements ; i++) for (i= queue_first_element(&alarm_queue) ;
i <= queue_last_element(&alarm_queue);
i++)
{ {
if (((ALARM*) queue_element(&alarm_queue,i))->thread_id == thread_id) ALARM *element= (ALARM*) queue_element(&alarm_queue,i);
if (element->thread_id == thread_id)
{ {
ALARM *tmp=(ALARM*) queue_remove(&alarm_queue,i); element->expire_time= 0;
tmp->expire_time=0; queue_replace(&alarm_queue, i);
queue_insert(&alarm_queue,(uchar*) tmp);
reschedule_alarms(); reschedule_alarms();
break; break;
} }
@ -508,7 +492,7 @@ void thr_alarm_info(ALARM_INFO *info)
info->max_used_alarms= max_used_alarms; info->max_used_alarms= max_used_alarms;
if ((info->active_alarms= alarm_queue.elements)) if ((info->active_alarms= alarm_queue.elements))
{ {
ulong now=(ulong) my_time(0); time_t now= my_time(0);
long time_diff; long time_diff;
ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue); ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue);
time_diff= (long) (alarm_data->expire_time - now); time_diff= (long) (alarm_data->expire_time - now);
@ -556,7 +540,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
{ {
if (alarm_queue.elements) if (alarm_queue.elements)
{ {
ulong sleep_time,now= my_time(0); time_t sleep_time,now= my_time(0);
if (alarm_aborted) if (alarm_aborted)
sleep_time=now+1; sleep_time=now+1;
else else
@ -792,20 +776,6 @@ static void *test_thread(void *arg)
return 0; return 0;
} }
#ifdef USE_ONE_SIGNAL_HAND
static sig_handler print_signal_warning(int sig)
{
printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name());
fflush(stdout);
#ifdef DONT_REMEMBER_SIGNAL
my_sigset(sig,print_signal_warning); /* int. thread system calls */
#endif
if (sig == SIGALRM)
alarm(2); /* reschedule alarm */
}
#endif /* USE_ONE_SIGNAL_HAND */
static void *signal_hand(void *arg __attribute__((unused))) static void *signal_hand(void *arg __attribute__((unused)))
{ {
sigset_t set; sigset_t set;

View File

@ -583,9 +583,9 @@ my_bool engine_table_options_frm_read(const uchar *buff, uint length,
} }
if (buff < buff_end) if (buff < buff_end)
sql_print_warning("Table %`s was created in a later MariaDB version - " sql_print_warning("Table '%s' was created in a later MariaDB version - "
"unknown table attributes were ignored", "unknown table attributes were ignored",
share->table_name); share->table_name.str);
DBUG_RETURN(buff > buff_end); DBUG_RETURN(buff > buff_end);
} }

View File

@ -136,9 +136,9 @@ Event_queue::init_queue(THD *thd)
LOCK_QUEUE_DATA(); LOCK_QUEUE_DATA();
if (init_queue_ex(&queue, EVENT_QUEUE_INITIAL_SIZE , 0 /*offset*/, if (::init_queue(&queue, EVENT_QUEUE_INITIAL_SIZE , 0 /*offset*/,
0 /*max_on_top*/, event_queue_element_compare_q, 0 /*max_on_top*/, event_queue_element_compare_q,
NULL, EVENT_QUEUE_EXTENT)) NullS, 0, EVENT_QUEUE_EXTENT))
{ {
sql_print_error("Event Scheduler: Can't initialize the execution queue"); sql_print_error("Event Scheduler: Can't initialize the execution queue");
goto err; goto err;
@ -325,11 +325,13 @@ void
Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern, Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
bool (*comparator)(LEX_STRING, Event_basic *)) bool (*comparator)(LEX_STRING, Event_basic *))
{ {
uint i= 0; uint i;
DBUG_ENTER("Event_queue::drop_matching_events"); DBUG_ENTER("Event_queue::drop_matching_events");
DBUG_PRINT("enter", ("pattern=%s", pattern.str)); DBUG_PRINT("enter", ("pattern=%s", pattern.str));
while (i < queue.elements) for (i= queue_first_element(&queue) ;
i <= queue_last_element(&queue) ;
)
{ {
Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i); Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
DBUG_PRINT("info", ("[%s.%s]?", et->dbname.str, et->name.str)); DBUG_PRINT("info", ("[%s.%s]?", et->dbname.str, et->name.str));
@ -339,7 +341,8 @@ Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
The queue is ordered. If we remove an element, then all elements The queue is ordered. If we remove an element, then all elements
after it will shift one position to the left, if we imagine it as after it will shift one position to the left, if we imagine it as
an array from left to the right. In this case we should not an array from left to the right. In this case we should not
increment the counter and the (i < queue.elements) condition is ok. increment the counter and the (i <= queue_last_element() condition
is ok.
*/ */
queue_remove(&queue, i); queue_remove(&queue, i);
delete et; delete et;
@ -403,7 +406,9 @@ Event_queue::find_n_remove_event(LEX_STRING db, LEX_STRING name)
uint i; uint i;
DBUG_ENTER("Event_queue::find_n_remove_event"); DBUG_ENTER("Event_queue::find_n_remove_event");
for (i= 0; i < queue.elements; ++i) for (i= queue_first_element(&queue);
i <= queue_last_element(&queue);
i++)
{ {
Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i); Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?", db.str, name.str, DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?", db.str, name.str,
@ -441,7 +446,9 @@ Event_queue::recalculate_activation_times(THD *thd)
LOCK_QUEUE_DATA(); LOCK_QUEUE_DATA();
DBUG_PRINT("info", ("%u loaded events to be recalculated", queue.elements)); DBUG_PRINT("info", ("%u loaded events to be recalculated", queue.elements));
for (i= 0; i < queue.elements; i++) for (i= queue_first_element(&queue);
i <= queue_last_element(&queue);
i++)
{ {
((Event_queue_element*)queue_element(&queue, i))->compute_next_execution_time(); ((Event_queue_element*)queue_element(&queue, i))->compute_next_execution_time();
((Event_queue_element*)queue_element(&queue, i))->update_timing_fields(thd); ((Event_queue_element*)queue_element(&queue, i))->update_timing_fields(thd);
@ -454,16 +461,19 @@ Event_queue::recalculate_activation_times(THD *thd)
have removed all. The queue has been ordered in a way the disabled have removed all. The queue has been ordered in a way the disabled
events are at the end. events are at the end.
*/ */
for (i= queue.elements; i > 0; i--) for (i= queue_last_element(&queue);
(int) i >= (int) queue_first_element(&queue);
i--)
{ {
Event_queue_element *element = (Event_queue_element*)queue_element(&queue, i - 1); Event_queue_element *element=
(Event_queue_element*)queue_element(&queue, i);
if (element->status != Event_parse_data::DISABLED) if (element->status != Event_parse_data::DISABLED)
break; break;
/* /*
This won't cause queue re-order, because we remove This won't cause queue re-order, because we remove
always the last element. always the last element.
*/ */
queue_remove(&queue, i - 1); queue_remove(&queue, i);
delete element; delete element;
} }
UNLOCK_QUEUE_DATA(); UNLOCK_QUEUE_DATA();
@ -499,7 +509,9 @@ Event_queue::empty_queue()
sql_print_information("Event Scheduler: Purging the queue. %u events", sql_print_information("Event Scheduler: Purging the queue. %u events",
queue.elements); queue.elements);
/* empty the queue */ /* empty the queue */
for (i= 0; i < queue.elements; ++i) for (i= queue_first_element(&queue);
i <= queue_last_element(&queue);
i++)
{ {
Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i); Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
delete et; delete et;
@ -525,7 +537,9 @@ Event_queue::dbug_dump_queue(time_t now)
uint i; uint i;
DBUG_ENTER("Event_queue::dbug_dump_queue"); DBUG_ENTER("Event_queue::dbug_dump_queue");
DBUG_PRINT("info", ("Dumping queue . Elements=%u", queue.elements)); DBUG_PRINT("info", ("Dumping queue . Elements=%u", queue.elements));
for (i = 0; i < queue.elements; i++) for (i= queue_first_element(&queue);
i <= queue_last_element(&queue);
i++)
{ {
et= ((Event_queue_element*)queue_element(&queue, i)); et= ((Event_queue_element*)queue_element(&queue, i));
DBUG_PRINT("info", ("et: 0x%lx name: %s.%s", (long) et, DBUG_PRINT("info", ("et: 0x%lx name: %s.%s", (long) et,
@ -592,7 +606,7 @@ Event_queue::get_top_for_execution_if_time(THD *thd,
continue; continue;
} }
top= ((Event_queue_element*) queue_element(&queue, 0)); top= (Event_queue_element*) queue_top(&queue);
thd->set_current_time(); /* Get current time */ thd->set_current_time(); /* Get current time */
@ -634,10 +648,10 @@ Event_queue::get_top_for_execution_if_time(THD *thd,
top->dbname.str, top->name.str, top->dbname.str, top->name.str,
top->dropped? "Dropping.":""); top->dropped? "Dropping.":"");
delete top; delete top;
queue_remove(&queue, 0); queue_remove_top(&queue);
} }
else else
queue_replaced(&queue); queue_replace_top(&queue);
dbug_dump_queue(thd->query_start()); dbug_dump_queue(thd->query_start());
break; break;

View File

@ -1151,7 +1151,9 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length) void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length)
{ {
uchar *reuse_end= reuse->base + reuse->max_keys * key_length; uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
for (uint i= 0; i < queue->elements; ++i) for (uint i= queue_first_element(queue);
i <= queue_last_element(queue);
i++)
{ {
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i); BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
if (bp->base + bp->max_keys * key_length == reuse->base) if (bp->base + bp->max_keys * key_length == reuse->base)
@ -1240,7 +1242,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
first_cmp_arg= (void*) &sort_length; first_cmp_arg= (void*) &sort_length;
} }
if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0, if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
(queue_compare) cmp, first_cmp_arg)) (queue_compare) cmp, first_cmp_arg, 0, 0))
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
for (buffpek= Fb ; buffpek <= Tb ; buffpek++) for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
{ {
@ -1277,7 +1279,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
error= 0; /* purecov: inspected */ error= 0; /* purecov: inspected */
goto end; /* purecov: inspected */ goto end; /* purecov: inspected */
} }
queue_replaced(&queue); // Top element has been used queue_replace_top(&queue); // Top element has been used
} }
else else
cmp= 0; // Not unique cmp= 0; // Not unique
@ -1325,14 +1327,14 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
if (!(error= (int) read_to_buffer(from_file,buffpek, if (!(error= (int) read_to_buffer(from_file,buffpek,
rec_length))) rec_length)))
{ {
VOID(queue_remove(&queue,0)); VOID(queue_remove_top(&queue));
reuse_freed_buff(&queue, buffpek, rec_length); reuse_freed_buff(&queue, buffpek, rec_length);
break; /* One buffer have been removed */ break; /* One buffer have been removed */
} }
else if (error == -1) else if (error == -1)
goto err; /* purecov: inspected */ goto err; /* purecov: inspected */
} }
queue_replaced(&queue); /* Top element has been replaced */ queue_replace_top(&queue); /* Top element has been replaced */
} }
} }
buffpek= (BUFFPEK*) queue_top(&queue); buffpek= (BUFFPEK*) queue_top(&queue);

View File

@ -2567,7 +2567,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
Initialize priority queue, initialized to reading forward. Initialize priority queue, initialized to reading forward.
*/ */
if ((error= init_queue(&m_queue, m_tot_parts, (uint) PARTITION_BYTES_IN_POS, if ((error= init_queue(&m_queue, m_tot_parts, (uint) PARTITION_BYTES_IN_POS,
0, key_rec_cmp, (void*)this))) 0, key_rec_cmp, (void*)this, 0, 0)))
goto err_handler; goto err_handler;
/* /*
@ -4622,7 +4622,7 @@ int ha_partition::handle_unordered_scan_next_partition(uchar * buf)
int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
{ {
uint i; uint i;
uint j= 0; uint j= queue_first_element(&m_queue);
bool found= FALSE; bool found= FALSE;
DBUG_ENTER("ha_partition::handle_ordered_index_scan"); DBUG_ENTER("ha_partition::handle_ordered_index_scan");
@ -4716,7 +4716,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
*/ */
queue_set_max_at_top(&m_queue, reverse_order); queue_set_max_at_top(&m_queue, reverse_order);
queue_set_cmp_arg(&m_queue, (void*)m_curr_key_info); queue_set_cmp_arg(&m_queue, (void*)m_curr_key_info);
m_queue.elements= j; m_queue.elements= j - queue_first_element(&m_queue);
queue_fix(&m_queue); queue_fix(&m_queue);
return_top_record(buf); return_top_record(buf);
table->status= 0; table->status= 0;
@ -4787,7 +4787,7 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
if (error == HA_ERR_END_OF_FILE) if (error == HA_ERR_END_OF_FILE)
{ {
/* Return next buffered row */ /* Return next buffered row */
queue_remove(&m_queue, (uint) 0); queue_remove_top(&m_queue);
if (m_queue.elements) if (m_queue.elements)
{ {
DBUG_PRINT("info", ("Record returned from partition %u (2)", DBUG_PRINT("info", ("Record returned from partition %u (2)",
@ -4799,7 +4799,7 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
} }
DBUG_RETURN(error); DBUG_RETURN(error);
} }
queue_replaced(&m_queue); queue_replace_top(&m_queue);
return_top_record(buf); return_top_record(buf);
DBUG_PRINT("info", ("Record returned from partition %u", m_top_entry)); DBUG_PRINT("info", ("Record returned from partition %u", m_top_entry));
DBUG_RETURN(0); DBUG_RETURN(0);
@ -4830,7 +4830,7 @@ int ha_partition::handle_ordered_prev(uchar *buf)
{ {
if (error == HA_ERR_END_OF_FILE) if (error == HA_ERR_END_OF_FILE)
{ {
queue_remove(&m_queue, (uint) 0); queue_remove_top(&m_queue);
if (m_queue.elements) if (m_queue.elements)
{ {
return_top_record(buf); return_top_record(buf);
@ -4842,7 +4842,7 @@ int ha_partition::handle_ordered_prev(uchar *buf)
} }
DBUG_RETURN(error); DBUG_RETURN(error);
} }
queue_replaced(&m_queue); queue_replace_top(&m_queue);
return_top_record(buf); return_top_record(buf);
DBUG_PRINT("info", ("Record returned from partition %d", m_top_entry)); DBUG_PRINT("info", ("Record returned from partition %d", m_top_entry));
DBUG_RETURN(0); DBUG_RETURN(0);

View File

@ -1129,7 +1129,7 @@ public:
virtual handlerton *partition_ht() const virtual handlerton *partition_ht() const
{ {
handlerton *h= m_file[0]->ht; handlerton *h= m_file[0]->ht;
for (int i=1; i < m_tot_parts; i++) for (uint i=1; i < m_tot_parts; i++)
DBUG_ASSERT(h == m_file[i]->ht); DBUG_ASSERT(h == m_file[i]->ht);
return h; return h;
} }

View File

@ -1778,10 +1778,12 @@ Item *Item_in_optimizer::expr_cache_insert_transformer(uchar *thd_arg)
if (args[0]->cols() == 1) if (args[0]->cols() == 1)
depends_on.push_front((Item**)args); depends_on.push_front((Item**)args);
else else
for (int i= 0; i < args[0]->cols(); i++) {
for (uint i= 0; i < args[0]->cols(); i++)
{ {
depends_on.push_front(args[0]->addr(i)); depends_on.push_front(args[0]->addr(i));
} }
}
if (args[1]->expr_cache_is_needed(thd)) if (args[1]->expr_cache_is_needed(thd))
DBUG_RETURN(set_expr_cache(thd, depends_on)); DBUG_RETURN(set_expr_cache(thd, depends_on));

View File

@ -3957,8 +3957,6 @@ subselect_hash_sj_engine::make_unique_engine()
Item_iterator_row it(item_in->left_expr); Item_iterator_row it(item_in->left_expr);
/* The only index on the temporary table. */ /* The only index on the temporary table. */
KEY *tmp_key= tmp_table->key_info; KEY *tmp_key= tmp_table->key_info;
/* Number of keyparts in tmp_key. */
uint tmp_key_parts= tmp_key->key_parts;
JOIN_TAB *tab; JOIN_TAB *tab;
DBUG_ENTER("subselect_hash_sj_engine::make_unique_engine"); DBUG_ENTER("subselect_hash_sj_engine::make_unique_engine");
@ -4879,7 +4877,8 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
merge_keys[i]->sort_keys(); merge_keys[i]->sort_keys();
if (init_queue(&pq, keys_count, 0, FALSE, if (init_queue(&pq, keys_count, 0, FALSE,
subselect_rowid_merge_engine::cmp_keys_by_cur_rownum, NULL)) subselect_rowid_merge_engine::cmp_keys_by_cur_rownum, NULL,
0, 0))
return TRUE; return TRUE;
return FALSE; return FALSE;

View File

@ -262,18 +262,20 @@ static int net_data_is_ready(my_socket sd)
#endif /* EMBEDDED_LIBRARY */ #endif /* EMBEDDED_LIBRARY */
/** /**
Remove unwanted characters from connection Intialize NET handler for new reads:
and check if disconnected.
Read from socket until there is nothing more to read. Discard - Read from socket until there is nothing more to read. Discard
what is read. what is read.
- Initialize net for new net_read/net_write calls.
If there is anything when to read 'net_clear' is called this If there is anything when to read 'net_clear' is called this
normally indicates an error in the protocol. normally indicates an error in the protocol. Normally one should not
need to do clear the communication buffer. If one compiles without
-DUSE_NET_CLEAR then one wins one read call / query.
When connection is properly closed (for TCP it means with When connection is properly closed (for TCP it means with
a FIN packet), then select() considers a socket "ready to read", a FIN packet), then select() considers a socket "ready to read",
in the sense that there's EOF to read, but read() returns 0. in the sense that there's EOF to read, but read() returns 0.
@param net NET handler @param net NET handler
@param clear_buffer if <> 0, then clear all data from comm buff @param clear_buffer if <> 0, then clear all data from comm buff
@ -281,20 +283,18 @@ static int net_data_is_ready(my_socket sd)
void net_clear(NET *net, my_bool clear_buffer __attribute__((unused))) void net_clear(NET *net, my_bool clear_buffer __attribute__((unused)))
{ {
#if !defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF)
size_t count;
int ready;
#endif
DBUG_ENTER("net_clear"); DBUG_ENTER("net_clear");
/* /*
We don't do a clear in case of DBUG_OFF to catch bugs We don't do a clear in case of not DBUG_OFF to catch bugs in the
in the protocol handling protocol handling.
*/ */
#if !defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF) #if (!defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF)) || defined(USE_NET_CLEAR)
if (clear_buffer) if (clear_buffer)
{ {
size_t count;
int ready;
while ((ready= net_data_is_ready(net->vio->sd)) > 0) while ((ready= net_data_is_ready(net->vio->sd)) > 0)
{ {
/* The socket is ready */ /* The socket is ready */

View File

@ -1155,10 +1155,7 @@ QUICK_SELECT_I::QUICK_SELECT_I()
QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr, QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
bool no_alloc, MEM_ROOT *parent_alloc, bool no_alloc, MEM_ROOT *parent_alloc,
bool *create_error) bool *create_error)
:dont_free(0),doing_key_read(0),/*error(0),*/free_file(0),/*in_range(0),*/cur_range(NULL),last_range(0) :doing_key_read(0),/*error(0),*/free_file(0),/*in_range(0),*/cur_range(NULL),last_range(0),dont_free(0)
//psergey3-merge: check whether we need doing_key_read and last_range
// was:
// :free_file(0),cur_range(NULL),last_range(0),dont_free(0)
{ {
my_bitmap_map *bitmap; my_bitmap_map *bitmap;
DBUG_ENTER("QUICK_RANGE_SELECT::QUICK_RANGE_SELECT"); DBUG_ENTER("QUICK_RANGE_SELECT::QUICK_RANGE_SELECT");
@ -1594,7 +1591,7 @@ int QUICK_ROR_UNION_SELECT::init()
DBUG_ENTER("QUICK_ROR_UNION_SELECT::init"); DBUG_ENTER("QUICK_ROR_UNION_SELECT::init");
if (init_queue(&queue, quick_selects.elements, 0, if (init_queue(&queue, quick_selects.elements, 0,
FALSE , QUICK_ROR_UNION_SELECT::queue_cmp, FALSE , QUICK_ROR_UNION_SELECT::queue_cmp,
(void*) this)) (void*) this, 0, 0))
{ {
bzero(&queue, sizeof(QUEUE)); bzero(&queue, sizeof(QUEUE));
DBUG_RETURN(1); DBUG_RETURN(1);
@ -8293,12 +8290,12 @@ int QUICK_ROR_UNION_SELECT::get_next()
{ {
if (error != HA_ERR_END_OF_FILE) if (error != HA_ERR_END_OF_FILE)
DBUG_RETURN(error); DBUG_RETURN(error);
queue_remove(&queue, 0); queue_remove_top(&queue);
} }
else else
{ {
quick->save_last_pos(); quick->save_last_pos();
queue_replaced(&queue); queue_replace_top(&queue);
} }
if (!have_prev_rowid) if (!have_prev_rowid)

View File

@ -423,7 +423,7 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
if (end <= begin || if (end <= begin ||
merge_buffer_size < (ulong) (key_length * (end - begin + 1)) || merge_buffer_size < (ulong) (key_length * (end - begin + 1)) ||
init_queue(&queue, (uint) (end - begin), offsetof(BUFFPEK, key), 0, init_queue(&queue, (uint) (end - begin), offsetof(BUFFPEK, key), 0,
buffpek_compare, &compare_context)) buffpek_compare, &compare_context, 0, 0))
return 1; return 1;
/* we need space for one key when a piece of merge buffer is re-read */ /* we need space for one key when a piece of merge buffer is re-read */
merge_buffer_size-= key_length; merge_buffer_size-= key_length;
@ -468,7 +468,7 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
*/ */
top->key+= key_length; top->key+= key_length;
if (--top->mem_count) if (--top->mem_count)
queue_replaced(&queue); queue_replace_top(&queue);
else /* next piece should be read */ else /* next piece should be read */
{ {
/* save old_key not to overwrite it in read_to_buffer */ /* save old_key not to overwrite it in read_to_buffer */
@ -478,14 +478,14 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
if (bytes_read == (uint) (-1)) if (bytes_read == (uint) (-1))
goto end; goto end;
else if (bytes_read > 0) /* top->key, top->mem_count are reset */ else if (bytes_read > 0) /* top->key, top->mem_count are reset */
queue_replaced(&queue); /* in read_to_buffer */ queue_replace_top(&queue); /* in read_to_buffer */
else else
{ {
/* /*
Tree for old 'top' element is empty: remove it from the queue and Tree for old 'top' element is empty: remove it from the queue and
give all its memory to the nearest tree. give all its memory to the nearest tree.
*/ */
queue_remove(&queue, 0); queue_remove_top(&queue);
reuse_freed_buff(&queue, top, key_length); reuse_freed_buff(&queue, top, key_length);
} }
} }

View File

@ -473,14 +473,15 @@ static void _ftb_init_index_search(FT_INFO *ftb)
int i; int i;
FTB_WORD *ftbw; FTB_WORD *ftbw;
if ((ftb->state != READY && ftb->state !=INDEX_DONE) || if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY)
ftb->keynr == NO_SUCH_KEY)
return; return;
ftb->state=INDEX_SEARCH; ftb->state=INDEX_SEARCH;
for (i=ftb->queue.elements; i; i--) for (i= queue_last_element(&ftb->queue);
(int) i >= (int) queue_first_element(&ftb->queue);
i--)
{ {
ftbw=(FTB_WORD *)(ftb->queue.root[i]); ftbw=(FTB_WORD *)(queue_element(&ftb->queue, i));
if (ftbw->flags & FTB_FLAG_TRUNC) if (ftbw->flags & FTB_FLAG_TRUNC)
{ {
@ -585,7 +586,7 @@ FT_INFO * maria_ft_init_boolean_search(MARIA_HA *info, uint keynr,
sizeof(void *)))) sizeof(void *))))
goto err; goto err;
reinit_queue(&ftb->queue, ftb->queue.max_elements, 0, 0, reinit_queue(&ftb->queue, ftb->queue.max_elements, 0, 0,
(int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0); (int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0, 0, 0);
for (ftbw= ftb->last_word; ftbw; ftbw= ftbw->prev) for (ftbw= ftb->last_word; ftbw; ftbw= ftbw->prev)
queue_insert(&ftb->queue, (uchar *)ftbw); queue_insert(&ftb->queue, (uchar *)ftbw);
ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root, ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root,
@ -828,7 +829,7 @@ int maria_ft_boolean_read_next(FT_INFO *ftb, char *record)
/* update queue */ /* update queue */
_ft2_search(ftb, ftbw, 0); _ft2_search(ftb, ftbw, 0);
queue_replaced(& ftb->queue); queue_replace_top(&ftb->queue);
} }
ftbe=ftb->root; ftbe=ftb->root;

View File

@ -253,12 +253,12 @@ FT_INFO *maria_ft_init_nlq_search(MARIA_HA *info, uint keynr, uchar *query,
{ {
QUEUE best; QUEUE best;
init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp, init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp,
0); 0, 0, 0);
tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push, tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push,
&best, left_root_right); &best, left_root_right);
while (best.elements) while (best.elements)
{ {
my_off_t docid=((FT_DOC *)queue_remove(& best, 0))->dpos; my_off_t docid= ((FT_DOC *)queue_remove_top(&best))->dpos;
if (!(*info->read_record)(info, record, docid)) if (!(*info->read_record)(info, record, docid))
{ {
info->update|= HA_STATE_AKTIV; info->update|= HA_STATE_AKTIV;

View File

@ -933,7 +933,7 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0, if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
(int (*)(void*, uchar *,uchar*)) info->key_cmp, (int (*)(void*, uchar *,uchar*)) info->key_cmp,
(void*) info)) (void*) info, 0, 0))
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
for (buffpek= Fb ; buffpek <= Tb ; buffpek++) for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
@ -982,7 +982,7 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
uchar *base= buffpek->base; uchar *base= buffpek->base;
uint max_keys=buffpek->max_keys; uint max_keys=buffpek->max_keys;
VOID(queue_remove(&queue,0)); VOID(queue_remove_top(&queue));
/* Put room used by buffer to use in other buffer */ /* Put room used by buffer to use in other buffer */
for (refpek= (BUFFPEK**) &queue_top(&queue); for (refpek= (BUFFPEK**) &queue_top(&queue);
@ -1007,7 +1007,7 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
} }
else if (error == -1) else if (error == -1)
goto err; /* purecov: inspected */ goto err; /* purecov: inspected */
queue_replaced(&queue); /* Top element has been replaced */ queue_replace_top(&queue); /* Top element has been replaced */
} }
} }
buffpek=(BUFFPEK*) queue_top(&queue); buffpek=(BUFFPEK*) queue_top(&queue);

View File

@ -590,7 +590,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
Create a global priority queue in preparation for making Create a global priority queue in preparation for making
temporary Huffman trees. temporary Huffman trees.
*/ */
if (init_queue(&queue,256,0,0,compare_huff_elements,0)) if (init_queue(&queue, 256, 0, 0, compare_huff_elements, 0, 0, 0))
goto err; goto err;
/* /*
@ -1521,7 +1521,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
if (queue.max_elements < found) if (queue.max_elements < found)
{ {
delete_queue(&queue); delete_queue(&queue);
if (init_queue(&queue,found,0,0,compare_huff_elements,0)) if (init_queue(&queue,found, 0, 0, compare_huff_elements, 0, 0, 0))
return -1; return -1;
} }
@ -1625,8 +1625,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
Make a priority queue from the queue. Construct its index so that we Make a priority queue from the queue. Construct its index so that we
have a partially ordered tree. have a partially ordered tree.
*/ */
for (i=found/2 ; i > 0 ; i--) queue_fix(&queue);
_downheap(&queue,i);
/* The Huffman algorithm. */ /* The Huffman algorithm. */
bytes_packed=0; bits_packed=0; bytes_packed=0; bits_packed=0;
@ -1637,12 +1636,9 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
Popping from a priority queue includes a re-ordering of the queue, Popping from a priority queue includes a re-ordering of the queue,
to get the next least incidence element to the top. to get the next least incidence element to the top.
*/ */
a=(HUFF_ELEMENT*) queue_remove(&queue,0); a=(HUFF_ELEMENT*) queue_remove_top(&queue);
/* /* Copy the next least incidence element */
Copy the next least incidence element. The queue implementation b=(HUFF_ELEMENT*) queue_top(&queue);
reserves root[0] for temporary purposes. root[1] is the top.
*/
b=(HUFF_ELEMENT*) queue.root[1];
/* Get a new element from the element buffer. */ /* Get a new element from the element buffer. */
new_huff_el=huff_tree->element_buffer+found+i; new_huff_el=huff_tree->element_buffer+found+i;
/* The new element gets the sum of the two least incidence elements. */ /* The new element gets the sum of the two least incidence elements. */
@ -1664,8 +1660,8 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
Replace the copied top element by the new element and re-order the Replace the copied top element by the new element and re-order the
queue. queue.
*/ */
queue.root[1]=(uchar*) new_huff_el; queue_top(&queue)= (uchar*) new_huff_el;
queue_replaced(&queue); queue_replace_top(&queue);
} }
huff_tree->root=(HUFF_ELEMENT*) queue.root[1]; huff_tree->root=(HUFF_ELEMENT*) queue.root[1];
huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8; huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8;
@ -1796,8 +1792,7 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
Make a priority queue from the queue. Construct its index so that we Make a priority queue from the queue. Construct its index so that we
have a partially ordered tree. have a partially ordered tree.
*/ */
for (i=(found+1)/2 ; i > 0 ; i--) queue_fix(&queue);
_downheap(&queue,i);
/* The Huffman algorithm. */ /* The Huffman algorithm. */
for (i=0 ; i < found-1 ; i++) for (i=0 ; i < found-1 ; i++)
@ -1811,12 +1806,9 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
incidence). Popping from a priority queue includes a re-ordering incidence). Popping from a priority queue includes a re-ordering
of the queue, to get the next least incidence element to the top. of the queue, to get the next least incidence element to the top.
*/ */
a= (my_off_t*) queue_remove(&queue, 0); a= (my_off_t*) queue_remove_top(&queue);
/* /* Copy the next least incidence element. */
Copy the next least incidence element. The queue implementation b= (my_off_t*) queue_top(&queue);
reserves root[0] for temporary purposes. root[1] is the top.
*/
b= (my_off_t*) queue.root[1];
/* Create a new element in a local (automatic) buffer. */ /* Create a new element in a local (automatic) buffer. */
new_huff_el= element_buffer + i; new_huff_el= element_buffer + i;
/* The new element gets the sum of the two least incidence elements. */ /* The new element gets the sum of the two least incidence elements. */
@ -1836,8 +1828,8 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
queue. This successively replaces the references to counts by queue. This successively replaces the references to counts by
references to HUFF_ELEMENTs. references to HUFF_ELEMENTs.
*/ */
queue.root[1]=(uchar*) new_huff_el; queue_top(&queue)= (uchar*) new_huff_el;
queue_replaced(&queue); queue_replace_top(&queue);
} }
DBUG_RETURN(bytes_packed+(bits_packed+7)/8); DBUG_RETURN(bytes_packed+(bits_packed+7)/8);
} }

View File

@ -482,16 +482,18 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
static void _ftb_init_index_search(FT_INFO *ftb) static void _ftb_init_index_search(FT_INFO *ftb)
{ {
int i; uint i;
FTB_WORD *ftbw; FTB_WORD *ftbw;
if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY) if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY)
return; return;
ftb->state=INDEX_SEARCH; ftb->state=INDEX_SEARCH;
for (i=ftb->queue.elements; i; i--) for (i= queue_last_element(&ftb->queue);
(int) i >= (int) queue_first_element(&ftb->queue);
i--)
{ {
ftbw=(FTB_WORD *)(ftb->queue.root[i]); ftbw=(FTB_WORD *)(queue_element(&ftb->queue, i));
if (ftbw->flags & FTB_FLAG_TRUNC) if (ftbw->flags & FTB_FLAG_TRUNC)
{ {
@ -595,12 +597,12 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, uchar *query,
sizeof(void *)))) sizeof(void *))))
goto err; goto err;
reinit_queue(&ftb->queue, ftb->queue.max_elements, 0, 0, reinit_queue(&ftb->queue, ftb->queue.max_elements, 0, 0,
(int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0); (int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0, 0, 0);
for (ftbw= ftb->last_word; ftbw; ftbw= ftbw->prev) for (ftbw= ftb->last_word; ftbw; ftbw= ftbw->prev)
queue_insert(&ftb->queue, (uchar *)ftbw); queue_insert(&ftb->queue, (uchar *)ftbw);
ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root, ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root,
sizeof(FTB_WORD *)*ftb->queue.elements); sizeof(FTB_WORD *)*ftb->queue.elements);
memcpy(ftb->list, ftb->queue.root+1, sizeof(FTB_WORD *)*ftb->queue.elements); memcpy(ftb->list, &queue_top(&ftb->queue), sizeof(FTB_WORD *)*ftb->queue.elements);
my_qsort2(ftb->list, ftb->queue.elements, sizeof(FTB_WORD *), my_qsort2(ftb->list, ftb->queue.elements, sizeof(FTB_WORD *),
(qsort2_cmp)FTB_WORD_cmp_list, (void*) ftb->charset); (qsort2_cmp)FTB_WORD_cmp_list, (void*) ftb->charset);
if (ftb->queue.elements<2) ftb->with_scan &= ~FTB_FLAG_TRUNC; if (ftb->queue.elements<2) ftb->with_scan &= ~FTB_FLAG_TRUNC;
@ -839,7 +841,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record)
/* update queue */ /* update queue */
_ft2_search(ftb, ftbw, 0); _ft2_search(ftb, ftbw, 0);
queue_replaced(& ftb->queue); queue_replace_top(&ftb->queue);
} }
ftbe=ftb->root; ftbe=ftb->root;

View File

@ -250,12 +250,12 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, uchar *query,
{ {
QUEUE best; QUEUE best;
init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp, init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp,
0); 0, 0, 0);
tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push, tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push,
&best, left_root_right); &best, left_root_right);
while (best.elements) while (best.elements)
{ {
my_off_t docid=((FT_DOC *)queue_remove(& best, 0))->dpos; my_off_t docid= ((FT_DOC *)queue_remove_top(&best))->dpos;
if (!(*info->read_record)(info,docid,record)) if (!(*info->read_record)(info,docid,record))
{ {
info->update|= HA_STATE_AKTIV; info->update|= HA_STATE_AKTIV;

View File

@ -5,6 +5,7 @@
valgrind="valgrind --alignment=8 --leak-check=yes" valgrind="valgrind --alignment=8 --leak-check=yes"
silent="-s" silent="-s"
rm -f test1.TMD
if test -f mi_test1$MACH ; then suffix=$MACH ; else suffix=""; fi if test -f mi_test1$MACH ; then suffix=$MACH ; else suffix=""; fi
./mi_test1$suffix $silent ./mi_test1$suffix $silent

View File

@ -576,7 +576,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
Create a global priority queue in preparation for making Create a global priority queue in preparation for making
temporary Huffman trees. temporary Huffman trees.
*/ */
if (init_queue(&queue,256,0,0,compare_huff_elements,0)) if (init_queue(&queue, 256, 0, 0, compare_huff_elements, 0, 0, 0))
goto err; goto err;
/* /*
@ -1511,7 +1511,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
if (queue.max_elements < found) if (queue.max_elements < found)
{ {
delete_queue(&queue); delete_queue(&queue);
if (init_queue(&queue,found,0,0,compare_huff_elements,0)) if (init_queue(&queue,found, 0, 0, compare_huff_elements, 0, 0, 0))
return -1; return -1;
} }
@ -1615,8 +1615,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
Make a priority queue from the queue. Construct its index so that we Make a priority queue from the queue. Construct its index so that we
have a partially ordered tree. have a partially ordered tree.
*/ */
for (i=found/2 ; i > 0 ; i--) queue_fix(&queue);
_downheap(&queue,i);
/* The Huffman algorithm. */ /* The Huffman algorithm. */
bytes_packed=0; bits_packed=0; bytes_packed=0; bits_packed=0;
@ -1627,12 +1626,9 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
Popping from a priority queue includes a re-ordering of the queue, Popping from a priority queue includes a re-ordering of the queue,
to get the next least incidence element to the top. to get the next least incidence element to the top.
*/ */
a=(HUFF_ELEMENT*) queue_remove(&queue,0); a=(HUFF_ELEMENT*) queue_remove_top(&queue);
/* /* Copy the next least incidence element */
Copy the next least incidence element. The queue implementation b=(HUFF_ELEMENT*) queue_top(&queue);
reserves root[0] for temporary purposes. root[1] is the top.
*/
b=(HUFF_ELEMENT*) queue.root[1];
/* Get a new element from the element buffer. */ /* Get a new element from the element buffer. */
new_huff_el=huff_tree->element_buffer+found+i; new_huff_el=huff_tree->element_buffer+found+i;
/* The new element gets the sum of the two least incidence elements. */ /* The new element gets the sum of the two least incidence elements. */
@ -1654,8 +1650,8 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
Replace the copied top element by the new element and re-order the Replace the copied top element by the new element and re-order the
queue. queue.
*/ */
queue.root[1]=(uchar*) new_huff_el; queue_top(&queue)= (uchar*) new_huff_el;
queue_replaced(&queue); queue_replace_top(&queue);
} }
huff_tree->root=(HUFF_ELEMENT*) queue.root[1]; huff_tree->root=(HUFF_ELEMENT*) queue.root[1];
huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8; huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8;
@ -1786,8 +1782,7 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
Make a priority queue from the queue. Construct its index so that we Make a priority queue from the queue. Construct its index so that we
have a partially ordered tree. have a partially ordered tree.
*/ */
for (i=(found+1)/2 ; i > 0 ; i--) queue_fix(&queue);
_downheap(&queue,i);
/* The Huffman algorithm. */ /* The Huffman algorithm. */
for (i=0 ; i < found-1 ; i++) for (i=0 ; i < found-1 ; i++)
@ -1801,12 +1796,9 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
incidence). Popping from a priority queue includes a re-ordering incidence). Popping from a priority queue includes a re-ordering
of the queue, to get the next least incidence element to the top. of the queue, to get the next least incidence element to the top.
*/ */
a= (my_off_t*) queue_remove(&queue, 0); a= (my_off_t*) queue_remove_top(&queue);
/* /* Copy the next least incidence element. */
Copy the next least incidence element. The queue implementation b= (my_off_t*) queue_top(&queue);
reserves root[0] for temporary purposes. root[1] is the top.
*/
b= (my_off_t*) queue.root[1];
/* Create a new element in a local (automatic) buffer. */ /* Create a new element in a local (automatic) buffer. */
new_huff_el= element_buffer + i; new_huff_el= element_buffer + i;
/* The new element gets the sum of the two least incidence elements. */ /* The new element gets the sum of the two least incidence elements. */
@ -1826,8 +1818,8 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
queue. This successively replaces the references to counts by queue. This successively replaces the references to counts by
references to HUFF_ELEMENTs. references to HUFF_ELEMENTs.
*/ */
queue.root[1]=(uchar*) new_huff_el; queue_top(&queue)= (uchar*) new_huff_el;
queue_replaced(&queue); queue_replace_top(&queue);
} }
DBUG_RETURN(bytes_packed+(bits_packed+7)/8); DBUG_RETURN(bytes_packed+(bits_packed+7)/8);
} }

View File

@ -920,7 +920,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0, if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
(int (*)(void*, uchar *,uchar*)) info->key_cmp, (int (*)(void*, uchar *,uchar*)) info->key_cmp,
(void*) info)) (void*) info, 0, 0))
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
for (buffpek= Fb ; buffpek <= Tb ; buffpek++) for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
@ -969,7 +969,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
uchar *base= buffpek->base; uchar *base= buffpek->base;
uint max_keys=buffpek->max_keys; uint max_keys=buffpek->max_keys;
VOID(queue_remove(&queue,0)); VOID(queue_remove_top(&queue));
/* Put room used by buffer to use in other buffer */ /* Put room used by buffer to use in other buffer */
for (refpek= (BUFFPEK**) &queue_top(&queue); for (refpek= (BUFFPEK**) &queue_top(&queue);
@ -994,7 +994,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
} }
else if (error == -1) else if (error == -1)
goto err; /* purecov: inspected */ goto err; /* purecov: inspected */
queue_replaced(&queue); /* Top element has been replaced */ queue_replace_top(&queue); /* Top element has been replaced */
} }
} }
buffpek=(BUFFPEK*) queue_top(&queue); buffpek=(BUFFPEK*) queue_top(&queue);

View File

@ -52,7 +52,7 @@ int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag)
if (init_queue(q,info->tables, 0, if (init_queue(q,info->tables, 0,
(myisam_readnext_vec[search_flag] == SEARCH_SMALLER), (myisam_readnext_vec[search_flag] == SEARCH_SMALLER),
queue_key_cmp, queue_key_cmp,
info->open_tables->table->s->keyinfo[inx].seg)) info->open_tables->table->s->keyinfo[inx].seg, 0, 0))
error=my_errno; error=my_errno;
} }
else else
@ -60,7 +60,7 @@ int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag)
if (reinit_queue(q,info->tables, 0, if (reinit_queue(q,info->tables, 0,
(myisam_readnext_vec[search_flag] == SEARCH_SMALLER), (myisam_readnext_vec[search_flag] == SEARCH_SMALLER),
queue_key_cmp, queue_key_cmp,
info->open_tables->table->s->keyinfo[inx].seg)) info->open_tables->table->s->keyinfo[inx].seg, 0, 0))
error=my_errno; error=my_errno;
} }
} }

View File

@ -32,7 +32,7 @@ int myrg_rnext(MYRG_INFO *info, uchar *buf, int inx)
{ {
if (err == HA_ERR_END_OF_FILE) if (err == HA_ERR_END_OF_FILE)
{ {
queue_remove(&(info->by_key),0); queue_remove_top(&(info->by_key));
if (!info->by_key.elements) if (!info->by_key.elements)
return HA_ERR_END_OF_FILE; return HA_ERR_END_OF_FILE;
} }
@ -43,7 +43,7 @@ int myrg_rnext(MYRG_INFO *info, uchar *buf, int inx)
{ {
/* Found here, adding to queue */ /* Found here, adding to queue */
queue_top(&(info->by_key))=(uchar *)(info->current_table); queue_top(&(info->by_key))=(uchar *)(info->current_table);
queue_replaced(&(info->by_key)); queue_replace_top(&(info->by_key));
} }
/* now, mymerge's read_next is as simple as one queue_top */ /* now, mymerge's read_next is as simple as one queue_top */

View File

@ -29,7 +29,7 @@ int myrg_rnext_same(MYRG_INFO *info, uchar *buf)
{ {
if (err == HA_ERR_END_OF_FILE) if (err == HA_ERR_END_OF_FILE)
{ {
queue_remove(&(info->by_key),0); queue_remove_top(&(info->by_key));
if (!info->by_key.elements) if (!info->by_key.elements)
return HA_ERR_END_OF_FILE; return HA_ERR_END_OF_FILE;
} }
@ -40,7 +40,7 @@ int myrg_rnext_same(MYRG_INFO *info, uchar *buf)
{ {
/* Found here, adding to queue */ /* Found here, adding to queue */
queue_top(&(info->by_key))=(uchar *)(info->current_table); queue_top(&(info->by_key))=(uchar *)(info->current_table);
queue_replaced(&(info->by_key)); queue_replace_top(&(info->by_key));
} }
/* now, mymerge's read_next is as simple as one queue_top */ /* now, mymerge's read_next is as simple as one queue_top */

View File

@ -32,7 +32,7 @@ int myrg_rprev(MYRG_INFO *info, uchar *buf, int inx)
{ {
if (err == HA_ERR_END_OF_FILE) if (err == HA_ERR_END_OF_FILE)
{ {
queue_remove(&(info->by_key),0); queue_remove_top(&(info->by_key));
if (!info->by_key.elements) if (!info->by_key.elements)
return HA_ERR_END_OF_FILE; return HA_ERR_END_OF_FILE;
} }
@ -43,7 +43,7 @@ int myrg_rprev(MYRG_INFO *info, uchar *buf, int inx)
{ {
/* Found here, adding to queue */ /* Found here, adding to queue */
queue_top(&(info->by_key))=(uchar *)(info->current_table); queue_top(&(info->by_key))=(uchar *)(info->current_table);
queue_replaced(&(info->by_key)); queue_replace_top(&(info->by_key));
} }
/* now, mymerge's read_prev is as simple as one queue_top */ /* now, mymerge's read_prev is as simple as one queue_top */