summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@hundin.mysql.fi>2001-12-05 13:03:00 +0200
committerunknown <monty@hundin.mysql.fi>2001-12-05 13:03:00 +0200
commiteca2a1a3dcd0b64b3fdfefe78f981d654396451c (patch)
tree739c2cfffa69408c6460ba4c419a59d5b594cbb1 /sql
parent7c999bb03223114a4d07f23db2842363d32d1859 (diff)
downloadmariadb-git-eca2a1a3dcd0b64b3fdfefe78f981d654396451c.tar.gz
Update of query cache code.
Changed some sql_alloc() -> thd->alloc() Removed a lot of compiler warnings on Linux Alpha (64 bit) Fixed some core dumps on 64 bit systems (wrong type for packet_len) Docs/manual.texi: Added base information about the query cache. include/hash.h: Export hash_replace include/myisam.h: Update of query cache code libmysql/net.c: Add casts to make things safe on 64 bit systems. myisam/mi_write.c: Update of query cache code myisammrg/myrg_extra.c: Update of query cache code mysys/hash.c: Added safety check to hash_replace sql/field.cc: Removed compiler warnings. sql/field.h: Removed compiler warnings sql/ha_myisam.cc: Fixed wrong type of packet_len sql/item.h: Remove warnings sql/log_event.cc: Cleanup sql/log_event.h: Cleanup to make code more readable sql/mf_iocache.cc: Fixed wrong type sql/mysql_priv.h: Update of query cache code sql/mysqld.cc: Update of query cache code sql/net_serv.cc: Remove compiler warnings sql/opt_range.h: Remove compiler warnings sql/sql_cache.cc: Update of query cache code sql/sql_cache.h: Update of query cache code sql/sql_class.h: Cleanup sql/sql_insert.cc: Use thd->alloc() instead of sql_alloc() sql/sql_parse.cc: Fixed compiler warnings. Changed some sql_alloc() -> thd->alloc() sql/sql_select.cc: Changed sql_alloc() -> thd_alloc() sql/sql_select.h: Faster alloc() sql/sql_show.cc: Update of query cache code sql/sql_table.cc: Faster alloc() sql/table.cc: Faster alloc()
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc235
-rw-r--r--sql/field.h140
-rw-r--r--sql/ha_myisam.cc4
-rw-r--r--sql/item.h4
-rw-r--r--sql/log_event.cc248
-rw-r--r--sql/log_event.h265
-rw-r--r--sql/mf_iocache.cc4
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/mysqld.cc12
-rw-r--r--sql/net_serv.cc36
-rw-r--r--sql/opt_range.h6
-rw-r--r--sql/sql_cache.cc2610
-rw-r--r--sql/sql_cache.h198
-rw-r--r--sql/sql_class.h83
-rw-r--r--sql/sql_insert.cc8
-rw-r--r--sql/sql_parse.cc110
-rw-r--r--sql/sql_select.cc43
-rw-r--r--sql/sql_select.h18
-rw-r--r--sql/sql_show.cc5
-rw-r--r--sql/sql_table.cc2
-rw-r--r--sql/table.cc3
21 files changed, 2119 insertions, 1917 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 2f98d2e0fe8..fc5feba8eb8 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -219,14 +219,15 @@ static bool test_if_real(const char *str,int length)
****************************************************************************/
Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
- :ptr(ptr_arg),null_ptr(null_ptr_arg),null_bit(null_bit_arg),
- table(table_arg),query_id(0),key_start(0),part_of_key(0),part_of_sortkey(0),
- table_name(table_arg ? table_arg->table_name : 0),
- field_name(field_name_arg), unireg_check(unireg_check_arg),
- field_length(length_arg)
+ :ptr(ptr_arg),null_ptr(null_ptr_arg),
+ table(table_arg),table_name(table_arg ? table_arg->table_name : 0),
+ field_name(field_name_arg),
+ query_id(0),key_start(0),part_of_key(0),part_of_sortkey(0),
+ unireg_check(unireg_check_arg),
+ field_length(length_arg),null_bit(null_bit_arg)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
}
@@ -242,8 +243,8 @@ void Field::copy_from_tmp(int row_offset)
memcpy(ptr,ptr+row_offset,pack_length());
if (null_ptr)
{
- *null_ptr= ((null_ptr[0] & (uchar) ~(uint) null_bit) |
- null_ptr[row_offset] & (uchar) null_bit);
+ *null_ptr= (uchar) ((null_ptr[0] & (uchar) ~(uint) null_bit) |
+ null_ptr[row_offset] & (uchar) null_bit);
}
}
@@ -1049,7 +1050,7 @@ void Field_short::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[0];
else
- to[0] = ptr[0] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
to[1] = ptr[1];
}
else
@@ -1058,7 +1059,7 @@ void Field_short::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[1];
else
- to[0] = ptr[1] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[1] ^ 128); /* Revers signbit */
to[1] = ptr[0];
}
}
@@ -1129,12 +1130,12 @@ void Field_medium::store(double nr)
}
else if (nr >= (double) (long) (1L << 24))
{
- ulong tmp=(ulong) (1L << 24)-1L;
+ uint32 tmp=(uint32) (1L << 24)-1L;
int3store(ptr,tmp);
current_thd->cuted_fields++;
}
else
- int3store(ptr,(ulong) nr);
+ int3store(ptr,(uint32) nr);
}
else
{
@@ -1171,7 +1172,7 @@ void Field_medium::store(longlong nr)
current_thd->cuted_fields++;
}
else
- int3store(ptr,(ulong) nr);
+ int3store(ptr,(uint32) nr);
}
else
{
@@ -1449,7 +1450,7 @@ int Field_long::cmp(const char *a_ptr, const char *b_ptr)
longget(b,b_ptr);
}
if (unsigned_flag)
- return ((ulong) a < (ulong) b) ? -1 : ((ulong) a > (ulong) b) ? 1 : 0;
+ return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 : 0;
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
@@ -1461,7 +1462,7 @@ void Field_long::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[0];
else
- to[0] = ptr[0] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
to[1] = ptr[1];
to[2] = ptr[2];
to[3] = ptr[3];
@@ -1472,7 +1473,7 @@ void Field_long::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[3];
else
- to[0] = ptr[3] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[3] ^ 128); /* Revers signbit */
to[1] = ptr[2];
to[2] = ptr[1];
to[3] = ptr[0];
@@ -1660,7 +1661,7 @@ void Field_longlong::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[0];
else
- to[0] = ptr[0] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
to[1] = ptr[1];
to[2] = ptr[2];
to[3] = ptr[3];
@@ -1675,7 +1676,7 @@ void Field_longlong::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[7];
else
- to[0] = ptr[7] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[7] ^ 128); /* Revers signbit */
to[1] = ptr[6];
to[2] = ptr[5];
to[3] = ptr[4];
@@ -1910,7 +1911,7 @@ void Field_float::sort_string(char *to,uint length __attribute__((unused)))
{ /* make complement */
uint i;
for (i=0 ; i < sizeof(nr); i++)
- tmp[i]=tmp[i] ^ (uchar) 255;
+ tmp[i]= (uchar) (tmp[i] ^ (uchar) 255);
}
else
{
@@ -2278,10 +2279,10 @@ void Field_timestamp::store(longlong nr)
{
part1=(long) (nr/LL(1000000));
part2=(long) (nr - (longlong) part1*LL(1000000));
- l_time.year= part1/10000L; part1%=10000L;
+ l_time.year= (int) (part1/10000L); part1%=10000L;
l_time.month= (int) part1 / 100;
- l_time.day= (int) part1 % 100;
- l_time.hour= part2/10000L; part2%=10000L;
+ l_time.day= (int) part1 % 100;
+ l_time.hour= (int) (part2/10000L); part2%=10000L;
l_time.minute=(int) part2 / 100;
l_time.second=(int) part2 % 100;
timestamp=my_gmt_sec(&l_time);
@@ -2295,7 +2296,7 @@ void Field_timestamp::store(longlong nr)
}
else
#endif
- longstore(ptr,(ulong)timestamp);
+ longstore(ptr,(uint32) timestamp);
}
@@ -2596,7 +2597,7 @@ void Field_time::store(longlong nr)
double Field_time::val_real(void)
{
- ulong j= (ulong) uint3korr(ptr);
+ uint32 j= (uint32) uint3korr(ptr);
return (double) j;
}
@@ -2632,19 +2633,19 @@ bool Field_time::get_time(TIME *ltime)
ltime->neg= 1;
tmp=-tmp;
}
- ltime->hour=tmp/10000;
+ ltime->hour= (int) (tmp/10000);
tmp-=ltime->hour*10000;
- ltime->minute= tmp/100;
- ltime->second= tmp % 100;
+ ltime->minute= (int) tmp/100;
+ ltime->second= (int) tmp % 100;
ltime->second_part=0;
return 0;
}
int Field_time::cmp(const char *a_ptr, const char *b_ptr)
{
- long a,b;
- a=(long) sint3korr(a_ptr);
- b=(long) sint3korr(b_ptr);
+ int32 a,b;
+ a=(int32) sint3korr(a_ptr);
+ b=(int32) sint3korr(b_ptr);
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
@@ -2755,14 +2756,14 @@ void Field_year::sql_type(String &res) const
** Stored as a 4 byte unsigned int
****************************************************************************/
-void Field_date::store(const char *from,uint len)
+void Field_date::store(const char *from, uint len)
{
TIME l_time;
- ulong tmp;
+ uint32 tmp;
if (str_to_TIME(from,len,&l_time,1) == TIMESTAMP_NONE)
tmp=0;
else
- tmp=(ulong) l_time.year*10000L + (ulong) (l_time.month*100+l_time.day);
+ tmp=(uint32) l_time.year*10000L + (uint32) (l_time.month*100+l_time.day);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -2934,7 +2935,7 @@ void Field_newdate::store(double nr)
void Field_newdate::store(longlong nr)
{
- long tmp;
+ int32 tmp;
if (nr >= LL(100000000) && nr <= LL(99991231235959))
nr=nr/LL(1000000); // Timestamp to date
if (nr < 0L || nr > 99991231L)
@@ -2944,16 +2945,16 @@ void Field_newdate::store(longlong nr)
}
else
{
- tmp=(long) nr;
+ tmp=(int32) nr;
if (tmp)
{
if (tmp < YY_PART_YEAR*10000L) // Fix short dates
- tmp+=20000000L;
+ tmp+= (uint32) 20000000L;
else if (tmp < 999999L)
- tmp+=19000000L;
+ tmp+= (uint32) 19000000L;
}
- uint month=((tmp/100) % 100);
- uint day= tmp%100;
+ uint month= (uint) ((tmp/100) % 100);
+ uint day= (uint) (tmp%100);
if (month > 12 || day > 31)
{
tmp=0L; // Don't allow date to change
@@ -2962,7 +2963,7 @@ void Field_newdate::store(longlong nr)
else
tmp= day + month*32 + (tmp/10000)*16*32;
}
- int3store(ptr,tmp);
+ int3store(ptr,(int32) tmp);
}
void Field_newdate::store_time(TIME *ltime,timestamp_type type)
@@ -2987,7 +2988,7 @@ double Field_newdate::val_real(void)
longlong Field_newdate::val_int(void)
{
- ulong j=uint3korr(ptr);
+ ulong j= uint3korr(ptr);
j= (j % 32L)+(j / 32L % 16L)*100L + (j/(16L*32L))*10000L;
return (longlong) j;
}
@@ -2997,25 +2998,25 @@ String *Field_newdate::val_str(String *val_buffer,
{
val_buffer->alloc(field_length);
val_buffer->length(field_length);
- ulong tmp=(ulong) uint3korr(ptr);
+ uint32 tmp=(uint32) uint3korr(ptr);
int part;
char *pos=(char*) val_buffer->ptr()+10;
/* Open coded to get more speed */
- *pos--=0;
+ *pos--=0; // End NULL
part=(int) (tmp & 31);
- *pos--='0'+part%10;
- *pos--='0'+part/10;
- *pos--='-';
+ *pos--= (char) ('0'+part%10);
+ *pos--= (char) ('0'+part/10);
+ *pos--= '-';
part=(int) (tmp >> 5 & 15);
- *pos--='0'+part%10;
- *pos--='0'+part/10;
- *pos--='-';
+ *pos--= (char) ('0'+part%10);
+ *pos--= (char) ('0'+part/10);
+ *pos--= '-';
part=(int) (tmp >> 9);
- *pos--='0'+part%10; part/=10;
- *pos--='0'+part%10; part/=10;
- *pos--='0'+part%10; part/=10;
- *pos='0'+part;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos= (char) ('0'+part);
return val_buffer;
}
@@ -3023,7 +3024,7 @@ bool Field_newdate::get_date(TIME *ltime,bool fuzzydate)
{
if (is_null())
return 1;
- ulong tmp=(ulong) uint3korr(ptr);
+ uint32 tmp=(uint32) uint3korr(ptr);
bzero((char*) ltime,sizeof(*ltime));
ltime->day= tmp & 31;
ltime->month= (tmp >> 5) & 15;
@@ -3039,9 +3040,9 @@ bool Field_newdate::get_time(TIME *ltime)
int Field_newdate::cmp(const char *a_ptr, const char *b_ptr)
{
- ulong a,b;
- a=(ulong) uint3korr(a_ptr);
- b=(ulong) uint3korr(b_ptr);
+ uint32 a,b;
+ a=(uint32) uint3korr(a_ptr);
+ b=(uint32) uint3korr(b_ptr);
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
@@ -3175,44 +3176,44 @@ String *Field_datetime::val_str(String *val_buffer,
pos=(char*) val_buffer->ptr()+19;
*pos--=0;
- *pos--='0'+(char) (part2%10); part2/=10;
- *pos--='0'+(char) (part2%10); part3= (int) (part2 / 10);
- *pos--=':';
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--=':';
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) part3;
- *pos--=' ';
- *pos--='0'+(char) (part1%10); part1/=10;
- *pos--='0'+(char) (part1%10); part1/=10;
- *pos--='-';
- *pos--='0'+(char) (part1%10); part1/=10;
- *pos--='0'+(char) (part1%10); part3= (int) (part1/10);
- *pos--='-';
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos='0'+(char) part3;
+ *pos--= (char) ('0'+(char) (part2%10)); part2/=10;
+ *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
+ *pos--= ':';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= ':';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) part3);
+ *pos--= ' ';
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= '-';
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
+ *pos--= '-';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos=(char) ('0'+(char) part3);
return val_buffer;
}
bool Field_datetime::get_date(TIME *ltime,bool fuzzydate)
{
longlong tmp=Field_datetime::val_int();
- long part1,part2;
- part1=(long) (tmp/LL(1000000));
- part2=(long) (tmp - (ulonglong) part1*LL(1000000));
+ uint32 part1,part2;
+ part1=(uint32) (tmp/LL(1000000));
+ part2=(uint32) (tmp - (ulonglong) part1*LL(1000000));
ltime->time_type= TIMESTAMP_FULL;
- ltime->neg=0;
- ltime->second_part=0;
- ltime->second= part2%100;
- ltime->minute= part2/100%100;
- ltime->hour= part2/10000;
- ltime->day= part1%100;
- ltime->month= part1/100%100;
- ltime->year= part1/10000;
+ ltime->neg= 0;
+ ltime->second_part= 0;
+ ltime->second= (int) (part2%100);
+ ltime->minute= (int) (part2/100%100);
+ ltime->hour= (int) (part2/10000);
+ ltime->day= (int) (part1%100);
+ ltime->month= (int) (part1/100%100);
+ ltime->year= (int) (part1/10000);
return (!fuzzydate && (!ltime->month || !ltime->day)) ? 1 : 0;
}
@@ -3331,7 +3332,7 @@ void Field_string::store(longlong nr)
{
char buff[22];
char *end=longlong10_to_str(nr,buff,-10);
- Field_string::store(buff,end-buff);
+ Field_string::store(buff,(uint) (end-buff));
}
@@ -3522,7 +3523,7 @@ void Field_varstring::store(longlong nr)
{
char buff[22];
char *end=longlong10_to_str(nr,buff,-10);
- Field_varstring::store(buff,end-buff);
+ Field_varstring::store(buff,(uint) (end-buff));
}
@@ -3613,9 +3614,9 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length)
uint length=uint2korr(from);
if (length > max_length)
length=max_length;
- *to++= (length & 255);
+ *to++= (char) (length & 255);
if (max_length > 255)
- *to++= (uchar) (length >> 8);
+ *to++= (char) (length >> 8);
if (length)
memcpy(to, from+2, length);
return to+length;
@@ -3704,7 +3705,7 @@ uint Field_varstring::max_packed_col_length(uint max_length)
** packlength slot and may be from 1-4.
****************************************************************************/
-Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
bool binary_arg)
@@ -3721,7 +3722,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
}
-void Field_blob::store_length(ulong number)
+void Field_blob::store_length(uint32 number)
{
switch (packlength) {
case 1:
@@ -3748,9 +3749,9 @@ void Field_blob::store_length(ulong number)
shortstore(ptr,(unsigned short) number);
break;
case 3:
- if (number > (ulong) (1L << 24))
+ if (number > (uint32) (1L << 24))
{
- number= (ulong) (1L << 24)-1L;
+ number= (uint32) (1L << 24)-1L;
current_thd->cuted_fields++;
}
int3store(ptr,number);
@@ -3768,11 +3769,11 @@ void Field_blob::store_length(ulong number)
}
-ulong Field_blob::get_length(const char *pos)
+uint32 Field_blob::get_length(const char *pos)
{
switch (packlength) {
case 1:
- return (ulong) (uchar) pos[0];
+ return (uint32) (uchar) pos[0];
case 2:
{
uint16 tmp;
@@ -3782,10 +3783,10 @@ ulong Field_blob::get_length(const char *pos)
else
#endif
shortget(tmp,pos);
- return (ulong) tmp;
+ return (uint32) tmp;
}
case 3:
- return (ulong) uint3korr(pos);
+ return (uint32) uint3korr(pos);
case 4:
{
uint32 tmp;
@@ -3795,7 +3796,7 @@ ulong Field_blob::get_length(const char *pos)
else
#endif
longget(tmp,pos);
- return (ulong) tmp;
+ return (uint32) tmp;
}
}
return 0; // Impossible
@@ -3841,14 +3842,14 @@ void Field_blob::store(const char *from,uint len)
void Field_blob::store(double nr)
{
value.set(nr);
- Field_blob::store(value.ptr(),value.length());
+ Field_blob::store(value.ptr(),(uint) value.length());
}
void Field_blob::store(longlong nr)
{
value.set(nr);
- Field_blob::store(value.ptr(),value.length());
+ Field_blob::store(value.ptr(), (uint) value.length());
}
@@ -3859,7 +3860,7 @@ double Field_blob::val_real(void)
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
return 0.0;
- ulong length=get_length(ptr);
+ uint32 length=get_length(ptr);
char save=blob[length]; // Ok to patch blob in NISAM
blob[length]=0;
@@ -3875,7 +3876,7 @@ longlong Field_blob::val_int(void)
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
return 0;
- ulong length=get_length(ptr);
+ uint32 length=get_length(ptr);
char save=blob[length]; // Ok to patch blob in NISAM
blob[length]=0;
@@ -3898,8 +3899,8 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
}
-int Field_blob::cmp(const char *a,ulong a_length, const char *b,
- ulong b_length)
+int Field_blob::cmp(const char *a,uint32 a_length, const char *b,
+ uint32 b_length)
{
int diff;
if (binary_flag)
@@ -3933,11 +3934,11 @@ int Field_blob::cmp_binary_offset(uint row_offset)
int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
- ulong max_length)
+ uint32 max_length)
{
char *a,*b;
uint diff;
- ulong a_length,b_length;
+ uint32 a_length,b_length;
memcpy_fixed(&a,a_ptr+packlength,sizeof(char*));
memcpy_fixed(&b,b_ptr+packlength,sizeof(char*));
a_length=get_length(a_ptr);
@@ -3956,9 +3957,9 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
void Field_blob::get_key_image(char *buff,uint length)
{
length-=HA_KEY_BLOB_LENGTH;
- ulong blob_length=get_length(ptr);
+ uint32 blob_length=get_length(ptr);
char *blob;
- if ((ulong) length > blob_length)
+ if ((uint32) length > blob_length)
{
#ifdef HAVE_purify
bzero(buff+2+blob_length, (length-blob_length));
@@ -4052,7 +4053,7 @@ char *Field_blob::pack(char *to, const char *from, uint max_length)
{
char *save=ptr;
ptr=(char*) from;
- ulong length=get_length(); // Length of from string
+ uint32 length=get_length(); // Length of from string
if (length > max_length)
{
ptr=to;
@@ -4075,7 +4076,7 @@ char *Field_blob::pack(char *to, const char *from, uint max_length)
const char *Field_blob::unpack(char *to, const char *from)
{
memcpy(to,from,packlength);
- ulong length=get_length(from);
+ uint32 length=get_length(from);
from+=packlength;
if (length)
memcpy_fixed(to+packlength, &from, sizeof(from));
@@ -4140,7 +4141,7 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length)
{
char *save=ptr;
ptr=(char*) from;
- ulong length=get_length(); // Length of from string
+ uint32 length=get_length(); // Length of from string
if (length > max_length)
length=max_length;
*to++= (uchar) length;
@@ -4163,9 +4164,9 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from,
uint length=uint2korr(from);
if (length > max_length)
length=max_length;
- *to++= (length & 255);
+ *to++= (char) (length & 255);
if (max_length > 255)
- *to++= (uchar) (length >> 8);
+ *to++= (char) (length >> 8);
if (length)
memcpy(to, from+2, length);
return to+length;
@@ -4278,7 +4279,7 @@ void Field_enum::store(const char *from,uint length)
conv=buff;
}
my_errno=0;
- tmp=strtoul(conv,&end,10);
+ tmp=(uint) strtoul(conv,&end,10);
if (my_errno || end != conv+length || tmp > typelib->count)
{
tmp=0;
@@ -4624,7 +4625,7 @@ uint pack_length_to_packflag(uint type)
Field *make_field(char *ptr, uint32 field_length,
- uchar *null_pos, uint null_bit,
+ uchar *null_pos, uchar null_bit,
uint pack_flag,
Field::utype unireg_check,
TYPELIB *interval,
diff --git a/sql/field.h b/sql/field.h
index e2af9853512..03fd6d46a78 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -16,8 +16,8 @@
/*
-** Because of the function new_field all field classes that have static
-** variables must declare the size_of() member function.
+ Because of the function new_field() all field classes that have static
+ variables must declare the size_of() member function.
*/
#ifdef __GNUC__
@@ -37,21 +37,22 @@ public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
static void operator delete(void *ptr_arg, size_t size) {} /*lint -e715 */
- enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL,
- CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD,
- BIT_FIELD, TIMESTAMP_FIELD,CAPITALIZE,BLOB_FIELD};
- char *ptr; // Position to field in record
+ char *ptr; // Position to field in record
uchar *null_ptr; // Byte where null_bit is
- uint8 null_bit; // And position to it
struct st_table *table; // Pointer for table
- ulong query_id; // For quick test of used fields
- key_map key_start,part_of_key,part_of_sortkey;// Field is part of these keys.
- const char *table_name,*field_name;
- utype unireg_check;
- uint32 field_length; // Length of field
- uint16 flags;
-
- Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uint null_bit_arg,
+ const char *table_name,*field_name;
+ ulong query_id; // For quick test of used fields
+ // Field is part of the following keys
+ key_map key_start,part_of_key,part_of_sortkey;
+ enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL,
+ CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD,
+ BIT_FIELD, TIMESTAMP_FIELD,CAPITALIZE,BLOB_FIELD};
+ utype unireg_check;
+ uint32 field_length; // Length of field
+ uint16 flags;
+ uchar null_bit; // Bit used to test null bit
+
+ Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg);
virtual ~Field() {}
@@ -77,7 +78,7 @@ public:
virtual enum_field_types real_type() const { return type(); }
inline int cmp(const char *str) { return cmp(ptr,str); }
virtual int cmp(const char *,const char *)=0;
- virtual int cmp_binary(const char *a,const char *b, ulong max_length=~0L)
+ virtual int cmp_binary(const char *a,const char *b, uint32 max_length=~0L)
{ return memcmp(a,b,pack_length()); }
virtual int cmp_offset(uint row_offset)
{ return memcmp(ptr,ptr+row_offset,pack_length()); }
@@ -101,30 +102,30 @@ public:
inline void set_null(int row_offset=0)
{ if (null_ptr) null_ptr[row_offset]|= null_bit; }
inline void set_notnull(int row_offset=0)
- { if (null_ptr) null_ptr[row_offset]&= ~null_bit; }
+ { if (null_ptr) null_ptr[row_offset]&= (uchar) ~null_bit; }
inline bool maybe_null(void) { return null_ptr != 0 || table->maybe_null; }
inline bool real_maybe_null(void) { return null_ptr != 0; }
virtual void make_field(Send_field *)=0;
virtual void sort_string(char *buff,uint length)=0;
virtual bool optimize_range();
virtual bool store_for_compare() { return 0; }
- inline Field *new_field(struct st_table *new_table)
- {
- Field *tmp= (Field*) sql_memdup((char*) this,size_of());
- if (tmp)
- {
- tmp->table=new_table;
- tmp->key_start=tmp->part_of_key=tmp->part_of_sortkey=0;
- tmp->unireg_check=Field::NONE;
- tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
- tmp->reset_fields();
- }
- return tmp;
- }
- inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uint null_bit_arg)
+ Field *new_field(MEM_ROOT *root, struct st_table *new_table)
+ {
+ Field *tmp= (Field*) memdup_root(root,(char*) this,size_of());
+ if (tmp)
{
- ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
+ tmp->table=new_table;
+ tmp->key_start=tmp->part_of_key=tmp->part_of_sortkey=0;
+ tmp->unireg_check=Field::NONE;
+ tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
+ tmp->reset_fields();
}
+ return tmp;
+ }
+ inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
+ {
+ ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
+ }
inline void move_field(char *ptr_arg) { ptr=ptr_arg; }
inline void move_field(my_ptrdiff_t ptr_diff)
{
@@ -157,7 +158,7 @@ public:
bool send(THD *thd, String *packet);
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
{
- uint length=pack_length();
+ uint32 length=pack_length();
memcpy(to,from,length);
return to+length;
}
@@ -212,10 +213,10 @@ public:
const uint8 dec;
bool zerofill,unsigned_flag; // Purify cannot handle bit fields
Field_num(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg, utype unireg_check_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg),
dec(dec_arg),zerofill(zero_arg),unsigned_flag(unsigned_arg)
@@ -230,7 +231,7 @@ public:
void add_zerofill_and_unsigned(String &res) const;
friend class create_field;
void make_field(Send_field *);
- uint decimals() const { return dec; }
+ uint decimals() const { return (uint) dec; }
uint size_of() const { return sizeof(*this); }
bool eq_def(Field *field);
};
@@ -239,7 +240,7 @@ public:
class Field_str :public Field {
public:
Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg, utype unireg_check_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
struct st_table *table_arg)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -256,10 +257,10 @@ public:
class Field_decimal :public Field_num {
public:
Field_decimal(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg,unsigned_arg)
@@ -285,7 +286,7 @@ public:
class Field_tiny :public Field_num {
public:
Field_tiny(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -314,7 +315,7 @@ public:
class Field_short :public Field_num {
public:
Field_short(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -343,7 +344,7 @@ public:
class Field_medium :public Field_num {
public:
Field_medium(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -372,7 +373,7 @@ public:
class Field_long :public Field_num {
public:
Field_long(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -407,7 +408,7 @@ public:
class Field_longlong :public Field_num {
public:
Field_longlong(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -442,10 +443,10 @@ public:
class Field_float :public Field_num {
public:
Field_float(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg,unsigned_arg)
@@ -469,16 +470,16 @@ public:
class Field_double :public Field_num {
public:
Field_double(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg,unsigned_arg)
{}
Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg,
- struct st_table *table_arg, uint dec_arg)
+ struct st_table *table_arg, uint8 dec_arg)
:Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0,
NONE, field_name_arg, table_arg,dec_arg,0,0)
{}
@@ -567,7 +568,7 @@ public:
class Field_year :public Field_tiny {
public:
Field_year(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
:Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -586,7 +587,7 @@ public:
class Field_date :public Field_str {
public:
- Field_date(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_date(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
:Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg,
@@ -612,7 +613,7 @@ public:
class Field_newdate :public Field_str {
public:
- Field_newdate(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_newdate(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
:Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg,
@@ -643,7 +644,7 @@ public:
class Field_time :public Field_str {
public:
- Field_time(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_time(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
:Field_str(ptr_arg, 8, null_ptr_arg, null_bit_arg,
@@ -671,7 +672,7 @@ public:
class Field_datetime :public Field_str {
public:
- Field_datetime(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_datetime(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
:Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg,
@@ -705,7 +706,7 @@ class Field_string :public Field_str {
bool binary_flag;
public:
Field_string(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,bool binary_arg)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -760,7 +761,7 @@ class Field_varstring :public Field_str {
bool binary_flag;
public:
Field_varstring(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,bool binary_arg)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -813,7 +814,7 @@ class Field_blob :public Field_str {
String value; // For temporaries
bool binary_flag;
public:
- Field_blob(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
bool binary_arg);
@@ -837,21 +838,22 @@ public:
longlong val_int(void);
String *val_str(String*,String *);
int cmp(const char *,const char*);
- int cmp(const char *a, ulong a_length, const char *b, ulong b_length);
+ int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
int cmp_offset(uint offset);
- int cmp_binary(const char *a,const char *b, ulong max_length=~0L);
+ int cmp_binary(const char *a,const char *b, uint32 max_length=~0L);
int cmp_binary_offset(uint row_offset);
int key_cmp(const byte *,const byte*);
int key_cmp(const byte *str, uint length);
uint32 key_length() const { return 0; }
void sort_string(char *buff,uint length);
- uint32 pack_length() const { return (uint32) (packlength+table->blob_ptr_size); }
- void reset(void) { bzero(ptr,packlength+sizeof(char*)); }
+ uint32 pack_length() const
+ { return (uint32) (packlength+table->blob_ptr_size); }
+ void reset(void) { bzero(ptr, packlength+sizeof(char*)); }
void reset_fields() { bzero((char*) &value,sizeof(value)); }
- void store_length(ulong number);
- inline ulong get_length(uint row_offset=0)
+ void store_length(uint32 number);
+ inline uint32 get_length(uint row_offset=0)
{ return get_length(ptr+row_offset); }
- ulong get_length(const char *ptr);
+ uint32 get_length(const char *ptr);
bool binary() const { return binary_flag; }
inline void get_ptr(char **str)
{
@@ -862,7 +864,7 @@ public:
memcpy(ptr,length,packlength);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
}
- inline void set_ptr(ulong length,char *data)
+ inline void set_ptr(uint32 length,char *data)
{
store_length(length);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
@@ -902,7 +904,7 @@ protected:
public:
TYPELIB *typelib;
Field_enum(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint packlength_arg,
TYPELIB *typelib_arg)
@@ -939,7 +941,7 @@ public:
class Field_set :public Field_enum {
public:
Field_set(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint32 packlength_arg,
TYPELIB *typelib_arg)
@@ -1022,7 +1024,7 @@ public:
Field *make_field(char *ptr, uint32 field_length,
- uchar *null_pos, uint null_bit,
+ uchar *null_pos, uchar null_bit,
uint pack_flag, Field::utype unireg_check,
TYPELIB *interval, const char *field_name,
struct st_table *table);
@@ -1065,7 +1067,7 @@ bool test_if_int(const char *str,int length);
#define f_is_zerofill(x) ((x) & FIELDFLAG_ZEROFILL)
#define f_is_packed(x) ((x) & FIELDFLAG_PACK)
#define f_packtype(x) (((x) >> FIELDFLAG_PACK_SHIFT) & 15)
-#define f_decimals(x) (((x) >> FIELDFLAG_DEC_SHIFT) & FIELDFLAG_MAX_DEC)
+#define f_decimals(x) ((uint8) (((x) >> FIELDFLAG_DEC_SHIFT) & FIELDFLAG_MAX_DEC))
#define f_is_alpha(x) (!f_is_num(x))
#define f_is_binary(x) ((x) & FIELDFLAG_BINARY)
#define f_is_enum(x) ((x) & FIELDFLAG_INTERVAL)
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 7a8585975cc..fa130c59a88 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -130,7 +130,7 @@ int ha_myisam::net_read_dump(NET* net)
my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME));
for(;;)
{
- uint packet_len = my_net_read(net);
+ ulong packet_len = my_net_read(net);
if (!packet_len)
break ; // end of file
if (packet_len == packet_error)
@@ -139,7 +139,7 @@ int ha_myisam::net_read_dump(NET* net)
error= -1;
goto err;
}
- if (my_write(data_fd, (byte*)net->read_pos, packet_len,
+ if (my_write(data_fd, (byte*)net->read_pos, (uint) packet_len,
MYF(MY_WME|MY_FNABP)))
{
error = errno;
diff --git a/sql/item.h b/sql/item.h
index a52860528f1..355d81d0c6c 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -206,14 +206,14 @@ public:
Item_real(const char *str_arg,uint length) :value(atof(str_arg))
{
name=(char*) str_arg;
- decimals=nr_of_decimals(str_arg);
+ decimals=(uint8) nr_of_decimals(str_arg);
max_length=length;
}
Item_real(const char *str,double val_arg,uint decimal_par,uint length)
:value(val_arg)
{
name=(char*) str;
- decimals=decimal_par;
+ decimals=(uint8) decimal_par;
max_length=length;
}
Item_real(double value_par) :value(value_par) {}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 72198038a07..b8c2435e84e 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -193,14 +193,14 @@ void Query_log_event::pack_info(String* packet)
char buf[256];
String tmp(buf, sizeof(buf));
tmp.length(0);
- if(db && db_len)
+ if (db && db_len)
{
tmp.append("use ");
tmp.append(db, db_len);
tmp.append("; ", 2);
}
- if(query && q_len)
+ if (query && q_len)
tmp.append(query, q_len);
net_store_data(packet, (char*)tmp.ptr(), tmp.length());
}
@@ -224,7 +224,7 @@ void Load_log_event::pack_info(String* packet)
char buf[256];
String tmp(buf, sizeof(buf));
tmp.length(0);
- if(db && db_len)
+ if (db && db_len)
{
tmp.append("use ");
tmp.append(db, db_len);
@@ -234,9 +234,9 @@ void Load_log_event::pack_info(String* packet)
tmp.append("LOAD DATA INFILE '");
tmp.append(fname, fname_len);
tmp.append("' ", 2);
- if(sql_ex.opt_flags && REPLACE_FLAG )
+ if (sql_ex.opt_flags && REPLACE_FLAG )
tmp.append(" REPLACE ");
- else if(sql_ex.opt_flags && IGNORE_FLAG )
+ else if (sql_ex.opt_flags && IGNORE_FLAG )
tmp.append(" IGNORE ");
tmp.append("INTO TABLE ");
@@ -278,12 +278,11 @@ void Load_log_event::pack_info(String* packet)
if (num_fields)
{
- uint i;
const char* field = fields;
tmp.append(" (");
- for(i = 0; i < num_fields; i++)
+ for (uint i = 0; i < num_fields; i++)
{
- if(i)
+ if (i)
tmp.append(" ,");
tmp.append( field);
@@ -304,7 +303,7 @@ void Rotate_log_event::pack_info(String* packet)
tmp.append(new_log_ident, ident_len);
tmp.append(";pos=");
tmp.append(llstr(pos,buf));
- if(flags & LOG_EVENT_FORCED_ROTATE_F)
+ if (flags & LOG_EVENT_FORCED_ROTATE_F)
tmp.append("; forced by master");
net_store_data(packet, tmp.ptr(), tmp.length());
}
@@ -414,7 +413,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
// if the read hits eof, we must report it as eof
// so the caller will know it can go into cond_wait to be woken up
// on the next update to the log
- if(!file->error) return LOG_READ_EOF;
+ if (!file->error) return LOG_READ_EOF;
return file->error > 0 ? LOG_READ_TRUNC: LOG_READ_IO;
}
data_len = uint4korr(buf + EVENT_LEN_OFFSET);
@@ -430,7 +429,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
{
if (packet->append(file, data_len))
{
- if(log_lock)
+ if (log_lock)
pthread_mutex_unlock(log_lock);
// here we should never hit eof in a non-error condtion
// eof means we are reading the event partially, which should
@@ -445,13 +444,13 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
#endif // MYSQL_CLIENT
#ifndef MYSQL_CLIENT
-#define UNLOCK_MUTEX if(log_lock) pthread_mutex_unlock(log_lock);
+#define UNLOCK_MUTEX if (log_lock) pthread_mutex_unlock(log_lock);
#else
#define UNLOCK_MUTEX
#endif
#ifndef MYSQL_CLIENT
-#define LOCK_MUTEX if(log_lock) pthread_mutex_lock(log_lock);
+#define LOCK_MUTEX if (log_lock) pthread_mutex_lock(log_lock);
#else
#define LOCK_MUTEX
#endif
@@ -501,7 +500,7 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, bool old_format)
}
buf[data_len] = 0;
memcpy(buf, head, header_size);
- if(my_b_read(file, (byte*) buf + header_size,
+ if (my_b_read(file, (byte*) buf + header_size,
data_len - header_size))
{
error = "read error";
@@ -511,7 +510,7 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, bool old_format)
res->register_temp_buf(buf);
err:
UNLOCK_MUTEX;
- if(error)
+ if (error)
{
sql_print_error(error);
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
@@ -679,7 +678,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
// EVENT_LEN_OFFSET
int header_size = (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
uint ident_offset;
- if(event_len < header_size)
+ if (event_len < header_size)
return;
buf += header_size;
if (old_format)
@@ -775,9 +774,9 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
bool same_db = 0;
- if(db && last_db)
+ if (db && last_db)
{
- if(!(same_db = !memcmp(last_db, db, db_len + 1)))
+ if (!(same_db = !memcmp(last_db, db, db_len + 1)))
memcpy(last_db, db, db_len + 1);
}
@@ -838,7 +837,7 @@ int Intvar_log_event::write_data(IO_CACHE* file)
void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
{
char llbuff[22];
- if(!short_form)
+ if (!short_form)
{
print_header(file);
fprintf(file, "\tIntvar\n");
@@ -971,86 +970,83 @@ char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
#ifndef MYSQL_CLIENT
Load_log_event::Load_log_event(THD* thd, sql_exchange* ex,
const char* db_arg, const char* table_name_arg,
- List<Item>& fields_arg, enum enum_duplicates handle_dup):
- Log_event(thd),thread_id(thd->thread_id),
- num_fields(0),fields(0),field_lens(0),field_block_len(0),
- table_name(table_name_arg),
- db(db_arg),
- fname(ex->file_name)
- {
- time_t end_time;
- time(&end_time);
- exec_time = (ulong) (end_time - thd->start_time);
- db_len = (db) ? (uint32) strlen(db) : 0;
- table_name_len = (table_name) ? (uint32) strlen(table_name) : 0;
- fname_len = (fname) ? (uint) strlen(fname) : 0;
- sql_ex.field_term = (char*) ex->field_term->ptr();
- sql_ex.field_term_len = (uint8) ex->field_term->length();
- sql_ex.enclosed = (char*) ex->enclosed->ptr();
- sql_ex.enclosed_len = (uint8) ex->enclosed->length();
- sql_ex.line_term = (char*) ex->line_term->ptr();
- sql_ex.line_term_len = (uint8) ex->line_term->length();
- sql_ex.line_start = (char*) ex->line_start->ptr();
- sql_ex.line_start_len = (uint8) ex->line_start->length();
- sql_ex.escaped = (char*) ex->escaped->ptr();
- sql_ex.escaped_len = (uint8) ex->escaped->length();
- sql_ex.opt_flags = 0;
- sql_ex.cached_new_format = -1;
+ List<Item>& fields_arg,
+ enum enum_duplicates handle_dup):
+ Log_event(thd), fields(0), field_lens(0),
+ table_name(table_name_arg), db(db_arg), fname(ex->file_name),
+ thread_id(thd->thread_id), num_fields(0), field_block_len(0)
+{
+ time_t end_time;
+ time(&end_time);
+ exec_time = (ulong) (end_time - thd->start_time);
+ db_len = (db) ? (uint32) strlen(db) : 0;
+ table_name_len = (table_name) ? (uint32) strlen(table_name) : 0;
+ fname_len = (fname) ? (uint) strlen(fname) : 0;
+ sql_ex.field_term = (char*) ex->field_term->ptr();
+ sql_ex.field_term_len = (uint8) ex->field_term->length();
+ sql_ex.enclosed = (char*) ex->enclosed->ptr();
+ sql_ex.enclosed_len = (uint8) ex->enclosed->length();
+ sql_ex.line_term = (char*) ex->line_term->ptr();
+ sql_ex.line_term_len = (uint8) ex->line_term->length();
+ sql_ex.line_start = (char*) ex->line_start->ptr();
+ sql_ex.line_start_len = (uint8) ex->line_start->length();
+ sql_ex.escaped = (char*) ex->escaped->ptr();
+ sql_ex.escaped_len = (uint8) ex->escaped->length();
+ sql_ex.opt_flags = 0;
+ sql_ex.cached_new_format = -1;
- if(ex->dumpfile)
- sql_ex.opt_flags |= DUMPFILE_FLAG;
- if(ex->opt_enclosed)
- sql_ex.opt_flags |= OPT_ENCLOSED_FLAG;
-
- sql_ex.empty_flags = 0;
-
- switch(handle_dup)
- {
- case DUP_IGNORE: sql_ex.opt_flags |= IGNORE_FLAG; break;
- case DUP_REPLACE: sql_ex.opt_flags |= REPLACE_FLAG; break;
- case DUP_ERROR: break;
- }
-
-
- if(!ex->field_term->length())
- sql_ex.empty_flags |= FIELD_TERM_EMPTY;
- if(!ex->enclosed->length())
- sql_ex.empty_flags |= ENCLOSED_EMPTY;
- if(!ex->line_term->length())
- sql_ex.empty_flags |= LINE_TERM_EMPTY;
- if(!ex->line_start->length())
- sql_ex.empty_flags |= LINE_START_EMPTY;
- if(!ex->escaped->length())
- sql_ex.empty_flags |= ESCAPED_EMPTY;
+ if (ex->dumpfile)
+ sql_ex.opt_flags |= DUMPFILE_FLAG;
+ if (ex->opt_enclosed)
+ sql_ex.opt_flags |= OPT_ENCLOSED_FLAG;
+
+ sql_ex.empty_flags = 0;
+
+ switch(handle_dup) {
+ case DUP_IGNORE: sql_ex.opt_flags |= IGNORE_FLAG; break;
+ case DUP_REPLACE: sql_ex.opt_flags |= REPLACE_FLAG; break;
+ case DUP_ERROR: break;
+ }
+
+
+ if (!ex->field_term->length())
+ sql_ex.empty_flags |= FIELD_TERM_EMPTY;
+ if (!ex->enclosed->length())
+ sql_ex.empty_flags |= ENCLOSED_EMPTY;
+ if (!ex->line_term->length())
+ sql_ex.empty_flags |= LINE_TERM_EMPTY;
+ if (!ex->line_start->length())
+ sql_ex.empty_flags |= LINE_START_EMPTY;
+ if (!ex->escaped->length())
+ sql_ex.empty_flags |= ESCAPED_EMPTY;
- skip_lines = ex->skip_lines;
-
- List_iterator<Item> li(fields_arg);
- field_lens_buf.length(0);
- fields_buf.length(0);
- Item* item;
- while((item = li++))
- {
- num_fields++;
- uchar len = (uchar) strlen(item->name);
- field_block_len += len + 1;
- fields_buf.append(item->name, len + 1);
- field_lens_buf.append((char*)&len, 1);
- }
+ skip_lines = ex->skip_lines;
- field_lens = (const uchar*)field_lens_buf.ptr();
- fields = fields_buf.ptr();
+ List_iterator<Item> li(fields_arg);
+ field_lens_buf.length(0);
+ fields_buf.length(0);
+ Item* item;
+ while((item = li++))
+ {
+ num_fields++;
+ uchar len = (uchar) strlen(item->name);
+ field_block_len += len + 1;
+ fields_buf.append(item->name, len + 1);
+ field_lens_buf.append((char*)&len, 1);
}
+ field_lens = (const uchar*)field_lens_buf.ptr();
+ fields = fields_buf.ptr();
+}
+
#endif
// the caller must do buf[event_len] = 0 before he starts using the
// constructed event
Load_log_event::Load_log_event(const char* buf, int event_len,
bool old_format):
- Log_event(buf, old_format),num_fields(0),fields(0),
- field_lens(0),field_block_len(0),
- table_name(0),db(0),fname(0)
+ Log_event(buf, old_format),fields(0),
+ field_lens(0), num_fields(0), field_block_len(0)
{
if (!event_len) // derived class, will call copy_log_event() itself
return;
@@ -1112,32 +1108,32 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
bool same_db = 0;
- if(db && last_db)
+ if (db && last_db)
{
- if(!(same_db = !memcmp(last_db, db, db_len + 1)))
+ if (!(same_db = !memcmp(last_db, db, db_len + 1)))
memcpy(last_db, db, db_len + 1);
}
- if(db && db[0] && !same_db)
+ if (db && db[0] && !same_db)
fprintf(file, "use %s;\n", db);
fprintf(file, "LOAD DATA INFILE '%-*s' ", fname_len, fname);
- if(sql_ex.opt_flags && REPLACE_FLAG )
+ if (sql_ex.opt_flags && REPLACE_FLAG )
fprintf(file," REPLACE ");
- else if(sql_ex.opt_flags && IGNORE_FLAG )
+ else if (sql_ex.opt_flags && IGNORE_FLAG )
fprintf(file," IGNORE ");
fprintf(file, "INTO TABLE %s ", table_name);
- if(sql_ex.field_term)
+ if (sql_ex.field_term)
{
fprintf(file, " FIELDS TERMINATED BY ");
pretty_print_str(file, sql_ex.field_term, sql_ex.field_term_len);
}
- if(sql_ex.enclosed)
+ if (sql_ex.enclosed)
{
- if(sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
+ if (sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
fprintf(file," OPTIONALLY ");
fprintf(file, " ENCLOSED BY ");
pretty_print_str(file, sql_ex.enclosed, sql_ex.enclosed_len);
@@ -1161,7 +1157,7 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
pretty_print_str(file, sql_ex.line_start, sql_ex.line_start_len);
}
- if((int)skip_lines > 0)
+ if ((int)skip_lines > 0)
fprintf(file, " IGNORE %ld LINES ", (long) skip_lines);
if (num_fields)
@@ -1169,9 +1165,9 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
uint i;
const char* field = fields;
fprintf( file, " (");
- for(i = 0; i < num_fields; i++)
+ for (i = 0; i < num_fields; i++)
{
- if(i)
+ if (i)
fputc(',', file);
fprintf(file, field);
@@ -1197,24 +1193,24 @@ void Load_log_event::set_fields(List<Item> &fields)
{
uint i;
const char* field = this->fields;
- for(i = 0; i < num_fields; i++)
- {
- fields.push_back(new Item_field(db, table_name, field));
- field += field_lens[i] + 1;
- }
+ for (i = 0; i < num_fields; i++)
+ {
+ fields.push_back(new Item_field(db, table_name, field));
+ field += field_lens[i] + 1;
+ }
}
Slave_log_event::Slave_log_event(THD* thd_arg,struct st_master_info* mi):
Log_event(thd_arg),mem_pool(0),master_host(0)
{
- if(!mi->inited)
+ if (!mi->inited)
return;
pthread_mutex_lock(&mi->lock);
master_host_len = strlen(mi->host);
master_log_len = strlen(mi->log_file_name);
// on OOM, just do not initialize the structure and print the error
- if((mem_pool = (char*)my_malloc(get_data_size() + 1,
+ if ((mem_pool = (char*)my_malloc(get_data_size() + 1,
MYF(MY_WME))))
{
master_host = mem_pool + SL_MASTER_HOST_OFFSET ;
@@ -1243,7 +1239,7 @@ Slave_log_event::~Slave_log_event()
void Slave_log_event::print(FILE* file, bool short_form, char* last_db)
{
char llbuff[22];
- if(short_form)
+ if (short_form)
return;
print_header(file);
fputc('\n', file);
@@ -1275,7 +1271,7 @@ void Slave_log_event::init_from_mem_pool(int data_size)
master_host_len = strlen(master_host);
// safety
master_log = master_host + master_host_len + 1;
- if(master_log > mem_pool + data_size)
+ if (master_log > mem_pool + data_size)
{
master_host = 0;
return;
@@ -1287,9 +1283,9 @@ Slave_log_event::Slave_log_event(const char* buf, int event_len):
Log_event(buf,0),mem_pool(0),master_host(0)
{
event_len -= LOG_EVENT_HEADER_LEN;
- if(event_len < 0)
+ if (event_len < 0)
return;
- if(!(mem_pool = (char*)my_malloc(event_len + 1, MYF(MY_WME))))
+ if (!(mem_pool = (char*)my_malloc(event_len + 1, MYF(MY_WME))))
return;
memcpy(mem_pool, buf + LOG_EVENT_HEADER_LEN, event_len);
mem_pool[event_len] = 0;
@@ -1396,7 +1392,7 @@ Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
Append_block_log_event::Append_block_log_event(const char* buf, int len):
Log_event(buf, 0),block(0)
{
- if((uint)len < APPEND_BLOCK_EVENT_OVERHEAD)
+ if ((uint)len < APPEND_BLOCK_EVENT_OVERHEAD)
return;
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
block = (char*)buf + APPEND_BLOCK_EVENT_OVERHEAD;
@@ -1448,7 +1444,7 @@ Delete_file_log_event::Delete_file_log_event(THD* thd_arg):
Delete_file_log_event::Delete_file_log_event(const char* buf, int len):
Log_event(buf, 0),file_id(0)
{
- if((uint)len < DELETE_FILE_EVENT_OVERHEAD)
+ if ((uint)len < DELETE_FILE_EVENT_OVERHEAD)
return;
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
}
@@ -1495,7 +1491,7 @@ Execute_load_log_event::Execute_load_log_event(THD* thd_arg):
Execute_load_log_event::Execute_load_log_event(const char* buf,int len):
Log_event(buf, 0),file_id(0)
{
- if((uint)len < EXEC_LOAD_EVENT_OVERHEAD)
+ if ((uint)len < EXEC_LOAD_EVENT_OVERHEAD)
return;
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + EL_FILE_ID_OFFSET);
}
@@ -1551,8 +1547,10 @@ int Query_log_event::exec_event(struct st_master_info* mi)
thd->net.last_error[0] = 0;
thd->slave_proxy_id = thread_id; // for temp tables
- // sanity check to make sure the master did not get a really bad
- // error on the query
+ /*
+ sanity check to make sure the master did not get a really bad
+ error on the query
+ */
if (!check_expected_error(thd, (expected_error = error_code)))
{
mysql_parse(thd, thd->query, q_len);
@@ -1609,7 +1607,7 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
thd->query = 0;
thd->query_error = 0;
- if(db_ok(thd->db, replicate_do_db, replicate_ignore_db))
+ if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
{
thd->set_time((time_t)when);
thd->current_tablenr = 0;
@@ -1623,7 +1621,7 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
tables.name = tables.real_name = (char*)table_name;
tables.lock_type = TL_WRITE;
// the table will be opened in mysql_load
- if(table_rules_on && !tables_ok(thd, &tables))
+ if (table_rules_on && !tables_ok(thd, &tables))
{
if (net)
skip_load_data_infile(net);
@@ -1632,7 +1630,7 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
{
char llbuff[22];
enum enum_duplicates handle_dup = DUP_IGNORE;
- if(sql_ex.opt_flags && REPLACE_FLAG)
+ if (sql_ex.opt_flags && REPLACE_FLAG)
handle_dup = DUP_REPLACE;
sql_exchange ex((char*)fname, sql_ex.opt_flags &&
DUMPFILE_FLAG );
@@ -1658,14 +1656,14 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
// about the packet sequence
thd->net.pkt_nr = net->pkt_nr;
}
- if(mysql_load(thd, &ex, &tables, fields, handle_dup, net != 0,
+ if (mysql_load(thd, &ex, &tables, fields, handle_dup, net != 0,
TL_WRITE))
thd->query_error = 1;
- if(thd->cuted_fields)
+ if (thd->cuted_fields)
sql_print_error("Slave: load data infile at position %s in log \
'%s' produced %d warning(s)", llstr(mi->pos,llbuff), RPL_LOG_NAME,
thd->cuted_fields );
- if(net)
+ if (net)
net->pkt_nr = thd->net.pkt_nr;
}
}
@@ -1680,10 +1678,10 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
thd->net.vio = 0;
thd->db = 0;// prevent db from being freed
close_thread_tables(thd);
- if(thd->query_error)
+ if (thd->query_error)
{
int sql_error = thd->net.last_errno;
- if(!sql_error)
+ if (!sql_error)
sql_error = ER_UNKNOWN_ERROR;
slave_print_error(sql_error, "Slave: Error '%s' running load data infile ",
@@ -1693,7 +1691,7 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
}
free_root(&thd->mem_root,0);
- if(thd->fatal_error)
+ if (thd->fatal_error)
{
sql_print_error("Slave: Fatal error running LOAD DATA INFILE ");
return 1;
@@ -1788,7 +1786,7 @@ int Intvar_log_event::exec_event(struct st_master_info* mi)
int Slave_log_event::exec_event(struct st_master_info* mi)
{
- if(mysql_bin_log.is_open())
+ if (mysql_bin_log.is_open())
mysql_bin_log.write(this);
return Log_event::exec_event(mi);
}
diff --git a/sql/log_event.h b/sql/log_event.h
index 329d748025d..4426232008b 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -244,42 +244,31 @@ public:
virtual bool is_valid() = 0;
virtual bool get_cache_stmt() { return 0; }
Log_event(const char* buf, bool old_format);
-#ifndef MYSQL_CLIENT
- Log_event(THD* thd_arg, uint16 flags_arg = 0);
-#endif
virtual ~Log_event() { free_temp_buf();}
void register_temp_buf(char* buf) { temp_buf = buf; }
void free_temp_buf()
+ {
+ if (temp_buf)
{
- if (temp_buf)
- {
- my_free(temp_buf, MYF(0));
- temp_buf = 0;
- }
+ my_free(temp_buf, MYF(0));
+ temp_buf = 0;
}
+ }
virtual int get_data_size() { return 0;}
virtual int get_data_body_offset() { return 0; }
int get_event_len() { return cached_event_len ? cached_event_len :
(cached_event_len = LOG_EVENT_HEADER_LEN + get_data_size()); }
-#ifdef MYSQL_CLIENT
- virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
- void print_timestamp(FILE* file, time_t *ts = 0);
- void print_header(FILE* file);
-#endif
-
-#ifndef MYSQL_CLIENT
- // if mutex is 0, the read will proceed without mutex
- static Log_event* read_log_event(IO_CACHE* file,
- pthread_mutex_t* log_lock,
- bool old_format);
-#else // avoid having to link mysqlbinlog against libpthread
- static Log_event* read_log_event(IO_CACHE* file, bool old_format);
-#endif
+
static Log_event* read_log_event(const char* buf, int event_len,
const char **error, bool old_format);
const char* get_type_str();
#ifndef MYSQL_CLIENT
+ // if mutex is 0, the read will proceed without mutex
+ Log_event(THD* thd_arg, uint16 flags_arg = 0);
+ static Log_event* read_log_event(IO_CACHE* file,
+ pthread_mutex_t* log_lock,
+ bool old_format);
static int read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock);
void set_log_seq(THD* thd, MYSQL_LOG* log);
@@ -291,6 +280,13 @@ public:
{
return thd ? thd->db : 0;
}
+#else
+ // avoid having to link mysqlbinlog against libpthread
+ static Log_event* read_log_event(IO_CACHE* file, bool old_format);
+
+ virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
+ void print_timestamp(FILE* file, time_t *ts = 0);
+ void print_header(FILE* file);
#endif
};
@@ -303,13 +299,16 @@ protected:
public:
const char* query;
const char* db;
- uint32 q_len; // if we already know the length of the query string
- // we pass it here, so we would not have to call strlen()
- // otherwise, set it to 0, in which case, we compute it with strlen()
+ /*
+ If we already know the length of the query string
+ we pass it here, so we would not have to call strlen()
+ otherwise, set it to 0, in which case, we compute it with strlen()
+ */
+ uint32 q_len;
uint32 db_len;
uint16 error_code;
ulong thread_id;
-#if !defined(MYSQL_CLIENT)
+#ifndef MYSQL_CLIENT
bool cache_stmt;
Query_log_event(THD* thd_arg, const char* query_arg,
@@ -318,6 +317,8 @@ public:
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
bool get_cache_stmt() { return cache_stmt; }
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
Query_log_event(const char* buf, int event_len, bool old_format);
@@ -340,9 +341,6 @@ public:
+ 2 // error_code
;
}
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
};
class Slave_log_event: public Log_event
@@ -352,24 +350,22 @@ protected:
void init_from_mem_pool(int data_size);
public:
char* master_host;
- int master_host_len;
- uint16 master_port;
char* master_log;
- int master_log_len;
ulonglong master_pos;
+ int master_host_len;
+ int master_log_len;
+ uint16 master_port;
-#ifndef MYSQL_CLIENT
- Slave_log_event(THD* thd_arg, struct st_master_info* mi);
- void pack_info(String* packet);
- int exec_event(struct st_master_info* mi);
-#endif
-
Slave_log_event(const char* buf, int event_len);
~Slave_log_event();
int get_data_size();
bool is_valid() { return master_host != 0; }
Log_event_type get_type_code() { return SLAVE_EVENT; }
-#ifdef MYSQL_CLIENT
+#ifndef MYSQL_CLIENT
+ Slave_log_event(THD* thd_arg, struct st_master_info* mi);
+ void pack_info(String* packet);
+ int exec_event(struct st_master_info* mi);
+#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
int write_data(IO_CACHE* file );
@@ -382,22 +378,21 @@ protected:
int copy_log_event(const char *buf, ulong event_len, bool old_format);
public:
+ const char* fields;
+ const uchar* field_lens;
+ const char* table_name;
+ const char* db;
+ const char* fname;
ulong thread_id;
uint32 table_name_len;
uint32 db_len;
uint32 fname_len;
uint32 num_fields;
- const char* fields;
- const uchar* field_lens;
uint32 field_block_len;
-
- const char* table_name;
- const char* db;
- const char* fname;
uint32 skip_lines;
sql_ex_info sql_ex;
-#if !defined(MYSQL_CLIENT)
+#ifndef MYSQL_CLIENT
String field_lens_buf;
String fields_buf;
@@ -408,10 +403,12 @@ public:
void pack_info(String* packet);
const char* get_db() { return db; }
int exec_event(struct st_master_info* mi)
- {
- return exec_event(thd->slave_net,mi);
- }
+ {
+ return exec_event(thd->slave_net,mi);
+ }
int exec_event(NET* net, struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
Load_log_event(const char* buf, int event_len, bool old_format);
@@ -434,9 +431,6 @@ public:
;
}
int get_data_body_offset() { return LOAD_EVENT_OVERHEAD; }
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
};
extern char server_version[SERVER_VERSION_LENGTH];
@@ -447,13 +441,7 @@ public:
uint32 created;
uint16 binlog_version;
char server_version[ST_SERVER_VER_LEN];
-#ifndef MYSQL_CLIENT
- Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
- {
- created = (uint32) when;
- memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
- }
-#endif
+
Start_log_event(const char* buf, bool old_format);
~Start_log_event() {}
Log_event_type get_type_code() { return START_EVENT;}
@@ -464,10 +452,14 @@ public:
return START_HEADER_LEN;
}
#ifndef MYSQL_CLIENT
+ Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
+ {
+ created = (uint32) when;
+ memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
+ }
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
-#endif
-#ifdef MYSQL_CLIENT
+#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
@@ -477,11 +469,7 @@ class Intvar_log_event: public Log_event
public:
ulonglong val;
uchar type;
-#ifndef MYSQL_CLIENT
- Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
- :Log_event(thd_arg),val(val_arg),type(type_arg)
- {}
-#endif
+
Intvar_log_event(const char* buf, bool old_format);
~Intvar_log_event() {}
Log_event_type get_type_code() { return INTVAR_EVENT;}
@@ -490,11 +478,12 @@ public:
int write_data(IO_CACHE* file);
bool is_valid() { return 1; }
#ifndef MYSQL_CLIENT
+ Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
+ :Log_event(thd_arg),val(val_arg),type(type_arg)
+ {}
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
-#endif
-
-#ifdef MYSQL_CLIENT
+#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
@@ -502,10 +491,6 @@ public:
class Stop_log_event: public Log_event
{
public:
-#ifndef MYSQL_CLIENT
- Stop_log_event() :Log_event((THD*)0)
- {}
-#endif
Stop_log_event(const char* buf, bool old_format):Log_event(buf,
old_format)
{
@@ -513,11 +498,11 @@ public:
~Stop_log_event() {}
Log_event_type get_type_code() { return STOP_EVENT;}
bool is_valid() { return 1; }
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-#ifndef MYSQL_CLIENT
+#ifndef MYSQL_CLIENT
+ Stop_log_event() :Log_event((THD*)0) {}
int exec_event(struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
@@ -525,19 +510,10 @@ class Rotate_log_event: public Log_event
{
public:
const char* new_log_ident;
- uchar ident_len;
ulonglong pos;
+ uint8 ident_len;
bool alloced;
-#ifndef MYSQL_CLIENT
- Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
- uint ident_len_arg = 0,ulonglong pos_arg = 4) :
- Log_event(thd_arg),
- new_log_ident(new_log_ident_arg),
- ident_len(ident_len_arg ? ident_len_arg :
- (uint) strlen(new_log_ident_arg)), pos(pos_arg),
- alloced(0)
- {}
-#endif
+
Rotate_log_event(const char* buf, int event_len, bool old_format);
~Rotate_log_event()
{
@@ -548,64 +524,81 @@ public:
int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
bool is_valid() { return new_log_ident != 0; }
int write_data(IO_CACHE* file);
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-#ifndef MYSQL_CLIENT
+#ifndef MYSQL_CLIENT
+ Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
+ uint8 ident_len_arg = 0,ulonglong pos_arg = 4) :
+ Log_event(thd_arg), new_log_ident(new_log_ident_arg),
+ pos(pos_arg),
+ ident_len(ident_len_arg ? ident_len_arg :
+ (uint8) strlen(new_log_ident_arg)),
+ alloced(0)
+ {}
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
+
/* the classes below are for the new LOAD DATA INFILE logging */
class Create_file_log_event: public Load_log_event
{
protected:
- // pretend we are Load event, so we can write out just
- // our Load part - used on the slave when writing event out to
- // SQL_LOAD-*.info file
+ /*
+ Pretend we are Load event, so we can write out just
+ our Load part - used on the slave when writing event out to
+ SQL_LOAD-*.info file
+ */
bool fake_base;
public:
char* block;
uint block_len;
uint file_id;
-#ifndef MYSQL_CLIENT
- Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
- const char* table_name_arg,
- List<Item>& fields_arg,
- enum enum_duplicates handle_dup,
- char* block_arg, uint block_len_arg);
-#endif
-
+
Create_file_log_event(const char* buf, int event_len);
~Create_file_log_event()
{
}
Log_event_type get_type_code()
- {
- return fake_base ? Load_log_event::get_type_code() : CREATE_FILE_EVENT;
- }
- int get_data_size() { return fake_base ? Load_log_event::get_data_size() :
- Load_log_event::get_data_size() +
- 4 + 1 + block_len;}
- int get_data_body_offset() { return fake_base ? LOAD_EVENT_OVERHEAD:
- LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN; }
+ {
+ return fake_base ? Load_log_event::get_type_code() : CREATE_FILE_EVENT;
+ }
+ int get_data_size()
+ {
+ return (fake_base ? Load_log_event::get_data_size() :
+ Load_log_event::get_data_size() +
+ 4 + 1 + block_len);
+ }
+ int get_data_body_offset()
+ {
+ return (fake_base ? LOAD_EVENT_OVERHEAD:
+ LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN);
+ }
bool is_valid() { return block != 0; }
int write_data_header(IO_CACHE* file);
int write_data_body(IO_CACHE* file);
- int write_base(IO_CACHE* file); // cut out Create_file extentions and
- // write it as Load event - used on the slave
+ /*
+ Cut out Create_file extentions and write it as Load event - used on the
+ slave.
+ */
+ int write_base(IO_CACHE* file);
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
#ifndef MYSQL_CLIENT
+ Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
+ const char* table_name_arg,
+ List<Item>& fields_arg,
+ enum enum_duplicates handle_dup,
+ char* block_arg, uint block_len_arg);
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
+
class Append_block_log_event: public Log_event
{
public:
@@ -613,12 +606,6 @@ public:
uint block_len;
uint file_id;
-#ifndef MYSQL_CLIENT
- Append_block_log_event(THD* thd, char* block_arg,
- uint block_len_arg);
- int exec_event(struct st_master_info* mi);
-#endif
-
Append_block_log_event(const char* buf, int event_len);
~Append_block_log_event()
{
@@ -628,23 +615,22 @@ public:
bool is_valid() { return block != 0; }
int write_data(IO_CACHE* file);
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
#ifndef MYSQL_CLIENT
+ Append_block_log_event(THD* thd, char* block_arg,
+ uint block_len_arg);
+ int exec_event(struct st_master_info* mi);
void pack_info(String* packet);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
+
class Delete_file_log_event: public Log_event
{
public:
uint file_id;
-#ifndef MYSQL_CLIENT
- Delete_file_log_event(THD* thd);
-#endif
-
Delete_file_log_event(const char* buf, int event_len);
~Delete_file_log_event()
{
@@ -654,12 +640,12 @@ public:
bool is_valid() { return file_id != 0; }
int write_data(IO_CACHE* file);
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
#ifndef MYSQL_CLIENT
+ Delete_file_log_event(THD* thd);
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
@@ -668,10 +654,6 @@ class Execute_load_log_event: public Log_event
public:
uint file_id;
-#ifndef MYSQL_CLIENT
- Execute_load_log_event(THD* thd);
-#endif
-
Execute_load_log_event(const char* buf, int event_len);
~Execute_load_log_event()
{
@@ -681,16 +663,13 @@ public:
bool is_valid() { return file_id != 0; }
int write_data(IO_CACHE* file);
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
#ifndef MYSQL_CLIENT
+ Execute_load_log_event(THD* thd);
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
-#endif
-
-
-
+#endif /* _LOG_EVENT_H */
diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc
index 2a7b25eab2f..860318d5a79 100644
--- a/sql/mf_iocache.cc
+++ b/sql/mf_iocache.cc
@@ -50,14 +50,14 @@ extern "C" {
int _my_b_net_read(register IO_CACHE *info, byte *Buffer,
uint Count __attribute__((unused)))
{
- int read_length;
+ ulong read_length;
NET *net= &(current_thd)->net;
DBUG_ENTER("_my_b_net_read");
if (!info->end_of_file)
DBUG_RETURN(1); /* because my_b_get (no _) takes 1 byte at a time */
read_length=my_net_read(net);
- if (read_length == (int) packet_error)
+ if (read_length == packet_error)
{
info->error= -1;
DBUG_RETURN(1);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 5830c946372..4e3757d3f23 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -332,7 +332,7 @@ int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
ulong select_type,select_result *result);
int mysql_union(THD *thd,LEX *lex,select_result *result);
-Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
+Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field,
bool group,bool modify_item);
int mysql_create_table(THD *thd,const char *db, const char *table_name,
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 1cb06c8a461..bc3fb3f7cb7 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -3091,8 +3091,8 @@ struct show_var_st init_vars[]= {
{"record_rnd_buffer", (char*) &record_rnd_cache_size, SHOW_LONG},
{"rpl_recovery_rank", (char*) &rpl_recovery_rank, SHOW_LONG},
{"query_buffer_size", (char*) &query_buff_size, SHOW_LONG},
- {"query_cache_limit", (char*) &query_cache_limit, SHOW_LONG},
- {"query_cache_size", (char*) &query_cache_size, SHOW_LONG},
+ {"query_cache_limit", (char*) &query_cache.query_cache_limit, SHOW_LONG},
+ {"query_cache_size", (char*) &query_cache.query_cache_size, SHOW_LONG},
{"query_cache_startup_type",(char*) &query_cache_startup_type, SHOW_LONG},
{"safe_show_database", (char*) &opt_safe_show_db, SHOW_BOOL},
{"server_id", (char*) &server_id, SHOW_LONG},
@@ -3157,11 +3157,11 @@ struct show_var_st status_vars[]= {
{"Open_streams", (char*) &my_stream_opened, SHOW_INT_CONST},
{"Opened_tables", (char*) &opened_tables, SHOW_LONG},
{"Questions", (char*) 0, SHOW_QUESTION},
- {"Qcache_queries", (char*) &query_cache.queries_in_cache,
+ {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache,
SHOW_LONG},
{"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG},
{"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
- {"Qcache_refused", (char*) &query_cache.refused, SHOW_LONG},
+ {"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG},
{"Qcache_free_memory", (char*) &query_cache.free_memory,SHOW_LONG},
{"Rpl_status", (char*) 0, SHOW_RPL_STATUS},
{"Select_full_join", (char*) &select_full_join_count, SHOW_LONG},
@@ -3726,12 +3726,11 @@ static void get_options(int argc,char **argv)
opt_slow_log=1;
opt_slow_logname=optarg;
break;
- case (int)OPT_SKIP_SLAVE_START:
+ case (int) OPT_SKIP_SLAVE_START:
opt_skip_slave_start = 1;
break;
case (int) OPT_SKIP_NEW:
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
- default_table_type=DB_TYPE_ISAM;
myisam_delay_key_write=0;
myisam_concurrent_insert=0;
myisam_recover_options= HA_RECOVER_NONE;
@@ -3739,6 +3738,7 @@ static void get_options(int argc,char **argv)
my_use_symdir=0;
have_symlink=SHOW_OPTION_DISABLED;
ha_open_options&= ~HA_OPEN_ABORT_IF_CRASHED;
+ query_cache_size=0;
break;
case (int) OPT_SAFE:
opt_specialflag|= SPECIAL_SAFE_MODE;
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index ac622bca254..5a39b071b4f 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -109,7 +109,7 @@ static int net_write_buff(NET *net,const char *packet,ulong len);
int my_net_init(NET *net, Vio* vio)
{
- if (!(net->buff=(uchar*) my_malloc(net_buffer_length+
+ if (!(net->buff=(uchar*) my_malloc((uint32) net_buffer_length+
NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
return 1;
@@ -162,7 +162,7 @@ static my_bool net_realloc(NET *net, ulong length)
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
/* We must allocate some extra bytes for the end 0 and to be able to
read big compressed blocks */
- if (!(buff=(uchar*) my_realloc((char*) net->buff, pkt_length +
+ if (!(buff=(uchar*) my_realloc((char*) net->buff, (uint32) pkt_length +
NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
{
@@ -189,7 +189,7 @@ void net_clear(NET *net)
if (!vio_is_blocking(net->vio)) /* Safety if SSL */
{
while ( (count = vio_read(net->vio, (char*) (net->buff),
- net->max_packet)) > 0)
+ (uint32) net->max_packet)) > 0)
DBUG_PRINT("info",("skipped %d bytes from file: %s",
count,vio_description(net->vio)));
if (is_blocking)
@@ -243,7 +243,7 @@ my_net_write(NET *net,const char *packet,ulong len)
{
const ulong z_size = MAX_THREE_BYTES;
int3store(buff, z_size);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net, (char*) buff, NET_HEADER_SIZE) ||
net_write_buff(net, packet, z_size))
return 1;
@@ -252,7 +252,7 @@ my_net_write(NET *net,const char *packet,ulong len)
}
/* Write last packet */
int3store(buff,len);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE))
return 1;
return net_write_buff(net,packet,len);
@@ -282,7 +282,7 @@ net_write_command(NET *net,uchar command,const char *packet,ulong len)
do
{
int3store(buff, MAX_THREE_BYTES);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net,(char*) buff, header_size) ||
net_write_buff(net,packet,len))
return 1;
@@ -294,7 +294,7 @@ net_write_command(NET *net,uchar command,const char *packet,ulong len)
len=length; /* Data left to be written */
}
int3store(buff,length);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
return test(net_write_buff(net,(char*) buff,header_size) ||
net_write_buff(net,packet,len) || net_flush(net));
}
@@ -357,8 +357,8 @@ net_real_write(NET *net,const char *packet,ulong len)
ulong complen;
uchar *b;
uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
- if (!(b=(uchar*) my_malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE,
- MYF(MY_WME))))
+ if (!(b=(uchar*) my_malloc((uint32) len + NET_HEADER_SIZE +
+ COMP_HEADER_SIZE, MYF(MY_WME))))
{
#ifdef MYSQL_SERVER
net->last_errno=ER_OUT_OF_RESOURCES;
@@ -395,7 +395,7 @@ net_real_write(NET *net,const char *packet,ulong len)
pos=(char*) packet; end=pos+len;
while (pos != end)
{
- if ((long) (length=vio_write(net->vio,pos,(ulong) (end-pos))) <= 0)
+ if ((long) (length=vio_write(net->vio,pos,(uint32) (end-pos))) <= 0)
{
my_bool interrupted = vio_should_retry(net->vio);
#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2))
@@ -479,7 +479,7 @@ net_real_write(NET *net,const char *packet,ulong len)
big packet
*/
-static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed)
+static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed)
{
ALARM alarm_buff;
uint retry_count=0;
@@ -502,7 +502,7 @@ static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed)
}
return;
}
- remain -= length;
+ remain -= (uint32) length;
statistic_add(bytes_received,length,&LOCK_bytes_received);
}
}
@@ -527,8 +527,8 @@ my_real_read(NET *net, ulong *complen)
ALARM alarm_buff;
#endif
my_bool net_blocking=vio_is_blocking(net->vio);
- ulong remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
- NET_HEADER_SIZE);
+ uint32 remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
+ NET_HEADER_SIZE);
*complen = 0;
net->reading_or_writing=1;
@@ -605,7 +605,7 @@ my_real_read(NET *net, ulong *complen)
continue;
}
#endif
- DBUG_PRINT("error",("Couldn't read packet: remain: %d errno: %d length: %d alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
+ DBUG_PRINT("error",("Couldn't read packet: remain: %lu errno: %d length: %ld alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
len= packet_error;
net->error=2; /* Close socket */
#ifdef MYSQL_SERVER
@@ -614,7 +614,7 @@ my_real_read(NET *net, ulong *complen)
#endif
goto end;
}
- remain -= (ulong) length;
+ remain -= (uint32) length;
pos+= (ulong) length;
statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received);
}
@@ -661,14 +661,14 @@ my_real_read(NET *net, ulong *complen)
{
#ifdef MYSQL_SERVER
if (i == 1)
- my_net_skip_rest(net, len, &alarmed);
+ my_net_skip_rest(net, (uint32) len, &alarmed);
#endif
len= packet_error; /* Return error */
goto end;
}
}
pos=net->buff + net->where_b;
- remain = len;
+ remain = (uint32) len;
}
}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 07d1216a42f..83eb10235ea 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -48,9 +48,9 @@ class QUICK_RANGE :public Sql_alloc {
uint flag_arg)
: min_key((char*) sql_memdup(min_key_arg,min_length_arg+1)),
max_key((char*) sql_memdup(max_key_arg,max_length_arg+1)),
- min_length(min_length_arg),
- max_length(max_length_arg),
- flag(flag_arg)
+ min_length((uint16) min_length_arg),
+ max_length((uint16) max_length_arg),
+ flag((uint16) flag_arg)
{}
};
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 38db67ba38f..bc9b95fe773 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -14,6 +14,194 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/*
+ Description of the query cache:
+
+1. Query_cache object consists of
+ - query cache memory pool (cache)
+ - queries hash (queries)
+ - tables hash (tables)
+ - list of blocks ordered as they allocated in memory
+(first_block)
+ - list of queries block (queries_blocks)
+ - list of used tables (tables_blocks)
+
+2. Query cache memory pool (cache) consists of
+ - table of steps of memory bins allocation
+ - table of free memory bins
+ - blocks of memory
+
+3. Memory blocks
+
+Every memory block has the following structure:
+
++----------------------------------------------------------+
+| Block header (Query_cache_block structure) |
++----------------------------------------------------------+
+|Table of database table lists (used for queries & tables) |
++----------------------------------------------------------+
+| Type depended header |
+|(Query_cache_query, Query_cache_table, Query_cache_result)|
++----------------------------------------------------------+
+| Data ... |
++----------------------------------------------------------+
+
+Block header consists of:
+- type:
+ FREE Free memory block
+ QUERY Query block
+ RESULT Ready to send result
+ RES_CONT Result's continuation
+ RES_BEG First block of results, that is not yet complete,
+ written to cache
+ RES_INCOMPLETE Allocated for results data block
+ TABLE Block with database table description
+ INCOMPLETE The destroyed block
+- length of block (length)
+- length of data & headers (used)
+- physical list links (pnext/pprev) - used for the list of
+ blocks ordered as they are allocated in physical memory
+- logical list links (next/prev) - used for queries block list, tables block
+ list, free memory block lists and list of results block in query
+- number of elements in table of database table list (n_tables)
+
+4. Query & results blocks
+
+Query stored in cache consists of following blocks:
+
+more more
+recent+-------------+ old
+<-----|Query block 1|------> double linked list of queries block
+ prev | | next
+ +-------------+
+ <-| table 0 |-> (see "Table of database table lists" description)
+ <-| table 1 |->
+ | ... | +--------------------------+
+ +-------------+ +-------------------------+ |
+NET | | | V V |
+struct| | +-+------------+ +------------+ |
+<-----|query header |----->|Result block|-->|Result block|-+ doublelinked
+writer| |result| |<--| | list of results
+ +-------------+ +------------+ +------------+
+ |charset | +------------+ +------------+ no table of dbtables
+ |encoding + | | result | | result |
+ |query text |<-----| header | | header |------+
+ +-------------+parent| | | |parent|
+ ^ +------------+ +------------+ |
+ | |result data | |result data | |
+ | +------------+ +------------+ |
+ +---------------------------------------------------+
+
+First query is registered. During the registration query block is
+allocated. This query block is included in query hash and is linked
+with appropriate database tables lists (if there is no appropriate
+list exists it will be created).
+
+Later when query has performed results is written into the result blocks.
+A result block cannot be smaller then QUERY_CACHE_MIN_RESULT_DATA_SIZE.
+
+When new result is written to cache it is appended to the last result
+block, if no more free space left in the last block, new block is
+allocated.
+
+5. Table of database table lists.
+
+For quick invalidation of queries all query are linked in lists on used
+database tables basis (when table will be changed (insert/delete/...)
+this queries will be removed from cache).
+
+Root of such list is table block:
+
+ +------------+ list of used tables (used while invalidation of
+<----| Table |-----> whole database)
+ prev| block |next +-----------+
+ | | +-----------+ |Query block|
+ | | |Query block| +-----------+
+ +------------+ +-----------+ | ... |
+ +->| table 0 |------>|table 0 |----->| table N |---+
+ |+-| |<------| |<-----| |<-+|
+ || +------------+ | ... | | ... | ||
+ || |table header| +-----------+ +-----------+ ||
+ || +------------+ | ... | | ... | ||
+ || |db name + | +-----------+ +-----------+ ||
+ || |table name | ||
+ || +------------+ ||
+ |+--------------------------------------------------------+|
+ +----------------------------------------------------------+
+
+Table block is included into the tables hash (tables).
+
+6. Free blocks, free blocks bins & steps of freeblock bins.
+
+When we just started only one free memory block existed. All query
+cache memory (that will be used for block allocation) were
+containing in this block.
+When a new block is allocated we find most suitable memory block
+(minimal of >= required size). If such a block can not be found, we try
+to find max block < required size (if we allocate block for results).
+If there is no free memory, oldest query is removed from cache, and then
+we try to allocate memory. Last step should be repeated until we find
+suitable block or until there is no unlocked query found.
+
+If the block is found and its length more then we need, it should be
+split into 2 blocks.
+New blocks cannot be smaller then min_allocation_unit_bytes.
+
+When a block becomes free, its neighbor-blocks should be tested and if
+there are free blocks among them, they should be joined into one block.
+
+Free memory blocks are stored in bins according to their sizes.
+The bins are stored in size-descending order.
+These bins are distributed (by size) approximately logarithmically.
+
+First bin (number 0) stores free blocks with
+size <= query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2.
+It is first (number 0) step.
+On the next step distributed (1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
+QUERY_CACHE_MEM_BIN_PARTS_MUL bins. This bins allocated in interval from
+query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 to
+query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 >>
+QUERY_CACHE_MEM_BIN_STEP_PWR2
+...
+On each step interval decreases in 2 power of
+QUERY_CACHE_MEM_BIN_STEP_PWR2
+times, number of bins (that distributed on this step) increases. If on
+the previous step there were N bins distributed , on the current there
+would be distributed
+(N + QUERY_CACHE_MEM_BIN_PARTS_INC) * QUERY_CACHE_MEM_BIN_PARTS_MUL
+bins.
+Last distributed bin stores blocks with size near min_allocation_unit
+bytes.
+
+For example:
+ query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 = 100,
+ min_allocation_unit = 17,
+ QUERY_CACHE_MEM_BIN_STEP_PWR2 = 1,
+ QUERY_CACHE_MEM_BIN_PARTS_INC = 1,
+ QUERY_CACHE_MEM_BIN_PARTS_MUL = 1
+ (in followed picture showed right (low) bound of bin):
+
+ | 100>>1 50>>1 |25>>1|
+ | | | | | |
+ | 100 75 50 41 33 25 21 18 15| 12 | - bins right (low) bounds
+
+ |\---/\-----/\--------/\--------|---/ |
+ | 0 1 2 3 | | - steps
+ \-----------------------------/ \---/
+ bins that we store in cache this bin showed for example only
+
+
+Calculation of steps/bins distribution is performed only when query cache
+is resized.
+
+When we need to find appropriate bin, first we should find appropriate
+step, then we should calculate number of bins that are using data
+stored in Query_cache_memory_bin_step structure.
+
+Free memory blocks are sorted in bins in lists with size-ascending order
+(more small blocks needed frequently then bigger one).
+*/
+
#include "mysql_priv.h"
#include <m_ctype.h>
#include <my_dir.h>
@@ -25,36 +213,36 @@
#else
#include "../myisammrg/myrg_def.h"
#endif
+#include <assert.h>
-#ifdef EXTRA_DEBUG
-#define MUTEX_LOCK(M) { DBUG_PRINT("info", ("mutex lock 0x%lx", (ulong)(M))); \
+#if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
+#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \
pthread_mutex_lock(M);}
#define SEM_LOCK(M) { int val = 0; sem_getvalue (M, &val); \
- DBUG_PRINT("info", ("sem lock 0x%lx (%d)", (ulong)(M), val)); \
- sem_wait(M); DBUG_PRINT("info", ("sem lock ok")); }
-#define MUTEX_UNLOCK(M) {DBUG_PRINT("info", ("mutex unlock 0x%lx",\
+ DBUG_PRINT("lock", ("sem lock 0x%lx (%d)", (ulong)(M), val)); \
+ sem_wait(M); DBUG_PRINT("lock", ("sem lock ok")); }
+#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
(ulong)(M))); pthread_mutex_unlock(M);}
-#define SEM_UNLOCK(M) {DBUG_PRINT("info", ("sem unlock 0x%lx", (ulong)(M))); \
- sem_post(M); DBUG_PRINT("info", ("sem unlock ok")); }
-#define STRUCT_LOCK(M) {DBUG_PRINT("info", ("%d struct lock...",__LINE__)); \
- pthread_mutex_lock(M);DBUG_PRINT("info", ("struct lock OK"));}
+#define SEM_UNLOCK(M) {DBUG_PRINT("lock", ("sem unlock 0x%lx", (ulong)(M))); \
+ sem_post(M); DBUG_PRINT("lock", ("sem unlock ok")); }
+#define STRUCT_LOCK(M) {DBUG_PRINT("lock", ("%d struct lock...",__LINE__)); \
+ pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));}
#define STRUCT_UNLOCK(M) { \
- DBUG_PRINT("info", ("%d struct unlock...",__LINE__)); \
- pthread_mutex_unlock(M);DBUG_PRINT("info", ("struct unlock OK"));}
-#define BLOCK_LOCK_WR(B) {DBUG_PRINT("info", ("%d LOCK_WR 0x%lx",\
+ DBUG_PRINT("lock", ("%d struct unlock...",__LINE__)); \
+ pthread_mutex_unlock(M);DBUG_PRINT("lock", ("struct unlock OK"));}
+#define BLOCK_LOCK_WR(B) {DBUG_PRINT("lock", ("%d LOCK_WR 0x%lx",\
__LINE__,(ulong)(B))); \
B->query()->lock_writing();}
-#define BLOCK_LOCK_RD(B) {DBUG_PRINT("info", ("%d LOCK_RD 0x%lx",\
+#define BLOCK_LOCK_RD(B) {DBUG_PRINT("lock", ("%d LOCK_RD 0x%lx",\
__LINE__,(ulong)(B))); \
B->query()->lock_reading();}
#define BLOCK_UNLOCK_WR(B) { \
- DBUG_PRINT("info", ("%d UNLOCK_WR 0x%lx",\
+ DBUG_PRINT("lock", ("%d UNLOCK_WR 0x%lx",\
__LINE__,(ulong)(B)));B->query()->unlock_writing();}
#define BLOCK_UNLOCK_RD(B) { \
- DBUG_PRINT("info", ("%d UNLOCK_RD 0x%lx",\
+ DBUG_PRINT("lock", ("%d UNLOCK_RD 0x%lx",\
__LINE__,(ulong)(B)));B->query()->unlock_reading();}
-#define DUMP(C) {C->bins_dump();C->cache_dump();\
- C->queries_dump();C->tables_dump();}
+#define DUMP(C) DBUG_EXECUTE("qcache", {(C)->queries_dump();(C)->tables_dump();})
#else
#define MUTEX_LOCK(M) pthread_mutex_lock(M)
#define SEM_LOCK(M) sem_wait(M)
@@ -70,24 +258,24 @@
#endif
/*****************************************************************************
- * Query_cache_block_table method(s)
- *****************************************************************************/
+ Query_cache_block_table method(s)
+*****************************************************************************/
inline Query_cache_block * Query_cache_block_table::block()
{
- return (Query_cache_block *)( ((byte*)this) -
- ALIGN_SIZE(sizeof(Query_cache_block_table))*n -
- ALIGN_SIZE(sizeof(Query_cache_block)));
+ return (Query_cache_block *)(((byte*)this) -
+ sizeof(Query_cache_block_table)*n -
+ ALIGN_SIZE(sizeof(Query_cache_block)));
};
/*****************************************************************************
- * Query_cache_block method(s)
- *****************************************************************************/
+ Query_cache_block method(s)
+*****************************************************************************/
void Query_cache_block::init(ulong block_length)
{
DBUG_ENTER("Query_cache_block::init");
- DBUG_PRINT("info", ("init block 0x%lx", (ulong) this));
+ DBUG_PRINT("qcache", ("init block 0x%lx", (ulong) this));
length = block_length;
used = 0;
type = Query_cache_block::FREE;
@@ -98,15 +286,15 @@ void Query_cache_block::init(ulong block_length)
void Query_cache_block::destroy()
{
DBUG_ENTER("Query_cache_block::destroy");
- DBUG_PRINT("info", ("destroy block 0x%lx, type %d",
- (ulong)this, type));
+ DBUG_PRINT("qcache", ("destroy block 0x%lx, type %d",
+ (ulong) this, type));
type = INCOMPLETE;
DBUG_VOID_RETURN;
}
inline uint Query_cache_block::headers_len()
{
- return (ALIGN_SIZE(sizeof(Query_cache_block_table))*n_tables +
+ return (ALIGN_SIZE(sizeof(Query_cache_block_table)*n_tables) +
ALIGN_SIZE(sizeof(Query_cache_block)));
}
@@ -147,7 +335,7 @@ inline Query_cache_block_table * Query_cache_block::table(TABLE_COUNTER_TYPE n)
{
return ((Query_cache_block_table *)
(((byte*)this)+ALIGN_SIZE(sizeof(Query_cache_block)) +
- n*ALIGN_SIZE(sizeof(Query_cache_block_table))));
+ n*sizeof(Query_cache_block_table)));
}
@@ -155,8 +343,10 @@ inline Query_cache_block_table * Query_cache_block::table(TABLE_COUNTER_TYPE n)
* Query_cache_table method(s)
*****************************************************************************/
-byte * Query_cache_table::cache_key(const byte *record, uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C"
+{
+byte *query_cache_table_get_key(const byte *record, uint *length,
+ my_bool not_used __attribute__((unused)))
{
Query_cache_block* table_block = (Query_cache_block*) record;
*length = (table_block->used - table_block->headers_len() -
@@ -164,15 +354,11 @@ byte * Query_cache_table::cache_key(const byte *record, uint *length,
return (((byte *) table_block->data()) +
ALIGN_SIZE(sizeof(Query_cache_table)));
}
-
-void Query_cache_table::free_cache(void *entry)
-{
- //NOP
}
/*****************************************************************************
- * Query_cache_query methods
- *****************************************************************************/
+ Query_cache_query methods
+*****************************************************************************/
void Query_cache_query::init_n_lock()
{
@@ -182,17 +368,18 @@ void Query_cache_query::init_n_lock()
pthread_mutex_init(&clients_guard,MY_MUTEX_INIT_FAST);
clients = 0;
lock_writing();
- DBUG_PRINT("info", ("inited & locked query for block 0x%lx",
- ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx",
+ ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
DBUG_VOID_RETURN;
}
+
void Query_cache_query::unlock_n_destroy()
{
DBUG_ENTER("Query_cache_query::unlock_n_destroy");
this->unlock_writing();
- DBUG_PRINT("info", ("destroyed & unlocked query for block 0x%lx",
- ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
+ ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
sem_destroy(&lock);
pthread_mutex_destroy(&clients_guard);
DBUG_VOID_RETURN;
@@ -200,10 +387,10 @@ void Query_cache_query::unlock_n_destroy()
/*
- Following methods work for block rwad/write locking only in this
+ Following methods work for block read/write locking only in this
particular case and in interaction with structure_guard_mutex.
- Lock for write prevents any other locking.
+ Lock for write prevents any other locking. (exclusive use)
Lock for read prevents only locking for write.
*/
@@ -215,9 +402,9 @@ void Query_cache_query::lock_writing()
/*
Needed for finding queries, that we may delete from cache.
- We don't want wait while block become unlocked, in addition
- block locking mean that query now used and we not need to
- remove it
+ We don't want to wait while block become unlocked. In addition,
+ block locking means that query is now used and we don't need to
+ remove it.
*/
my_bool Query_cache_query::try_lock_writing()
@@ -225,10 +412,10 @@ my_bool Query_cache_query::try_lock_writing()
DBUG_ENTER("Query_cache_block::try_lock_writing");
if (sem_trywait(&lock)!=0 || clients != 0)
{
- DBUG_PRINT("info", ("can't lock mutex"));
+ DBUG_PRINT("qcache", ("can't lock mutex"));
DBUG_RETURN(0);
}
- DBUG_PRINT("info", ("mutex 'lock' 0x%lx locked", (ulong) &lock));
+ DBUG_PRINT("qcache", ("mutex 'lock' 0x%lx locked", (ulong) &lock));
DBUG_RETURN(1);
}
@@ -236,8 +423,8 @@ my_bool Query_cache_query::try_lock_writing()
void Query_cache_query::lock_reading()
{
MUTEX_LOCK(&clients_guard);
- clients++;
- if (clients == 1) SEM_LOCK(&lock);
+ if (!clients++)
+ SEM_LOCK(&lock);
MUTEX_UNLOCK(&clients_guard);
}
@@ -251,32 +438,27 @@ void Query_cache_query::unlock_writing()
void Query_cache_query::unlock_reading()
{
MUTEX_LOCK(&clients_guard);
- clients--;
- if (clients == 0) SEM_UNLOCK(&lock);
+ if (--clients == 0)
+ SEM_UNLOCK(&lock);
MUTEX_UNLOCK(&clients_guard);
-
}
-
-byte * Query_cache_query::cache_key( const byte *record, uint *length,
- my_bool not_used)
+extern "C"
+{
+byte *query_cache_query_get_key(const byte *record, uint *length,
+ my_bool not_used)
{
- Query_cache_block * query_block = (Query_cache_block *) record;
+ Query_cache_block *query_block = (Query_cache_block*) record;
*length = (query_block->used - query_block->headers_len() -
ALIGN_SIZE(sizeof(Query_cache_query)));
- return (((byte *)query_block->data()) +
+ return (((byte *) query_block->data()) +
ALIGN_SIZE(sizeof(Query_cache_query)));
}
-
-
-void Query_cache_query::free_cache(void *entry)
-{
- //NOP
}
/*****************************************************************************
- * Query cache store functions
- *****************************************************************************/
+ Functions to store things into the query cache
+*****************************************************************************/
void query_cache_insert(NET *net, const char *packet, ulong length)
{
@@ -292,27 +474,29 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
if (net->query_cache_query != 0)
{
STRUCT_LOCK(&query_cache.structure_guard_mutex);
- if (net->query_cache_query != 0)
+ Query_cache_block *query_block = ((Query_cache_block*)
+ net->query_cache_query);
+ if (query_block)
{
- Query_cache_block * query_block = (Query_cache_block*)
- net->query_cache_query;
- DUMP((&query_cache));
+ Query_cache_query *header = query_block->query();
+ Query_cache_block *result = header->result();
+
+ DUMP(&query_cache);
BLOCK_LOCK_WR(query_block);
- DBUG_PRINT("info", ("insert packet %lu bytes long",length));
- Query_cache_query * header = query_block->query();
+ DBUG_PRINT("qcache", ("insert packet %lu bytes long",length));
- Query_cache_block * result = header->result();
/*
- STRUCT_UNLOCK(&query_cache.structure_guard_mutex); will be done by
- query_cache.append_result_data if success (if no success we need
+ On success STRUCT_UNLOCK(&query_cache.structure_guard_mutex) will be
+ done by query_cache.append_result_data if success (if not we need
query_cache.structure_guard_mutex locked to free query)
*/
- if (!query_cache.append_result_data( result, length, (gptr) packet,
- query_block, result))
+ if (!query_cache.append_result_data(&result, length, (gptr) packet,
+ query_block))
{
DBUG_PRINT("warning", ("Can't append data"));
header->result(result);
- DBUG_PRINT("info", ("free query 0x%lx", (ulong)query_block));
+ DBUG_PRINT("qcache", ("free query 0x%lx", (ulong) query_block));
+ // The following call will remove the lock on query_block
query_cache.free_query(query_block);
// append_result_data no success => we need unlock
STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
@@ -327,26 +511,26 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
DBUG_VOID_RETURN;
}
+
void query_cache_abort(NET *net)
{
DBUG_ENTER("query_cache_abort");
#ifndef DBUG_OFF
- // debuging method wreck may cause this
+ // Debugging method wreck may cause this
if (query_cache.query_cache_size == 0)
DBUG_VOID_RETURN;
#endif
-
- // quick check on unlocked structure
- if (net->query_cache_query != 0)
+ if (net->query_cache_query != 0) // Quick check on unlocked structure
{
STRUCT_LOCK(&query_cache.structure_guard_mutex);
- DUMP((&query_cache));
- Query_cache_block * query_block = ((Query_cache_block*)
+ Query_cache_block *query_block = ((Query_cache_block*)
net->query_cache_query);
- if (query_block)
+ if (query_block) // Test if changed by other thread
{
+ DUMP(&query_cache);
BLOCK_LOCK_WR(query_block);
+ // The following call will remove the lock on query_block
query_cache.free_query(query_block);
net->query_cache_query=0;
}
@@ -355,37 +539,30 @@ void query_cache_abort(NET *net)
DBUG_VOID_RETURN;
}
-void query_cache_end_of_result(NET * net)
+
+void query_cache_end_of_result(NET *net)
{
DBUG_ENTER("query_cache_end_of_result");
#ifndef DBUG_OFF
- // debuging method wreck may couse this
+ // Debugging method wreck may cause this
if (query_cache.query_cache_size == 0) DBUG_VOID_RETURN;
#endif
- //quick check on unlocked structure
- if (net->query_cache_query != 0)
+ if (net->query_cache_query != 0) // Quick check on unlocked structure
{
STRUCT_LOCK(&query_cache.structure_guard_mutex);
- if (net->query_cache_query != 0)
+ Query_cache_block *query_block = ((Query_cache_block*)
+ net->query_cache_query);
+ if (query_block)
{
- Query_cache_block * query_block = (Query_cache_block*)
- net->query_cache_query;
- DUMP((&query_cache));
+ DUMP(&query_cache);
BLOCK_LOCK_WR(query_block);
STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
- Query_cache_query * header = query_block->query();
-#ifndef DBUG_OFF
- if (header->result() != 0)
- {
-#endif
- header->found_rows(current_thd->limit_found_rows);
- header->result()->type = Query_cache_block::RESULT;
+ Query_cache_query *header = query_block->query();
#ifndef DBUG_OFF
- }
- else
+ if (header->result() == 0)
{
DBUG_PRINT("error", ("end of data whith no result. query '%s'",
header->query()));
@@ -393,13 +570,15 @@ void query_cache_end_of_result(NET * net)
DBUG_VOID_RETURN;
}
#endif
+ header->found_rows(current_thd->limit_found_rows);
+ header->result()->type = Query_cache_block::RESULT;
net->query_cache_query=0;
header->writer(0);
BLOCK_UNLOCK_WR(query_block);
}
else
{
- //cache was flushed or resized and query was deleted => do nothing
+ // Cache was flushed or resized and query was deleted => do nothing
STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
}
net->query_cache_query=0;
@@ -407,48 +586,39 @@ void query_cache_end_of_result(NET * net)
DBUG_VOID_RETURN;
}
-void query_cache_invalidate_by_MyISAM_filename(char * filename)
+void query_cache_invalidate_by_MyISAM_filename(const char *filename)
{
query_cache.invalidate_by_MyISAM_filename(filename);
}
-/*****************************************************************************
- * Query_cache methods
- *****************************************************************************/
/*****************************************************************************
- * interface methods
- *****************************************************************************/
+ Query_cache methods
+*****************************************************************************/
-Query_cache::Query_cache(
- ulong query_cache_limit,
+Query_cache::Query_cache(ulong query_cache_limit,
ulong min_allocation_unit,
ulong min_result_data_size,
uint def_query_hash_size ,
- uint def_table_hash_size):
-
- query_cache_size(0),
- query_cache_limit(query_cache_limit),
- min_allocation_unit(min_allocation_unit),
- min_result_data_size(min_result_data_size),
- def_query_hash_size(def_query_hash_size),
- def_table_hash_size(def_table_hash_size),
- queries_in_cache(0), hits(0), inserts(0), refused(0),
- initialized(0)
-{
- if (min_allocation_unit < ALIGN_SIZE(sizeof(Query_cache_block)) +
- ALIGN_SIZE(sizeof(Query_cache_block_table)) +
- ALIGN_SIZE(sizeof(Query_cache_query)) + 3)
- {
- min_allocation_unit=ALIGN_SIZE(sizeof(Query_cache_block)) +
- ALIGN_SIZE(sizeof(Query_cache_block_table)) +
- ALIGN_SIZE(sizeof(Query_cache_query)) + 3;
- }
+ uint def_table_hash_size)
+ :query_cache_size(0),
+ query_cache_limit(query_cache_limit),
+ min_allocation_unit(min_allocation_unit),
+ min_result_data_size(min_result_data_size),
+ def_query_hash_size(def_query_hash_size),
+ def_table_hash_size(def_table_hash_size),
+ queries_in_cache(0), hits(0), inserts(0), refused(0),
+ initialized(0)
+{
+ ulong min_needed=(ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_block_table)) +
+ ALIGN_SIZE(sizeof(Query_cache_query)) + 3);
+ set_if_bigger(min_allocation_unit,min_needed);
this->min_allocation_unit = min_allocation_unit;
- if (min_result_data_size < min_allocation_unit)
- this->min_result_data_size = min_allocation_unit;
+ set_if_bigger(this->min_result_data_size,min_allocation_unit);
}
+
ulong Query_cache::resize(ulong query_cache_size)
{
/*
@@ -456,102 +626,93 @@ ulong Query_cache::resize(ulong query_cache_size)
query_cache_size < this->query_cache_size
*/
/*
- TODO: try to copy old cache in new mamory
+ TODO: try to copy old cache in new memory
*/
DBUG_ENTER("Query_cache::resize");
- DBUG_PRINT("info", ("from %lu to %lu",this->query_cache_size,\
- query_cache_size));
+ DBUG_PRINT("qcache", ("from %lu to %lu",this->query_cache_size,
+ query_cache_size));
free_cache(0);
this->query_cache_size=query_cache_size;
DBUG_RETURN(init_cache());
}
+
void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
{
/*
- TODO may be better convert keywords to upper case when query
- stored/compared
+ TODO:
+ Maybe better convert keywords to upper case when query stored/compared.
+ (Not important at this stage)
*/
+ TABLE_COUNTER_TYPE tables;
DBUG_ENTER("Query_cache::store_query");
if (query_cache_size == 0)
DBUG_VOID_RETURN;
- LEX * lex = &thd->lex;
- NET * net = &thd->net;
-
- TABLE_COUNTER_TYPE tables = 0;
-
- if ((tables = is_cachable(thd, thd->query_length,
- thd->query, lex, tables_used))){
+ if ((tables = is_cacheable(thd, thd->query_length,
+ thd->query, &thd->lex, tables_used)))
+ {
+ NET *net = &thd->net;
+ byte flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
STRUCT_LOCK(&structure_guard_mutex);
+
if (query_cache_size == 0)
DBUG_VOID_RETURN;
-
DUMP(this);
/*
- prepare flags:
- most significant bit - CLIENT_LONG_FLAG,
- other - charset number (0 no charset convertion)
+ Prepare flags:
+ most significant bit - CLIENT_LONG_FLAG,
+ other - charset number (0 no charset convertion)
*/
- byte flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
if (thd->convert_set != 0)
{
- flags |= (byte) thd->convert_set->number();
-#ifndef DBUG_OFF
- if ( (thd->convert_set->number() & QUERY_CACHE_CHARSET_CONVERT_MASK) !=
- thd->convert_set->number())
- {
- wreck(__LINE__,
- "charset number bigger than QUERY_CACHE_CHARSET_CONVERT_MASK");
- }
-#endif
+ flags|= (byte) thd->convert_set->number();
+ DBUG_ASSERT(thd->convert_set->number() < 128);
}
- /* check: Is it another thread who process same query? */
- thd->query[thd->query_length] = (char)flags;
+ /* Check if another thread is processing the same query? */
+ thd->query[thd->query_length] = (char) flags;
Query_cache_block *competitor = (Query_cache_block *)
hash_search(&queries, thd->query, thd->query_length+1);
- thd->query[thd->query_length] = '\0';
- DBUG_PRINT("info", ("competitor 0x%lx, flags %x", (ulong)competitor,
+ DBUG_PRINT("qcache", ("competitor 0x%lx, flags %x", (ulong) competitor,
flags));
-
if (competitor == 0)
{
- thd->query[thd->query_length] = (char)flags;
- Query_cache_block * query_block =
- write_block_data(thd->query_length+1,
- (gptr) thd->query,
- ALIGN_SIZE(sizeof(Query_cache_query)),
- Query_cache_block::QUERY, tables, 1);
- thd->query[thd->query_length] = '\0';
+ /* Query is not in cache and no one is working with it; Store it */
+ thd->query[thd->query_length] = (char) flags;
+ Query_cache_block *query_block;
+ query_block= write_block_data(thd->query_length+1,
+ (gptr) thd->query,
+ ALIGN_SIZE(sizeof(Query_cache_query)),
+ Query_cache_block::QUERY, tables, 1);
if (query_block != 0)
{
- DBUG_PRINT("info", ("query block 0x%lx allocated, %lu",
- (ulong)query_block, query_block->used));
+ DBUG_PRINT("qcache", ("query block 0x%lx allocated, %lu",
+ (ulong) query_block, query_block->used));
- Query_cache_query * header = query_block->query();
+ Query_cache_query *header = query_block->query();
header->init_n_lock();
- if (hash_insert(&queries, (byte*)query_block))
+ if (hash_insert(&queries, (byte*) query_block))
{
refused++;
- DBUG_PRINT("info", ("insertion in query hash"));
+ DBUG_PRINT("qcache", ("insertion in query hash"));
header->unlock_n_destroy();
free_memory_block(query_block);
STRUCT_UNLOCK(&structure_guard_mutex);
- DBUG_VOID_RETURN;
+ goto end;
}
if (!register_all_tables(query_block, tables_used, tables))
{
refused++;
- DBUG_PRINT("warning", ("tables list incliding filed"));
+ DBUG_PRINT("warning", ("tables list including failed"));
hash_delete(&queries, (char *) query_block);
header->unlock_n_destroy();
free_memory_block(query_block);
STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_VOID_RETURN;
}
- double_linked_list_simple_include(query_block, queries_blocks);
+ double_linked_list_simple_include(query_block, &queries_blocks);
inserts++;
queries_in_cache++;
STRUCT_UNLOCK(&structure_guard_mutex);
@@ -563,29 +724,36 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
}
else
{
- refused++;
// We have not enough memory to store query => do nothing
+ refused++;
STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_PRINT("warning", ("Can't allocate query"));
}
}
else
{
+ // Another thread is processing the same query => do nothing
refused++;
- // Another thread already procass same query => do nothing
- DBUG_PRINT("info", ("Another thread process same query"));
STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_PRINT("qcache", ("Another thread process same query"));
}
}
else
refused++;
+
+end:
+ thd->query[thd->query_length]= 0; // Restore end null
DBUG_VOID_RETURN;
}
-my_bool Query_cache::send_result_to_client(
- THD *thd, char *sql, uint query_length)
-{
+my_bool
+Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
+{
+ Query_cache_query *query;
+ Query_cache_block *first_result_block, *result_block;
+ Query_cache_block_table *block_table, *block_table_end;
+ byte flags;
DBUG_ENTER("Query_cache::send_result_to_client");
if (query_cache_size == 0 ||
@@ -597,138 +765,142 @@ my_bool Query_cache::send_result_to_client(
thd->query_cache_type == 0)
{
- DBUG_PRINT("info", ("query cache disabled on not in autocommit mode"));
- DBUG_RETURN(1);
+ DBUG_PRINT("qcache", ("query cache disabled on not in autocommit mode"));
+ goto err;
+ }
+ /*
+ We can't cache the query if we are using a temporary table because
+ we don't know if the query is using a temporary table.
+
+ TODO: We could parse the query and then check if the query used
+ a temporary table.
+ */
+ if (thd->temporary_tables != 0 || !thd->safe_to_cache_query)
+ {
+ DBUG_PRINT("qcache", ("SELECT is non-cacheable"));
+ goto err;
}
- char *begin = sql;
- while(*begin == ' ' || *begin == '\t') begin++;
- if ( toupper(begin[0])!='S' ||
- toupper(begin[1])!='E' ||
- toupper(begin[2])!='L')
+ /* Test if the query is a SELECT */
+ while (*sql == ' ' || *sql == '\t')
{
- DBUG_PRINT("info", ("Not look like SELECT"));
- DBUG_RETURN(1);
+ sql++;
+ query_length--;
}
- if (thd->temporary_tables != 0 || !thd->safe_to_cache_query )
+ if (toupper(sql[0]) != 'S' || toupper(sql[1]) != 'E' ||
+ toupper(sql[2]) !='L')
{
- DBUG_PRINT("info", ("SELECT is non-cachable"));
- DBUG_RETURN(1);
+ DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
+ goto err;
}
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size == 0)
{
- DBUG_PRINT("info", ("query cache disabled on not in autocommit mode"));
- DBUG_RETURN(1);
+ DBUG_PRINT("qcache", ("query cache disabled and not in autocommit mode"));
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ goto err;
}
- DBUG_PRINT("info", (" sql %u '%s'", query_length, sql));
- Query_cache_block *query_block = 0;
+ DBUG_PRINT("qcache", (" sql %u '%s'", query_length, sql));
+ Query_cache_block *query_block;
/*
prepare flags:
- most significant bit - CLIENT_LONG_FLAG,
- other - charset number (0 no charset convertion)
+ Most significant bit - CLIENT_LONG_FLAG,
+ Other - charset number (0 no charset convertion)
*/
- byte flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
+ flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
if (thd->convert_set != 0)
{
flags |= (byte) thd->convert_set->number();
-#ifndef DBUG_OFF
- if ( (thd->convert_set->number() & QUERY_CACHE_CHARSET_CONVERT_MASK) !=
- thd->convert_set->number())
- {
- wreck(__LINE__,
- "charset number bigger than QUERY_CACHE_CHARSET_CONVERT_MASK");
- }
-#endif
+ DBUG_ASSERT(thd->convert_set->number() < 128);
}
sql[query_length] = (char) flags;
- query_block = (Query_cache_block *)
- hash_search(&queries, sql, query_length+1);
+ query_block = (Query_cache_block *) hash_search(&queries, sql,
+ query_length+1);
sql[query_length] = '\0';
- /*quick abort on unlocked data*/
+ /* Quick abort on unlocked data */
if (query_block == 0 ||
query_block->query()->result() == 0 ||
query_block->query()->result()->type != Query_cache_block::RESULT)
{
STRUCT_UNLOCK(&structure_guard_mutex);
- DBUG_PRINT("info", ("No query in query hash or no results"));
- DBUG_RETURN(1);
+ DBUG_PRINT("qcache", ("No query in query hash or no results"));
+ goto err;
}
- DBUG_PRINT("info", ("Query in query hash 0x%lx", (ulong)query_block));
+ DBUG_PRINT("qcache", ("Query in query hash 0x%lx", (ulong)query_block));
- /* now lock and test that nothing changed while blocks was unlocked */
+ /* Now lock and test that nothing changed while blocks was unlocked */
BLOCK_LOCK_RD(query_block);
STRUCT_UNLOCK(&structure_guard_mutex);
- Query_cache_query * query = query_block->query();
- Query_cache_block * first_result_block = query->result();
- Query_cache_block * result_block = first_result_block;
- if (result_block == 0 ||
- result_block->type != Query_cache_block::RESULT)
- {
- DBUG_PRINT("info", ("query found, but no data or data incomplete"));
- DBUG_RETURN(1); //no data in query
- }
- DBUG_PRINT("info", ("Query have result 0x%lx", (ulong)query));
-
- //check access;
- TABLE_COUNTER_TYPE t = 0;
- for(; t < query_block->n_tables; t++)
- {
- TABLE_LIST table_list;
- table_list.next = 0;
- table_list.use_index = table_list.ignore_index = 0;
- table_list.table = 0;
- table_list.grant.grant_table = 0;
- table_list.grant.version = table_list.grant.privilege =
- table_list.grant.want_privilege = 0;
- table_list.outer_join = 0;
- table_list.straight = 0;
- table_list.updating = 0;
- table_list.shared = 0;
-
- Query_cache_table * table = query_block->table(t)->parent;
- table_list.db = table->db();
- table_list.name = table_list.real_name = table->table();
- if (check_table_access(thd,SELECT_ACL,&table_list))
- {
- DBUG_PRINT("info",
- ("probably no SELECT access to %s.%s =>\
- return to normal processing",
- table_list.db, table_list.name));
- DBUG_RETURN(1); //no access
- }
+ query = query_block->query();
+ result_block= first_result_block= query->result();
+
+ if (result_block == 0 || result_block->type != Query_cache_block::RESULT)
+ {
+ /* The query is probably yet processed */
+ DBUG_PRINT("qcache", ("query found, but no data or data incomplete"));
+ goto err;
}
+ DBUG_PRINT("qcache", ("Query have result 0x%lx", (ulong) query));
+
+ // Check access;
+ block_table= query_block->table(0);
+ block_table_end= block_table+query_block->n_tables;
+ for ( ; block_table != block_table_end; block_table++)
+ {
+ TABLE_LIST table_list;
+ bzero((char*) &table_list,sizeof(table_list));
+ Query_cache_table *table = block_table->parent;
+ table_list.db = table->db();
+ table_list.name = table_list.real_name = table->table();
+ if (check_table_access(thd,SELECT_ACL,&table_list))
+ {
+ DBUG_PRINT("qcache",
+ ("probably no SELECT access to %s.%s => return to normal processing",
+ table_list.db, table_list.name));
+ goto err;
+ }
+ }
move_to_query_list_end(query_block);
hits++;
+ /*
+ Send cached result to client
+ */
do
{
- DBUG_PRINT("info", ("Results (len %lu, used %lu, headers %lu)",
+ DBUG_PRINT("qcache", ("Results (len %lu, used %lu, headers %lu)",
result_block->length, result_block->used,
result_block->headers_len()+
ALIGN_SIZE(sizeof(Query_cache_result))));
- Query_cache_result * result = result_block->result();
- net_real_write(&thd->net, result->data(),
- result_block->used -
- result_block->headers_len() -
- ALIGN_SIZE(sizeof(Query_cache_result)));
+ Query_cache_result *result = result_block->result();
+ if (net_real_write(&thd->net, result->data(),
+ result_block->used -
+ result_block->headers_len() -
+ ALIGN_SIZE(sizeof(Query_cache_result))))
+ break; // Client aborted
result_block = result_block->next;
} while (result_block != first_result_block);
thd->limit_found_rows = query->found_rows();
BLOCK_UNLOCK_RD(query_block);
-
DBUG_RETURN(0);
+
+err:
+ DBUG_RETURN(1);
}
+/*
+ Remove all cached queries that uses any of the tables in the list
+*/
+
void Query_cache::invalidate(TABLE_LIST *tables_used)
{
DBUG_ENTER("Query_cache::invalidate (table list)");
@@ -746,6 +918,10 @@ void Query_cache::invalidate(TABLE_LIST *tables_used)
DBUG_VOID_RETURN;
}
+/*
+ Remove all cached queries that uses the given table
+*/
+
void Query_cache::invalidate(TABLE *table)
{
DBUG_ENTER("Query_cache::invalidate (table)");
@@ -759,6 +935,14 @@ void Query_cache::invalidate(TABLE *table)
DBUG_VOID_RETURN;
}
+
+/*
+ Remove all cached queries that uses the given table type.
+ TODO: This is currently used to invalidate InnoDB tables on commit.
+ We should remove this function and only invalidate tables
+ used in the transaction.
+*/
+
void Query_cache::invalidate(Query_cache_table::query_cache_table_type type)
{
DBUG_ENTER("Query_cache::invalidate (type)");
@@ -771,25 +955,27 @@ void Query_cache::invalidate(Query_cache_table::query_cache_table_type type)
Query_cache_block *table_block = tables_blocks[type];
do
{
- /*
- store next block address defore deletetion of current block
- */
+ /* Store next block address defore deleting the current block */
Query_cache_block *next = table_block->next;
invalidate_table(table_block);
- if (next == table_block)
+ if (next == table_block) // End of list
break;
table_block = next;
- } while (table_block != tables_blocks[type]);
-
+ } while (table_block != tables_blocks[type]);
}
STRUCT_UNLOCK(&structure_guard_mutex);
}
DBUG_VOID_RETURN;
}
+
+/*
+ Remove all cached queries that uses the given database
+*/
+
void Query_cache::invalidate(char *db)
{
DBUG_ENTER("Query_cache::invalidate (db)");
@@ -802,13 +988,13 @@ void Query_cache::invalidate(char *db)
int i = 0;
for(; i < (int) Query_cache_table::TYPES_NUMBER; i++)
{
- if (tables_blocks[i] != 0) //cache not empty
+ if (tables_blocks[i] != 0) // Cache not empty
{
Query_cache_block *table_block = tables_blocks[i];
do
{
/*
- store next block address defore deletetion of current block
+ Store next block address defore deletetion of current block
*/
Query_cache_block *next = table_block->next;
@@ -827,27 +1013,29 @@ void Query_cache::invalidate(char *db)
DBUG_VOID_RETURN;
}
-void Query_cache::invalidate_by_MyISAM_filename(char * filename)
+
+void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
{
DBUG_ENTER("Query_cache::invalidate_by_MyISAM_filename");
if (query_cache_size > 0)
{
+ /* Calculate the key outside the lock to make the lock shorter */
+ char key[MAX_DBKEY_LENGTH];
+ uint key_length= filename_2_table_key(key, filename);
STRUCT_LOCK(&structure_guard_mutex);
- if (query_cache_size > 0)
+ if (query_cache_size > 0) // Safety if cache removed
{
- char key[MAX_DBKEY_LENGTH];
- uint key_length =
- Query_cache::filename_2_table_key(key, filename);
-
- Query_cache_block *table_block;
- if ((table_block = (Query_cache_block*)
- hash_search(&tables, key, key_length)))
- invalidate_table(table_block);
+ Query_cache_block *table_block;
+ if ((table_block = (Query_cache_block*) hash_search(&tables, key,
+ key_length)))
+ invalidate_table(table_block);
}
STRUCT_UNLOCK(&structure_guard_mutex);
}
DBUG_VOID_RETURN;
}
+
+
void Query_cache::flush()
{
DBUG_ENTER("Query_cache::flush");
@@ -873,6 +1061,7 @@ void Query_cache::pack(ulong join_limit, uint iteration_limit)
DBUG_VOID_RETURN;
}
+
void Query_cache::destroy()
{
DBUG_ENTER("Query_cache::destroy");
@@ -882,161 +1071,10 @@ void Query_cache::destroy()
DBUG_VOID_RETURN;
}
-#ifndef DBUG_OFF
-
-void Query_cache::wreck(uint line, const char * message)
-{
- DBUG_ENTER("Query_cache::wreck");
- query_cache_size = 0;
- DBUG_PRINT("error", (" %s", message));
- DBUG_PRINT("warning", ("=================================="));
- DBUG_PRINT("warning", ("%5d QUERY CACHE WRECK => DISABLED",line));
- DBUG_PRINT("warning", ("=================================="));
- current_thd->killed = 1;
- bins_dump();
- cache_dump();
- DBUG_VOID_RETURN;
-}
-
-void Query_cache::bins_dump()
-{
- DBUG_PRINT("info", ("mem_bin_num=%u, mem_bin_steps=%u",
- mem_bin_num, mem_bin_steps));
- DBUG_PRINT("info", ("-------------------------"));
- DBUG_PRINT("info", (" size idx step"));
- DBUG_PRINT("info", ("-------------------------"));
- uint i = 0;
- for(; i < mem_bin_steps; i++)
- {
- DBUG_PRINT("info", ("%10lu %3d %10lu", steps[i].size, steps[i].idx,
- steps[i].increment));
- }
- DBUG_PRINT("info", ("-------------------------"));
- DBUG_PRINT("info", (" size num"));
- DBUG_PRINT("info", ("-------------------------"));
- i = 0;
- for(; i < mem_bin_num; i++)
- {
- DBUG_PRINT("info", ("%10lu %3d 0x%lx", bins[i].size, bins[i].number,
- (ulong)&(bins[i])));
- if (bins[i].free_blocks)
- {
- Query_cache_block * block = bins[i].free_blocks;
- do{
- DBUG_PRINT("info", ("\\-- %lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
- block->length, (ulong)block,
- (ulong)block->next, (ulong)block->prev,
- (ulong)block->pnext, (ulong)block->pprev));
- block = block->next;
- } while ( block != bins[i].free_blocks );
- }
- }
- DBUG_PRINT("info", ("-------------------------"));
-}
-
-void Query_cache::cache_dump()
-{
- DBUG_PRINT("info", ("-------------------------------------"));
- DBUG_PRINT("info", (" length used t nt"));
- DBUG_PRINT("info", ("-------------------------------------"));
- Query_cache_block * i = first_block;
- do
- {
- DBUG_PRINT("info",
- ("%10lu %10lu %1d %2d 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
- i->length, i->used, (int)i->type,
- i->n_tables, (ulong)i,
- (ulong)i->next, (ulong)i->prev, (ulong)i->pnext,
- (ulong)i->pprev));
- i = i->pnext;
- } while ( i != first_block );
- DBUG_PRINT("info", ("-------------------------------------"));
-}
-void Query_cache::queries_dump()
-{
- DBUG_PRINT("info", ("------------------"));
- DBUG_PRINT("info", (" QUERIES"));
- DBUG_PRINT("info", ("------------------"));
- if (queries_blocks != 0)
- {
- Query_cache_block * i = queries_blocks;
- do
- {
- uint len;
- char * str = (char*) Query_cache_query::cache_key((byte*) i, &len, 0);
- byte flags = (byte) str[len-1];
- str[len-1] = 0; //safe only under structure_guard_mutex locked
- DBUG_PRINT("info", ("%u (%u,%u) %s",len,
- ((flags & QUERY_CACHE_CLIENT_LONG_FLAG_MASK)?1:0),
- (flags & QUERY_CACHE_CHARSET_CONVERT_MASK), str));
- str[len-1] = (char)flags;
- DBUG_PRINT("info", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong)i,
- (ulong)i->next, (ulong)i->prev, (ulong)i->pnext,
- (ulong)i->pprev));
- TABLE_COUNTER_TYPE t = 0;
- for (; t < i->n_tables; t++)
- {
- Query_cache_table * table = i->table(t)->parent;
- DBUG_PRINT("info", ("-t- '%s' '%s'", table->db(), table->table()));
- }
- Query_cache_query * header = i->query();
- if (header->result())
- {
- Query_cache_block * result_block = header->result();
- Query_cache_block * result_beg = result_block;
- do
- {
- DBUG_PRINT("info", ("-r- %u %lu/%lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
- (uint) result_block->type,
- result_block->length, result_block->used,
- (ulong) result_block,
- (ulong) result_block->next,
- (ulong) result_block->prev,
- (ulong) result_block->pnext,
- (ulong) result_block->pprev));
- result_block = result_block->next;
- } while ( result_block != result_beg );
- }
- i = i->next;
- } while ( i != queries_blocks );
- }
- else
- {
- DBUG_PRINT("info", ("no queries in list"));
- }
- DBUG_PRINT("info", ("------------------"));
-}
-
-void Query_cache::tables_dump()
-{
- DBUG_PRINT("info", ("--------------------"));
- DBUG_PRINT("info", ("TABLES"));
- DBUG_PRINT("info", ("--------------------"));
- int i = 0;
- for(; i < (int) Query_cache_table::TYPES_NUMBER; i++)
- {
- DBUG_PRINT("info", ("--- type %u", i));
- if (tables_blocks[i] != 0)
- {
- Query_cache_block * table_block = tables_blocks[i];
- do
- {
- Query_cache_table * table = table_block->table();
- DBUG_PRINT("info", ("'%s' '%s'", table->db(), table->table()));
- table_block = table_block->next;
- } while ( table_block != tables_blocks[i]);
- }
- else
- DBUG_PRINT("info", ("no tables in list"));
- }
- DBUG_PRINT("info", ("--------------------"));
-}
-
-#endif
/*****************************************************************************
- * init/destroy
- *****************************************************************************/
+ init/destroy
+*****************************************************************************/
void Query_cache::init()
{
@@ -1046,205 +1084,174 @@ void Query_cache::init()
DBUG_VOID_RETURN;
}
+
ulong Query_cache::init_cache()
{
+ uint mem_bin_count, num, step;
+ ulong mem_bin_size, prev_size, inc;
+ ulong additional_data_size, max_mem_bin_size, approx_additional_data_size;
+
DBUG_ENTER("Query_cache::init_cache");
if (!initialized)
- {
- DBUG_PRINT("info", ("first time init"));
init();
- }
- ulong additional_data_size = 0,
- approx_additional_data_size = sizeof(Query_cache) +
- sizeof(gptr)*(def_query_hash_size+def_query_hash_size);
-
- ulong max_mem_bin_size = 0;
+ approx_additional_data_size = (sizeof(Query_cache) +
+ sizeof(gptr)*(def_query_hash_size+
+ def_query_hash_size));
if (query_cache_size < approx_additional_data_size)
- {
- additional_data_size = 0;
- approx_additional_data_size = 0;
- make_disabled();
- }
- else
- {
- query_cache_size -= approx_additional_data_size;
+ goto err;
- //Count memory bins number.
+ query_cache_size -= approx_additional_data_size;
- /*
- The idea is inherited from GNU malloc with some add-ons.
- Free memory blocks are stored in bins according to their sizes.
- The bins are stored in size-descending order.
- The bins are approximately logarithmically separated by size.
-
- Opposite to GNU malloc bin splitting is not fixed but calculated
- depending on cache size. Spliting calculating stored in cache and
- then used for bin finding.
-
- For example:
- query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 = 100,
- min_allocation_unit = 17,
- QUERY_CACHE_MEM_BIN_STEP_PWR2 = 1,
- QUERY_CACHE_MEM_BIN_PARTS_INC = 1,
- QUERY_CACHE_MEM_BIN_PARTS_MUL = 1
- (in followed picture showed right (low) bound of bin):
+ /*
+ Count memory bins number.
+ Check section 6. in start comment for the used algorithm.
+ */
- | 100>>1 50>>1 |25>>1|
- | | | | | |
- | 100 75 50 41 33 25 21 18 15| 12 | - bins right (low) bounds
- |\---/\-----/\--------/\--------|---/ |
- | 0 1 2 3 | | - steps
- \-----------------------------/ \---/
- bins that we store in cache this bin showed for example only
- */
- max_mem_bin_size =
- query_cache_size >> QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2;
- uint mem_bin_count = 1 + QUERY_CACHE_MEM_BIN_PARTS_INC;
- mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
- mem_bin_num = 1;
- mem_bin_steps = 1;
- ulong mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
- ulong prev_size = 0;
- while (mem_bin_size > min_allocation_unit)
- {
- mem_bin_num += mem_bin_count;
- prev_size = mem_bin_size;
- mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
- mem_bin_steps++;
- mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
- mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
-
- //prevent too small bins spacing
- if (mem_bin_count > (mem_bin_size>>QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
- mem_bin_count=(mem_bin_size>>QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
- }
- ulong inc = (prev_size - mem_bin_size) / mem_bin_count;
- mem_bin_num += (mem_bin_count - (min_allocation_unit - mem_bin_size)/inc);
+ max_mem_bin_size = query_cache_size >> QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2;
+ mem_bin_count = (uint) ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
+ QUERY_CACHE_MEM_BIN_PARTS_MUL);
+ mem_bin_num = 1;
+ mem_bin_steps = 1;
+ mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
+ prev_size = 0;
+ while (mem_bin_size > min_allocation_unit)
+ {
+ mem_bin_num += mem_bin_count;
+ prev_size = mem_bin_size;
+ mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
mem_bin_steps++;
- additional_data_size = mem_bin_num *
- ALIGN_SIZE(sizeof(Query_cache_memory_bin))+
- mem_bin_steps * ALIGN_SIZE(sizeof(Query_cache_memory_bin_step));
+ mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
+ mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
+
+ // Prevent too small bins spacing
+ if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
+ mem_bin_count= (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
}
+ inc = (prev_size - mem_bin_size) / mem_bin_count;
+ mem_bin_num += (mem_bin_count - (min_allocation_unit - mem_bin_size)/inc);
+ mem_bin_steps++;
+ additional_data_size = ((mem_bin_num+1) *
+ ALIGN_SIZE(sizeof(Query_cache_memory_bin))+
+ (mem_bin_steps *
+ ALIGN_SIZE(sizeof(Query_cache_memory_bin_step))));
+
if (query_cache_size < additional_data_size)
- {
- additional_data_size = 0;
- approx_additional_data_size = 0;
- make_disabled();
- }
- else
- query_cache_size -= additional_data_size;
+ goto err;
+ query_cache_size -= additional_data_size;
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size <= min_allocation_unit)
{
- DBUG_PRINT("info",
+ DBUG_PRINT("qcache",
(" query_cache_size <= min_allocation_unit => cache disabled"));
- make_disabled();
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ goto err;
}
- else
+
+ if (!(cache = (byte *)
+ my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
{
- if ( (cache = (byte *)
- my_malloc_lock(query_cache_size+additional_data_size, MYF(0)))==0 )
- {
- DBUG_PRINT("warning",
- ("can't allocate query cache memory => cache disabled"));
- make_disabled();
- }
- else
- {
- DBUG_PRINT("info",
- ("cache length %lu, min unit %lu, %u bins",
- query_cache_size, min_allocation_unit, mem_bin_num));
-
- steps = (Query_cache_memory_bin_step *) cache;
- bins = (Query_cache_memory_bin *)
- (cache +
- mem_bin_steps * ALIGN_SIZE(sizeof(Query_cache_memory_bin_step)));
-
- first_block = (Query_cache_block *) (cache + additional_data_size);
- first_block->init(query_cache_size);
- first_block->pnext=first_block->pprev=first_block;
- first_block->next=first_block->prev=first_block;
-
- free_memory = query_cache_size;
-
- /* prepare bins */
-
- bins[0].init(max_mem_bin_size);
- steps[0].init(max_mem_bin_size,0,0);
- uint mem_bin_count = 1 + QUERY_CACHE_MEM_BIN_PARTS_INC;
- mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
- uint num = 1;
- ulong mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
- uint step = 1;
- while (mem_bin_size > min_allocation_unit)
- {
- ulong inc = (steps[step-1].size - mem_bin_size) / mem_bin_count;
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ goto err;
+ }
- unsigned long size = mem_bin_size;
- uint i = mem_bin_count;
- for(; i > 0; i--)
- {
- bins[num+i-1].init(size);
- size += inc;
- }
- num += mem_bin_count;
- steps[step].init(mem_bin_size, num-1, inc);
- mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
- step++;
- mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
- mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
- if (mem_bin_count > (mem_bin_size>>QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
- mem_bin_count=(mem_bin_size>>QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
- }
- ulong inc = (steps[step-1].size - mem_bin_size) / mem_bin_count;
- /*
- num + mem_bin_count > mem_bin_num, but index never be > mem_bin_num
- because block with size < min_allocated_unit never will be requested
- */
- steps[step].init(mem_bin_size, num + mem_bin_count - 1, inc);
- uint skiped = (min_allocation_unit - mem_bin_size)/inc;
- ulong size = mem_bin_size + inc*skiped;
- uint i = mem_bin_count - skiped;
- for(; i > 0; i--)
- {
- bins[num+i-1].init(size);
- size += inc;
- }
+ DBUG_PRINT("qcache", ("cache length %lu, min unit %lu, %u bins",
+ query_cache_size, min_allocation_unit, mem_bin_num));
- insert_into_free_memory_list(first_block);
+ steps = (Query_cache_memory_bin_step *) cache;
+ bins = ((Query_cache_memory_bin *)
+ (cache + mem_bin_steps *
+ ALIGN_SIZE(sizeof(Query_cache_memory_bin_step))));
- DUMP(this);
+ first_block = (Query_cache_block *) (cache + additional_data_size);
+ first_block->init(query_cache_size);
+ first_block->pnext=first_block->pprev=first_block;
+ first_block->next=first_block->prev=first_block;
- VOID(hash_init(&queries,def_query_hash_size, 0, 0,
- Query_cache_query::cache_key,
- (void (*)(void*))Query_cache_query::free_cache,
- 0));
- VOID(hash_init(&tables,def_table_hash_size, 0, 0,
- Query_cache_table::cache_key,
- (void (*)(void*))Query_cache_table::free_cache,
- 0));
+ /* Prepare bins */
+
+ bins[0].init(max_mem_bin_size);
+ steps[0].init(max_mem_bin_size,0,0);
+ mem_bin_count = (uint) ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
+ QUERY_CACHE_MEM_BIN_PARTS_MUL);
+ num= step= 1;
+ mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
+ while (mem_bin_size > min_allocation_unit)
+ {
+ ulong incr = (steps[step-1].size - mem_bin_size) / mem_bin_count;
+ unsigned long size = mem_bin_size;
+ for (uint i= mem_bin_count; i > 0; i--)
+ {
+ bins[num+i-1].init(size);
+ size += incr;
}
+ num += mem_bin_count;
+ steps[step].init(mem_bin_size, num-1, incr);
+ mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
+ step++;
+ mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
+ mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
+ if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
+ mem_bin_count=(mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
}
+ inc = (steps[step-1].size - mem_bin_size) / mem_bin_count;
+
+ /*
+ num + mem_bin_count > mem_bin_num, but index never be > mem_bin_num
+ because block with size < min_allocated_unit never will be requested
+ */
+
+ steps[step].init(mem_bin_size, num + mem_bin_count - 1, inc);
+ {
+ uint skiped = (min_allocation_unit - mem_bin_size)/inc;
+ ulong size = mem_bin_size + inc*skiped;
+ uint i = mem_bin_count - skiped;
+ while (i-- > 0)
+ {
+ bins[num+i].init(size);
+ size += inc;
+ }
+ }
+ bins[mem_bin_num].number= 1; // For easy end test
+ free_memory= 0;
+ insert_into_free_memory_list(first_block);
+
+ DUMP(this);
+
+ VOID(hash_init(&queries,def_query_hash_size, 0, 0,
+ query_cache_query_get_key, 0, 0));
+ VOID(hash_init(&tables,def_table_hash_size, 0, 0,
+ query_cache_table_get_key, 0, 0));
+
queries_in_cache = 0;
queries_blocks = 0;
STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_RETURN(query_cache_size +
additional_data_size + approx_additional_data_size);
+
+err:
+ make_disabled();
+ DBUG_RETURN(0);
}
+
+/* Disable the use of the query cache */
+
void Query_cache::make_disabled()
{
DBUG_ENTER("Query_cache::make_disabled");
- query_cache_size = 0;
- free_memory = 0;
- bins = 0;
- steps = 0;
- cache = 0;
- mem_bin_num = mem_bin_steps = 0;
+ query_cache_size= 0;
+ free_memory= 0;
+ bins= 0;
+ steps= 0;
+ cache= 0;
+ mem_bin_num= mem_bin_steps= 0;
+ queries_in_cache= 0;
+ first_block= 0;
DBUG_VOID_RETURN;
}
+
void Query_cache::free_cache(my_bool destruction)
{
DBUG_ENTER("Query_cache::free_cache");
@@ -1261,20 +1268,14 @@ void Query_cache::free_cache(my_bool destruction)
}
#endif
- bins[0].free_blocks->destroy(); /* all cache memory must be
- in one this block */
- DBUG_PRINT("info", ("free memory %lu (should be %lu)",
- free_memory , query_cache_size));
- free_memory = 0;
-
- my_free((gptr)cache, MYF(MY_ALLOW_ZERO_PTR));
- first_block = 0;
- bins = 0;
- cache = 0;
- query_cache_size = 0;
+ /* Becasue we did a flush, all cache memory must be in one this block */
+ bins[0].free_blocks->destroy();
+ DBUG_PRINT("qcache", ("free memory %lu (should be %lu)",
+ free_memory , query_cache_size));
+ my_free((gptr) cache, MYF(MY_ALLOW_ZERO_PTR));
+ make_disabled();
hash_free(&queries);
hash_free(&tables);
- queries_in_cache = 0;
if (!destruction)
STRUCT_UNLOCK(&structure_guard_mutex);
}
@@ -1282,85 +1283,100 @@ void Query_cache::free_cache(my_bool destruction)
}
/*****************************************************************************
- * free block data
- *****************************************************************************/
+ Free block data
+*****************************************************************************/
+
+/*
+ The following assumes we have a lock on the cache
+*/
void Query_cache::flush_cache()
{
- while(queries_blocks != 0){
+ while (queries_blocks != 0)
+ {
BLOCK_LOCK_WR(queries_blocks);
free_query(queries_blocks);
}
}
+/*
+ Free oldest query that is not in use by another thread.
+ Returns 1 if we couldn't remove anything
+*/
+
my_bool Query_cache::free_old_query()
{
DBUG_ENTER("Query_cache::free_old_query");
- if (queries_blocks == 0)
+ if (!queries_blocks)
{
- DBUG_RETURN(0);
- }
- /*
- try_lock_writing used to prevent clinch because
- here lock sequence is breached, also we don't need remove
- locked queries at this point
- */
- Query_cache_block *query_block = 0;
- if (queries_blocks != 0)
- {
- Query_cache_block *i = queries_blocks;
- do
+ /*
+ try_lock_writing used to prevent client because here lock
+ sequence is breached.
+ Also we don't need remove locked queries at this point.
+ */
+ Query_cache_block *query_block = 0;
+ if (queries_blocks != 0)
{
- Query_cache_query * header = i->query();
- if (header->result() != 0 &&
- header->result()->type == Query_cache_block::RESULT &&
- i->query()->try_lock_writing())
+ Query_cache_block *block = queries_blocks;
+ /* Search until we find first query that we can remove */
+ do
{
- query_block = i;
- break;
- }
- i = i->next;
- } while ( i != queries_blocks );
- }
+ Query_cache_query *header = block->query();
+ if (header->result() != 0 &&
+ header->result()->type == Query_cache_block::RESULT &&
+ block->query()->try_lock_writing())
+ {
+ query_block = block;
+ break;
+ }
+ } while ((block=block->next) != queries_blocks );
+ }
- if (query_block != 0)
- {
- free_query(query_block);
- DBUG_RETURN(1);
+ if (query_block != 0)
+ {
+ free_query(query_block);
+ DBUG_RETURN(0);
+ }
}
- else
- DBUG_RETURN(0);
+ DBUG_RETURN(1); // Nothing to remove
}
-/* query_block must be lock_writing() */
-void Query_cache::free_query(Query_cache_block * query_block)
+/*
+ Free query from query cache.
+ query_block must be locked for writing.
+ This function will remove (and destroy) the lock for the query.
+*/
+
+void Query_cache::free_query(Query_cache_block *query_block)
{
DBUG_ENTER("Query_cache::free_query");
- DBUG_PRINT("info", ("free query 0x%lx %lu bytes result",
- (ulong)query_block,
+ DBUG_PRINT("qcache", ("free query 0x%lx %lu bytes result",
+ (ulong) query_block,
query_block->query()->length() ));
+
queries_in_cache--;
hash_delete(&queries,(byte *) query_block);
- Query_cache_query * query = query_block->query();
+ Query_cache_query *query = query_block->query();
+
if (query->writer() != 0)
{
+ /* Tell MySQL that this query should not be cached anymore */
query->writer()->query_cache_query = 0;
query->writer(0);
}
- double_linked_list_exclude(query_block, queries_blocks);
- TABLE_COUNTER_TYPE i = 0;
- for(; i < query_block->n_tables; i++)
- {
- unlink_table(query_block->table(i));
- }
+ double_linked_list_exclude(query_block, &queries_blocks);
+ Query_cache_block_table *table=query_block->table(0);
+
+ for (TABLE_COUNTER_TYPE i=0; i < query_block->n_tables; i++)
+ unlink_table(table++);
Query_cache_block *result_block = query->result();
if (result_block != 0)
{
- Query_cache_block * block = result_block;
+ Query_cache_block *block = result_block;
do
{
- Query_cache_block * current = block;
+ Query_cache_block *current = block;
block = block->next;
free_memory_block(current);
} while (block != result_block);
@@ -1373,8 +1389,8 @@ void Query_cache::free_query(Query_cache_block * query_block)
}
/*****************************************************************************
- * query data creation
- *****************************************************************************/
+ Query data creation
+*****************************************************************************/
Query_cache_block *
Query_cache::write_block_data(ulong data_len, gptr data,
@@ -1383,217 +1399,223 @@ Query_cache::write_block_data(ulong data_len, gptr data,
TABLE_COUNTER_TYPE ntab,
my_bool under_guard)
{
+ ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(ntab*sizeof(Query_cache_block_table)) +
+ header_len);
+ ulong len = data_len + all_headers_len;
DBUG_ENTER("Query_cache::write_block_data");
- ulong all_headers_len = ALIGN_SIZE(sizeof(Query_cache_block)) +
- ntab*ALIGN_SIZE(sizeof(Query_cache_block_table)) +
- header_len;
- DBUG_PRINT("info", ("data: %ld, header: %ld, all header: %ld",
+ DBUG_PRINT("qcache", ("data: %ld, header: %ld, all header: %ld",
data_len, header_len, all_headers_len));
- ulong len = data_len + all_headers_len;
- Query_cache_block * block = allocate_block(max(len, min_allocation_unit),
- 1, 0, under_guard);
+ Query_cache_block *block = allocate_block(max(len, min_allocation_unit),
+ 1, 0, under_guard);
if (block != 0)
{
block->type = type;
block->n_tables = ntab;
block->used = len;
- memcpy((void*)(((byte *) block)+
- all_headers_len),
- (void*)data,
- data_len);
+ memcpy((void*) (((byte *) block)+ all_headers_len),
+ (void*) data, data_len);
}
DBUG_RETURN(block);
}
+
+/*
+ On success STRUCT_UNLOCK(&query_cache.structure_guard_mutex) will be done.
+*/
+
my_bool
-Query_cache::append_result_data(Query_cache_block * &result,
+Query_cache::append_result_data(Query_cache_block **current_block,
ulong data_len, gptr data,
- Query_cache_block * query_block,
- Query_cache_block * first_data_block)
+ Query_cache_block *query_block)
{
- DBUG_ENTER("Query_cache::uppend_result_data");
- DBUG_PRINT("info", ("append %lu bytes to 0x%lx query"));
+ DBUG_ENTER("Query_cache::append_result_data");
+ DBUG_PRINT("qcache", ("append %lu bytes to 0x%lx query",
+ data_len, query_block));
+
if (query_block->query()->add(data_len) > query_cache_limit)
{
- DBUG_PRINT("info", ("size limit reached %lu > %lu",
+ DBUG_PRINT("qcache", ("size limit reached %lu > %lu",
query_block->query()->length(),
query_cache_limit));
- result=0;
+ *current_block=0; // Mark error
DBUG_RETURN(0);
}
- if (first_data_block == 0)
+ if (*current_block == 0)
{
- DBUG_PRINT("info", ("allocated first result data block 0x%xl", data_len));
+ DBUG_PRINT("qcache", ("allocated first result data block %lu", data_len));
/*
- STRUCT_UNLOCK(&structure_guard_mutex); will be done by
- query_cache.append_result_data if success;
+ STRUCT_UNLOCK(&structure_guard_mutex) Will be done by
+ write_result_data if success;
*/
- DBUG_RETURN(write_result_data(result, data_len, data, query_block,
+ DBUG_RETURN(write_result_data(current_block, data_len, data, query_block,
Query_cache_block::RES_BEG));
}
- else
- {
- result = first_data_block;
- }
- Query_cache_block * last_block = first_data_block->prev;
+ Query_cache_block *last_block = (*current_block)->prev;
- DBUG_PRINT("info", ("lastblock 0x%lx len %lu used %lu",
- (ulong)last_block, last_block->length,
+ DBUG_PRINT("qcache", ("lastblock 0x%lx len %lu used %lu",
+ (ulong) last_block, last_block->length,
last_block->used));
my_bool success = 1;
+ ulong last_block_free_space= last_block->length - last_block->used;
- ulong last_block_free_space = last_block->length - last_block->used;
-
- //write 'tail' of data, that can't be appended to last block
+ /*
+ We will first allocate and write the 'tail' of data, that doesn't fit
+ in the 'last_block'. Only if this succeeds, we will fill the last_block.
+ This saves us a memcpy if the query doesn't fit in the query cache.
+ */
- //try join blocks if physicaly next block is free...
+ // Try join blocks if physically next block is free...
if (last_block_free_space < data_len &&
append_next_free_block(last_block,
max(data_len - last_block_free_space,
QUERY_CACHE_MIN_RESULT_DATA_SIZE)))
last_block_free_space = last_block->length - last_block->used;
- //if no space in last block (even after join) allocate new block
+ // If no space in last block (even after join) allocate new block
if (last_block_free_space < data_len)
{
- //TODO try get memory from next free block (if exist) (is it needed?)
- DBUG_PRINT("info", ("allocate new block for %lu bytes",
+ // TODO: Try get memory from next free block (if exist) (is it needed?)
+ DBUG_PRINT("qcache", ("allocate new block for %lu bytes",
data_len-last_block_free_space));
Query_cache_block *new_block = 0;
/*
- STRUCT_UNLOCK(&structure_guard_mutex); will be done by
- query_cache.append_result_data
+ On success STRUCT_UNLOCK(&structure_guard_mutex) will be done
+ by the next call
*/
- success = write_result_data(new_block, data_len-last_block_free_space,
+ success = write_result_data(&new_block, data_len-last_block_free_space,
(gptr)(((byte*)data)+last_block_free_space),
query_block,
Query_cache_block::RES_CONT);
/*
new_block may be not 0 even !success (if write_result_data
- allocate small block but filed allocate continue
+ allocate small block but failed allocate continue
*/
if (new_block != 0)
double_linked_list_join(last_block, new_block);
}
else
- //it is success (nobody can prevent us write data)
+ {
+ // It is success (nobody can prevent us write data)
STRUCT_UNLOCK(&structure_guard_mutex);
+ }
- // append last block (if it is possible)
- if (last_block_free_space > 0)
+ // Now finally write data to the last block
+ if (success && last_block_free_space > 0)
{
ulong to_copy = min(data_len,last_block_free_space);
- DBUG_PRINT("info", ("use free space %lub at block 0x%lx to copy %lub",
+ DBUG_PRINT("qcache", ("use free space %lub at block 0x%lx to copy %lub",
last_block_free_space, (ulong)last_block, to_copy));
- memcpy((void*)(((byte*)last_block)+last_block->used),
- (void*)data,to_copy);
+ memcpy((void*) (((byte*) last_block) + last_block->used), (void*) data,
+ to_copy);
last_block->used+=to_copy;
}
-
DBUG_RETURN(success);
}
-my_bool Query_cache::write_result_data(Query_cache_block * &result_block,
+
+my_bool Query_cache::write_result_data(Query_cache_block **result_block,
ulong data_len, gptr data,
- Query_cache_block * query_block,
+ Query_cache_block *query_block,
Query_cache_block::block_type type)
{
DBUG_ENTER("Query_cache::write_result_data");
- DBUG_PRINT("info", ("data_len %lu",data_len));
+ DBUG_PRINT("qcache", ("data_len %lu",data_len));
- //reserve block(s) for filling
+ // Reserve block(s) for filling
my_bool success = allocate_data_chain(result_block, data_len, query_block);
if (success)
{
- //it is success (nobody can prevent us write data)
+ // It is success (nobody can prevent us write data)
STRUCT_UNLOCK(&structure_guard_mutex);
- byte * rest = (byte*) data;
- Query_cache_block * block = result_block;
- uint headers_len = ALIGN_SIZE(sizeof(Query_cache_block)) +
- ALIGN_SIZE(sizeof(Query_cache_result));
- // now fill list of blocks that created by allocate_data_chain
+ byte *rest = (byte*) data;
+ Query_cache_block *block = *result_block;
+ uint headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_result)));
+ // Now fill list of blocks that created by allocate_data_chain
do
{
block->type = type;
ulong length = block->used - headers_len;
- DBUG_PRINT("info", ("write %lu byte in block 0x%lx",length,
+ DBUG_PRINT("qcache", ("write %lu byte in block 0x%lx",length,
(ulong)block));
- memcpy((void*)(((byte*)block)+headers_len),
- (void*)rest,length);
-
+ memcpy((void*)(((byte*) block)+headers_len), (void*) rest, length);
rest += length;
block = block->next;
type = Query_cache_block::RES_CONT;
- } while (block != result_block);
+ } while (block != *result_block);
}
else
{
- if (result_block != 0)
+ if (*result_block != 0)
{
- // destroy list of blocks that created & locked by lock_result_data
- Query_cache_block * block = result_block;
+ // Destroy list of blocks that was created & locked by lock_result_data
+ Query_cache_block *block = *result_block;
do
{
- Query_cache_block * current = block;
+ Query_cache_block *current = block;
block = block->next;
free_memory_block(current);
- } while (block != result_block);
- result_block = 0;
+ } while (block != *result_block);
+ *result_block = 0;
/*
- it is not success => not unlock structure_guard_mutex (we need it to
- free query)
+ It is not success => not unlock structure_guard_mutex (we need it to
+ free query)
*/
}
}
- DBUG_PRINT("info", ("success %d", (int) success));
+ DBUG_PRINT("qcache", ("success %d", (int) success));
DBUG_RETURN(success);
}
-my_bool Query_cache::allocate_data_chain(Query_cache_block * &result_block,
+/*
+ Allocate one or more blocks to hold data
+*/
+
+my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
ulong data_len,
- Query_cache_block * query_block)
+ Query_cache_block *query_block)
{
- DBUG_ENTER("Query_cache::allocate_data_chain");
-
- ulong all_headers_len = ALIGN_SIZE(sizeof(Query_cache_block)) +
- ALIGN_SIZE(sizeof(Query_cache_result));
+ ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_result)));
ulong len = data_len + all_headers_len;
- DBUG_PRINT("info", ("data_len %lu, all_headers_len %lu",
+ DBUG_ENTER("Query_cache::allocate_data_chain");
+ DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
data_len, all_headers_len));
- result_block = allocate_block(max(min_result_data_size,len),
- min_result_data_size == 0,
- all_headers_len + min_result_data_size,
- 1);
- my_bool success = (result_block != 0);
+ *result_block = allocate_block(max(min_result_data_size,len),
+ min_result_data_size == 0,
+ all_headers_len + min_result_data_size,
+ 1);
+ my_bool success = (*result_block != 0);
if (success)
{
- result_block->n_tables = 0;
- result_block->used = 0;
- result_block->type = Query_cache_block::RES_INCOMPLETE;
- result_block->next = result_block->prev = result_block;
- Query_cache_result * header = result_block->result();
+ Query_cache_block *new_block= *result_block;
+ new_block->n_tables = 0;
+ new_block->used = 0;
+ new_block->type = Query_cache_block::RES_INCOMPLETE;
+ new_block->next = new_block->prev = new_block;
+ Query_cache_result *header = new_block->result();
header->parent(query_block);
- Query_cache_block * next_block = 0;
- if (result_block->length < len)
+ if (new_block->length < len)
{
/*
- allocated less memory then we need (no big memory blocks) =>
- to be continue
+ We got less memory then we need (no big memory blocks) =>
+ Continue to allocated more blocks until we got everything we need.
*/
- Query_cache_block * next_block;
- if ((success = allocate_data_chain(next_block,
- len - result_block->length,
+ Query_cache_block *next_block;
+ if ((success = allocate_data_chain(&next_block,
+ len - new_block->length,
query_block)))
- double_linked_list_join(result_block, next_block);
+ double_linked_list_join(new_block, next_block);
}
if (success)
{
- result_block->used = min(len, result_block->length);
+ new_block->used = min(len, new_block->length);
- DBUG_PRINT("info", ("Block len %lu used %lu",
- result_block->length, result_block->used));
+ DBUG_PRINT("qcache", ("Block len %lu used %lu",
+ new_block->length, new_block->used));
}
else
DBUG_PRINT("warning", ("Can't allocate block for continue"));
@@ -1604,25 +1626,28 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block * &result_block,
}
/*****************************************************************************
- * tables management
- *****************************************************************************/
+ Tables management
+*****************************************************************************/
+
+/*
+ Invalidate the first table in the table_list
+*/
void Query_cache::invalidate_table(TABLE_LIST *table_list)
{
if (table_list->table != 0)
- invalidate_table(table_list->table);
+ invalidate_table(table_list->table); // Table is open
else
{
- char key[MAX_DBKEY_LENGTH], *key_ptr;
+ char key[MAX_DBKEY_LENGTH];
uint key_length;
Query_cache_block *table_block;
key_length=(uint) (strmov(strmov(key,table_list->db)+1,
table_list->real_name) -key)+ 1;
- key_ptr = key;
- // we dont store temporary tables => no key_length+=4 ...
+ // We don't store temporary tables => no key_length+=4 ...
if ((table_block = (Query_cache_block*)
- hash_search(&tables,key_ptr,key_length)))
+ hash_search(&tables,key,key_length)))
invalidate_table(table_block);
}
}
@@ -1630,302 +1655,328 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list)
void Query_cache::invalidate_table(TABLE *table)
{
Query_cache_block *table_block;
- if ((table_block = (Query_cache_block*)
- hash_search(&tables,table->table_cache_key,table->key_length)))
+ if ((table_block = ((Query_cache_block*)
+ hash_search(&tables, table->table_cache_key,
+ table->key_length))))
invalidate_table(table_block);
}
void Query_cache::invalidate_table_in_db(Query_cache_block *table_block,
- char * db)
+ char *db)
{
/*
table key consist of data_base_name + '\0' + table_name +'\0'...
- => we may use strcmp.
+ => we may use strcmp to compare database names.
*/
- if (strcmp(db, (char*)(table_block->table()->db()))==0)
- {
+ if (strcmp(db, (char*)(table_block->table()->db())) == 0)
invalidate_table(table_block);
- }
}
+
void Query_cache::invalidate_table(Query_cache_block *table_block)
{
- Query_cache_block_table * list_root = table_block->table(0);
- while(list_root->next != list_root)
+ Query_cache_block_table *list_root = table_block->table(0);
+ while (list_root->next != list_root)
{
- Query_cache_block * query_block = list_root->next->block();
+ Query_cache_block *query_block = list_root->next->block();
BLOCK_LOCK_WR(query_block);
free_query(query_block);
}
}
-my_bool Query_cache::register_all_tables(Query_cache_block * block,
- TABLE_LIST * tables_used,
+
+my_bool Query_cache::register_all_tables(Query_cache_block *block,
+ TABLE_LIST *tables_used,
TABLE_COUNTER_TYPE tables)
{
- DBUG_PRINT("info", ("register tables block 0x%lx, n %d, header %x",
- (ulong)block, (int) tables,
- (int)ALIGN_SIZE(sizeof(Query_cache_block)) ));
+ TABLE_COUNTER_TYPE n;
+ DBUG_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x",
+ (ulong) block, (int) tables,
+ (int) ALIGN_SIZE(sizeof(Query_cache_block))));
- TABLE_COUNTER_TYPE n = 0;
- TABLE_LIST * i = tables_used;
- for(; i != 0; i=i->next, n++)
+ Query_cache_block_table *block_table = block->table(0);
+
+ for (n=0; tables_used; tables_used=tables_used->next, n++, block_table++)
{
- DBUG_PRINT("info",
+ DBUG_PRINT("qcache",
("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx",
- i->real_name, i->db, (ulong) i->table,
- i->table->key_length,
- (ulong) i->table->table_cache_key));
- Query_cache_block_table * block_table = block->table(n);
+ tables_used->real_name, tables_used->db,
+ (ulong) tables_used->table,
+ tables_used->table->key_length,
+ (ulong) tables_used->table->table_cache_key));
block_table->n=n;
- if (!insert_table(i->table->key_length,
- i->table->table_cache_key, block_table,
- Query_cache_table::type_convertion(i->table->db_type)))
+ if (!insert_table(tables_used->table->key_length,
+ tables_used->table->table_cache_key, block_table,
+ Query_cache_table::type_convertion(tables_used->table->
+ db_type)))
break;
- if (i->table->db_type == DB_TYPE_MRG_MYISAM)
+ /*
+ TODO: (Low priority)
+ The following has to be recoded to not test for a specific table
+ type but instead call a handler function that does this for us.
+ Something like the following:
+
+ tables_used->table->file->register_used_filenames(callback,
+ first_argument);
+ */
+ if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
{
- ha_myisammrg * handler = (ha_myisammrg *)i->table->file;
+ ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
MYRG_INFO *file = handler->myrg_info();
- MYRG_TABLE *table = file->open_tables;
- for(;table != file->end_table ; table++)
+ for (MYRG_TABLE *table = file->open_tables;
+ table != file->end_table ;
+ table++)
{
char key[MAX_DBKEY_LENGTH];
- uint key_length =
- Query_cache::filename_2_table_key(key, table->table->filename);
- n++;
- Query_cache_block_table * block_table = block->table(n);
- block_table->n=n;
+ uint key_length =filename_2_table_key(key, table->table->filename);
+ (++block_table)->n= ++n;
if (!insert_table(key_length, key, block_table,
Query_cache_table::type_convertion(DB_TYPE_MYISAM)))
goto err;
}
}
}
+
err:
- if (i != 0)
- {
- n--;
- DBUG_PRINT("info", ("filed at table %d", (int)n));
- TABLE_COUNTER_TYPE idx = 0;
- for(i = tables_used;
- idx < n;
- idx++)
- {
- unlink_table(block->table(n));
- }
+ if (tables_used)
+ {
+ DBUG_PRINT("qcache", ("failed at table %d", (int) n));
+ /* Unlink the tables we allocated above */
+ for (Query_cache_block_table *tmp = block->table(0) ;
+ tmp != block_table;
+ tmp++)
+ unlink_table(tmp);
}
- return(i == 0);
+ return (tables_used == 0);
}
-my_bool Query_cache::insert_table(uint key_len, char * key,
- Query_cache_block_table * node,
- Query_cache_table::query_cache_table_type
- type)
+/*
+ Insert used tablename in cache
+ Returns 0 on error
+*/
+
+my_bool
+Query_cache::insert_table(uint key_len, char *key,
+ Query_cache_block_table *node,
+ Query_cache_table::query_cache_table_type type)
{
DBUG_ENTER("Query_cache::insert_table");
- DBUG_PRINT("info", ("insert table node 0x%lx, len %d",
+ DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d",
(ulong)node, key_len));
- Query_cache_block *table_block = (Query_cache_block *)
- hash_search(&tables, key, key_len);
+
+ Query_cache_block *table_block = ((Query_cache_block *)
+ hash_search(&tables, key, key_len));
if (table_block == 0)
{
- DBUG_PRINT("info", ("new table block from 0x%lx (%u)",
- (ulong)key, (int) key_len));
+ DBUG_PRINT("qcache", ("new table block from 0x%lx (%u)",
+ (ulong) key, (int) key_len));
table_block = write_block_data(key_len, (gptr) key,
ALIGN_SIZE(sizeof(Query_cache_table)),
Query_cache_block::TABLE,
1, 1);
if (table_block == 0)
{
- DBUG_PRINT("info", ("Can't write table name to cache"));
+ DBUG_PRINT("qcache", ("Can't write table name to cache"));
DBUG_RETURN(0);
}
- Query_cache_table * header = table_block->table();
+ Query_cache_table *header = table_block->table();
header->type(type);
double_linked_list_simple_include(table_block,
- tables_blocks[type]);
- Query_cache_block_table * list_root = table_block->table(0);
+ &tables_blocks[type]);
+ Query_cache_block_table *list_root = table_block->table(0);
list_root->n = 0;
list_root->next = list_root->prev = list_root;
- if (hash_insert(&tables, (const byte *)table_block))
+ if (hash_insert(&tables, (const byte *) table_block))
{
- DBUG_PRINT("info", ("Can't insert table to hash"));
+ DBUG_PRINT("qcache", ("Can't insert table to hash"));
// write_block_data return locked block
free_memory_block(table_block);
DBUG_RETURN(0);
}
- char * db = header->db();
+ char *db = header->db();
+ /*
+ TODO: Eliminate strlen() by sending this to the function
+ To do this we have to add db_len to the TABLE_LIST and TABLE structures.
+ */
header->table(db + strlen(db) + 1);
}
- Query_cache_block_table * list_root = table_block->table(0);
- node->next = list_root->next; list_root->next = node;
- node->next->prev = node; node->prev = list_root;
+ Query_cache_block_table *list_root = table_block->table(0);
+ node->next = list_root->next;
+ list_root->next = node;
+ node->next->prev = node;
+ node->prev = list_root;
node->parent = table_block->table();
DBUG_RETURN(1);
}
-void Query_cache::unlink_table(Query_cache_block_table * node)
+
+void Query_cache::unlink_table(Query_cache_block_table *node)
{
- node->prev->next = node->next; node->next->prev = node->prev;
- Query_cache_block_table * neighbour = node->next;
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+ Query_cache_block_table *neighbour = node->next;
if (neighbour->next == neighbour)
{
- // list is empty (neighbour is root of list)
- Query_cache_block * table_block = neighbour->block();
+ // list is empty (neighbor is root of list)
+ Query_cache_block *table_block = neighbour->block();
double_linked_list_exclude(table_block,
- tables_blocks[table_block->table()->type()]);
+ &tables_blocks[table_block->table()->type()]);
hash_delete(&tables,(byte *) table_block);
free_memory_block(table_block);
}
}
/*****************************************************************************
- * free memory management
- *****************************************************************************/
+ Free memory management
+*****************************************************************************/
-Query_cache_block * Query_cache::allocate_block(ulong len,
- my_bool not_less,
- ulong min,
- my_bool under_guard)
+Query_cache_block *
+Query_cache::allocate_block(ulong len, my_bool not_less, ulong min,
+ my_bool under_guard)
{
DBUG_ENTER("Query_cache::allocate_n_lock_block");
- DBUG_PRINT("info", ("len %lu, not less %d, min %lu, uder_guard %d",
+ DBUG_PRINT("qcache", ("len %lu, not less %d, min %lu, uder_guard %d",
len, not_less,min,under_guard));
if (len >= min(query_cache_size, query_cache_limit))
{
- DBUG_PRINT("info", ("Query cache hase only %lu memory and limit %lu",
+ DBUG_PRINT("qcache", ("Query cache hase only %lu memory and limit %lu",
query_cache_size, query_cache_limit));
DBUG_RETURN(0); // in any case we don't have such piece of memory
}
- if (!under_guard){STRUCT_LOCK(&structure_guard_mutex);};
+ if (!under_guard)
+ STRUCT_LOCK(&structure_guard_mutex);
- Query_cache_block *block = get_free_block(len, not_less, min);
- while( block == 0 && free_old_query())
+ /* Free old queries until we have enough memory to store this block */
+ Query_cache_block *block;
+ do
{
- block = get_free_block(len, not_less, min);
+ block= get_free_block(len, not_less, min);
}
+ while (block == 0 && !free_old_query());
- if (block!=0)
+ if (block != 0) // If we found a suitable block
{
if (block->length > ALIGN_SIZE(len) + min_allocation_unit)
split_block(block,ALIGN_SIZE(len));
}
- if (!under_guard){STRUCT_UNLOCK(&structure_guard_mutex);};
+ if (!under_guard)
+ STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_RETURN(block);
}
-Query_cache_block * Query_cache::get_free_block (ulong len,
- my_bool not_less,
- ulong min)
+
+Query_cache_block *
+Query_cache::get_free_block(ulong len, my_bool not_less, ulong min)
{
- DBUG_ENTER("Query_cache::get_free_block");
Query_cache_block *block = 0, *first = 0;
- DBUG_PRINT("info",("length %lu, not_less %d, min %lu", len,
+ DBUG_ENTER("Query_cache::get_free_block");
+ DBUG_PRINT("qcache",("length %lu, not_less %d, min %lu", len,
(int)not_less, min));
- /* find block with minimal size > len */
-
+ /* Find block with minimal size > len */
uint start = find_bin(len);
// try matching bin
if (bins[start].number != 0)
{
- Query_cache_block * list = bins[start].free_blocks;
+ Query_cache_block *list = bins[start].free_blocks;
first = list;
- while(first->next != list && first->length < len)
- {
+ while (first->next != list && first->length < len)
first=first->next;
- }
if (first->length >= len)
block=first;
}
if (block == 0 && start > 0)
{
- DBUG_PRINT("info",("try bins whith more bigger blocks"));
- //try more big bins
+ DBUG_PRINT("qcache",("Try bins with bigger block size"));
+ // Try more big bins
int i = start - 1;
- while(i > 0 && bins[i].number == 0)
+ while (i > 0 && bins[i].number == 0)
i--;
if (bins[i].number > 0)
block = bins[i].free_blocks;
}
- // if no big blocks => try less size (if it is possible)
+
+ // If no big blocks => try less size (if it is possible)
if (block == 0 && ! not_less)
{
- DBUG_PRINT("info",("try smaller blocks"));
+ DBUG_PRINT("qcache",("Try to allocate a smaller block"));
if (first != 0 && first->length > min)
block = first;
else
{
uint i = start + 1;
- while( i < mem_bin_num && bins[i].number == 0)
- i++;
- if (i < mem_bin_num && bins[i].number > 0 &&
- bins[i].free_blocks->prev->length >= min)
+ /* bins[mem_bin_num].number contains 1 for easy end test */
+ for (i= start+1 ; bins[i].number == 0 ; i++) ;
+ if (i < mem_bin_num && bins[i].free_blocks->prev->length >= min)
block = bins[i].free_blocks->prev;
}
}
if (block != 0)
exclude_from_free_memory_list(block);
- DBUG_PRINT("info",("getting block 0x%lx", (ulong) block));
+ DBUG_PRINT("qcache",("getting block 0x%lx", (ulong) block));
DBUG_RETURN(block);
}
-void Query_cache::free_memory_block(Query_cache_block * block)
+
+void Query_cache::free_memory_block(Query_cache_block *block)
{
DBUG_ENTER("Query_cache::free_n_unlock_memory_block");
block->used=0;
- DBUG_PRINT("info",("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx",
+ DBUG_PRINT("qcache",("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx",
(ulong) first_block, (ulong) block,block->pnext,
(ulong) block->pprev));
+
if (block->pnext != first_block && block->pnext->is_free())
- {
block = join_free_blocks(block, block->pnext);
- }
if (block != first_block && block->pprev->is_free())
- {
block = join_free_blocks(block->pprev, block->pprev);
- }
insert_into_free_memory_list(block);
DBUG_VOID_RETURN;
}
-void Query_cache::split_block(Query_cache_block * block,ulong len)
+
+void Query_cache::split_block(Query_cache_block *block,ulong len)
{
DBUG_ENTER("Query_cache::split_block");
- Query_cache_block * new_block = (Query_cache_block *)(((byte*)block)+len);
+ Query_cache_block *new_block = (Query_cache_block*)(((byte*) block)+len);
new_block->init(block->length - len);
block->length=len;
- new_block->pnext = block->pnext; block->pnext = new_block;
- new_block->pprev = block; new_block->pnext->pprev = new_block;
+ new_block->pnext = block->pnext;
+ block->pnext = new_block;
+ new_block->pprev = block;
+ new_block->pnext->pprev = new_block;
insert_into_free_memory_list(new_block);
- DBUG_PRINT("info", ("split 0x%lx (%lu) new 0x%lx",
+ DBUG_PRINT("qcache", ("split 0x%lx (%lu) new 0x%lx",
(ulong) block, len, (ulong) new_block));
DBUG_VOID_RETURN;
}
+
Query_cache_block *
Query_cache::join_free_blocks(Query_cache_block *first_block,
- Query_cache_block * block_in_list)
+ Query_cache_block *block_in_list)
{
+ Query_cache_block *second_block;
DBUG_ENTER("Query_cache::join_free_blocks");
- DBUG_PRINT("info",
+ DBUG_PRINT("qcache",
("join first 0x%lx, pnext 0x%lx, in list 0x%lx",
(ulong) first_block, (ulong) first_block->pnext,
(ulong) block_in_list));
- exclude_from_free_memory_list(block_in_list);
- Query_cache_block * second_block = first_block->pnext;
- // may be was not free block
- second_block->type = Query_cache_block::FREE;second_block->used=0;
+ exclude_from_free_memory_list(block_in_list);
+ second_block = first_block->pnext;
+ // May be was not free block
+ second_block->type = Query_cache_block::FREE;
+ second_block->used=0;
second_block->destroy();
first_block->length += second_block->length;
@@ -1935,136 +1986,135 @@ Query_cache::join_free_blocks(Query_cache_block *first_block,
DBUG_RETURN(first_block);
}
-my_bool Query_cache::append_next_free_block(Query_cache_block * block,
+
+my_bool Query_cache::append_next_free_block(Query_cache_block *block,
ulong add_size)
{
+ Query_cache_block *next_block = block->pnext;
DBUG_ENTER("Query_cache::append_next_free_block");
DBUG_PRINT("enter", ("block 0x%lx, add_size %lu", (ulong) block,
add_size));
- Query_cache_block * next_block = block->pnext;
+
if (next_block->is_free())
{
- exclude_from_free_memory_list(next_block);
ulong old_len = block->length;
-
+ exclude_from_free_memory_list(next_block);
next_block->destroy();
block->length += next_block->length;
block->pnext = next_block->pnext;
next_block->pnext->pprev = block;
- if (block->length >
- ALIGN_SIZE(old_len + add_size) + min_allocation_unit)
+ if (block->length > ALIGN_SIZE(old_len + add_size) + min_allocation_unit)
split_block(block,ALIGN_SIZE(old_len + add_size));
DBUG_PRINT("exit", ("block was appended"));
DBUG_RETURN(1);
}
- else
- {
- DBUG_PRINT("exit", ("block was not appended"));
- DBUG_RETURN(0);
- }
+ DBUG_RETURN(0);
}
-void Query_cache::exclude_from_free_memory_list(Query_cache_block * free_block)
+
+void Query_cache::exclude_from_free_memory_list(Query_cache_block *free_block)
{
DBUG_ENTER("Query_cache::exclude_from_free_memory_list");
- Query_cache_memory_bin * bin = *((Query_cache_memory_bin **)
- free_block->data());
- double_linked_list_exclude(free_block ,bin->free_blocks);
+ Query_cache_memory_bin *bin = *((Query_cache_memory_bin **)
+ free_block->data());
+ double_linked_list_exclude(free_block, &bin->free_blocks);
bin->number--;
free_memory-=free_block->length;
- DBUG_PRINT("info",("exclude block 0x%lx, bin 0x%lx", (ulong) free_block,
- (ulong)bin));
+ DBUG_PRINT("qcache",("exclude block 0x%lx, bin 0x%lx", (ulong) free_block,
+ (ulong) bin));
DBUG_VOID_RETURN;
}
-void Query_cache::insert_into_free_memory_list(Query_cache_block * free_block)
+void Query_cache::insert_into_free_memory_list(Query_cache_block *free_block)
{
DBUG_ENTER("Query_cache::insert_into_free_memory_list");
uint idx = find_bin(free_block->length);
- insert_into_free_memory_sorted_list(free_block, bins[idx].free_blocks);
+ insert_into_free_memory_sorted_list(free_block, &bins[idx].free_blocks);
/*
- we have enough memory in block for storing bin reference due to
+ We have enough memory in block for storing bin reference due to
min_allocation_unit choice
*/
- Query_cache_memory_bin * *bin_ptr = (Query_cache_memory_bin**)
- free_block->data();
- *bin_ptr = &(bins[idx]);
- bins[idx].number++;
- DBUG_PRINT("info",("insert block 0x%lx, bin[%d] 0x%lx",
- (ulong) free_block, idx,
- (ulong) &(bins[idx])));
+ Query_cache_memory_bin **bin_ptr = ((Query_cache_memory_bin**)
+ free_block->data());
+ *bin_ptr = bins+idx;
+ (*bin_ptr)->number++;
+ DBUG_PRINT("qcache",("insert block 0x%lx, bin[%d] 0x%lx",
+ (ulong) free_block, idx, (ulong) *bin_ptr));
DBUG_VOID_RETURN;
}
uint Query_cache::find_bin(ulong size)
{
+ int i;
DBUG_ENTER("Query_cache::find_bin");
- //begin small blocks to big (small blocks frequently asked)
- int i = mem_bin_steps - 1;
- for(; i > 0 && steps[i-1].size < size; i--);
+ // Begin small blocks to big (small blocks frequently asked)
+ for (i=mem_bin_steps - 1; i > 0 && steps[i-1].size < size; i--) ;
if (i == 0)
{
// first bin not subordinate of common rules
- DBUG_PRINT("info", ("first bin (# 0), size %lu",size));
+ DBUG_PRINT("qcache", ("first bin (# 0), size %lu",size));
DBUG_RETURN(0);
}
uint bin = steps[i].idx - (uint)((size - steps[i].size)/steps[i].increment);
- DBUG_PRINT("info", ("bin %u step %u, size %lu", bin, i, size));
+ DBUG_PRINT("qcache", ("bin %u step %u, size %lu", bin, i, size));
DBUG_RETURN(bin);
}
+
/*****************************************************************************
- * lists management
- *****************************************************************************/
+ Lists management
+*****************************************************************************/
-void Query_cache::move_to_query_list_end(Query_cache_block * query_block)
+void Query_cache::move_to_query_list_end(Query_cache_block *query_block)
{
DBUG_ENTER("Query_cache::move_to_query_list_end");
- double_linked_list_exclude(query_block, queries_blocks);
- double_linked_list_simple_include(query_block, queries_blocks);
+ double_linked_list_exclude(query_block, &queries_blocks);
+ double_linked_list_simple_include(query_block, &queries_blocks);
DBUG_VOID_RETURN;
}
+
void Query_cache::insert_into_free_memory_sorted_list(Query_cache_block *
new_block,
- Query_cache_block *
- &list)
+ Query_cache_block **
+ list)
{
DBUG_ENTER("Query_cache::insert_into_free_memory_sorted_list");
/*
list sorted by size in ascendant order, because we need small blocks
- frequently than big one
+ more frequently than bigger ones
*/
new_block->used = 0;
new_block->n_tables = 0;
new_block->type = Query_cache_block::FREE;
- if (list == 0)
+ if (*list == 0)
{
- list = new_block->next=new_block->prev=new_block;
- DBUG_PRINT("info", ("inserted into empty list"));
+ *list = new_block->next=new_block->prev=new_block;
+ DBUG_PRINT("qcache", ("inserted into empty list"));
}
else
{
- Query_cache_block *point = list;
+ Query_cache_block *point = *list;
if (point->length >= new_block->length)
{
point = point->prev;
- list = new_block;
+ *list = new_block;
}
else
{
- while(point->next != list &&
- point->next->length < new_block->length)
- {
+ /* Find right position in sorted list to put block */
+ while (point->next != *list &&
+ point->next->length < new_block->length)
point=point->next;
- }
}
- new_block->prev = point; new_block->next = point->next;
- new_block->next->prev = new_block; point->next = new_block;
+ new_block->prev = point;
+ new_block->next = point->next;
+ new_block->next->prev = new_block;
+ point->next = new_block;
}
free_memory+=new_block->length;
DBUG_VOID_RETURN;
@@ -2072,48 +2122,50 @@ void Query_cache::insert_into_free_memory_sorted_list(Query_cache_block *
void
-Query_cache::double_linked_list_simple_include(Query_cache_block * point,
- Query_cache_block *
- &list_pointer)
+Query_cache::double_linked_list_simple_include(Query_cache_block *point,
+ Query_cache_block **
+ list_pointer)
{
DBUG_ENTER("Query_cache::double_linked_list_simple_include");
- DBUG_PRINT("info", ("including block 0x%lx", (ulong) point));
- if (list_pointer == 0)
- list_pointer=point->next=point->prev=point;
+ DBUG_PRINT("qcache", ("including block 0x%lx", (ulong) point));
+ if (*list_pointer == 0)
+ *list_pointer=point->next=point->prev=point;
else
{
- point->next = list_pointer;
- point->prev = list_pointer->prev;
+ point->next = (*list_pointer);
+ point->prev = (*list_pointer)->prev;
point->prev->next = point;
- list_pointer->prev = point;
- list_pointer = point;
+ (*list_pointer)->prev = point;
+ (*list_pointer) = point;
}
DBUG_VOID_RETURN;
}
void
Query_cache::double_linked_list_exclude(Query_cache_block *point,
- Query_cache_block * &list_pointer)
+ Query_cache_block **list_pointer)
{
DBUG_ENTER("Query_cache::double_linked_list_exclude");
- DBUG_PRINT("info", ("excluding block 0x%lx, list 0x%lx",
+ DBUG_PRINT("qcache", ("excluding block 0x%lx, list 0x%lx",
(ulong) point, (ulong) list_pointer));
if (point->next == point)
- list_pointer = 0; // empty list
+ *list_pointer = 0; // empty list
else
{
point->next->prev = point->prev;
point->prev->next = point->next;
- if (point == list_pointer) list_pointer = point->next;
+ if (point == *list_pointer)
+ *list_pointer = point->next;
}
DBUG_VOID_RETURN;
}
+
void Query_cache::double_linked_list_join(Query_cache_block *head_tail,
Query_cache_block *tail_head)
{
Query_cache_block *head_head = head_tail->next,
- *tail_tail = tail_head->prev;
+ *tail_tail = tail_head->prev;
head_head->prev = tail_tail;
head_tail->next = tail_head;
tail_head->prev = head_tail;
@@ -2121,72 +2173,68 @@ void Query_cache::double_linked_list_join(Query_cache_block *head_tail,
}
/*****************************************************************************
- * query
- *****************************************************************************/
+ Query
+*****************************************************************************/
/*
- if query is cachable return numder tables in query
- (query whithout tables tot chached)
+ if query is cacheable return number tables in query
+ (query without tables are not cached)
*/
-TABLE_COUNTER_TYPE Query_cache::is_cachable(THD *thd,
- uint query_len, char *query,
- LEX *lex, TABLE_LIST* tables_used)
+
+TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
+ char *query,
+ LEX *lex, TABLE_LIST *tables_used)
{
TABLE_COUNTER_TYPE tables = 0;
- DBUG_ENTER("Query_cache::is_cachable");
+ DBUG_ENTER("Query_cache::is_cacheable");
+
if (lex->sql_command == SQLCOM_SELECT &&
thd->temporary_tables == 0 &&
- (thd->query_cache_type == 1 || (thd->query_cache_type == 2 &&
- (lex->select->options &
+ (thd->query_cache_type == 1 ||
+ (thd->query_cache_type == 2 && (lex->select->options &
OPTION_TO_QUERY_CACHE))) &&
thd->safe_to_cache_query)
{
- DBUG_PRINT("info", ("options %lx %lx, type %u",
+ my_bool has_transactions = 0;
+ DBUG_PRINT("qcache", ("options %lx %lx, type %u",
OPTION_TO_QUERY_CACHE,
lex->select->options,
(int) thd->query_cache_type));
- my_bool has_transactions = 0;
- TABLE_LIST * i = tables_used;
- for(; i != 0; i=i->next)
+
+ for (; tables_used; tables_used=tables_used->next)
{
tables++;
- DBUG_PRINT("info", ("table %s, db %s, type %u", i->real_name,
- i->db, i->table->db_type));
+ DBUG_PRINT("qcache", ("table %s, db %s, type %u",
+ tables_used->real_name,
+ tables_used->db, tables_used->table->db_type));
has_transactions = (has_transactions ||
- i->table->file->has_transactions());
- if (i->table->db_type == DB_TYPE_MRG_ISAM)
+ tables_used->table->file->has_transactions());
+
+ if (tables_used->table->db_type == DB_TYPE_MRG_ISAM)
{
- DBUG_PRINT("info", ("select not cachable: used MRG_ISAM table(s)"));
+ DBUG_PRINT("qcache", ("select not cacheable: used MRG_ISAM table(s)"));
DBUG_RETURN(0);
}
- if (i->table->db_type == DB_TYPE_MRG_MYISAM)
+ if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
{
- ha_myisammrg * handler = (ha_myisammrg *)i->table->file;
+ ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
MYRG_INFO *file = handler->myrg_info();
- MYRG_TABLE *table = file->open_tables;
- for(;table != file->end_table ; table++)
- {
- tables++;
- DBUG_PRINT("loop", (" + 1 table (mrg_MyISAM)"));
- }
+ tables+= (file->end_table - file->open_tables);
}
}
if ((thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)) &&
has_transactions)
{
- DBUG_PRINT("info", ("not in autocommin mode"));
+ DBUG_PRINT("qcache", ("not in autocommin mode"));
DBUG_RETURN(0);
}
- else
- {
- DBUG_PRINT("info", ("select have %d tables", tables));
- DBUG_RETURN(tables);
- }
+ DBUG_PRINT("qcache", ("select is using %d tables", tables));
+ DBUG_RETURN(tables);
}
- DBUG_PRINT("info",
- ("not interest query: %d or not cachable, \
-options %lx %lx, type %u",
+
+ DBUG_PRINT("qcache",
+ ("not interesting query: %d or not cacheable, options %lx %lx, type %u",
(int) lex->sql_command,
OPTION_TO_QUERY_CACHE,
lex->select->options,
@@ -2194,31 +2242,36 @@ options %lx %lx, type %u",
DBUG_RETURN(0);
}
+
/*****************************************************************************
- * packing
- *****************************************************************************/
+ Packing
+*****************************************************************************/
void Query_cache::pack_cache()
{
- DBUG_ENTER("Query_cache::pack_cache");
STRUCT_LOCK(&structure_guard_mutex);
- DUMP(this);
- byte * border = 0;
- Query_cache_block * before = 0;
+ byte *border = 0;
+ Query_cache_block *before = 0;
ulong gap = 0;
my_bool ok = 1;
- Query_cache_block * i = first_block;
+ Query_cache_block *i = first_block;
+ DBUG_ENTER("Query_cache::pack_cache");
+ DUMP(this);
+
do
{
- ok = move_by_type(border, before, gap, i);
+ ok = move_by_type(&border, &before, &gap, i);
i = i->pnext;
} while (ok && i != first_block);
+
if (border != 0)
{
- Query_cache_block * new_block = (Query_cache_block *) border;
+ Query_cache_block *new_block = (Query_cache_block *) border;
new_block->init(gap);
- new_block->pnext = before->pnext; before->pnext = new_block;
- new_block->pprev = before; new_block->pnext->pprev = new_block;
+ new_block->pnext = before->pnext;
+ before->pnext = new_block;
+ new_block->pprev = before;
+ new_block->pnext->pprev = new_block;
insert_into_free_memory_list(new_block);
}
DUMP(this);
@@ -2226,219 +2279,225 @@ void Query_cache::pack_cache()
DBUG_VOID_RETURN;
}
-my_bool Query_cache::move_by_type(byte * &border,
- Query_cache_block * &before, ulong &gap, Query_cache_block * i)
+
+my_bool Query_cache::move_by_type(byte **border,
+ Query_cache_block **before, ulong *gap,
+ Query_cache_block *block)
{
DBUG_ENTER("Query_cache::move_by_type");
+
my_bool ok = 1;
- switch(i->type)
- {
+ switch (block->type) {
case Query_cache_block::FREE:
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx FREE", (ulong) block));
+ if (*border == 0)
{
- DBUG_PRINT("info", ("block 0x%lx FREE", (ulong) i));
- if (border == 0)
- {
- border = (byte *) i;
- before = i->pprev;
- DBUG_PRINT("info", ("gap begining here"));
- }
- exclude_from_free_memory_list(i);
- gap +=i->length;
- i->pprev->pnext=i->pnext;
- i->pnext->pprev=i->pprev;
- i->destroy();
- DBUG_PRINT("info", ("added to gap (%lu)", gap));
- break;
+ *border = (byte *) block;
+ *before = block->pprev;
+ DBUG_PRINT("qcache", ("gap beginning here"));
}
+ exclude_from_free_memory_list(block);
+ *gap +=block->length;
+ block->pprev->pnext=block->pnext;
+ block->pnext->pprev=block->pprev;
+ block->destroy();
+ DBUG_PRINT("qcache", ("added to gap (%lu)", *gap));
+ break;
+ }
case Query_cache_block::TABLE:
- {
- DBUG_PRINT("info", ("block 0x%lx TABLE", (ulong) i));
- if (border == 0) break;
- ulong len = i->length,
- used = i->used;
- Query_cache_block_table * list_root = i->table(0);
- Query_cache_block_table
- *tprev = list_root->prev,
- *tnext = list_root->next;
- Query_cache_block
- *prev = i->prev,
- *next = i->next,
- *pprev = i->pprev,
- *pnext = i->pnext,
- *new_block =(Query_cache_block *) border;
- char * data = (char*)i->data();
- hash_delete(&tables, (byte *)i);
- i->destroy();
- new_block->init(len);
- new_block->type=Query_cache_block::TABLE;
- new_block->used=used;
- new_block->n_tables=1;
- memcpy((char*)new_block->data(), data,
- len-new_block->headers_len());
- relink(i, new_block, next, prev, pnext, pprev);
- if (tables_blocks[new_block->table()->type()] == i)
- {
- tables_blocks[new_block->table()->type()] = new_block;
- }
- Query_cache_block_table * nlist_root = new_block->table(0);
- nlist_root->n = 0;
- nlist_root->next = (tnext==list_root?nlist_root:tnext);
- nlist_root->prev = (tprev==list_root?nlist_root:tnext);
- tnext->prev = list_root;
- tprev->next = list_root;
- border += len;
- before = new_block;
- hash_insert(&tables, (const byte *)new_block);
- DBUG_PRINT("info", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
- len, (ulong) new_block, (ulong) border));
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx TABLE", (ulong) block));
+ if (*border == 0)
break;
- }
+ ulong len = block->length, used = block->used;
+ Query_cache_block_table *list_root = block->table(0);
+ Query_cache_block_table *tprev = list_root->prev,
+ *tnext = list_root->next;
+ Query_cache_block *prev = block->prev,
+ *next = block->next,
+ *pprev = block->pprev,
+ *pnext = block->pnext,
+ *new_block =(Query_cache_block *) *border;
+ char *data = (char*) block->data();
+ byte *key;
+ uint key_length;
+ key=query_cache_table_get_key((byte*) block, &key_length,0);
+ hash_search(&tables, key, key_length);
+
+ block->destroy();
+ new_block->init(len);
+ new_block->type=Query_cache_block::TABLE;
+ new_block->used=used;
+ new_block->n_tables=1;
+ memcpy((char*) new_block->data(), data, len-new_block->headers_len());
+ relink(block, new_block, next, prev, pnext, pprev);
+ if (tables_blocks[new_block->table()->type()] == block)
+ tables_blocks[new_block->table()->type()] = new_block;
+
+ Query_cache_block_table *nlist_root = new_block->table(0);
+ nlist_root->n = 0;
+ nlist_root->next = (tnext == list_root ? nlist_root : tnext);
+ nlist_root->prev = (tprev == list_root ? nlist_root: tnext);
+ tnext->prev = list_root;
+ tprev->next = list_root;
+ *border += len;
+ *before = new_block;
+ /* Fix hash to point at moved block */
+ hash_replace(&tables, tables.current_record, (byte*) new_block);
+
+ DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
+ len, (ulong) new_block, (ulong) *border));
+ break;
+ }
case Query_cache_block::QUERY:
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx QUERY", (ulong) block));
+ if (*border == 0)
+ break;
+ BLOCK_LOCK_WR(block);
+ ulong len = block->length, used = block->used;
+ TABLE_COUNTER_TYPE n_tables = block->n_tables;
+ Query_cache_block *prev = block->prev,
+ *next = block->next,
+ *pprev = block->pprev,
+ *pnext = block->pnext,
+ *new_block =(Query_cache_block*) *border;
+ char *data = (char*) block->data();
+ Query_cache_block *first_result_block = ((Query_cache_query *)
+ block->data())->result();
+ byte *key;
+ uint key_length;
+ key=query_cache_query_get_key((byte*) block, &key_length,0);
+ hash_search(&queries, key, key_length);
+
+ memcpy((char*) new_block->table(0), (char*) block->table(0),
+ ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
+ block->query()->unlock_n_destroy();
+ block->destroy();
+ new_block->init(len);
+ new_block->type=Query_cache_block::QUERY;
+ new_block->used=used;
+ new_block->n_tables=n_tables;
+ memcpy((char*) new_block->data(), data, len - new_block->headers_len());
+ relink(block, new_block, next, prev, pnext, pprev);
+ if (queries_blocks == block)
+ queries_blocks = new_block;
+ for (TABLE_COUNTER_TYPE j=0; j < n_tables; j++)
{
- DBUG_PRINT("info", ("block 0x%lx QUERY", (ulong) i));
- if (border == 0) break;
- BLOCK_LOCK_WR(i);
- ulong len = i->length,
- used = i->used;
- TABLE_COUNTER_TYPE n_tables = i->n_tables;
- Query_cache_block
- *prev = i->prev,
- *next = i->next,
- *pprev = i->pprev,
- *pnext = i->pnext,
- *new_block =(Query_cache_block *) border;
- char * data = (char*)i->data();
- Query_cache_block * first_result_block = ((Query_cache_query *)
- i->data())->result();
- hash_delete(&queries, (byte *)i);
- memcpy((char*)new_block->table(0), (char*)i->table(0),
- n_tables * ALIGN_SIZE(sizeof(Query_cache_block_table)));
- i->query()->unlock_n_destroy();
- i->destroy();
- new_block->init(len);
- new_block->type=Query_cache_block::QUERY;
- new_block->used=used;
- new_block->n_tables=n_tables;
- memcpy((char*)new_block->data(), data,
- len - new_block->headers_len());
- relink(i, new_block, next, prev, pnext, pprev);
- if (queries_blocks == i)
- queries_blocks = new_block;
- TABLE_COUNTER_TYPE j=0;
- for(; j< n_tables; j++)
- {
- Query_cache_block_table * block_table = new_block->table(j);
- block_table->next->prev = block_table;
- block_table->prev->next = block_table;
- }
- DBUG_PRINT("info", ("after cicle tt"));
- border += len;
- before = new_block;
- new_block->query()->result(first_result_block);
- if (first_result_block != 0)
- {
- Query_cache_block * result_block = first_result_block;
- do
- {
- result_block->result()->parent(new_block);
- result_block = result_block->next;
- } while ( result_block != first_result_block );
- }
- NET * net = new_block->query()->writer();
- if (net != 0)
+ Query_cache_block_table *block_table = new_block->table(j);
+ block_table->next->prev = block_table;
+ block_table->prev->next = block_table;
+ }
+ DBUG_PRINT("qcache", ("after circle tt"));
+ *border += len;
+ *before = new_block;
+ new_block->query()->result(first_result_block);
+ if (first_result_block != 0)
+ {
+ Query_cache_block *result_block = first_result_block;
+ do
{
- net->query_cache_query = (gptr) new_block;
- }
- hash_insert(&queries, (const byte *)new_block);
- DBUG_PRINT("info", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
- len, (ulong) new_block, (ulong) border));
- break;
+ result_block->result()->parent(new_block);
+ result_block = result_block->next;
+ } while ( result_block != first_result_block );
}
+ NET *net = new_block->query()->writer();
+ if (net != 0)
+ {
+ net->query_cache_query = (gptr) new_block;
+ }
+ /* Fix hash to point at moved block */
+ hash_replace(&queries, queries.current_record, (byte*) new_block);
+ DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
+ len, (ulong) new_block, (ulong) *border));
+ break;
+ }
case Query_cache_block::RES_INCOMPLETE:
case Query_cache_block::RES_BEG:
case Query_cache_block::RES_CONT:
case Query_cache_block::RESULT:
- {
- DBUG_PRINT("info", ("block 0x%lx RES* (%d)", (ulong) i, (int)i->type));
- if (border == 0) break;
- Query_cache_block
- *query_block = i->result()->parent(),
- *next = i->next,
- *prev = i->prev;
- Query_cache_block::block_type type = i->type;
- BLOCK_LOCK_WR(query_block);
- ulong len = i->length,
- used = i->used;
- Query_cache_block
- *pprev = i->pprev,
- *pnext = i->pnext,
- *new_block =(Query_cache_block *) border;
- char * data = (char*)i->data();
- i->destroy();
- new_block->init(len);
- new_block->type=type;
- new_block->used=used;
- memcpy((char*)new_block->data(), data,
- len - new_block->headers_len());
- relink(i, new_block, next, prev, pnext, pprev);
- new_block->result()->parent(query_block);
- Query_cache_query * query = query_block->query();
- if (query->result() == i)
- query->result(new_block);
- border += len;
- before = new_block;
- /* if result writing complete && we have free space in block */
- ulong free_space = new_block->length - new_block->used;
- if (query->result()->type == Query_cache_block::RESULT &&
- new_block->length > new_block->used &&
- gap + free_space > min_allocation_unit &&
- new_block->length - free_space > min_allocation_unit)
- {
- border -= free_space;
- gap += free_space;
- new_block->length -= free_space;
- }
- BLOCK_UNLOCK_WR(query_block);
- DBUG_PRINT("info", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
- len, (ulong) new_block, (ulong) border));
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx RES* (%d)", (ulong) block,
+ (int) block->type));
+ if (*border == 0)
break;
+ Query_cache_block *query_block = block->result()->parent(),
+ *next = block->next,
+ *prev = block->prev;
+ Query_cache_block::block_type type = block->type;
+ BLOCK_LOCK_WR(query_block);
+ ulong len = block->length, used = block->used;
+ Query_cache_block *pprev = block->pprev,
+ *pnext = block->pnext,
+ *new_block =(Query_cache_block*) *border;
+ char *data = (char*) block->data();
+ block->destroy();
+ new_block->init(len);
+ new_block->type=type;
+ new_block->used=used;
+ memcpy((char*) new_block->data(), data, len - new_block->headers_len());
+ relink(block, new_block, next, prev, pnext, pprev);
+ new_block->result()->parent(query_block);
+ Query_cache_query *query = query_block->query();
+ if (query->result() == block)
+ query->result(new_block);
+ *border += len;
+ *before = new_block;
+ /* If result writing complete && we have free space in block */
+ ulong free_space = new_block->length - new_block->used;
+ if (query->result()->type == Query_cache_block::RESULT &&
+ new_block->length > new_block->used &&
+ *gap + free_space > min_allocation_unit &&
+ new_block->length - free_space > min_allocation_unit)
+ {
+ *border -= free_space;
+ *gap += free_space;
+ new_block->length -= free_space;
}
+ BLOCK_UNLOCK_WR(query_block);
+ DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
+ len, (ulong) new_block, (ulong) *border));
+ break;
+ }
default:
- DBUG_PRINT("error", ("unexpectet block type %d, block 0x%lx",
- (int)i->type, (ulong) i));
+ DBUG_PRINT("error", ("unexpected block type %d, block 0x%lx",
+ (int)block->type, (ulong) block));
ok = 0;
}
DBUG_RETURN(ok);
}
-void Query_cache::relink(Query_cache_block * oblock,
- Query_cache_block * nblock,
- Query_cache_block * next, Query_cache_block * prev,
- Query_cache_block * pnext, Query_cache_block * pprev)
+
+void Query_cache::relink(Query_cache_block *oblock,
+ Query_cache_block *nblock,
+ Query_cache_block *next, Query_cache_block *prev,
+ Query_cache_block *pnext, Query_cache_block *pprev)
{
- nblock->prev = (prev==oblock?nblock:prev); //check pointer to himself
- nblock->next = (next==oblock?nblock:next);
+ nblock->prev = (prev == oblock ? nblock : prev); //check pointer to himself
+ nblock->next = (next == oblock ? nblock : next);
prev->next=nblock;
next->prev=nblock;
- nblock->pprev = pprev; //physical pointer to himself have only 1 free block
+ nblock->pprev = pprev; // Physical pointer to himself have only 1 free block
nblock->pnext = pnext;
pprev->pnext=nblock;
pnext->pprev=nblock;
}
+
my_bool Query_cache::join_results(ulong join_limit)
{
//TODO
- DBUG_ENTER("Query_cache::join_results");
my_bool has_moving = 0;
- Query_cache_block *query_block = 0;
+ DBUG_ENTER("Query_cache::join_results");
+
STRUCT_LOCK(&structure_guard_mutex);
if (queries_blocks != 0)
{
- Query_cache_block *i = queries_blocks;
+ Query_cache_block *block = queries_blocks;
do
{
- Query_cache_query * header = i->query();
+ Query_cache_query *header = block->query();
if (header->result() != 0 &&
header->result()->type == Query_cache_block::RESULT &&
header->length() > join_limit)
@@ -2451,32 +2510,32 @@ my_bool Query_cache::join_results(ulong join_limit)
{
has_moving = 1;
Query_cache_block *first_result = header->result();
- ulong new_len = header->length() +
- ALIGN_SIZE(sizeof(Query_cache_block)) +
- ALIGN_SIZE(sizeof(Query_cache_result));
+ ulong new_len = (header->length() +
+ ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_result)));
if (new_result_block->length >
ALIGN_SIZE(new_len) + min_allocation_unit)
- split_block(new_result_block,ALIGN_SIZE(new_len));
- BLOCK_LOCK_WR(i);
+ split_block(new_result_block, ALIGN_SIZE(new_len));
+ BLOCK_LOCK_WR(block);
header->result(new_result_block);
new_result_block->type = Query_cache_block::RESULT;
new_result_block->n_tables = 0;
new_result_block->used = new_len;
new_result_block->next = new_result_block->prev = new_result_block;
- DBUG_PRINT("info", ("new block %lu/%lu (%lu)",
+ DBUG_PRINT("qcache", ("new block %lu/%lu (%lu)",
new_result_block->length,
new_result_block->used,
header->length()));
Query_cache_result *new_result = new_result_block->result();
- new_result->parent(i);
+ new_result->parent(block);
byte *write_to = (byte*) new_result->data();
Query_cache_block *result_block = first_result;
do
{
- ulong len = result_block->used - result_block->headers_len() -
- ALIGN_SIZE(sizeof(Query_cache_result));
+ ulong len = (result_block->used - result_block->headers_len() -
+ ALIGN_SIZE(sizeof(Query_cache_result)));
DBUG_PRINT("loop", ("add block %lu/%lu (%lu)",
result_block->length,
result_block->used,
@@ -2485,36 +2544,197 @@ my_bool Query_cache::join_results(ulong join_limit)
(char*) result_block->result()->data(),
len);
write_to += len;
- Query_cache_block * old_result_block = result_block;
+ Query_cache_block *old_result_block = result_block;
result_block = result_block->next;
free_memory_block(old_result_block);
} while (result_block != first_result);
- BLOCK_UNLOCK_WR(i);
+ BLOCK_UNLOCK_WR(block);
}
}
- i = i->next;
- } while ( i != queries_blocks );
+ block = block->next;
+ } while ( block != queries_blocks );
}
STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_RETURN(has_moving);
}
-uint Query_cache::filename_2_table_key (char * key, char *filename)
+
+uint Query_cache::filename_2_table_key (char *key, const char *path)
{
- DBUG_ENTER("Query_cache::filename_2_table_key");
- char tablename[FN_REFLEN];
- char dbbuff[FN_REFLEN];
- char *dbname;
+ char tablename[FN_REFLEN+2], *filename, *dbname;
Query_cache_block *table_block;
- fn_format(tablename,filename,"","",3);
+ uint db_length;
+ DBUG_ENTER("Query_cache::filename_2_table_key");
+
+ /* Safety if filename didn't have a directory name */
+ tablename[0]= FN_LIBCHAR;
+ tablename[1]= FN_LIBCHAR;
+ /* Convert filename to this OS's format in tablename */
+ fn_format(tablename + 2, path, "", "", MY_REPLACE_EXT);
+ filename= tablename + dirname_length(tablename + 2) + 2;
+ /* Find start of databasename */
+ for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ;
+ db_length= (filename - dbname) - 1;
+ DBUG_PRINT("qcache", ("table '%-.*s.%s'", db_length, dbname, filename));
+
+ DBUG_RETURN((uint) (strmov(strnmov(key, dbname, db_length) + 1,
+ filename) -key) + 1);
+}
+
+
+/****************************************************************************
+ Functions to be used when debugging
+****************************************************************************/
+
+#ifndef DBUG_OFF
+
+void Query_cache::wreck(uint line, const char *message)
+{
+ DBUG_ENTER("Query_cache::wreck");
+ query_cache_size = 0;
+ if (*message)
+ DBUG_PRINT("error", (" %s", message));
+ DBUG_PRINT("warning", ("=================================="));
+ DBUG_PRINT("warning", ("%5d QUERY CACHE WRECK => DISABLED",line));
+ DBUG_PRINT("warning", ("=================================="));
+ current_thd->killed = 1;
+ bins_dump();
+ cache_dump();
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache::bins_dump()
+{
+ uint i;
+ DBUG_PRINT("qcache", ("mem_bin_num=%u, mem_bin_steps=%u",
+ mem_bin_num, mem_bin_steps));
+ DBUG_PRINT("qcache", ("-------------------------"));
+ DBUG_PRINT("qcache", (" size idx step"));
+ DBUG_PRINT("qcache", ("-------------------------"));
+ for (i=0; i < mem_bin_steps; i++)
+ {
+ DBUG_PRINT("qcache", ("%10lu %3d %10lu", steps[i].size, steps[i].idx,
+ steps[i].increment));
+ }
+ DBUG_PRINT("qcache", ("-------------------------"));
+ DBUG_PRINT("qcache", (" size num"));
+ DBUG_PRINT("qcache", ("-------------------------"));
+ for (i=0; i < mem_bin_num; i++)
+ {
+ DBUG_PRINT("qcache", ("%10lu %3d 0x%lx", bins[i].size, bins[i].number,
+ (ulong)&(bins[i])));
+ if (bins[i].free_blocks)
+ {
+ Query_cache_block *block = bins[i].free_blocks;
+ do{
+ DBUG_PRINT("qcache", ("\\-- %lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
+ block->length, (ulong)block,
+ (ulong)block->next, (ulong)block->prev,
+ (ulong)block->pnext, (ulong)block->pprev));
+ block = block->next;
+ } while ( block != bins[i].free_blocks );
+ }
+ }
+ DBUG_PRINT("qcache", ("-------------------------"));
+}
- int path_len = (strrchr(filename, '/') - filename);
- strncpy(dbbuff, filename, path_len);
- dbbuff[path_len] = '\0';
- dbname = strrchr(dbbuff, '/') + 1;
- DBUG_PRINT("info", ("table %s.%s", dbname, tablename));
+void Query_cache::cache_dump()
+{
+ DBUG_PRINT("qcache", ("-------------------------------------"));
+ DBUG_PRINT("qcache", (" length used t nt"));
+ DBUG_PRINT("qcache", ("-------------------------------------"));
+ Query_cache_block *i = first_block;
+ do
+ {
+ DBUG_PRINT("qcache",
+ ("%10lu %10lu %1d %2d 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
+ i->length, i->used, (int)i->type,
+ i->n_tables, (ulong)i,
+ (ulong)i->next, (ulong)i->prev, (ulong)i->pnext,
+ (ulong)i->pprev));
+ i = i->pnext;
+ } while ( i != first_block );
+ DBUG_PRINT("qcache", ("-------------------------------------"));
+}
+
- DBUG_RETURN( (uint) (strmov(strmov(key, dbname) + 1,
- tablename) -key) + 1);
+void Query_cache::queries_dump()
+{
+ DBUG_PRINT("qcache", ("------------------"));
+ DBUG_PRINT("qcache", (" QUERIES"));
+ DBUG_PRINT("qcache", ("------------------"));
+ if (queries_blocks != 0)
+ {
+ Query_cache_block *block = queries_blocks;
+ do
+ {
+ uint len;
+ char *str = (char*) query_cache_query_get_key((byte*) block, &len, 0);
+ byte flags = (byte) str[len-1];
+ DBUG_PRINT("qcache", ("%u (%u,%u) %.*s",len,
+ ((flags & QUERY_CACHE_CLIENT_LONG_FLAG_MASK)? 1:0),
+ (flags & QUERY_CACHE_CHARSET_CONVERT_MASK), len,
+ str));
+ DBUG_PRINT("qcache", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong) block,
+ (ulong) block->next, (ulong) block->prev,
+ (ulong)block->pnext, (ulong)block->pprev));
+
+ for (TABLE_COUNTER_TYPE t = 0; t < block->n_tables; t++)
+ {
+ Query_cache_table *table = block->table(t)->parent;
+ DBUG_PRINT("qcache", ("-t- '%s' '%s'", table->db(), table->table()));
+ }
+ Query_cache_query *header = block->query();
+ if (header->result())
+ {
+ Query_cache_block *result_block = header->result();
+ Query_cache_block *result_beg = result_block;
+ do
+ {
+ DBUG_PRINT("qcache", ("-r- %u %lu/%lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
+ (uint) result_block->type,
+ result_block->length, result_block->used,
+ (ulong) result_block,
+ (ulong) result_block->next,
+ (ulong) result_block->prev,
+ (ulong) result_block->pnext,
+ (ulong) result_block->pprev));
+ result_block = result_block->next;
+ } while ( result_block != result_beg );
+ }
+ } while ((block=block->next) != queries_blocks);
+ }
+ else
+ {
+ DBUG_PRINT("qcache", ("no queries in list"));
+ }
+ DBUG_PRINT("qcache", ("------------------"));
+}
+
+
+void Query_cache::tables_dump()
+{
+ DBUG_PRINT("qcache", ("--------------------"));
+ DBUG_PRINT("qcache", ("TABLES"));
+ DBUG_PRINT("qcache", ("--------------------"));
+ for (int i=0; i < (int) Query_cache_table::TYPES_NUMBER; i++)
+ {
+ DBUG_PRINT("qcache", ("--- type %u", i));
+ if (tables_blocks[i] != 0)
+ {
+ Query_cache_block *table_block = tables_blocks[i];
+ do
+ {
+ Query_cache_table *table = table_block->table();
+ DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table()));
+ table_block = table_block->next;
+ } while ( table_block != tables_blocks[i]);
+ }
+ else
+ DBUG_PRINT("qcache", ("no tables in list"));
+ }
+ DBUG_PRINT("qcache", ("--------------------"));
}
+#endif /* DBUG_OFF */
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index 0b786fb1560..09eb745e405 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -66,7 +66,7 @@ struct Query_cache_block_table
TABLE_COUNTER_TYPE n; // numbr in table (from 0)
Query_cache_block_table *next, *prev;
Query_cache_table *parent;
- inline Query_cache_block * block();
+ inline Query_cache_block *block();
};
@@ -82,30 +82,28 @@ struct Query_cache_block
*pprev to join free blocks
*prev to access to opposite side of list in cyclic sorted list
*/
- Query_cache_block
- *pnext,*pprev, // physical next/previous block
- *next,*prev; // logical next/previous block
+ Query_cache_block *pnext,*pprev, // physical next/previous block
+ *next,*prev; // logical next/previous block
block_type type;
TABLE_COUNTER_TYPE n_tables; // number of tables in query
inline my_bool is_free(void) { return type == FREE; }
-
void init(ulong length);
void destroy();
inline uint headers_len();
inline gptr data(void);
- inline Query_cache_query * query();
- inline Query_cache_table * table();
- inline Query_cache_result * result();
- inline Query_cache_block_table * table(TABLE_COUNTER_TYPE n);
+ inline Query_cache_query *query();
+ inline Query_cache_table *table();
+ inline Query_cache_result *result();
+ inline Query_cache_block_table *table(TABLE_COUNTER_TYPE n);
};
struct Query_cache_query
{
ulonglong limit_found_rows;
- Query_cache_block * res;
- NET * wri;
+ Query_cache_block *res;
+ NET *wri;
ulong len;
sem_t lock; // R/W lock of block
pthread_mutex_t clients_guard;
@@ -115,9 +113,9 @@ struct Query_cache_query
void unlock_n_destroy();
inline ulonglong found_rows() { return limit_found_rows; }
inline void found_rows(ulonglong rows) { limit_found_rows = rows; }
- inline Query_cache_block * result() { return res; }
+ inline Query_cache_block *result() { return res; }
inline void result(Query_cache_block *p) { res=p; }
- inline NET * writer() { return wri; }
+ inline NET *writer() { return wri; }
inline void writer(NET *p) { wri=p; }
inline ulong length() { return len; }
inline ulong add(ulong packet_len) { return(len += packet_len); }
@@ -132,9 +130,7 @@ struct Query_cache_query
my_bool try_lock_writing();
void unlock_writing();
void unlock_reading();
- static byte * cache_key(const byte *record, uint *length,
- my_bool not_used);
- static void free_cache(void *entry);
+ static byte *cache_key(const byte *record, uint *length, my_bool not_used);
};
@@ -146,44 +142,45 @@ struct Query_cache_table
return (type == DB_TYPE_INNODB ? INNODB : OTHER);
}
- char * tbl;
+ char *tbl;
query_cache_table_type tp;
inline query_cache_table_type type() { return tp; }
inline void type(query_cache_table_type t) { tp = t;}
- inline char * db() { return (char *) data(); }
- inline char * table() { return tbl; }
- inline void table(char * table) { tbl = table; }
+ inline char *db() { return (char *) data(); }
+ inline char *table() { return tbl; }
+ inline void table(char *table) { tbl = table; }
inline gptr data()
{
return (gptr)(((byte*)this)+
ALIGN_SIZE(sizeof(Query_cache_table)));
}
-
- static byte * cache_key(const byte *record, uint *length,
- my_bool not_used);
- static void free_cache(void *entry);
};
-
struct Query_cache_result
{
Query_cache_block *query;
- inline gptr data(){return (gptr)(((byte*)this)+
- ALIGN_SIZE(sizeof(Query_cache_result)));}
-
+ inline gptr data()
+ {
+ return (gptr)(((byte*) this)+
+ ALIGN_SIZE(sizeof(Query_cache_result)));
+ }
/* data_continue (if not whole packet contained by this block) */
- inline Query_cache_block * parent() { return query; }
+ inline Query_cache_block *parent() { return query; }
inline void parent (Query_cache_block *p) { query=p; }
};
extern "C" {
+ byte *query_cache_query_get_key(const byte *record, uint *length,
+ my_bool not_used);
+ byte *query_cache_table_get_key(const byte *record, uint *length,
+ my_bool not_used);
void query_cache_insert(THD *thd, const char *packet, ulong length);
void query_cache_end_of_result(THD *thd);
void query_cache_abort(THD *thd);
- void query_cache_invalidate_by_MyISAM_filename(char* filename);
+ void query_cache_invalidate_by_MyISAM_filename(const char* filename);
}
struct Query_cache_memory_bin
@@ -192,7 +189,7 @@ struct Query_cache_memory_bin
ulong size;
#endif
uint number;
- Query_cache_block * free_blocks;
+ Query_cache_block *free_blocks;
inline void init(ulong size)
{
@@ -219,94 +216,92 @@ struct Query_cache_memory_bin_step
class Query_cache
{
- protected:
- byte * cache; // cache memory
- Query_cache_block *first_block; // physical location block list
- Query_cache_block *queries_blocks; // query list (LIFO)
- Query_cache_block *tables_blocks[Query_cache_table::TYPES_NUMBER];
-
- Query_cache_memory_bin * bins; // free block lists
- Query_cache_memory_bin_step * steps; // bins spacing info
- uint mem_bin_num, mem_bin_steps; // See at init_cache & find_bin
-
- /* options */
- ulong query_cache_size, query_cache_limit,
- min_allocation_unit, min_result_data_size;
- uint def_query_hash_size, def_table_hash_size;
-
- /* statistics */
public:
+ /* Info */
+ ulong query_cache_size, query_cache_limit;
+ /* statistics */
ulong free_memory, queries_in_cache, hits, inserts, refused;
-protected:
- my_bool initialized;
+protected:
/*
- Locked when searched or changed global query or
- tables lists or hashes. When operate inside
- query structure locked own query block mutex
- LOCK SEQUENCE (to prevent clinch):
+ The following mutex is locked when searching or changing global
+ query, tables lists or hashes. When we are operating inside the
+ query structure we locked an internal query block mutex.
+ LOCK SEQUENCE (to prevent deadlocks):
1. structure_guard_mutex
2. query block / table block / free block
3. results blocks (only when must become free).
*/
pthread_mutex_t structure_guard_mutex;
+ byte *cache; // cache memory
+ Query_cache_block *first_block; // physical location block list
+ Query_cache_block *queries_blocks; // query list (LIFO)
+ Query_cache_block *tables_blocks[Query_cache_table::TYPES_NUMBER];
+ Query_cache_memory_bin *bins; // free block lists
+ Query_cache_memory_bin_step *steps; // bins spacing info
HASH queries, tables;
+ uint mem_bin_num, mem_bin_steps; // See at init_cache & find_bin
+ my_bool initialized;
+
+ /* options */
+ ulong min_allocation_unit, min_result_data_size;
+ uint def_query_hash_size, def_table_hash_size;
/* Exclude/include from cyclic double linked list */
- static void double_linked_list_exclude(Query_cache_block * point,
- Query_cache_block * &list_pointer);
- static void double_linked_list_simple_include(Query_cache_block * point,
- Query_cache_block *
- &list_pointer);
+ static void double_linked_list_exclude(Query_cache_block *point,
+ Query_cache_block **list_pointer);
+ static void double_linked_list_simple_include(Query_cache_block *point,
+ Query_cache_block **
+ list_pointer);
static void double_linked_list_join(Query_cache_block *head_tail,
Query_cache_block *tail_head);
/* Table key generation */
- static uint filename_2_table_key (char * key, char *filename);
+ static uint filename_2_table_key (char *key, const char *filename);
- /* Following function work properly only when structure_guard_mutex locked */
+ /* The following functions require that structure_guard_mutex is locked */
void flush_cache();
my_bool free_old_query();
- void free_query(Query_cache_block * point);
- my_bool allocate_data_chain(Query_cache_block * &result_block,
+ void free_query(Query_cache_block *point);
+ my_bool allocate_data_chain(Query_cache_block **result_block,
ulong data_len,
- Query_cache_block * query_block);
+ Query_cache_block *query_block);
void invalidate_table(TABLE_LIST *table);
void invalidate_table(TABLE *table);
void invalidate_table_in_db(Query_cache_block *table_block,
- char * db);
+ char *db);
void invalidate_table(Query_cache_block *table_block);
- my_bool register_all_tables(Query_cache_block * block,
- TABLE_LIST * tables_used,
+ my_bool register_all_tables(Query_cache_block *block,
+ TABLE_LIST *tables_used,
TABLE_COUNTER_TYPE tables);
- my_bool insert_table(uint key_len, char * key,
- Query_cache_block_table * node,
+ my_bool insert_table(uint key_len, char *key,
+ Query_cache_block_table *node,
Query_cache_table::query_cache_table_type type);
- void unlink_table(Query_cache_block_table * node);
- Query_cache_block * get_free_block (ulong len, my_bool not_less,
+ void unlink_table(Query_cache_block_table *node);
+ Query_cache_block *get_free_block (ulong len, my_bool not_less,
ulong min);
- void free_memory_block(Query_cache_block * point);
+ void free_memory_block(Query_cache_block *point);
void split_block(Query_cache_block *block, ulong len);
- Query_cache_block * join_free_blocks(Query_cache_block *first_block,
- Query_cache_block * block_in_list);
- my_bool append_next_free_block(Query_cache_block * block,
+ Query_cache_block *join_free_blocks(Query_cache_block *first_block,
+ Query_cache_block *block_in_list);
+ my_bool append_next_free_block(Query_cache_block *block,
ulong add_size);
- void exclude_from_free_memory_list(Query_cache_block * free_block);
- void insert_into_free_memory_list(Query_cache_block * new_block);
- my_bool move_by_type(byte * &border, Query_cache_block * &before,
- ulong &gap, Query_cache_block * i);
+ void exclude_from_free_memory_list(Query_cache_block *free_block);
+ void insert_into_free_memory_list(Query_cache_block *new_block);
+ my_bool move_by_type(byte **border, Query_cache_block **before,
+ ulong *gap, Query_cache_block *i);
uint find_bin(ulong size);
- void move_to_query_list_end(Query_cache_block * block);
- void insert_into_free_memory_sorted_list(Query_cache_block * new_block,
- Query_cache_block * &list);
+ void move_to_query_list_end(Query_cache_block *block);
+ void insert_into_free_memory_sorted_list(Query_cache_block *new_block,
+ Query_cache_block **list);
void pack_cache();
- void relink(Query_cache_block * oblock,
- Query_cache_block * nblock,
- Query_cache_block * next,
- Query_cache_block * prev,
- Query_cache_block * pnext,
- Query_cache_block * pprev);
+ void relink(Query_cache_block *oblock,
+ Query_cache_block *nblock,
+ Query_cache_block *next,
+ Query_cache_block *prev,
+ Query_cache_block *pnext,
+ Query_cache_block *pprev);
my_bool join_results(ulong join_limit);
/*
@@ -317,38 +312,35 @@ protected:
ulong init_cache();
void make_disabled();
void free_cache(my_bool destruction);
- Query_cache_block * write_block_data(ulong data_len, gptr data,
+ Query_cache_block *write_block_data(ulong data_len, gptr data,
ulong header_len,
Query_cache_block::block_type type,
TABLE_COUNTER_TYPE ntab = 0,
my_bool under_guard=0);
- my_bool append_result_data(Query_cache_block * &result,
+ my_bool append_result_data(Query_cache_block **result,
ulong data_len, gptr data,
- Query_cache_block * parent,
- Query_cache_block * first_data_block);
- my_bool write_result_data(Query_cache_block * &result,
+ Query_cache_block *parent);
+ my_bool write_result_data(Query_cache_block **result,
ulong data_len, gptr data,
- Query_cache_block * parent,
+ Query_cache_block *parent,
Query_cache_block::block_type
type=Query_cache_block::RESULT);
- Query_cache_block * allocate_block(ulong len, my_bool not_less,
+ Query_cache_block *allocate_block(ulong len, my_bool not_less,
ulong min,
my_bool under_guard=0);
/*
- If query is cachable return numder tables in query
+ If query is cacheable return number tables in query
(query without tables not cached)
*/
- TABLE_COUNTER_TYPE is_cachable(THD *thd, uint query_len, char *query,
- LEX *lex,
- TABLE_LIST *tables_used);
+ TABLE_COUNTER_TYPE is_cacheable(THD *thd, uint32 query_len, char *query,
+ LEX *lex, TABLE_LIST *tables_used);
public:
Query_cache(ulong query_cache_limit = ULONG_MAX,
ulong min_allocation_unit = QUERY_CACHE_MIN_ALLOCATION_UNIT,
ulong min_result_data_size = QUERY_CACHE_MIN_RESULT_DATA_SIZE,
uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE,
- uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE
- );
+ uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE);
/* resize query cache (return real query size, 0 if disabled) */
ulong resize(ulong query_cache_size);
@@ -371,10 +363,10 @@ protected:
void invalidate(Query_cache_table::query_cache_table_type type);
/* Remove all queries that uses any of the tables in following database */
- void invalidate(char * db);
+ void invalidate(char *db);
/* Remove all queries that uses any of the listed following table */
- void invalidate_by_MyISAM_filename(char * filename);
+ void invalidate_by_MyISAM_filename(const char *filename);
/* Remove all queries from cache */
void flush();
@@ -386,7 +378,7 @@ protected:
void destroy();
#ifndef DBUG_OFF
- void wreck(uint line, const char * message);
+ void wreck(uint line, const char *message);
void bins_dump();
void cache_dump();
void queries_dump();
diff --git a/sql/sql_class.h b/sql/sql_class.h
index e036da982f0..5d20508e728 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -236,35 +236,35 @@ class delayed_insert;
class THD :public ilink {
public:
- NET net;
- LEX lex;
- MEM_ROOT mem_root;
- HASH user_vars;
- String packet; /* Room for 1 row */
- struct sockaddr_in remote;
- struct rand_struct rand;
- char *query,*thread_stack;
- char *host,*user,*priv_user,*db,*ip;
- const char *proc_info, *host_or_ip;
- uint client_capabilities,sql_mode,max_packet_length;
- uint master_access,db_access;
- TABLE *open_tables,*temporary_tables, *handler_tables;
+ NET net;
+ LEX lex;
+ MEM_ROOT mem_root;
+ HASH user_vars;
+ String packet; /* Room for 1 row */
+ struct sockaddr_in remote;
+ struct rand_struct rand;
+ char *query,*thread_stack;
+ char *host,*user,*priv_user,*db,*ip;
+ const char *proc_info, *host_or_ip;
+ uint client_capabilities,sql_mode,max_packet_length;
+ uint master_access,db_access;
+ TABLE *open_tables,*temporary_tables, *handler_tables;
MYSQL_LOCK *lock,*locked_tables;
- ULL *ull;
+ ULL *ull;
struct st_my_thread_var *mysys_var;
enum enum_server_command command;
- uint32 server_id;
- uint32 log_seq;
- uint32 file_id; // for LOAD DATA INFILE
+ uint32 server_id;
+ uint32 log_seq;
+ uint32 file_id; // for LOAD DATA INFILE
const char *where;
- time_t start_time,time_after_lock,user_time;
- time_t connect_time,thr_create_time; // track down slow pthread_create
+ time_t start_time,time_after_lock,user_time;
+ time_t connect_time,thr_create_time; // track down slow pthread_create
thr_lock_type update_lock_default;
delayed_insert *di;
struct st_transactions {
IO_CACHE trans_log;
- THD_TRANS all; /* Trans since BEGIN WORK */
- THD_TRANS stmt; /* Trans for current statement */
+ THD_TRANS all; // Trans since BEGIN WORK
+ THD_TRANS stmt; // Trans for current statement
uint bdb_lock_count;
} transaction;
Item *free_list, *handler_items;
@@ -277,17 +277,20 @@ public:
Vio* active_vio;
pthread_mutex_t active_vio_lock;
#endif
- ulonglong next_insert_id,last_insert_id,current_insert_id, limit_found_rows;
- ha_rows select_limit,offset_limit,default_select_limit,cuted_fields,
- max_join_size, sent_row_count, examined_row_count;
- table_map used_tables;
- ulong query_id,version, inactive_timeout,options,thread_id;
- long dbug_thread_id;
+ ulonglong next_insert_id,last_insert_id,current_insert_id,
+ limit_found_rows;
+ ha_rows select_limit,offset_limit,default_select_limit,cuted_fields,
+ max_join_size, sent_row_count, examined_row_count;
+ table_map used_tables;
+ ulong query_id,version, inactive_timeout,options,thread_id;
+ long dbug_thread_id;
pthread_t real_id;
- uint current_tablenr,tmp_table,cond_count,col_access,query_length;
- uint server_status,open_options;
+ uint current_tablenr,tmp_table,cond_count,col_access;
+ uint server_status,open_options;
+ uint32 query_length;
enum_tx_isolation tx_isolation, session_tx_isolation;
char scramble[9];
+ uint8 query_cache_type; // type of query cache processing
bool slave_thread;
bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
bool no_errors, allow_sum_func, password, fatal_error;
@@ -296,18 +299,18 @@ public:
bool query_error, bootstrap, cleanup_done;
bool safe_to_cache_query;
bool volatile killed;
- //type of query cache processing
- byte query_cache_type;
+ /*
+ If we do a purge of binary logs, log index info of the threads
+ that are currently reading it needs to be adjusted. To do that
+ each thread that is using LOG_INFO needs to adjust the pointer to it
+ */
LOG_INFO* current_linfo;
- // if we do a purge of binary logs, log index info of the threads
- // that are currently reading it needs to be adjusted. To do that
- // each thread that is using LOG_INFO needs to adjust the pointer to it
-
- ulong slave_proxy_id; // in slave thread we need to know in behalf of which
- // thread the query is being run to replicate temp tables properly
-
- NET* slave_net; // network connection from slave to master
-
+ /*
+ In slave thread we need to know in behalf of which
+ thread the query is being run to replicate temp tables properly
+ */
+ ulong slave_proxy_id;
+ NET* slave_net; // network connection from slave -> m.
THD();
~THD();
void cleanup(void);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 5c43cacd85b..548e7c9062f 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -739,9 +739,9 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
}
client_thd->proc_info="allocating local table";
- copy= (TABLE*) sql_alloc(sizeof(*copy)+
- (table->fields+1)*sizeof(Field**)+
- table->reclength);
+ copy= (TABLE*) client_thd->alloc(sizeof(*copy)+
+ (table->fields+1)*sizeof(Field**)+
+ table->reclength);
if (!copy)
goto error;
*copy= *table;
@@ -759,7 +759,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
found_next_number_field=table->found_next_number_field;
for (org_field=table->field ; *org_field ; org_field++,field++)
{
- if (!(*field= (*org_field)->new_field(copy)))
+ if (!(*field= (*org_field)->new_field(&client_thd->mem_root,copy)))
return 0;
(*field)->move_field(adjust_ptrs); // Point at copy->record[0]
if (*org_field == found_next_number_field)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index ef06eaf9145..769527c92fe 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -29,25 +29,42 @@
#include <my_dir.h>
#include <assert.h>
+#ifdef HAVE_OPENSSL
+/*
+ Without SSL the handshake consists of one packet. This packet
+ has both client capabilites and scrambled password.
+ With SSL the handshake might consist of two packets. If the first
+ packet (client capabilities) has CLIENT_SSL flag set, we have to
+ switch to SSL and read the second packet. The scrambled password
+ is in the second packet and client_capabilites field will be ignored.
+ Maybe it is better to accept flags other than CLIENT_SSL from the
+ second packet?
+*/
+#define SSL_HANDSHAKE_SIZE 2
+#define NORMAL_HANDSHAKE_SIZE 6
+#define MIN_HANDSHAKE_SIZE 2
+#else
+#define MIN_HANDSHAKE_SIZE 6
+#endif /* HAVE_OPENSSL */
#define SCRAMBLE_LENGTH 8
+
extern int yyparse(void);
extern "C" pthread_mutex_t THR_LOCK_keycache;
#ifdef SOLARIS
extern "C" int gethostname(char *name, int namelen);
#endif
-static int check_for_max_user_connections(const char *user, int u_length,
- const char *host);
+static int check_for_max_user_connections(const char *user, const char *host);
static void decrease_user_connections(const char *user, const char *host);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
-static bool check_dup(THD *thd,const char *db,const char *name,
- TABLE_LIST *tables);
+static bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
static void mysql_init_query(THD *thd);
static void remove_escape(char *name);
static void refresh_status(void);
-static bool append_file_to_dir(char **filename_ptr, char *table_name);
+static bool append_file_to_dir(THD *thd, char **filename_ptr,
+ char *table_name);
static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result);
const char *any_db="*any*"; // Special symbol for check_access
@@ -160,7 +177,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
db ? db : (char*) "");
thd->db_access=0;
if (max_user_connections &&
- check_for_max_user_connections(user, strlen(user), thd->host))
+ check_for_max_user_connections(user, thd->host))
return -1;
if (db && db[0])
{
@@ -210,8 +227,7 @@ void init_max_user_conn(void)
}
-static int check_for_max_user_connections(const char *user, int u_length,
- const char *host)
+static int check_for_max_user_connections(const char *user, const char *host)
{
int error=1;
uint temp_len;
@@ -363,51 +379,35 @@ check_connections(THD *thd)
}
vio_keepalive(net->vio, TRUE);
- /* nasty, but any other way? */
- uint pkt_len = 0;
+ ulong pkt_len=0;
{
/* buff[] needs to big enough to hold the server_version variable */
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+32],*end;
int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB;
+
if (opt_using_transactions)
client_flags|=CLIENT_TRANSACTIONS;
#ifdef HAVE_COMPRESS
client_flags |= CLIENT_COMPRESS;
#endif /* HAVE_COMPRESS */
+#ifdef HAVE_OPENSSL
+ if (ssl_acceptor_fd)
+ client_flags |= CLIENT_SSL; /* Wow, SSL is avalaible! */
+#endif /* HAVE_OPENSSL */
- end=strmov(buff,server_version)+1;
+ end=strnmov(buff,server_version,SERVER_VERSION_LENGTH)+1;
int4store((uchar*) end,thd->thread_id);
end+=4;
memcpy(end,thd->scramble,SCRAMBLE_LENGTH+1);
end+=SCRAMBLE_LENGTH +1;
-#ifdef HAVE_OPENSSL
- if (ssl_acceptor_fd)
- client_flags |= CLIENT_SSL; /* Wow, SSL is avalaible! */
- /*
- * Without SSL the handshake consists of one packet. This packet
- * has both client capabilites and scrambled password.
- * With SSL the handshake might consist of two packets. If the first
- * packet (client capabilities) has CLIENT_SSL flag set, we have to
- * switch to SSL and read the second packet. The scrambled password
- * is in the second packet and client_capabilites field will be ignored.
- * Maybe it is better to accept flags other than CLIENT_SSL from the
- * second packet?
- */
-#define SSL_HANDSHAKE_SIZE 2
-#define NORMAL_HANDSHAKE_SIZE 6
-#define MIN_HANDSHAKE_SIZE 2
-
-#else
-#define MIN_HANDSHAKE_SIZE 6
-#endif /* HAVE_OPENSSL */
int2store(end,client_flags);
- end[2]=MY_CHARSET_CURRENT;
+ end[2]=(char) MY_CHARSET_CURRENT;
int2store(end+3,thd->server_status);
bzero(end+5,13);
end+=18;
- if (net_write_command(net,protocol_version, buff,
+ if (net_write_command(net,(uchar) protocol_version, buff,
(uint) (end-buff)) ||
- (pkt_len=my_net_read(net)) == packet_error ||
+ (pkt_len= my_net_read(net)) == packet_error ||
pkt_len < MIN_HANDSHAKE_SIZE)
{
inc_host_errors(&thd->remote.sin_addr);
@@ -426,12 +426,9 @@ check_connections(THD *thd)
if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
thd->sql_mode|= MODE_IGNORE_SPACE;
#ifdef HAVE_OPENSSL
- DBUG_PRINT("info",
- ("pkt_len:%d, client capabilities: %d",
- pkt_len, thd->client_capabilities) );
+ DBUG_PRINT("info", ("client capabilities: %d", thd->client_capabilities));
if (thd->client_capabilities & CLIENT_SSL)
{
- DBUG_PRINT("info", ("Agreed to change IO layer to SSL") );
/* Do the SSL layering. */
DBUG_PRINT("info", ("IO layer change in progress..."));
sslaccept(ssl_acceptor_fd, net->vio, thd->inactive_timeout);
@@ -439,8 +436,8 @@ check_connections(THD *thd)
if ((pkt_len=my_net_read(net)) == packet_error ||
pkt_len < NORMAL_HANDSHAKE_SIZE)
{
- DBUG_PRINT("info", ("pkt_len:%d", pkt_len));
- DBUG_PRINT("error", ("Failed to read user information"));
+ DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
+ pkt_len));
inc_host_errors(&thd->remote.sin_addr);
return(ER_HANDSHAKE_ERROR);
}
@@ -469,7 +466,7 @@ check_connections(THD *thd)
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
opt_using_transactions)
thd->net.return_status= &thd->server_status;
- net->timeout=net_read_timeout;
+ net->timeout=(uint) net_read_timeout;
if (check_user(thd,COM_CONNECT, user, passwd, db, 1))
return (-1);
thd->password=test(passwd[0]);
@@ -693,8 +690,8 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
goto err;
thd->free_list = 0;
+ thd->query_length=(uint) strlen(tbl_name);
thd->query = tbl_name;
- thd->query_length=strlen(tbl_name);
if ((error = mysqld_dump_create_info(thd, table, -1)))
{
my_error(ER_GET_ERRNO, MYF(0));
@@ -715,7 +712,8 @@ err:
bool do_command(THD *thd)
{
char *packet;
- uint old_timeout,packet_length;
+ uint old_timeout;
+ ulong packet_length;
NET *net;
enum enum_server_command command;
DBUG_ENTER("do_command");
@@ -725,7 +723,7 @@ bool do_command(THD *thd)
packet=0;
old_timeout=net->timeout;
- net->timeout=thd->inactive_timeout; /* Wait max for 8 hours */
+ net->timeout=(uint) thd->inactive_timeout; // Wait max for 8 hours
net->last_error[0]=0; // Clear error message
net->last_errno=0;
@@ -745,7 +743,7 @@ bool do_command(THD *thd)
command_name[command]));
}
net->timeout=old_timeout; // Timeout for writing
- DBUG_RETURN(dispatch_command(command,thd, packet+1, packet_length));
+ DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length));
}
@@ -842,6 +840,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
pos--;
packet_length--;
}
+ thd->query_length= packet_length;
if (!(thd->query= (char*) thd->memdup((gptr) (packet),packet_length+1)))
break;
thd->query[packet_length]=0;
@@ -872,8 +871,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
thd->free_list=0;
table_list.name=table_list.real_name=thd->strdup(packet);
- thd->query=fields=thd->strdup(strend(packet)+1);
thd->query_length=strlen(thd->query);
+ thd->query=fields=thd->strdup(strend(packet)+1);
mysql_log.write(thd,command,"%s %s",table_list.real_name,fields);
remove_escape(table_list.real_name); // This can't have wildcards
@@ -1302,8 +1301,10 @@ mysql_execute_command(void)
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
#else
/* Fix names if symlinked tables */
- if (append_file_to_dir(&lex->create_info.data_file_name, tables->name) ||
- append_file_to_dir(&lex->create_info.index_file_name, tables->name))
+ if (append_file_to_dir(thd, &lex->create_info.data_file_name,
+ tables->name) ||
+ append_file_to_dir(thd,&lex->create_info.index_file_name,
+ tables->name))
{
res=-1;
break;
@@ -1314,7 +1315,7 @@ mysql_execute_command(void)
select_result *result;
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- check_dup(thd,tables->db,tables->real_name,tables->next))
+ check_dup(tables->db, tables->real_name, tables->next))
{
net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
@@ -1618,7 +1619,7 @@ mysql_execute_command(void)
if (thd->select_limit < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit
- if (check_dup(thd,tables->db,tables->real_name,tables->next))
+ if (check_dup(tables->db, tables->real_name, tables->next))
{
net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
@@ -1906,7 +1907,7 @@ mysql_execute_command(void)
}
case SQLCOM_SET_OPTION:
{
- uint org_options=thd->options;
+ ulong org_options=thd->options;
thd->options=select_lex->options;
thd->update_lock_default= ((thd->options & OPTION_LOW_PRIORITY_UPDATES) ?
TL_WRITE_LOW_PRIORITY : TL_WRITE);
@@ -2975,8 +2976,7 @@ void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
/* Check if name is used in table list */
-static bool check_dup(THD *thd,const char *db,const char *name,
- TABLE_LIST *tables)
+static bool check_dup(const char *db, const char *name, TABLE_LIST *tables)
{
for (; tables ; tables=tables->next)
if (!strcmp(name,tables->real_name) && !strcmp(db,tables->db))
@@ -3083,7 +3083,7 @@ static void refresh_status(void)
/* If pointer is not a null pointer, append filename to it */
-static bool append_file_to_dir(char **filename_ptr, char *table_name)
+static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name)
{
char buff[FN_REFLEN],*ptr, *end;
if (!*filename_ptr)
@@ -3099,7 +3099,7 @@ static bool append_file_to_dir(char **filename_ptr, char *table_name)
/* Fix is using unix filename format on dos */
strmov(buff,*filename_ptr);
end=convert_dirname(buff, *filename_ptr, NullS);
- if (!(ptr=sql_alloc((uint) (end-buff)+strlen(table_name)+1)))
+ if (!(ptr=thd->alloc((uint) (end-buff)+(uint) strlen(table_name)+1)))
return 1; // End of memory
*filename_ptr=ptr;
strxmov(ptr,buff,table_name,NullS);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2673c746bbc..5789e537a6a 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -47,7 +47,8 @@ static void find_best(JOIN *join,table_map rest_tables,uint index,
static uint cache_record_length(JOIN *join,uint index);
static double prev_record_reads(JOIN *join,table_map found_ref);
static bool get_best_combination(JOIN *join);
-static store_key *get_store_key(KEYUSE *keyuse, table_map used_tables,
+static store_key *get_store_key(THD *thd,
+ KEYUSE *keyuse, table_map used_tables,
KEY_PART_INFO *key_part, char *key_buff,
uint maybe_null);
static bool make_simple_join(JOIN *join,TABLE *tmp_table);
@@ -795,7 +796,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
(procedure && (procedure->flags & PROC_GROUP)))
{
alloc_group_fields(&join,group);
- setup_copy_fields(&join.tmp_table_param,all_fields);
+ setup_copy_fields(thd, &join.tmp_table_param,all_fields);
if (make_sum_func_list(&join,all_fields) || thd->fatal_error)
goto err; /* purecov: inspected */
}
@@ -2152,7 +2153,8 @@ get_best_combination(JOIN *join)
if (!keyuse->used_tables &&
!(join->select_options & SELECT_DESCRIBE))
{ // Compare against constant
- store_key_item *tmp=new store_key_item(keyinfo->key_part[i].field,
+ store_key_item *tmp=new store_key_item(thd,
+ keyinfo->key_part[i].field,
(char*)key_buff +
maybe_null,
maybe_null ?
@@ -2166,7 +2168,8 @@ get_best_combination(JOIN *join)
tmp->copy();
}
else
- *ref_key++= get_store_key(keyuse,join->const_table_map,
+ *ref_key++= get_store_key(join->thd,
+ keyuse,join->const_table_map,
&keyinfo->key_part[i],
(char*) key_buff,maybe_null);
key_buff+=keyinfo->key_part[i].store_length;
@@ -2208,25 +2211,28 @@ get_best_combination(JOIN *join)
static store_key *
-get_store_key(KEYUSE *keyuse, table_map used_tables, KEY_PART_INFO *key_part,
- char *key_buff, uint maybe_null)
+get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
+ KEY_PART_INFO *key_part, char *key_buff, uint maybe_null)
{
if (!((~used_tables) & keyuse->used_tables)) // if const item
{
- return new store_key_const_item(key_part->field,
+ return new store_key_const_item(thd,
+ key_part->field,
key_buff + maybe_null,
maybe_null ? key_buff : 0,
key_part->length,
keyuse->val);
}
else if (keyuse->val->type() == Item::FIELD_ITEM)
- return new store_key_field(key_part->field,
+ return new store_key_field(thd,
+ key_part->field,
key_buff + maybe_null,
maybe_null ? key_buff : 0,
key_part->length,
((Item_field*) keyuse->val)->field,
keyuse->val->full_name());
- return new store_key_item(key_part->field,
+ return new store_key_item(thd,
+ key_part->field,
key_buff + maybe_null,
maybe_null ? key_buff : 0,
key_part->length,
@@ -3272,7 +3278,7 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
** for send_fields
****************************************************************************/
-Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
+Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field,
bool group, bool modify_item)
{
@@ -3314,7 +3320,7 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
item->name,table,item->binary);
}
}
- current_thd->fatal_error=1;
+ thd->fatal_error=1;
return 0; // Error
}
case Item::FIELD_ITEM:
@@ -3322,7 +3328,8 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
Field *org_field=((Item_field*) item)->field,*new_field;
*from_field=org_field;
- if ((new_field= org_field->new_field(table))) // Should always be true
+ // The following should always be true
+ if ((new_field= org_field->new_field(&thd->mem_root,table)))
{
if (modify_item)
((Item_field*) item)->result_field= new_field;
@@ -3510,8 +3517,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!arg->const_item())
{
Field *new_field=
- create_tmp_field(table,arg,arg->type(),&copy_func,tmp_from_field,
- group != 0,not_all_columns);
+ create_tmp_field(thd, table,arg,arg->type(),&copy_func,
+ tmp_from_field, group != 0,not_all_columns);
if (!new_field)
goto err; // Should be OOM
tmp_from_field++;
@@ -3527,7 +3534,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
else
{
- Field *new_field=create_tmp_field(table,item,type,&copy_func,
+ Field *new_field=create_tmp_field(thd, table, item,type, &copy_func,
tmp_from_field, group != 0,
not_all_columns);
if (!new_field)
@@ -3708,7 +3715,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!using_unique_constraint)
{
group->buff=(char*) group_buff;
- if (!(group->field=field->new_field(table)))
+ if (!(group->field=field->new_field(&thd->mem_root,table)))
goto err; /* purecov: inspected */
if (maybe_null)
{
@@ -6410,7 +6417,7 @@ test_if_group_changed(List<Item_buff> &list)
*/
bool
-setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields)
+setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields)
{
Item *pos;
List_iterator<Item> li(fields);
@@ -6438,7 +6445,7 @@ setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields)
/* set up save buffer and change result_field to point at saved value */
Field *field= item->field;
- item->result_field=field->new_field(field->table);
+ item->result_field=field->new_field(&thd->mem_root,field->table);
char *tmp=(char*) sql_alloc(field->pack_length()+1);
if (!tmp)
goto err;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 4fcffae31d2..1e62f1b7809 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -190,7 +190,7 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func);
-bool setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields);
+bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,List<Item> &fields);
void copy_fields(TMP_TABLE_PARAM *param);
void copy_funcs(Item_result_field **func_ptr);
bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
@@ -210,7 +210,7 @@ class store_key :public Sql_alloc
char *null_ptr;
char err;
public:
- store_key(Field *field_arg, char *ptr, char *null, uint length)
+ store_key(THD *thd, Field *field_arg, char *ptr, char *null, uint length)
:null_ptr(null),err(0)
{
if (field_arg->type() == FIELD_TYPE_BLOB)
@@ -219,7 +219,7 @@ class store_key :public Sql_alloc
field_arg->table, field_arg->binary());
else
{
- to_field=field_arg->new_field(field_arg->table);
+ to_field=field_arg->new_field(&thd->mem_root,field_arg->table);
if (to_field)
to_field->move_field(ptr, (uchar*) null, 1);
}
@@ -235,9 +235,9 @@ class store_key_field: public store_key
Copy_field copy_field;
const char *field_name;
public:
- store_key_field(Field *to_field_arg, char *ptr, char *null_ptr_arg,
+ store_key_field(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg,
uint length, Field *from_field, const char *name_arg)
- :store_key(to_field_arg,ptr,
+ :store_key(thd, to_field_arg,ptr,
null_ptr_arg ? null_ptr_arg : from_field->maybe_null() ? &err
: NullS,length), field_name(name_arg)
{
@@ -260,9 +260,9 @@ class store_key_item :public store_key
protected:
Item *item;
public:
- store_key_item(Field *to_field_arg, char *ptr, char *null_ptr_arg,
+ store_key_item(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg,
uint length, Item *item_arg)
- :store_key(to_field_arg,ptr,
+ :store_key(thd, to_field_arg,ptr,
null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
&err : NullS, length), item(item_arg)
{}
@@ -279,10 +279,10 @@ class store_key_const_item :public store_key_item
{
bool inited;
public:
- store_key_const_item(Field *to_field_arg, char *ptr,
+ store_key_const_item(THD *thd, Field *to_field_arg, char *ptr,
char *null_ptr_arg, uint length,
Item *item_arg)
- :store_key_item(to_field_arg,ptr,
+ :store_key_item(thd, to_field_arg,ptr,
null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
&err : NullS, length, item_arg), inited(0)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 19c3d89caaf..16790ac1621 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1054,9 +1054,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
thd_info->query=0;
if (tmp->query)
{
- uint length=(uint) strlen(tmp->query);
- if (length > max_query_length)
- length=max_query_length;
+ /* query_length is always set before tmp->query */
+ uint length= min(max_query_length, tmp->query_length);
thd_info->query=(char*) thd->memdup(tmp->query,length+1);
thd_info->query[length]=0;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index ae450680fbb..737c8fccd9d 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -704,7 +704,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(0);
}
- Field *field=create_tmp_field(&tmp_table,item,item->type(),
+ Field *field=create_tmp_field(thd, &tmp_table, item, item->type(),
(Item_result_field***) 0, &tmp_field,0,0);
if (!field ||
!(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
diff --git a/sql/table.cc b/sql/table.cc
index eb6d8fbb9cd..11c30f12ca2 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -467,7 +467,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
key_part->key_part_flag|= HA_PART_KEY;
if (field->type() != FIELD_TYPE_BLOB)
{ // Create a new field
- field=key_part->field=field->new_field(outparam);
+ field=key_part->field=field->new_field(&outparam->mem_root,
+ outparam);
field->field_length=key_part->length;
}
}