diff options
author | monty@hundin.mysql.fi <> | 2001-12-05 13:03:00 +0200 |
---|---|---|
committer | monty@hundin.mysql.fi <> | 2001-12-05 13:03:00 +0200 |
commit | 1de4fff5ba80982cbed3a524488528c83ed8f945 (patch) | |
tree | 739c2cfffa69408c6460ba4c419a59d5b594cbb1 /sql | |
parent | 1d26537da53fee228b2f9d974d4806a06b76e33e (diff) | |
download | mariadb-git-1de4fff5ba80982cbed3a524488528c83ed8f945.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)
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 235 | ||||
-rw-r--r-- | sql/field.h | 140 | ||||
-rw-r--r-- | sql/ha_myisam.cc | 4 | ||||
-rw-r--r-- | sql/item.h | 4 | ||||
-rw-r--r-- | sql/log_event.cc | 248 | ||||
-rw-r--r-- | sql/log_event.h | 265 | ||||
-rw-r--r-- | sql/mf_iocache.cc | 4 | ||||
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 12 | ||||
-rw-r--r-- | sql/net_serv.cc | 36 | ||||
-rw-r--r-- | sql/opt_range.h | 6 | ||||
-rw-r--r-- | sql/sql_cache.cc | 2610 | ||||
-rw-r--r-- | sql/sql_cache.h | 198 | ||||
-rw-r--r-- | sql/sql_class.h | 83 | ||||
-rw-r--r-- | sql/sql_insert.cc | 8 | ||||
-rw-r--r-- | sql/sql_parse.cc | 110 | ||||
-rw-r--r-- | sql/sql_select.cc | 43 | ||||
-rw-r--r-- | sql/sql_select.h | 18 | ||||
-rw-r--r-- | sql/sql_show.cc | 5 | ||||
-rw-r--r-- | sql/sql_table.cc | 2 | ||||
-rw-r--r-- | sql/table.cc | 3 |
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(),©_func,tmp_from_field, - group != 0,not_all_columns); + create_tmp_field(thd, table,arg,arg->type(),©_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,©_func, + Field *new_field=create_tmp_field(thd, table, item,type, ©_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; } } |