| 1 | /* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
| 2 | |
| 3 | This program is free software; you can redistribute it and/or modify |
| 4 | it under the terms of the GNU General Public License as published by |
| 5 | the Free Software Foundation; version 2 of the License. |
| 6 | |
| 7 | This program is distributed in the hope that it will be useful, |
| 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | GNU General Public License for more details. |
| 11 | |
| 12 | You should have received a copy of the GNU General Public License |
| 13 | along with this program; if not, write to the Free Software |
| 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
| 15 | |
| 16 | #ifndef _SQL_CACHE_H |
| 17 | #define _SQL_CACHE_H |
| 18 | |
| 19 | #include "hash.h" |
| 20 | #include "my_base.h" /* ha_rows */ |
| 21 | |
| 22 | class MY_LOCALE; |
| 23 | struct TABLE_LIST; |
| 24 | class Time_zone; |
| 25 | struct LEX; |
| 26 | struct TABLE; |
| 27 | typedef struct st_changed_table_list CHANGED_TABLE_LIST; |
| 28 | |
| 29 | /* Query cache */ |
| 30 | |
| 31 | /* |
| 32 | Can't create new free memory block if unused memory in block less |
| 33 | then QUERY_CACHE_MIN_ALLOCATION_UNIT. |
| 34 | if QUERY_CACHE_MIN_ALLOCATION_UNIT == 0 then |
| 35 | QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automaticaly |
| 36 | */ |
| 37 | #define QUERY_CACHE_MIN_ALLOCATION_UNIT 512 |
| 38 | |
| 39 | /* inittial size of hashes */ |
| 40 | #define QUERY_CACHE_DEF_QUERY_HASH_SIZE 1024 |
| 41 | #define QUERY_CACHE_DEF_TABLE_HASH_SIZE 1024 |
| 42 | |
| 43 | /* minimal result data size when data allocated */ |
| 44 | #define QUERY_CACHE_MIN_RESULT_DATA_SIZE (1024*4) |
| 45 | |
| 46 | /* |
| 47 | start estimation of first result block size only when number of queries |
| 48 | bigger then: |
| 49 | */ |
| 50 | #define QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER 3 |
| 51 | |
| 52 | |
| 53 | |
| 54 | /* memory bins size spacing (see at Query_cache::init_cache (sql_cache.cc)) */ |
| 55 | #define QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 4 |
| 56 | #define QUERY_CACHE_MEM_BIN_STEP_PWR2 2 |
| 57 | #define QUERY_CACHE_MEM_BIN_PARTS_INC 1 |
| 58 | #define QUERY_CACHE_MEM_BIN_PARTS_MUL 1.2 |
| 59 | #define QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2 3 |
| 60 | |
| 61 | /* how many free blocks check when finding most suitable before other 'end' |
| 62 | of list of free blocks */ |
| 63 | #define QUERY_CACHE_MEM_BIN_TRY 5 |
| 64 | |
| 65 | /* packing parameters */ |
| 66 | #define QUERY_CACHE_PACK_ITERATION 2 |
| 67 | #define QUERY_CACHE_PACK_LIMIT (512*1024L) |
| 68 | |
| 69 | #define TABLE_COUNTER_TYPE uint |
| 70 | |
| 71 | struct Query_cache_block; |
| 72 | struct Query_cache_block_table; |
| 73 | struct Query_cache_table; |
| 74 | struct Query_cache_query; |
| 75 | struct Query_cache_result; |
| 76 | class Query_cache; |
| 77 | struct Query_cache_tls; |
| 78 | struct LEX; |
| 79 | class THD; |
| 80 | |
| 81 | typedef my_bool (*qc_engine_callback)(THD *thd, const char *table_key, |
| 82 | uint key_length, |
| 83 | ulonglong *engine_data); |
| 84 | |
| 85 | /** |
| 86 | This class represents a node in the linked chain of queries |
| 87 | belonging to one table. |
| 88 | |
| 89 | @note The root of this linked list is not a query-type block, but the table- |
| 90 | type block which all queries has in common. |
| 91 | */ |
| 92 | struct Query_cache_block_table |
| 93 | { |
| 94 | Query_cache_block_table() {} /* Remove gcc warning */ |
| 95 | |
| 96 | /** |
| 97 | This node holds a position in a static table list belonging |
| 98 | to the associated query (base 0). |
| 99 | */ |
| 100 | TABLE_COUNTER_TYPE n; |
| 101 | |
| 102 | /** |
| 103 | Pointers to the next and previous node, linking all queries with |
| 104 | a common table. |
| 105 | */ |
| 106 | Query_cache_block_table *next, *prev; |
| 107 | |
| 108 | /** |
| 109 | A pointer to the table-type block which all |
| 110 | linked queries has in common. |
| 111 | */ |
| 112 | Query_cache_table *parent; |
| 113 | |
| 114 | /** |
| 115 | A method to calculate the address of the query cache block |
| 116 | owning this node. The purpose of this calculation is to |
| 117 | make it easier to move the query cache block without having |
| 118 | to modify all the pointer addresses. |
| 119 | */ |
| 120 | inline Query_cache_block *block(); |
| 121 | }; |
| 122 | |
| 123 | struct Query_cache_block |
| 124 | { |
| 125 | Query_cache_block() {} /* Remove gcc warning */ |
| 126 | enum block_type {FREE, QUERY, RESULT, RES_CONT, RES_BEG, |
| 127 | RES_INCOMPLETE, TABLE, INCOMPLETE}; |
| 128 | |
| 129 | size_t length; // length of all block |
| 130 | size_t used; // length of data |
| 131 | /* |
| 132 | Not used **pprev, **prev because really needed access to pervious block: |
| 133 | *pprev to join free blocks |
| 134 | *prev to access to opposite side of list in cyclic sorted list |
| 135 | */ |
| 136 | Query_cache_block *pnext,*pprev, // physical next/previous block |
| 137 | *next,*prev; // logical next/previous block |
| 138 | block_type type; |
| 139 | TABLE_COUNTER_TYPE n_tables; // number of tables in query |
| 140 | |
| 141 | inline bool is_free(void) { return type == FREE; } |
| 142 | void init(size_t length); |
| 143 | void destroy(); |
| 144 | uint (); |
| 145 | uchar* data(void); |
| 146 | Query_cache_query *query(); |
| 147 | Query_cache_table *table(); |
| 148 | Query_cache_result *result(); |
| 149 | Query_cache_block_table *table(TABLE_COUNTER_TYPE n); |
| 150 | }; |
| 151 | |
| 152 | struct Query_cache_query |
| 153 | { |
| 154 | ulonglong limit_found_rows; |
| 155 | mysql_rwlock_t lock; |
| 156 | Query_cache_block *res; |
| 157 | Query_cache_tls *wri; |
| 158 | size_t len; |
| 159 | unsigned int last_pkt_nr; |
| 160 | uint8 tbls_type; |
| 161 | uint8 ready; |
| 162 | ulonglong hit_count; |
| 163 | |
| 164 | Query_cache_query() {} /* Remove gcc warning */ |
| 165 | inline void init_n_lock(); |
| 166 | void unlock_n_destroy(); |
| 167 | inline ulonglong found_rows() { return limit_found_rows; } |
| 168 | inline void found_rows(ulonglong rows) { limit_found_rows= rows; } |
| 169 | inline Query_cache_block *result() { return res; } |
| 170 | inline void result(Query_cache_block *p) { res= p; } |
| 171 | inline Query_cache_tls *writer() { return wri; } |
| 172 | inline void writer(Query_cache_tls *p) { wri= p; } |
| 173 | inline uint8 tables_type() { return tbls_type; } |
| 174 | inline void tables_type(uint8 type) { tbls_type= type; } |
| 175 | inline size_t length() { return len; } |
| 176 | inline size_t add(size_t packet_len) { return(len+= packet_len); } |
| 177 | inline void length(size_t length_arg) { len= length_arg; } |
| 178 | inline uchar* query() |
| 179 | { |
| 180 | return (((uchar*)this) + ALIGN_SIZE(sizeof(Query_cache_query))); |
| 181 | } |
| 182 | /** |
| 183 | following used to check if result ready in plugin without |
| 184 | locking rw_lock of the query. |
| 185 | */ |
| 186 | inline void set_results_ready() { ready= 1; } |
| 187 | inline bool is_results_ready() { return ready; } |
| 188 | inline void increment_hits() { hit_count++; } |
| 189 | inline ulonglong hits() { return hit_count; } |
| 190 | void lock_writing(); |
| 191 | void lock_reading(); |
| 192 | bool try_lock_writing(); |
| 193 | void unlock_writing(); |
| 194 | void unlock_reading(); |
| 195 | }; |
| 196 | |
| 197 | |
| 198 | struct Query_cache_table |
| 199 | { |
| 200 | Query_cache_table() {} /* Remove gcc warning */ |
| 201 | char *tbl; |
| 202 | uint32 key_len; |
| 203 | uint8 suffix_len; /* For partitioned tables */ |
| 204 | uint8 table_type; |
| 205 | /* unique for every engine reference */ |
| 206 | qc_engine_callback callback_func; |
| 207 | /* data need by some engines */ |
| 208 | ulonglong engine_data_buff; |
| 209 | |
| 210 | /** |
| 211 | The number of queries depending of this table. |
| 212 | */ |
| 213 | int32 m_cached_query_count; |
| 214 | /** |
| 215 | If table included in the table hash to be found by other queries |
| 216 | */ |
| 217 | my_bool hashed; |
| 218 | |
| 219 | inline char *db() { return (char *) data(); } |
| 220 | inline char *table() { return tbl; } |
| 221 | inline void table(char *table_arg) { tbl= table_arg; } |
| 222 | inline uint32 key_length() { return key_len; } |
| 223 | inline void key_length(uint32 len) { key_len= len; } |
| 224 | inline uint8 suffix_length() { return suffix_len; } |
| 225 | inline void suffix_length(uint8 len) { suffix_len= len; } |
| 226 | inline uint8 type() { return table_type; } |
| 227 | inline void type(uint8 t) { table_type= t; } |
| 228 | inline qc_engine_callback callback() { return callback_func; } |
| 229 | inline void callback(qc_engine_callback fn){ callback_func= fn; } |
| 230 | inline ulonglong engine_data() { return engine_data_buff; } |
| 231 | inline void engine_data(ulonglong data_arg){ engine_data_buff= data_arg; } |
| 232 | inline my_bool is_hashed() { return hashed; } |
| 233 | inline void set_hashed(my_bool hash) { hashed= hash; } |
| 234 | inline uchar* data() |
| 235 | { |
| 236 | return (uchar*)(((uchar*)this)+ |
| 237 | ALIGN_SIZE(sizeof(Query_cache_table))); |
| 238 | } |
| 239 | }; |
| 240 | |
| 241 | struct Query_cache_result |
| 242 | { |
| 243 | Query_cache_result() {} /* Remove gcc warning */ |
| 244 | Query_cache_block *query; |
| 245 | |
| 246 | inline uchar* data() |
| 247 | { |
| 248 | return (uchar*)(((uchar*) this)+ |
| 249 | ALIGN_SIZE(sizeof(Query_cache_result))); |
| 250 | } |
| 251 | /* data_continue (if not whole packet contained by this block) */ |
| 252 | inline Query_cache_block *parent() { return query; } |
| 253 | inline void parent (Query_cache_block *p) { query=p; } |
| 254 | }; |
| 255 | |
| 256 | |
| 257 | extern "C" |
| 258 | { |
| 259 | uchar *query_cache_query_get_key(const uchar *record, size_t *length, |
| 260 | my_bool not_used); |
| 261 | uchar *query_cache_table_get_key(const uchar *record, size_t *length, |
| 262 | my_bool not_used); |
| 263 | } |
| 264 | extern "C" void query_cache_invalidate_by_MyISAM_filename(const char* filename); |
| 265 | |
| 266 | |
| 267 | struct Query_cache_memory_bin |
| 268 | { |
| 269 | Query_cache_memory_bin() {} /* Remove gcc warning */ |
| 270 | #ifndef DBUG_OFF |
| 271 | size_t size; |
| 272 | #endif |
| 273 | uint number; |
| 274 | Query_cache_block *free_blocks; |
| 275 | |
| 276 | inline void init(size_t size_arg) |
| 277 | { |
| 278 | #ifndef DBUG_OFF |
| 279 | size = size_arg; |
| 280 | #endif |
| 281 | number = 0; |
| 282 | free_blocks = 0; |
| 283 | } |
| 284 | }; |
| 285 | |
| 286 | struct Query_cache_memory_bin_step |
| 287 | { |
| 288 | Query_cache_memory_bin_step() {} /* Remove gcc warning */ |
| 289 | size_t size; |
| 290 | size_t increment; |
| 291 | size_t idx; |
| 292 | inline void init(size_t size_arg, size_t idx_arg, size_t increment_arg) |
| 293 | { |
| 294 | size = size_arg; |
| 295 | idx = idx_arg; |
| 296 | increment = increment_arg; |
| 297 | } |
| 298 | }; |
| 299 | |
| 300 | class Query_cache |
| 301 | { |
| 302 | public: |
| 303 | /* Info */ |
| 304 | size_t query_cache_size, query_cache_limit; |
| 305 | /* statistics */ |
| 306 | size_t free_memory, queries_in_cache, hits, inserts, refused, |
| 307 | free_memory_blocks, total_blocks, lowmem_prunes; |
| 308 | |
| 309 | |
| 310 | private: |
| 311 | #ifndef DBUG_OFF |
| 312 | my_thread_id m_cache_lock_thread_id; |
| 313 | #endif |
| 314 | mysql_cond_t COND_cache_status_changed; |
| 315 | uint m_requests_in_progress; |
| 316 | enum Cache_lock_status { UNLOCKED, LOCKED_NO_WAIT, LOCKED }; |
| 317 | Cache_lock_status m_cache_lock_status; |
| 318 | enum Cache_staus {OK, DISABLE_REQUEST, DISABLED}; |
| 319 | Cache_staus m_cache_status; |
| 320 | |
| 321 | void free_query_internal(Query_cache_block *point); |
| 322 | void invalidate_table_internal(THD *thd, uchar *key, size_t key_length); |
| 323 | |
| 324 | protected: |
| 325 | /* |
| 326 | The following mutex is locked when searching or changing global |
| 327 | query, tables lists or hashes. When we are operating inside the |
| 328 | query structure we locked an internal query block mutex. |
| 329 | LOCK SEQUENCE (to prevent deadlocks): |
| 330 | 1. structure_guard_mutex |
| 331 | 2. query block (for operation inside query (query block/results)) |
| 332 | |
| 333 | Thread doing cache flush releases the mutex once it sets |
| 334 | m_cache_lock_status flag, so other threads may bypass the cache as |
| 335 | if it is disabled, not waiting for reset to finish. The exception |
| 336 | is other threads that were going to do cache flush---they'll wait |
| 337 | till the end of a flush operation. |
| 338 | */ |
| 339 | mysql_mutex_t structure_guard_mutex; |
| 340 | size_t additional_data_size; |
| 341 | uchar *cache; // cache memory |
| 342 | Query_cache_block *first_block; // physical location block list |
| 343 | Query_cache_block *queries_blocks; // query list (LIFO) |
| 344 | Query_cache_block *tables_blocks; |
| 345 | |
| 346 | Query_cache_memory_bin *bins; // free block lists |
| 347 | Query_cache_memory_bin_step *steps; // bins spacing info |
| 348 | HASH queries, tables; |
| 349 | /* options */ |
| 350 | size_t min_allocation_unit, min_result_data_size; |
| 351 | uint def_query_hash_size, def_table_hash_size; |
| 352 | |
| 353 | size_t mem_bin_num, mem_bin_steps; // See at init_cache & find_bin |
| 354 | |
| 355 | bool initialized; |
| 356 | |
| 357 | /* Exclude/include from cyclic double linked list */ |
| 358 | static void double_linked_list_exclude(Query_cache_block *point, |
| 359 | Query_cache_block **list_pointer); |
| 360 | static void double_linked_list_simple_include(Query_cache_block *point, |
| 361 | Query_cache_block ** |
| 362 | list_pointer); |
| 363 | static void double_linked_list_join(Query_cache_block *head_tail, |
| 364 | Query_cache_block *tail_head); |
| 365 | |
| 366 | /* The following functions require that structure_guard_mutex is locked */ |
| 367 | void flush_cache(); |
| 368 | my_bool free_old_query(); |
| 369 | void free_query(Query_cache_block *point); |
| 370 | my_bool allocate_data_chain(Query_cache_block **result_block, |
| 371 | size_t data_len, |
| 372 | Query_cache_block *query_block, |
| 373 | my_bool first_block); |
| 374 | void invalidate_table(THD *thd, TABLE_LIST *table); |
| 375 | void invalidate_table(THD *thd, TABLE *table); |
| 376 | void invalidate_table(THD *thd, uchar *key, size_t key_length); |
| 377 | void invalidate_table(THD *thd, Query_cache_block *table_block); |
| 378 | void invalidate_query_block_list(THD *thd, |
| 379 | Query_cache_block_table *list_root); |
| 380 | |
| 381 | TABLE_COUNTER_TYPE |
| 382 | register_tables_from_list(THD *thd, TABLE_LIST *tables_used, |
| 383 | TABLE_COUNTER_TYPE counter, |
| 384 | Query_cache_block_table **block_table); |
| 385 | my_bool register_all_tables(THD *thd, Query_cache_block *block, |
| 386 | TABLE_LIST *tables_used, |
| 387 | TABLE_COUNTER_TYPE tables); |
| 388 | void unlink_table(Query_cache_block_table *node); |
| 389 | Query_cache_block *get_free_block (size_t len, my_bool not_less, |
| 390 | size_t min); |
| 391 | void free_memory_block(Query_cache_block *point); |
| 392 | void split_block(Query_cache_block *block, size_t len); |
| 393 | Query_cache_block *join_free_blocks(Query_cache_block *first_block, |
| 394 | Query_cache_block *block_in_list); |
| 395 | my_bool append_next_free_block(Query_cache_block *block, |
| 396 | size_t add_size); |
| 397 | void exclude_from_free_memory_list(Query_cache_block *free_block); |
| 398 | void insert_into_free_memory_list(Query_cache_block *new_block); |
| 399 | my_bool move_by_type(uchar **border, Query_cache_block **before, |
| 400 | size_t *gap, Query_cache_block *i); |
| 401 | uint find_bin(size_t size); |
| 402 | void move_to_query_list_end(Query_cache_block *block); |
| 403 | void insert_into_free_memory_sorted_list(Query_cache_block *new_block, |
| 404 | Query_cache_block **list); |
| 405 | void pack_cache(); |
| 406 | void relink(Query_cache_block *oblock, |
| 407 | Query_cache_block *nblock, |
| 408 | Query_cache_block *next, |
| 409 | Query_cache_block *prev, |
| 410 | Query_cache_block *pnext, |
| 411 | Query_cache_block *pprev); |
| 412 | my_bool join_results(size_t join_limit); |
| 413 | |
| 414 | /* |
| 415 | Following function control structure_guard_mutex |
| 416 | by themself or don't need structure_guard_mutex |
| 417 | */ |
| 418 | size_t init_cache(); |
| 419 | void make_disabled(); |
| 420 | void free_cache(); |
| 421 | Query_cache_block *write_block_data(size_t data_len, uchar* data, |
| 422 | size_t , |
| 423 | Query_cache_block::block_type type, |
| 424 | TABLE_COUNTER_TYPE ntab = 0); |
| 425 | my_bool append_result_data(Query_cache_block **result, |
| 426 | size_t data_len, uchar* data, |
| 427 | Query_cache_block *parent); |
| 428 | my_bool write_result_data(Query_cache_block **result, |
| 429 | size_t data_len, uchar* data, |
| 430 | Query_cache_block *parent, |
| 431 | Query_cache_block::block_type |
| 432 | type=Query_cache_block::RESULT); |
| 433 | inline size_t get_min_first_result_data_size(); |
| 434 | inline size_t get_min_append_result_data_size(); |
| 435 | Query_cache_block *allocate_block(size_t len, my_bool not_less, |
| 436 | size_t min); |
| 437 | /* |
| 438 | If query is cacheable return number tables in query |
| 439 | (query without tables not cached) |
| 440 | */ |
| 441 | TABLE_COUNTER_TYPE is_cacheable(THD *thd, |
| 442 | LEX *lex, TABLE_LIST *tables_used, |
| 443 | uint8 *tables_type); |
| 444 | TABLE_COUNTER_TYPE process_and_count_tables(THD *thd, |
| 445 | TABLE_LIST *tables_used, |
| 446 | uint8 *tables_type); |
| 447 | |
| 448 | static my_bool ask_handler_allowance(THD *thd, TABLE_LIST *tables_used); |
| 449 | public: |
| 450 | |
| 451 | Query_cache(size_t query_cache_limit = ULONG_MAX, |
| 452 | size_t min_allocation_unit = QUERY_CACHE_MIN_ALLOCATION_UNIT, |
| 453 | size_t min_result_data_size = QUERY_CACHE_MIN_RESULT_DATA_SIZE, |
| 454 | uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE, |
| 455 | uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE); |
| 456 | |
| 457 | inline bool is_disabled(void) { return m_cache_status != OK; } |
| 458 | inline bool is_disable_in_progress(void) |
| 459 | { return m_cache_status == DISABLE_REQUEST; } |
| 460 | |
| 461 | /* initialize cache (mutex) */ |
| 462 | void init(); |
| 463 | /* resize query cache (return real query size, 0 if disabled) */ |
| 464 | size_t resize(size_t query_cache_size); |
| 465 | /* set limit on result size */ |
| 466 | inline void result_size_limit(size_t limit){query_cache_limit=limit;} |
| 467 | /* set minimal result data allocation unit size */ |
| 468 | size_t set_min_res_unit(size_t size); |
| 469 | |
| 470 | /* register query in cache */ |
| 471 | void store_query(THD *thd, TABLE_LIST *used_tables); |
| 472 | |
| 473 | /* |
| 474 | Check if the query is in the cache and if this is true send the |
| 475 | data to client. |
| 476 | */ |
| 477 | int send_result_to_client(THD *thd, char *query, uint query_length); |
| 478 | |
| 479 | /* Remove all queries that uses any of the listed following tables */ |
| 480 | void invalidate(THD *thd, TABLE_LIST *tables_used, |
| 481 | my_bool using_transactions); |
| 482 | void invalidate(THD *thd, CHANGED_TABLE_LIST *tables_used); |
| 483 | void invalidate_locked_for_write(THD *thd, TABLE_LIST *tables_used); |
| 484 | void invalidate(THD *thd, TABLE *table, my_bool using_transactions); |
| 485 | void invalidate(THD *thd, const char *key, size_t key_length, |
| 486 | my_bool using_transactions); |
| 487 | |
| 488 | /* Remove all queries that uses any of the tables in following database */ |
| 489 | void invalidate(THD *thd, const char *db); |
| 490 | |
| 491 | /* Remove all queries that uses any of the listed following table */ |
| 492 | void invalidate_by_MyISAM_filename(const char *filename); |
| 493 | |
| 494 | void flush(); |
| 495 | void pack(THD *thd, |
| 496 | size_t join_limit = QUERY_CACHE_PACK_LIMIT, |
| 497 | uint iteration_limit = QUERY_CACHE_PACK_ITERATION); |
| 498 | |
| 499 | void destroy(); |
| 500 | |
| 501 | void insert(THD *thd, Query_cache_tls *query_cache_tls, |
| 502 | const char *packet, |
| 503 | size_t length, |
| 504 | unsigned pkt_nr); |
| 505 | my_bool insert_table(THD *thd, size_t key_len, const char *key, |
| 506 | Query_cache_block_table *node, |
| 507 | size_t db_length, uint8 suffix_length_arg, |
| 508 | uint8 cache_type, |
| 509 | qc_engine_callback callback, |
| 510 | ulonglong engine_data, |
| 511 | my_bool hash); |
| 512 | |
| 513 | void end_of_result(THD *thd); |
| 514 | void abort(THD *thd, Query_cache_tls *query_cache_tls); |
| 515 | |
| 516 | /* |
| 517 | The following functions are only used when debugging |
| 518 | We don't protect these with ifndef DBUG_OFF to not have to recompile |
| 519 | everything if we want to add checks of the cache at some places. |
| 520 | */ |
| 521 | void wreck(uint line, const char *message); |
| 522 | void bins_dump(); |
| 523 | void cache_dump(); |
| 524 | void queries_dump(); |
| 525 | void tables_dump(); |
| 526 | my_bool check_integrity(bool not_locked); |
| 527 | my_bool in_list(Query_cache_block * root, Query_cache_block * point, |
| 528 | const char *name); |
| 529 | my_bool in_table_list(Query_cache_block_table * root, |
| 530 | Query_cache_block_table * point, |
| 531 | const char *name); |
| 532 | my_bool in_blocks(Query_cache_block * point); |
| 533 | |
| 534 | /* Table key generation */ |
| 535 | static uint filename_2_table_key (char *key, const char *filename, |
| 536 | uint32 *db_langth); |
| 537 | |
| 538 | enum Cache_try_lock_mode {WAIT, TIMEOUT, TRY}; |
| 539 | bool try_lock(THD *thd, Cache_try_lock_mode mode= WAIT); |
| 540 | void lock(THD *thd); |
| 541 | void lock_and_suspend(void); |
| 542 | void unlock(void); |
| 543 | |
| 544 | void disable_query_cache(THD *thd); |
| 545 | }; |
| 546 | |
| 547 | #ifdef HAVE_QUERY_CACHE |
| 548 | struct Query_cache_query_flags |
| 549 | { |
| 550 | unsigned int client_long_flag:1; |
| 551 | unsigned int client_protocol_41:1; |
| 552 | unsigned int client_depr_eof:1; |
| 553 | unsigned int protocol_type:2; |
| 554 | unsigned int more_results_exists:1; |
| 555 | unsigned int in_trans:1; |
| 556 | unsigned int autocommit:1; |
| 557 | unsigned int pkt_nr; |
| 558 | uint character_set_client_num; |
| 559 | uint character_set_results_num; |
| 560 | uint collation_connection_num; |
| 561 | ha_rows limit; |
| 562 | Time_zone *time_zone; |
| 563 | sql_mode_t sql_mode; |
| 564 | ulonglong max_sort_length; |
| 565 | ulonglong group_concat_max_len; |
| 566 | size_t default_week_format; |
| 567 | size_t div_precision_increment; |
| 568 | MY_LOCALE *lc_time_names; |
| 569 | }; |
| 570 | #define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags) |
| 571 | #define QUERY_CACHE_DB_LENGTH_SIZE 2 |
| 572 | #include "sql_cache.h" |
| 573 | #define query_cache_abort(A,B) query_cache.abort(A,B) |
| 574 | #define query_cache_end_of_result(A) query_cache.end_of_result(A) |
| 575 | #define query_cache_store_query(A, B) query_cache.store_query(A, B) |
| 576 | #define query_cache_destroy() query_cache.destroy() |
| 577 | #define query_cache_result_size_limit(A) query_cache.result_size_limit(A) |
| 578 | #define query_cache_init() query_cache.init() |
| 579 | #define query_cache_resize(A) query_cache.resize(A) |
| 580 | #define query_cache_set_min_res_unit(A) query_cache.set_min_res_unit(A) |
| 581 | #define query_cache_invalidate3(A, B, C) query_cache.invalidate(A, B, C) |
| 582 | #define query_cache_invalidate1(A, B) query_cache.invalidate(A, B) |
| 583 | #define query_cache_send_result_to_client(A, B, C) \ |
| 584 | query_cache.send_result_to_client(A, B, C) |
| 585 | #define query_cache_invalidate_by_MyISAM_filename_ref \ |
| 586 | &query_cache_invalidate_by_MyISAM_filename |
| 587 | /* note the "maybe": it's a read without mutex */ |
| 588 | #define query_cache_maybe_disabled(T) \ |
| 589 | (T->variables.query_cache_type == 0 || query_cache.query_cache_size == 0) |
| 590 | #define query_cache_is_cacheable_query(L) \ |
| 591 | (((L)->sql_command == SQLCOM_SELECT) && (L)->safe_to_cache_query) |
| 592 | #else |
| 593 | #define QUERY_CACHE_FLAGS_SIZE 0 |
| 594 | #define query_cache_store_query(A, B) do { } while(0) |
| 595 | #define query_cache_destroy() do { } while(0) |
| 596 | #define query_cache_result_size_limit(A) do { } while(0) |
| 597 | #define query_cache_init() do { } while(0) |
| 598 | #define query_cache_resize(A) do { } while(0) |
| 599 | #define query_cache_set_min_res_unit(A) do { } while(0) |
| 600 | #define query_cache_invalidate3(A, B, C) do { } while(0) |
| 601 | #define query_cache_invalidate1(A,B) do { } while(0) |
| 602 | #define query_cache_send_result_to_client(A, B, C) 0 |
| 603 | #define query_cache_invalidate_by_MyISAM_filename_ref NULL |
| 604 | |
| 605 | #define query_cache_abort(A,B) do { } while(0) |
| 606 | #define query_cache_end_of_result(A) do { } while(0) |
| 607 | #define query_cache_maybe_disabled(T) 1 |
| 608 | #define query_cache_is_cacheable_query(L) 0 |
| 609 | #endif /*HAVE_QUERY_CACHE*/ |
| 610 | |
| 611 | extern Query_cache query_cache; |
| 612 | #endif |
| 613 | |