1 /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights
2 reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation,
22 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
23
24 /*
25 Description of the query cache:
26
27 1. Query_cache object consists of
28 - query cache memory pool (cache)
29 - queries hash (queries)
30 - tables hash (tables)
31 - list of blocks ordered as they allocated in memory
32 (first_block)
33 - list of queries block (queries_blocks)
34 - list of used tables (tables_blocks)
35
36 2. Query cache memory pool (cache) consists of
37 - table of steps of memory bins allocation
38 - table of free memory bins
39 - blocks of memory
40
41 3. Memory blocks
42
43 Every memory block has the following structure:
44
45 +----------------------------------------------------------+
46 | Block header (Query_cache_block structure) |
47 +----------------------------------------------------------+
48 |Table of database table lists (used for queries & tables) |
49 +----------------------------------------------------------+
50 | Type depended header |
51 |(Query_cache_query, Query_cache_table, Query_cache_result)|
52 +----------------------------------------------------------+
53 | Data ... |
54 +----------------------------------------------------------+
55
56 Block header consists of:
57 - type:
58 FREE Free memory block
59 QUERY Query block
60 RESULT Ready to send result
61 RES_CONT Result's continuation
62 RES_BEG First block of results, that is not yet complete,
63 written to cache
64 RES_INCOMPLETE Allocated for results data block
65 TABLE Block with database table description
66 INCOMPLETE The destroyed block
67 - length of block (length)
68 - length of data & headers (used)
69 - physical list links (pnext/pprev) - used for the list of
70 blocks ordered as they are allocated in physical memory
71 - logical list links (next/prev) - used for queries block list, tables block
72 list, free memory block lists and list of results block in query
73 - number of elements in table of database table list (n_tables)
74
75 4. Query & results blocks
76
77 Query stored in cache consists of following blocks:
78
79 more more
80 recent+-------------+ old
81 <-----|Query block 1|------> double linked list of queries block
82 prev | | next
83 +-------------+
84 <-| table 0 |-> (see "Table of database table lists" description)
85 <-| table 1 |->
86 | ... | +--------------------------+
87 +-------------+ +-------------------------+ |
88 NET | | | V V |
89 struct| | +-+------------+ +------------+ |
90 <-----|query header |----->|Result block|-->|Result block|-+ doublelinked
91 writer| |result| |<--| | list of results
92 +-------------+ +------------+ +------------+
93 |charset | +------------+ +------------+ no table of dbtables
94 |encoding + | | result | | result |
95 |query text |<-----| header | | header |------+
96 +-------------+parent| | | |parent|
97 ^ +------------+ +------------+ |
98 | |result data | |result data | |
99 | +------------+ +------------+ |
100 +---------------------------------------------------+
101
102 First query is registered. During the registration query block is
103 allocated. This query block is included in query hash and is linked
104 with appropriate database tables lists (if there is no appropriate
105 list exists it will be created).
106
107 Later when query has performed results is written into the result blocks.
108 A result block cannot be smaller then QUERY_CACHE_MIN_RESULT_DATA_SIZE.
109
110 When new result is written to cache it is appended to the last result
111 block, if no more free space left in the last block, new block is
112 allocated.
113
114 5. Table of database table lists.
115
116 For quick invalidation of queries all query are linked in lists on used
117 database tables basis (when table will be changed (insert/delete/...)
118 this queries will be removed from cache).
119
120 Root of such list is table block:
121
122 +------------+ list of used tables (used while invalidation of
123 <----| Table |-----> whole database)
124 prev| block |next +-----------+
125 | | +-----------+ |Query block|
126 | | |Query block| +-----------+
127 +------------+ +-----------+ | ... |
128 +->| table 0 |------>|table 0 |----->| table N |---+
129 |+-| |<------| |<-----| |<-+|
130 || +------------+ | ... | | ... | ||
131 || |table header| +-----------+ +-----------+ ||
132 || +------------+ | ... | | ... | ||
133 || |db name + | +-----------+ +-----------+ ||
134 || |table name | ||
135 || +------------+ ||
136 |+--------------------------------------------------------+|
137 +----------------------------------------------------------+
138
139 Table block is included into the tables hash (tables).
140
141 6. Free blocks, free blocks bins & steps of freeblock bins.
142
143 When we just started only one free memory block existed. All query
144 cache memory (that will be used for block allocation) were
145 containing in this block.
146 When a new block is allocated we find most suitable memory block
147 (minimal of >= required size). If such a block can not be found, we try
148 to find max block < required size (if we allocate block for results).
149 If there is no free memory, oldest query is removed from cache, and then
150 we try to allocate memory. Last step should be repeated until we find
151 suitable block or until there is no unlocked query found.
152
153 If the block is found and its length more then we need, it should be
154 split into 2 blocks.
155 New blocks cannot be smaller then min_allocation_unit_bytes.
156
157 When a block becomes free, its neighbor-blocks should be tested and if
158 there are free blocks among them, they should be joined into one block.
159
160 Free memory blocks are stored in bins according to their sizes.
161 The bins are stored in size-descending order.
162 These bins are distributed (by size) approximately logarithmically.
163
164 First bin (number 0) stores free blocks with
165 size <= query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2.
166 It is first (number 0) step.
167 On the next step distributed (1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
168 QUERY_CACHE_MEM_BIN_PARTS_MUL bins. This bins allocated in interval from
169 query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 to
170 query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 >>
171 QUERY_CACHE_MEM_BIN_STEP_PWR2
172 ...
173 On each step interval decreases in 2 power of
174 QUERY_CACHE_MEM_BIN_STEP_PWR2
175 times, number of bins (that distributed on this step) increases. If on
176 the previous step there were N bins distributed , on the current there
177 would be distributed
178 (N + QUERY_CACHE_MEM_BIN_PARTS_INC) * QUERY_CACHE_MEM_BIN_PARTS_MUL
179 bins.
180 Last distributed bin stores blocks with size near min_allocation_unit
181 bytes.
182
183 For example:
184 query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 = 100,
185 min_allocation_unit = 17,
186 QUERY_CACHE_MEM_BIN_STEP_PWR2 = 1,
187 QUERY_CACHE_MEM_BIN_PARTS_INC = 1,
188 QUERY_CACHE_MEM_BIN_PARTS_MUL = 1
189 (in followed picture showed right (low) bound of bin):
190
191 | 100>>1 50>>1 |25>>1|
192 | | | | | |
193 | 100 75 50 41 33 25 21 18 15| 12 | - bins right (low) bounds
194
195 |\---/\-----/\--------/\--------|---/ |
196 | 0 1 2 3 | | - steps
197 \-----------------------------/ \---/
198 bins that we store in cache this bin showed for example only
199
200
201 Calculation of steps/bins distribution is performed only when query cache
202 is resized.
203
204 When we need to find appropriate bin, first we should find appropriate
205 step, then we should calculate number of bins that are using data
206 stored in Query_cache_memory_bin_step structure.
207
208 Free memory blocks are sorted in bins in lists with size-ascending order
209 (more small blocks needed frequently then bigger one).
210
211 7. Packing cache.
212
213 Query cache packing is divided into two operation:
214 - pack_cache
215 - join_results
216
217 pack_cache moved all blocks to "top" of cache and create one block of free
218 space at the "bottom":
219
220 before pack_cache after pack_cache
221 +-------------+ +-------------+
222 | query 1 | | query 1 |
223 +-------------+ +-------------+
224 | table 1 | | table 1 |
225 +-------------+ +-------------+
226 | results 1.1 | | results 1.1 |
227 +-------------+ +-------------+
228 | free | | query 2 |
229 +-------------+ +-------------+
230 | query 2 | | table 2 |
231 +-------------+ ---> +-------------+
232 | table 2 | | results 1.2 |
233 +-------------+ +-------------+
234 | results 1.2 | | results 2 |
235 +-------------+ +-------------+
236 | free | | free |
237 +-------------+ | |
238 | results 2 | | |
239 +-------------+ | |
240 | free | | |
241 +-------------+ +-------------+
242
243 pack_cache scan blocks in physical address order and move every non-free
244 block "higher".
245
246 pack_cach remove every free block it finds. The length of the deleted block
247 is accumulated to the "gap". All non free blocks should be shifted with the
248 "gap" step.
249
250 join_results scans all complete queries. If the results of query are not
251 stored in the same block, join_results tries to move results so, that they
252 are stored in one block.
253
254 before join_results after join_results
255 +-------------+ +-------------+
256 | query 1 | | query 1 |
257 +-------------+ +-------------+
258 | table 1 | | table 1 |
259 +-------------+ +-------------+
260 | results 1.1 | | free |
261 +-------------+ +-------------+
262 | query 2 | | query 2 |
263 +-------------+ +-------------+
264 | table 2 | | table 2 |
265 +-------------+ ---> +-------------+
266 | results 1.2 | | free |
267 +-------------+ +-------------+
268 | results 2 | | results 2 |
269 +-------------+ +-------------+
270 | free | | results 1 |
271 | | | |
272 | | +-------------+
273 | | | free |
274 | | | |
275 +-------------+ +-------------+
276
277 If join_results allocated new block(s) then we need call pack_cache again.
278
279 7. Interface
280 The query cache interfaces with the rest of the server code through 7
281 functions:
282 1. Query_cache::send_result_to_client
283 - Called before parsing and used to match a statement with the stored
284 queries hash.
285 If a match is found the cached result set is sent through repeated
286 calls to net_write_packet. (note: calling thread doesn't have a regis-
287 tered result set writer: thd->net.query_cache_query=0)
288 2. Query_cache::store_query
289 - Called just before handle_select() and is used to register a result
290 set writer to the statement currently being processed
291 (thd->net.query_cache_query).
292 3. query_cache_insert
293 - Called from net_write_packet to append a result set to a cached query
294 if (and only if) this query has a registered result set writer
295 (thd->net.query_cache_query).
296 4. Query_cache::invalidate
297 Query_cache::invalidate_locked_for_write
298 - Called from various places to invalidate query cache based on data-
299 base, table and myisam file name. During an on going invalidation
300 the query cache is temporarily disabled.
301 5. Query_cache::flush
302 - Used when a RESET QUERY CACHE is issued. This clears the entire
303 cache block by block.
304 6. Query_cache::resize
305 - Used to change the available memory used by the query cache. This
306 will also invalidate the entrie query cache in one free operation.
307 7. Query_cache::pack
308 - Used when a FLUSH QUERY CACHE is issued. This changes the order of
309 the used memory blocks in physical memory order and move all avail-
310 able memory to the 'bottom' of the memory.
311
312
313 TODO list:
314
315 - Delayed till after-parsing qache answer (for column rights processing)
316 - Optimize cache resizing
317 - if new_size < old_size then pack & shrink
318 - if new_size > old_size copy cached query to new cache
319 - Move MRG_MYISAM table type processing to handlers, something like:
320 tables_used->table->file->register_used_filenames(callback,
321 first_argument);
322 - QC improvement suggested by Monty:
323 - Add a counter in open_table() for how many MERGE (ISAM or MyISAM)
324 tables are cached in the table cache.
325 (This will be trivial when we have the new table cache in place I
326 have been working on)
327 - After this we can add the following test around the for loop in
328 is_cacheable::
329
330 if (thd->temp_tables || global_merge_table_count)
331
332 - Another option would be to set thd->lex->safe_to_cache_query to 0
333 in 'get_lock_data' if any of the tables was a tmp table or a
334 MRG_ISAM table.
335 (This could be done with almost no speed penalty)
336 */
337
338 #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
339 #include "sql_priv.h"
340 #include "sql_cache.h"
341 #include "sql_parse.h" // check_table_access
342 #include "tztime.h" // struct Time_zone
343 #include "sql_acl.h" // SELECT_ACL
344 #include "sql_base.h" // TMP_TABLE_KEY_EXTRA
345 #include "debug_sync.h" // DEBUG_SYNC
346 #include "opt_trace.h"
347 #include "sql_table.h"
348 #ifdef HAVE_QUERY_CACHE
349 #include <m_ctype.h>
350 #include <my_dir.h>
351 #include <hash.h>
352 #include "../storage/myisammrg/ha_myisammrg.h"
353 #include "../storage/myisammrg/myrg_def.h"
354 #include "probes_mysql.h"
355 #include "transaction.h"
356
357 #ifdef EMBEDDED_LIBRARY
358 #include "emb_qcache.h"
359 #endif
360
361 using std::min;
362 using std::max;
363
364 #if !defined(EXTRA_DBUG) && !defined(DBUG_OFF)
365 #define RW_WLOCK(M) {DBUG_PRINT("lock", ("rwlock wlock 0x%lx",(ulong)(M))); \
366 if (!mysql_rwlock_wrlock(M)) DBUG_PRINT("lock", ("rwlock wlock ok")); \
367 else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); }
368 #define RW_RLOCK(M) {DBUG_PRINT("lock", ("rwlock rlock 0x%lx", (ulong)(M))); \
369 if (!mysql_rwlock_rdlock(M)) DBUG_PRINT("lock", ("rwlock rlock ok")); \
370 else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); }
371 #define RW_UNLOCK(M) {DBUG_PRINT("lock", ("rwlock unlock 0x%lx",(ulong)(M))); \
372 if (!mysql_rwlock_unlock(M)) DBUG_PRINT("lock", ("rwlock unlock ok")); \
373 else DBUG_PRINT("lock", ("rwlock unlock FAILED %d", errno)); }
374 #define BLOCK_LOCK_WR(B) {DBUG_PRINT("lock", ("%d LOCK_WR 0x%lx",\
375 __LINE__,(ulong)(B))); \
376 B->query()->lock_writing();}
377 #define BLOCK_LOCK_RD(B) {DBUG_PRINT("lock", ("%d LOCK_RD 0x%lx",\
378 __LINE__,(ulong)(B))); \
379 B->query()->lock_reading();}
380 #define BLOCK_UNLOCK_WR(B) { \
381 DBUG_PRINT("lock", ("%d UNLOCK_WR 0x%lx",\
382 __LINE__,(ulong)(B)));B->query()->unlock_writing();}
383 #define BLOCK_UNLOCK_RD(B) { \
384 DBUG_PRINT("lock", ("%d UNLOCK_RD 0x%lx",\
385 __LINE__,(ulong)(B)));B->query()->unlock_reading();}
386 #define DUMP(C) DBUG_EXECUTE("qcache", {\
387 (C)->cache_dump(); (C)->queries_dump();(C)->tables_dump();})
388 #else
389 #define RW_WLOCK(M) mysql_rwlock_wrlock(M)
390 #define RW_RLOCK(M) mysql_rwlock_rdlock(M)
391 #define RW_UNLOCK(M) mysql_rwlock_unlock(M)
392 #define BLOCK_LOCK_WR(B) B->query()->lock_writing()
393 #define BLOCK_LOCK_RD(B) B->query()->lock_reading()
394 #define BLOCK_UNLOCK_WR(B) B->query()->unlock_writing()
395 #define BLOCK_UNLOCK_RD(B) B->query()->unlock_reading()
396 #define DUMP(C)
397 #endif
398
399
400 /**
401 Macro that executes the requested action at a synchronization point
402 only if the thread has a associated THD session.
403 */
404 #if defined(ENABLED_DEBUG_SYNC)
405 #define QC_DEBUG_SYNC(name) \
406 do { \
407 THD *thd= current_thd; \
408 if (thd) \
409 DEBUG_SYNC(thd, name); \
410 } while (0)
411 #else
412 #define QC_DEBUG_SYNC(name)
413 #endif
414
415 // Max aligned size for ulong type query_cache_min_res_unit.
416 static const ulong max_aligned_min_res_unit_size= ((ULONG_MAX) &
417 (~(sizeof(double) - 1)));
418
419 /**
420 Thread state to be used when the query cache lock needs to be acquired.
421 Sets the thread state name in the constructor, resets on destructor.
422 */
423
424 struct Query_cache_wait_state
425 {
426 THD *m_thd;
427 PSI_stage_info m_old_stage;
428 const char *m_func;
429 const char *m_file;
430 int m_line;
431
Query_cache_wait_stateQuery_cache_wait_state432 Query_cache_wait_state(THD *thd, const char *func,
433 const char *file, unsigned int line)
434 : m_thd(thd),
435 m_old_stage(),
436 m_func(func), m_file(file), m_line(line)
437 {
438 if (m_thd)
439 set_thd_stage_info(m_thd,
440 &stage_waiting_for_query_cache_lock,
441 &m_old_stage,
442 m_func, m_file, m_line);
443 }
444
~Query_cache_wait_stateQuery_cache_wait_state445 ~Query_cache_wait_state()
446 {
447 if (m_thd)
448 set_thd_stage_info(m_thd, &m_old_stage, NULL, m_func, m_file, m_line);
449 }
450 };
451
452
453 /**
454 Serialize access to the query cache.
455 If the lock cannot be granted the thread hangs in a conditional wait which
456 is signalled on each unlock.
457
458 The lock attempt will also fail without wait if lock_and_suspend() is in
459 effect by another thread. This enables a quick path in execution to skip waits
460 when the outcome is known.
461
462 @param use_timeout TRUE if the lock can abort because of a timeout.
463
464 @note use_timeout is optional and default value is FALSE.
465
466 @return
467 @retval FALSE An exclusive lock was taken
468 @retval TRUE The locking attempt failed
469 */
470
try_lock(bool use_timeout)471 bool Query_cache::try_lock(bool use_timeout)
472 {
473 bool interrupt= FALSE;
474 THD *thd= current_thd;
475 Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
476 DBUG_ENTER("Query_cache::try_lock");
477
478 mysql_mutex_lock(&structure_guard_mutex);
479 while (1)
480 {
481 if (m_cache_lock_status == Query_cache::UNLOCKED)
482 {
483 m_cache_lock_status= Query_cache::LOCKED;
484 #ifndef DBUG_OFF
485 if (thd)
486 m_cache_lock_thread_id= thd->thread_id;
487 #endif
488 break;
489 }
490 else if (m_cache_lock_status == Query_cache::LOCKED_NO_WAIT)
491 {
492 /*
493 If query cache is protected by a LOCKED_NO_WAIT lock this thread
494 should avoid using the query cache as it is being evicted.
495 */
496 interrupt= TRUE;
497 break;
498 }
499 else
500 {
501 DBUG_ASSERT(m_cache_lock_status == Query_cache::LOCKED);
502 /*
503 To prevent send_result_to_client() and query_cache_insert() from
504 blocking execution for too long a timeout is put on the lock.
505 */
506 if (use_timeout)
507 {
508 struct timespec waittime;
509 set_timespec_nsec(waittime,(ulong)(50000000L)); /* Wait for 50 msec */
510 int res= mysql_cond_timedwait(&COND_cache_status_changed,
511 &structure_guard_mutex, &waittime);
512 if (res == ETIMEDOUT)
513 {
514 interrupt= TRUE;
515 break;
516 }
517 }
518 else
519 {
520 mysql_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
521 }
522 }
523 }
524 mysql_mutex_unlock(&structure_guard_mutex);
525
526 DBUG_RETURN(interrupt);
527 }
528
529
530 /**
531 Serialize access to the query cache.
532 If the lock cannot be granted the thread hangs in a conditional wait which
533 is signalled on each unlock.
534
535 This method also suspends the query cache so that other threads attempting to
536 lock the cache with try_lock() will fail directly without waiting.
537
538 It is used by all methods which flushes or destroys the whole cache.
539 */
540
lock_and_suspend(void)541 void Query_cache::lock_and_suspend(void)
542 {
543 THD *thd= current_thd;
544 Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
545 DBUG_ENTER("Query_cache::lock_and_suspend");
546
547 mysql_mutex_lock(&structure_guard_mutex);
548 while (m_cache_lock_status != Query_cache::UNLOCKED)
549 mysql_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
550 m_cache_lock_status= Query_cache::LOCKED_NO_WAIT;
551 #ifndef DBUG_OFF
552 if (thd)
553 m_cache_lock_thread_id= thd->thread_id;
554 #endif
555 /* Wake up everybody, a whole cache flush is starting! */
556 mysql_cond_broadcast(&COND_cache_status_changed);
557 mysql_mutex_unlock(&structure_guard_mutex);
558
559 DBUG_VOID_RETURN;
560 }
561
562 /**
563 Serialize access to the query cache.
564 If the lock cannot be granted the thread hangs in a conditional wait which
565 is signalled on each unlock.
566
567 It is used by all methods which invalidates one or more tables.
568 */
569
lock(void)570 void Query_cache::lock(void)
571 {
572 THD *thd= current_thd;
573 Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
574 DBUG_ENTER("Query_cache::lock");
575
576 mysql_mutex_lock(&structure_guard_mutex);
577 while (m_cache_lock_status != Query_cache::UNLOCKED)
578 mysql_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
579 m_cache_lock_status= Query_cache::LOCKED;
580 #ifndef DBUG_OFF
581 if (thd)
582 m_cache_lock_thread_id= thd->thread_id;
583 #endif
584 mysql_mutex_unlock(&structure_guard_mutex);
585
586 DBUG_VOID_RETURN;
587 }
588
589
590 /**
591 Set the query cache to UNLOCKED and signal waiting threads.
592 */
593
unlock(void)594 void Query_cache::unlock(void)
595 {
596 DBUG_ENTER("Query_cache::unlock");
597 mysql_mutex_lock(&structure_guard_mutex);
598 #ifndef DBUG_OFF
599 THD *thd= current_thd;
600 if (thd)
601 DBUG_ASSERT(m_cache_lock_thread_id == thd->thread_id);
602 #endif
603 DBUG_ASSERT(m_cache_lock_status == Query_cache::LOCKED ||
604 m_cache_lock_status == Query_cache::LOCKED_NO_WAIT);
605 m_cache_lock_status= Query_cache::UNLOCKED;
606 DBUG_PRINT("Query_cache",("Sending signal"));
607 mysql_cond_signal(&COND_cache_status_changed);
608 mysql_mutex_unlock(&structure_guard_mutex);
609 DBUG_VOID_RETURN;
610 }
611
612
613 /**
614 Helper function for determine if a SELECT statement has a SQL_NO_CACHE
615 directive.
616
617 @param sql A pointer to the first white space character after SELECT
618
619 @return
620 @retval TRUE The character string contains SQL_NO_CACHE
621 @retval FALSE No directive found.
622 */
623
has_no_cache_directive(char * sql)624 static bool has_no_cache_directive(char *sql)
625 {
626 int i=0;
627 while (sql[i] == ' ')
628 ++i;
629
630 if (my_toupper(system_charset_info, sql[i]) == 'S' &&
631 my_toupper(system_charset_info, sql[i+1]) == 'Q' &&
632 my_toupper(system_charset_info, sql[i+2]) == 'L' &&
633 my_toupper(system_charset_info, sql[i+3]) == '_' &&
634 my_toupper(system_charset_info, sql[i+4]) == 'N' &&
635 my_toupper(system_charset_info, sql[i+5]) == 'O' &&
636 my_toupper(system_charset_info, sql[i+6]) == '_' &&
637 my_toupper(system_charset_info, sql[i+7]) == 'C' &&
638 my_toupper(system_charset_info, sql[i+8]) == 'A' &&
639 my_toupper(system_charset_info, sql[i+9]) == 'C' &&
640 my_toupper(system_charset_info, sql[i+10]) == 'H' &&
641 my_toupper(system_charset_info, sql[i+11]) == 'E' &&
642 my_toupper(system_charset_info, sql[i+12]) == ' ')
643 return TRUE;
644
645 return FALSE;
646 }
647
648
649 /*****************************************************************************
650 Query_cache_block_table method(s)
651 *****************************************************************************/
652
block()653 inline Query_cache_block * Query_cache_block_table::block()
654 {
655 return (Query_cache_block *)(((uchar*)this) -
656 ALIGN_SIZE(sizeof(Query_cache_block_table)*n) -
657 ALIGN_SIZE(sizeof(Query_cache_block)));
658 }
659
660 /*****************************************************************************
661 Query_cache_block method(s)
662 *****************************************************************************/
663
init(ulong block_length)664 void Query_cache_block::init(ulong block_length)
665 {
666 DBUG_ENTER("Query_cache_block::init");
667 DBUG_PRINT("qcache", ("init block: 0x%lx length: %lu", (ulong) this,
668 block_length));
669 length = block_length;
670 used = 0;
671 type = Query_cache_block::FREE;
672 n_tables = 0;
673 DBUG_VOID_RETURN;
674 }
675
destroy()676 void Query_cache_block::destroy()
677 {
678 DBUG_ENTER("Query_cache_block::destroy");
679 DBUG_PRINT("qcache", ("destroy block 0x%lx, type %d",
680 (ulong) this, type));
681 type = INCOMPLETE;
682 DBUG_VOID_RETURN;
683 }
684
headers_len()685 inline uint Query_cache_block::headers_len()
686 {
687 return (ALIGN_SIZE(sizeof(Query_cache_block_table)*n_tables) +
688 ALIGN_SIZE(sizeof(Query_cache_block)));
689 }
690
data(void)691 inline uchar* Query_cache_block::data(void)
692 {
693 return (uchar*)( ((uchar*)this) + headers_len() );
694 }
695
query()696 inline Query_cache_query * Query_cache_block::query()
697 {
698 #ifndef DBUG_OFF
699 if (type != QUERY)
700 query_cache.wreck(__LINE__, "incorrect block type");
701 #endif
702 return (Query_cache_query *) data();
703 }
704
table()705 inline Query_cache_table * Query_cache_block::table()
706 {
707 #ifndef DBUG_OFF
708 if (type != TABLE)
709 query_cache.wreck(__LINE__, "incorrect block type");
710 #endif
711 return (Query_cache_table *) data();
712 }
713
result()714 inline Query_cache_result * Query_cache_block::result()
715 {
716 #ifndef DBUG_OFF
717 if (type != RESULT && type != RES_CONT && type != RES_BEG &&
718 type != RES_INCOMPLETE)
719 query_cache.wreck(__LINE__, "incorrect block type");
720 #endif
721 return (Query_cache_result *) data();
722 }
723
table(TABLE_COUNTER_TYPE n)724 inline Query_cache_block_table * Query_cache_block::table(TABLE_COUNTER_TYPE n)
725 {
726 return ((Query_cache_block_table *)
727 (((uchar*)this)+ALIGN_SIZE(sizeof(Query_cache_block)) +
728 n*sizeof(Query_cache_block_table)));
729 }
730
731
732 /*****************************************************************************
733 * Query_cache_table method(s)
734 *****************************************************************************/
735
736 extern "C"
737 {
query_cache_table_get_key(const uchar * record,size_t * length,my_bool not_used MY_ATTRIBUTE ((unused)))738 uchar *query_cache_table_get_key(const uchar *record, size_t *length,
739 my_bool not_used MY_ATTRIBUTE((unused)))
740 {
741 Query_cache_block* table_block = (Query_cache_block*) record;
742 *length = (table_block->used - table_block->headers_len() -
743 ALIGN_SIZE(sizeof(Query_cache_table)));
744 return (((uchar *) table_block->data()) +
745 ALIGN_SIZE(sizeof(Query_cache_table)));
746 }
747 }
748
749 /*****************************************************************************
750 Query_cache_query methods
751 *****************************************************************************/
752
753 /*
754 Following methods work for block read/write locking only in this
755 particular case and in interaction with structure_guard_mutex.
756
757 Lock for write prevents any other locking. (exclusive use)
758 Lock for read prevents only locking for write.
759 */
760
lock_writing()761 inline void Query_cache_query::lock_writing()
762 {
763 RW_WLOCK(&lock);
764 }
765
766
767 /*
768 Needed for finding queries, that we may delete from cache.
769 We don't want to wait while block become unlocked. In addition,
770 block locking means that query is now used and we don't need to
771 remove it.
772 */
773
try_lock_writing()774 my_bool Query_cache_query::try_lock_writing()
775 {
776 DBUG_ENTER("Query_cache_block::try_lock_writing");
777 if (mysql_rwlock_trywrlock(&lock) != 0)
778 {
779 DBUG_PRINT("info", ("can't lock rwlock"));
780 DBUG_RETURN(0);
781 }
782 DBUG_PRINT("info", ("rwlock 0x%lx locked", (ulong) &lock));
783 DBUG_RETURN(1);
784 }
785
786
lock_reading()787 inline void Query_cache_query::lock_reading()
788 {
789 RW_RLOCK(&lock);
790 }
791
792
unlock_writing()793 inline void Query_cache_query::unlock_writing()
794 {
795 RW_UNLOCK(&lock);
796 }
797
798
unlock_reading()799 inline void Query_cache_query::unlock_reading()
800 {
801 RW_UNLOCK(&lock);
802 }
803
804
init_n_lock()805 void Query_cache_query::init_n_lock()
806 {
807 DBUG_ENTER("Query_cache_query::init_n_lock");
808 res=0; wri = 0; len = 0;
809 mysql_rwlock_init(key_rwlock_query_cache_query_lock, &lock);
810 lock_writing();
811 DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx",
812 (long) (((uchar*) this) -
813 ALIGN_SIZE(sizeof(Query_cache_block)))));
814 DBUG_VOID_RETURN;
815 }
816
817
unlock_n_destroy()818 void Query_cache_query::unlock_n_destroy()
819 {
820 DBUG_ENTER("Query_cache_query::unlock_n_destroy");
821 DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
822 (long) (((uchar*) this) -
823 ALIGN_SIZE(sizeof(Query_cache_block)))));
824 /*
825 The following call is not needed on system where one can destroy an
826 active semaphore
827 */
828 this->unlock_writing();
829 mysql_rwlock_destroy(&lock);
830 DBUG_VOID_RETURN;
831 }
832
833
834 extern "C"
835 {
query_cache_query_get_key(const uchar * record,size_t * length,my_bool not_used)836 uchar *query_cache_query_get_key(const uchar *record, size_t *length,
837 my_bool not_used)
838 {
839 Query_cache_block *query_block = (Query_cache_block*) record;
840 *length = (query_block->used - query_block->headers_len() -
841 ALIGN_SIZE(sizeof(Query_cache_query)));
842 return (((uchar *) query_block->data()) +
843 ALIGN_SIZE(sizeof(Query_cache_query)));
844 }
845 }
846
847 /*****************************************************************************
848 Functions to store things into the query cache
849 *****************************************************************************/
850
851 /*
852 Note on double-check locking (DCL) usage.
853
854 Below, in query_cache_insert(), query_cache_abort() and
855 Query_cache::end_of_result() we use what is called double-check
856 locking (DCL) for Query_cache_tls::first_query_block.
857 I.e. we test it first without a lock, and, if positive, test again
858 under the lock.
859
860 This means that if we see 'first_query_block == 0' without a
861 lock we will skip the operation. But this is safe here: when we
862 started to cache a query, we called Query_cache::store_query(), and
863 'first_query_block' was set to non-zero in this thread (and the
864 thread always sees results of its memory operations, mutex or not).
865 If later we see 'first_query_block == 0' without locking a
866 mutex, that may only mean that some other thread have reset it by
867 invalidating the query. Skipping the operation in this case is the
868 right thing to do, as first_query_block won't get non-zero for
869 this query again.
870
871 See also comments in Query_cache::store_query() and
872 Query_cache::send_result_to_client().
873
874 NOTE, however, that double-check locking is not applicable in
875 'invalidate' functions, as we may erroneously skip invalidation,
876 because the thread doing invalidation may never see non-zero
877 'first_query_block'.
878 */
879
880
881 /**
882 libmysql convenience wrapper to insert data into query cache.
883 */
query_cache_insert(const char * packet,ulong length,unsigned pkt_nr)884 void query_cache_insert(const char *packet, ulong length,
885 unsigned pkt_nr)
886 {
887 THD *thd= current_thd;
888
889 /*
890 Current_thd can be NULL when a new connection is immediately ended
891 due to "Too many connections". thd->store_globals() has not been
892 called at this time and hence my_pthread_setspecific_ptr(THR_THD,
893 this) has not been called for this thread.
894 */
895
896 if (!thd)
897 return;
898
899 query_cache.insert(&thd->query_cache_tls,
900 packet, length,
901 pkt_nr);
902 }
903
904
905 /**
906 Insert the packet into the query cache.
907 */
908
909 void
insert(Query_cache_tls * query_cache_tls,const char * packet,ulong length,unsigned pkt_nr)910 Query_cache::insert(Query_cache_tls *query_cache_tls,
911 const char *packet, ulong length,
912 unsigned pkt_nr)
913 {
914 DBUG_ENTER("Query_cache::insert");
915
916 /* See the comment on double-check locking usage above. */
917 if (is_disabled() || query_cache_tls->first_query_block == NULL)
918 DBUG_VOID_RETURN;
919
920 QC_DEBUG_SYNC("wait_in_query_cache_insert");
921
922 if (try_lock())
923 DBUG_VOID_RETURN;
924
925 Query_cache_block *query_block = query_cache_tls->first_query_block;
926 if (query_block == NULL)
927 {
928 /*
929 We lost the writer and the currently processed query has been
930 invalidated; there is nothing left to do.
931 */
932 unlock();
933 DBUG_VOID_RETURN;
934 }
935 BLOCK_LOCK_WR(query_block);
936 Query_cache_query *header= query_block->query();
937 Query_cache_block *result= header->result();
938
939 DUMP(this);
940 DBUG_PRINT("qcache", ("insert packet %lu bytes long",length));
941
942 /*
943 On success, STRUCT_UNLOCK is done by append_result_data. Otherwise, we
944 still need structure_guard_mutex to free the query, and therefore unlock
945 it later in this function.
946 */
947 if (!append_result_data(&result, length, (uchar*) packet,
948 query_block))
949 {
950 DBUG_PRINT("warning", ("Can't append data"));
951 header->result(result);
952 DBUG_PRINT("qcache", ("free query 0x%lx", (ulong) query_block));
953 // The following call will remove the lock on query_block
954 query_cache.free_query(query_block);
955 query_cache.refused++;
956 // append_result_data no success => we need unlock
957 unlock();
958 DBUG_VOID_RETURN;
959 }
960
961 header->result(result);
962 header->last_pkt_nr= pkt_nr;
963 BLOCK_UNLOCK_WR(query_block);
964 DBUG_EXECUTE("check_querycache",check_integrity(0););
965
966 DBUG_VOID_RETURN;
967 }
968
969
970 void
abort(Query_cache_tls * query_cache_tls)971 Query_cache::abort(Query_cache_tls *query_cache_tls)
972 {
973 DBUG_ENTER("query_cache_abort");
974 THD *thd= current_thd;
975
976 /* See the comment on double-check locking usage above. */
977 if (is_disabled() || query_cache_tls->first_query_block == NULL)
978 DBUG_VOID_RETURN;
979
980 if (try_lock())
981 DBUG_VOID_RETURN;
982
983 /*
984 While we were waiting another thread might have changed the status
985 of the writer. Make sure the writer still exists before continue.
986 */
987 Query_cache_block *query_block= query_cache_tls->first_query_block;
988 if (query_block)
989 {
990 THD_STAGE_INFO(thd, stage_storing_result_in_query_cache);
991 DUMP(this);
992 BLOCK_LOCK_WR(query_block);
993 // The following call will remove the lock on query_block
994 free_query(query_block);
995 query_cache_tls->first_query_block= NULL;
996 DBUG_EXECUTE("check_querycache", check_integrity(1););
997 }
998
999 unlock();
1000
1001 DBUG_VOID_RETURN;
1002 }
1003
1004
end_of_result(THD * thd)1005 void Query_cache::end_of_result(THD *thd)
1006 {
1007 Query_cache_block *query_block;
1008 Query_cache_tls *query_cache_tls= &thd->query_cache_tls;
1009 ulonglong limit_found_rows= thd->limit_found_rows;
1010 DBUG_ENTER("Query_cache::end_of_result");
1011
1012 /* See the comment on double-check locking usage above. */
1013 if (query_cache_tls->first_query_block == NULL)
1014 DBUG_VOID_RETURN;
1015
1016 if (thd->killed || thd->is_error())
1017 {
1018 query_cache_abort(&thd->query_cache_tls);
1019 DBUG_VOID_RETURN;
1020 }
1021
1022 /* Ensure that only complete results are cached. */
1023 DBUG_ASSERT(thd->get_stmt_da()->is_eof());
1024
1025 #ifdef EMBEDDED_LIBRARY
1026 insert(query_cache_tls, (char*)thd,
1027 emb_count_querycache_size(thd), 0);
1028 #endif
1029
1030 if (try_lock())
1031 DBUG_VOID_RETURN;
1032
1033 query_block= query_cache_tls->first_query_block;
1034 if (query_block)
1035 {
1036 /*
1037 The writer is still present; finish last result block by chopping it to
1038 suitable size if needed and setting block type. Since this is the last
1039 block, the writer should be dropped.
1040 */
1041 THD_STAGE_INFO(thd, stage_storing_result_in_query_cache);
1042 DUMP(this);
1043 BLOCK_LOCK_WR(query_block);
1044 Query_cache_query *header= query_block->query();
1045 Query_cache_block *last_result_block;
1046 ulong allign_size;
1047 ulong len;
1048
1049 if (header->result() == 0)
1050 {
1051 DBUG_PRINT("error", ("End of data with no result blocks; "
1052 "Query '%s' removed from cache.", header->query()));
1053 /*
1054 Extra safety: empty result should not happen in the normal call
1055 to this function. In the release version that query should be ignored
1056 and removed from QC.
1057 */
1058 DBUG_ASSERT(0);
1059 free_query(query_block);
1060 unlock();
1061 DBUG_VOID_RETURN;
1062 }
1063 last_result_block= header->result()->prev;
1064 allign_size= ALIGN_SIZE(last_result_block->used);
1065 len= max(query_cache.min_allocation_unit, allign_size);
1066 if (last_result_block->length >= query_cache.min_allocation_unit + len)
1067 query_cache.split_block(last_result_block,len);
1068
1069 header->found_rows(limit_found_rows);
1070 header->result()->type= Query_cache_block::RESULT;
1071
1072 /* Drop the writer. */
1073 header->writer(0);
1074 query_cache_tls->first_query_block= NULL;
1075 BLOCK_UNLOCK_WR(query_block);
1076 DBUG_EXECUTE("check_querycache", check_integrity(1););
1077 }
1078
1079 unlock();
1080 DBUG_VOID_RETURN;
1081 }
1082
query_cache_invalidate_by_MyISAM_filename(const char * filename)1083 void query_cache_invalidate_by_MyISAM_filename(const char *filename)
1084 {
1085 query_cache.invalidate_by_MyISAM_filename(filename);
1086 DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
1087 }
1088
1089
1090 /*
1091 The following function forms part of the C plugin API
1092 */
1093 extern "C"
mysql_query_cache_invalidate4(THD * thd,const char * key,unsigned key_length,int using_trx)1094 void mysql_query_cache_invalidate4(THD *thd,
1095 const char *key, unsigned key_length,
1096 int using_trx)
1097 {
1098 query_cache.invalidate(thd, key, (uint32) key_length, (my_bool) using_trx);
1099 }
1100
1101
1102 /*****************************************************************************
1103 Query_cache methods
1104 *****************************************************************************/
1105
Query_cache(ulong query_cache_limit_arg,ulong min_allocation_unit_arg,ulong min_result_data_size_arg,uint def_query_hash_size_arg,uint def_table_hash_size_arg)1106 Query_cache::Query_cache(ulong query_cache_limit_arg,
1107 ulong min_allocation_unit_arg,
1108 ulong min_result_data_size_arg,
1109 uint def_query_hash_size_arg,
1110 uint def_table_hash_size_arg)
1111 :query_cache_size(0),
1112 query_cache_limit(query_cache_limit_arg),
1113 queries_in_cache(0), hits(0), inserts(0), refused(0),
1114 total_blocks(0), lowmem_prunes(0), m_query_cache_is_disabled(FALSE),
1115 min_allocation_unit(ALIGN_SIZE(min_allocation_unit_arg)),
1116 min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)),
1117 def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)),
1118 def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)),
1119 initialized(0)
1120 {
1121 ulong min_needed= (ALIGN_SIZE(sizeof(Query_cache_block)) +
1122 ALIGN_SIZE(sizeof(Query_cache_block_table)) +
1123 ALIGN_SIZE(sizeof(Query_cache_query)) + 3);
1124 set_if_bigger(min_allocation_unit,min_needed);
1125 this->min_allocation_unit= ALIGN_SIZE(min_allocation_unit);
1126 set_if_bigger(this->min_result_data_size,min_allocation_unit);
1127 }
1128
1129
resize(ulong query_cache_size_arg)1130 ulong Query_cache::resize(ulong query_cache_size_arg)
1131 {
1132 ulong new_query_cache_size;
1133 DBUG_ENTER("Query_cache::resize");
1134 DBUG_PRINT("qcache", ("from %lu to %lu",query_cache_size,
1135 query_cache_size_arg));
1136 DBUG_ASSERT(initialized);
1137
1138 lock_and_suspend();
1139
1140 /*
1141 Wait for all readers and writers to exit. When the list of all queries
1142 is iterated over with a block level lock, we are done.
1143 */
1144 Query_cache_block *block= queries_blocks;
1145 if (block)
1146 {
1147 do
1148 {
1149 BLOCK_LOCK_WR(block);
1150 Query_cache_query *query= block->query();
1151 if (query->writer())
1152 {
1153 /*
1154 Drop the writer; this will cancel any attempts to store
1155 the processed statement associated with this writer.
1156 */
1157 query->writer()->first_query_block= NULL;
1158 query->writer(0);
1159 refused++;
1160 }
1161 query->unlock_n_destroy();
1162 block= block->next;
1163 } while (block != queries_blocks);
1164 }
1165 free_cache();
1166
1167 query_cache_size= query_cache_size_arg;
1168 new_query_cache_size= init_cache();
1169
1170 if (new_query_cache_size)
1171 DBUG_EXECUTE("check_querycache",check_integrity(1););
1172
1173 unlock();
1174 DBUG_RETURN(new_query_cache_size);
1175 }
1176
1177
set_min_res_unit(ulong size)1178 ulong Query_cache::set_min_res_unit(ulong size)
1179 {
1180 if (size < min_allocation_unit)
1181 size= min_allocation_unit;
1182 else if (size > max_aligned_min_res_unit_size)
1183 size= max_aligned_min_res_unit_size;
1184
1185 return (min_result_data_size= ALIGN_SIZE(size));
1186 }
1187
1188
store_query(THD * thd,TABLE_LIST * tables_used)1189 void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
1190 {
1191 TABLE_COUNTER_TYPE local_tables;
1192 ulong tot_length;
1193 DBUG_ENTER("Query_cache::store_query");
1194 /*
1195 Testing 'query_cache_size' without a lock here is safe: the thing
1196 we may loose is that the query won't be cached, but we save on
1197 mutex locking in the case when query cache is disabled or the
1198 query is uncachable.
1199
1200 See also a note on double-check locking usage above.
1201 */
1202 if (thd->locked_tables_mode || query_cache_size == 0)
1203 DBUG_VOID_RETURN;
1204
1205 #ifndef EMBEDDED_LIBRARY
1206 /*
1207 Without active vio, net_write_packet() will not be called and
1208 therefore neither Query_cache::insert(). Since we will never get a
1209 complete query result in this case, it does not make sense to
1210 register the query in the first place.
1211 */
1212 if (thd->net.vio == NULL)
1213 DBUG_VOID_RETURN;
1214 #endif
1215
1216 uint8 tables_type= 0;
1217
1218 if ((local_tables= is_cacheable(thd, thd->query_length(),
1219 thd->query(), thd->lex, tables_used,
1220 &tables_type)))
1221 {
1222 NET *net= &thd->net;
1223 Query_cache_query_flags flags;
1224 // fill all gaps between fields with 0 to get repeatable key
1225 memset(&flags, 0, QUERY_CACHE_FLAGS_SIZE);
1226 flags.client_long_flag= MY_TEST(thd->client_capabilities & CLIENT_LONG_FLAG);
1227 flags.client_protocol_41= MY_TEST(thd->client_capabilities &
1228 CLIENT_PROTOCOL_41);
1229 /*
1230 Protocol influences result format, so statement results in the binary
1231 protocol (COM_EXECUTE) cannot be served to statements asking for results
1232 in the text protocol (COM_QUERY) and vice-versa.
1233 */
1234 flags.protocol_type= (unsigned int) thd->protocol->type();
1235 /* PROTOCOL_LOCAL results are not cached. */
1236 DBUG_ASSERT(flags.protocol_type != (unsigned int) Protocol::PROTOCOL_LOCAL);
1237 flags.more_results_exists= MY_TEST(thd->server_status &
1238 SERVER_MORE_RESULTS_EXISTS);
1239 flags.in_trans= thd->in_active_multi_stmt_transaction();
1240 flags.autocommit= MY_TEST(thd->server_status & SERVER_STATUS_AUTOCOMMIT);
1241 flags.pkt_nr= net->pkt_nr;
1242 flags.character_set_client_num=
1243 thd->variables.character_set_client->number;
1244 flags.character_set_results_num=
1245 (thd->variables.character_set_results ?
1246 thd->variables.character_set_results->number :
1247 UINT_MAX);
1248 flags.collation_connection_num=
1249 thd->variables.collation_connection->number;
1250 flags.limit= thd->variables.select_limit;
1251 flags.time_zone= thd->variables.time_zone;
1252 flags.sql_mode= thd->variables.sql_mode;
1253 flags.max_sort_length= thd->variables.max_sort_length;
1254 flags.lc_time_names= thd->variables.lc_time_names;
1255 flags.group_concat_max_len= thd->variables.group_concat_max_len;
1256 flags.div_precision_increment= thd->variables.div_precincrement;
1257 flags.default_week_format= thd->variables.default_week_format;
1258 DBUG_PRINT("qcache", ("\
1259 long %d, 4.1: %d, bin_proto: %d, more results %d, pkt_nr: %d, \
1260 CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
1261 sql mode: 0x%llx, sort len: %lu, conncat len: %lu, div_precision: %lu, \
1262 def_week_frmt: %lu, in_trans: %d, autocommit: %d",
1263 (int)flags.client_long_flag,
1264 (int)flags.client_protocol_41,
1265 (int)flags.protocol_type,
1266 (int)flags.more_results_exists,
1267 flags.pkt_nr,
1268 flags.character_set_client_num,
1269 flags.character_set_results_num,
1270 flags.collation_connection_num,
1271 (ulong) flags.limit,
1272 (ulong) flags.time_zone,
1273 flags.sql_mode,
1274 flags.max_sort_length,
1275 flags.group_concat_max_len,
1276 flags.div_precision_increment,
1277 flags.default_week_format,
1278 (int)flags.in_trans,
1279 (int)flags.autocommit));
1280
1281 /*
1282 Make InnoDB to release the adaptive hash index latch before
1283 acquiring the query cache mutex.
1284 */
1285 ha_release_temporary_latches(thd);
1286
1287 /*
1288 A table- or a full flush operation can potentially take a long time to
1289 finish. We choose not to wait for them and skip caching statements
1290 instead.
1291
1292 In case the wait time can't be determined there is an upper limit which
1293 causes try_lock() to abort with a time out.
1294
1295 The 'TRUE' parameter indicate that the lock is allowed to timeout
1296
1297 */
1298 if (try_lock(TRUE))
1299 DBUG_VOID_RETURN;
1300 if (query_cache_size == 0)
1301 {
1302 unlock();
1303 DBUG_VOID_RETURN;
1304 }
1305 DUMP(this);
1306
1307 if (ask_handler_allowance(thd, tables_used))
1308 {
1309 refused++;
1310 unlock();
1311 DBUG_VOID_RETURN;
1312 }
1313
1314 /* Key is query + database + flag */
1315 if (thd->db_length)
1316 {
1317 memcpy(thd->query() + thd->query_length() + 1 + sizeof(size_t),
1318 thd->db, thd->db_length);
1319 DBUG_PRINT("qcache", ("database: %s length: %u",
1320 thd->db, (unsigned) thd->db_length));
1321 }
1322 else
1323 {
1324 DBUG_PRINT("qcache", ("No active database"));
1325 }
1326 tot_length= thd->query_length() + thd->db_length + 1 +
1327 sizeof(size_t) + QUERY_CACHE_FLAGS_SIZE;
1328 /*
1329 We should only copy structure (don't use it location directly)
1330 because of alignment issue
1331 */
1332 memcpy((void*) (thd->query() + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
1333 &flags, QUERY_CACHE_FLAGS_SIZE);
1334
1335 /* Check if another thread is processing the same query? */
1336 Query_cache_block *competitor = (Query_cache_block *)
1337 my_hash_search(&queries, (uchar*) thd->query(), tot_length);
1338 DBUG_PRINT("qcache", ("competitor 0x%lx", (ulong) competitor));
1339 if (competitor == 0)
1340 {
1341 /* Query is not in cache and no one is working with it; Store it */
1342 Query_cache_block *query_block;
1343 query_block= write_block_data(tot_length, (uchar*) thd->query(),
1344 ALIGN_SIZE(sizeof(Query_cache_query)),
1345 Query_cache_block::QUERY, local_tables);
1346 if (query_block != 0)
1347 {
1348 DBUG_PRINT("qcache", ("query block 0x%lx allocated, %lu",
1349 (ulong) query_block, query_block->used));
1350
1351 Query_cache_query *header = query_block->query();
1352 header->init_n_lock();
1353 if (my_hash_insert(&queries, (uchar*) query_block))
1354 {
1355 refused++;
1356 DBUG_PRINT("qcache", ("insertion in query hash"));
1357 header->unlock_n_destroy();
1358 free_memory_block(query_block);
1359 unlock();
1360 goto end;
1361 }
1362 if (!register_all_tables(query_block, tables_used, local_tables))
1363 {
1364 refused++;
1365 DBUG_PRINT("warning", ("tables list including failed"));
1366 my_hash_delete(&queries, (uchar *) query_block);
1367 header->unlock_n_destroy();
1368 free_memory_block(query_block);
1369 unlock();
1370 goto end;
1371 }
1372 double_linked_list_simple_include(query_block, &queries_blocks);
1373 inserts++;
1374 queries_in_cache++;
1375 thd->query_cache_tls.first_query_block= query_block;
1376 header->writer(&thd->query_cache_tls);
1377 header->tables_type(tables_type);
1378
1379 unlock();
1380
1381 // init_n_lock make query block locked
1382 BLOCK_UNLOCK_WR(query_block);
1383 }
1384 else
1385 {
1386 // We have not enough memory to store query => do nothing
1387 refused++;
1388 unlock();
1389 DBUG_PRINT("warning", ("Can't allocate query"));
1390 }
1391 }
1392 else
1393 {
1394 // Another thread is processing the same query => do nothing
1395 refused++;
1396 unlock();
1397 DBUG_PRINT("qcache", ("Another thread process same query"));
1398 }
1399 }
1400 else if (thd->lex->sql_command == SQLCOM_SELECT)
1401 statistic_increment(refused, &structure_guard_mutex);
1402
1403 end:
1404 DBUG_VOID_RETURN;
1405 }
1406
1407
1408 #ifndef EMBEDDED_LIBRARY
1409 /**
1410 Send a single memory block from the query cache.
1411
1412 Respects the client/server protocol limits for the
1413 size of the network packet, and splits a large block
1414 in pieces to ensure that individual piece doesn't exceed
1415 the maximal allowed size of the network packet (16M).
1416
1417 @param[in] net NET handler
1418 @param[in] packet packet to send
1419 @param[in] len packet length
1420
1421 @return Operation status
1422 @retval FALSE On success
1423 @retval TRUE On error
1424 */
1425 static bool
send_data_in_chunks(NET * net,const uchar * packet,ulong len)1426 send_data_in_chunks(NET *net, const uchar *packet, ulong len)
1427 {
1428 /*
1429 On the client we may require more memory than max_allowed_packet
1430 to keep, both, the truncated last logical packet, and the
1431 compressed next packet. This never (or in practice never)
1432 happens without compression, since without compression it's very
1433 unlikely that a) a truncated logical packet would remain on the
1434 client when it's time to read the next packet b) a subsequent
1435 logical packet that is being read would be so large that
1436 size-of-new-packet + size-of-old-packet-tail >
1437 max_allowed_packet. To remedy this issue, we send data in 1MB
1438 sized packets, that's below the current client default of 16MB
1439 for max_allowed_packet, but large enough to ensure there is no
1440 unnecessary overhead from too many syscalls per result set.
1441 */
1442 static const ulong MAX_CHUNK_LENGTH= 1024*1024;
1443
1444 while (len > MAX_CHUNK_LENGTH)
1445 {
1446 if (net_write_packet(net, packet, MAX_CHUNK_LENGTH))
1447 return TRUE;
1448 packet+= MAX_CHUNK_LENGTH;
1449 len-= MAX_CHUNK_LENGTH;
1450 }
1451 if (len && net_write_packet(net, packet, len))
1452 return TRUE;
1453
1454 return FALSE;
1455 }
1456 #endif
1457
1458
1459 /*
1460 Check if the query is in the cache. If it was cached, send it
1461 to the user.
1462
1463 @param thd Pointer to the thread handler
1464 @param sql A pointer to the sql statement *
1465 @param query_length Length of the statement in characters
1466
1467 @return status code
1468 @retval 0 Query was not cached.
1469 @retval 1 The query was cached and user was sent the result.
1470 @retval -1 The query was cached but we didn't have rights to use it.
1471
1472 In case of -1, no error is sent to the client.
1473
1474 *) The buffer must be allocated memory of size:
1475 tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
1476 */
1477
1478 int
send_result_to_client(THD * thd,char * sql,uint query_length)1479 Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
1480 {
1481 ulonglong engine_data;
1482 Query_cache_query *query;
1483 #ifndef EMBEDDED_LIBRARY
1484 Query_cache_block *first_result_block;
1485 #endif
1486 Query_cache_block *result_block;
1487 Query_cache_block_table *block_table, *block_table_end;
1488 ulong tot_length;
1489 Query_cache_query_flags flags;
1490 enum xa_states xa_state= thd->transaction.xid_state.xa_state;
1491 DBUG_ENTER("Query_cache::send_result_to_client");
1492
1493 /*
1494 Testing 'query_cache_size' without a lock here is safe: the thing
1495 we may loose is that the query won't be served from cache, but we
1496 save on mutex locking in the case when query cache is disabled.
1497
1498 See also a note on double-check locking usage above.
1499 */
1500 if (is_disabled() || thd->locked_tables_mode ||
1501 thd->variables.query_cache_type == 0 || query_cache_size == 0)
1502 goto err;
1503
1504 /*
1505 Don't work with Query_cache if the state of XA transaction is
1506 either IDLE or PREPARED. If we didn't do so we would get an
1507 assert fired later in the function trx_start_if_not_started_low()
1508 that is called when we are checking that query cache is allowed at
1509 this moment to operate on an InnoDB table.
1510 */
1511 if (xa_state == XA_IDLE || xa_state == XA_PREPARED)
1512 goto err;
1513
1514 if (!thd->lex->safe_to_cache_query)
1515 {
1516 DBUG_PRINT("qcache", ("SELECT is non-cacheable"));
1517 goto err;
1518 }
1519
1520 {
1521 uint i= 0;
1522 /*
1523 Skip '(' characters in queries like following:
1524 (select a from t1) union (select a from t1);
1525 */
1526 while (sql[i]=='(')
1527 i++;
1528
1529 /*
1530 Test if the query is a SELECT
1531 (pre-space is removed in dispatch_command).
1532
1533 First '/' looks like comment before command it is not
1534 frequently appeared in real life, consequently we can
1535 check all such queries, too.
1536 */
1537 if ((my_toupper(system_charset_info, sql[i]) != 'S' ||
1538 my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
1539 my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
1540 sql[i] != '/')
1541 {
1542 DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
1543 goto err;
1544 }
1545
1546 if (query_length > 20 && has_no_cache_directive(&sql[i+6]))
1547 {
1548 /*
1549 We do not increase 'refused' statistics here since it will be done
1550 later when the query is parsed.
1551 */
1552 DBUG_PRINT("qcache", ("The statement has a SQL_NO_CACHE directive"));
1553 goto err;
1554 }
1555 }
1556 {
1557 /*
1558 We have allocated buffer space (in alloc_query) to hold the
1559 SQL statement(s) + the current database name + a flags struct.
1560 If the database name has changed during execution, which might
1561 happen if there are multiple statements, we need to make
1562 sure the new current database has a name with the same length
1563 as the previous one.
1564 */
1565 size_t db_len;
1566 memcpy((char *) &db_len, (sql + query_length + 1), sizeof(size_t));
1567 if (thd->db_length != db_len)
1568 {
1569 /*
1570 We should probably reallocate the buffer in this case,
1571 but for now we just leave it uncached
1572 */
1573
1574 DBUG_PRINT("qcache",
1575 ("Current database has changed since start of query"));
1576 goto err;
1577 }
1578 }
1579 /*
1580 Try to obtain an exclusive lock on the query cache. If the cache is
1581 disabled or if a full cache flush is in progress, the attempt to
1582 get the lock is aborted.
1583
1584 The 'TRUE' parameter indicate that the lock is allowed to timeout
1585 */
1586 if (try_lock(TRUE))
1587 goto err;
1588
1589 if (query_cache_size == 0)
1590 goto err_unlock;
1591
1592 Query_cache_block *query_block;
1593
1594 tot_length= query_length + 1 + sizeof(size_t) +
1595 thd->db_length + QUERY_CACHE_FLAGS_SIZE;
1596
1597 if (thd->db_length)
1598 {
1599 memcpy(sql + query_length + 1 + sizeof(size_t), thd->db, thd->db_length);
1600 DBUG_PRINT("qcache", ("database: '%s' length: %u",
1601 thd->db, (unsigned)thd->db_length));
1602 }
1603 else
1604 {
1605 DBUG_PRINT("qcache", ("No active database"));
1606 }
1607
1608 THD_STAGE_INFO(thd, stage_checking_query_cache_for_query);
1609
1610 // fill all gaps between fields with 0 to get repeatable key
1611 memset(&flags, 0, QUERY_CACHE_FLAGS_SIZE);
1612 flags.client_long_flag= MY_TEST(thd->client_capabilities & CLIENT_LONG_FLAG);
1613 flags.client_protocol_41= MY_TEST(thd->client_capabilities &
1614 CLIENT_PROTOCOL_41);
1615 flags.protocol_type= (unsigned int) thd->protocol->type();
1616 flags.more_results_exists= MY_TEST(thd->server_status &
1617 SERVER_MORE_RESULTS_EXISTS);
1618 flags.in_trans= thd->in_active_multi_stmt_transaction();
1619 flags.autocommit= MY_TEST(thd->server_status & SERVER_STATUS_AUTOCOMMIT);
1620 flags.pkt_nr= thd->net.pkt_nr;
1621 flags.character_set_client_num= thd->variables.character_set_client->number;
1622 flags.character_set_results_num=
1623 (thd->variables.character_set_results ?
1624 thd->variables.character_set_results->number :
1625 UINT_MAX);
1626 flags.collation_connection_num= thd->variables.collation_connection->number;
1627 flags.limit= thd->variables.select_limit;
1628 flags.time_zone= thd->variables.time_zone;
1629 flags.sql_mode= thd->variables.sql_mode;
1630 flags.max_sort_length= thd->variables.max_sort_length;
1631 flags.group_concat_max_len= thd->variables.group_concat_max_len;
1632 flags.div_precision_increment= thd->variables.div_precincrement;
1633 flags.default_week_format= thd->variables.default_week_format;
1634 flags.lc_time_names= thd->variables.lc_time_names;
1635 DBUG_PRINT("qcache", ("\
1636 long %d, 4.1: %d, bin_proto: %d, more results %d, pkt_nr: %d, \
1637 CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
1638 sql mode: 0x%llx, sort len: %lu, conncat len: %lu, div_precision: %lu, \
1639 def_week_frmt: %lu, in_trans: %d, autocommit: %d",
1640 (int)flags.client_long_flag,
1641 (int)flags.client_protocol_41,
1642 (int)flags.protocol_type,
1643 (int)flags.more_results_exists,
1644 flags.pkt_nr,
1645 flags.character_set_client_num,
1646 flags.character_set_results_num,
1647 flags.collation_connection_num,
1648 (ulong) flags.limit,
1649 (ulong) flags.time_zone,
1650 flags.sql_mode,
1651 flags.max_sort_length,
1652 flags.group_concat_max_len,
1653 flags.div_precision_increment,
1654 flags.default_week_format,
1655 (int)flags.in_trans,
1656 (int)flags.autocommit));
1657 memcpy((uchar *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
1658 (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE);
1659 query_block = (Query_cache_block *) my_hash_search(&queries, (uchar*) sql,
1660 tot_length);
1661 /* Quick abort on unlocked data */
1662 if (query_block == 0 ||
1663 query_block->query()->result() == 0 ||
1664 query_block->query()->result()->type != Query_cache_block::RESULT)
1665 {
1666 DBUG_PRINT("qcache", ("No query in query hash or no results"));
1667 goto err_unlock;
1668 }
1669 DBUG_PRINT("qcache", ("Query in query hash 0x%lx", (ulong)query_block));
1670
1671 /* Now lock and test that nothing changed while blocks was unlocked */
1672 BLOCK_LOCK_RD(query_block);
1673
1674 query = query_block->query();
1675 result_block= query->result();
1676 #ifndef EMBEDDED_LIBRARY
1677 first_result_block= result_block;
1678 #endif
1679
1680 if (result_block == 0 || result_block->type != Query_cache_block::RESULT)
1681 {
1682 /* The query is probably yet processed */
1683 DBUG_PRINT("qcache", ("query found, but no data or data incomplete"));
1684 BLOCK_UNLOCK_RD(query_block);
1685 goto err_unlock;
1686 }
1687 DBUG_PRINT("qcache", ("Query have result 0x%lx", (ulong) query));
1688
1689 if (thd->in_multi_stmt_transaction_mode() &&
1690 (query->tables_type() & HA_CACHE_TBL_TRANSACT))
1691 {
1692 DBUG_PRINT("qcache",
1693 ("we are in transaction and have transaction tables in query"));
1694 BLOCK_UNLOCK_RD(query_block);
1695 goto err_unlock;
1696 }
1697
1698 // Check access;
1699 THD_STAGE_INFO(thd, stage_checking_privileges_on_cached_query);
1700 block_table= query_block->table(0);
1701 block_table_end= block_table+query_block->n_tables;
1702 for (; block_table != block_table_end; block_table++)
1703 {
1704 TABLE_LIST table_list;
1705 TABLE *tmptable;
1706 Query_cache_table *table = block_table->parent;
1707
1708 /*
1709 Check that we have not temporary tables with same names of tables
1710 of this query. If we have such tables, we will not send data from
1711 query cache, because temporary tables hide real tables by which
1712 query in query cache was made.
1713 */
1714 for (tmptable= thd->temporary_tables; tmptable ; tmptable= tmptable->next)
1715 {
1716 if (tmptable->s->table_cache_key.length - TMP_TABLE_KEY_EXTRA ==
1717 table->key_length() &&
1718 !memcmp(tmptable->s->table_cache_key.str, table->data(),
1719 table->key_length()))
1720 {
1721 DBUG_PRINT("qcache",
1722 ("Temporary table detected: '%s.%s'",
1723 table_list.db, table_list.alias));
1724 unlock();
1725 /*
1726 We should not store result of this query because it contain
1727 temporary tables => assign following variable to make check
1728 faster.
1729 */
1730 thd->lex->safe_to_cache_query=0;
1731 BLOCK_UNLOCK_RD(query_block);
1732 DBUG_RETURN(-1);
1733 }
1734 }
1735
1736 memset(&table_list, 0, sizeof(table_list));
1737 table_list.db = table->db();
1738 table_list.alias= table_list.table_name= table->table();
1739 #ifndef NO_EMBEDDED_ACCESS_CHECKS
1740 if (check_table_access(thd,SELECT_ACL,&table_list, FALSE, 1,TRUE))
1741 {
1742 DBUG_PRINT("qcache",
1743 ("probably no SELECT access to %s.%s => return to normal processing",
1744 table_list.db, table_list.alias));
1745 unlock();
1746 thd->lex->safe_to_cache_query=0; // Don't try to cache this
1747 BLOCK_UNLOCK_RD(query_block);
1748 DBUG_RETURN(-1); // Privilege error
1749 }
1750 if (table_list.grant.want_privilege)
1751 {
1752 DBUG_PRINT("qcache", ("Need to check column privileges for %s.%s",
1753 table_list.db, table_list.alias));
1754 BLOCK_UNLOCK_RD(query_block);
1755 thd->lex->safe_to_cache_query= 0; // Don't try to cache this
1756 goto err_unlock; // Parse query
1757 }
1758 #endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
1759 engine_data= table->engine_data();
1760 if (table->callback())
1761 {
1762 char qcache_se_key_name[FN_REFLEN + 1];
1763 uint qcache_se_key_len;
1764 engine_data= table->engine_data();
1765
1766 qcache_se_key_len= build_table_filename(qcache_se_key_name,
1767 sizeof(qcache_se_key_name),
1768 table->db(), table->table(),
1769 "", SKIP_SYMDIR_ACCESS);
1770
1771 if (!(*table->callback())(thd, qcache_se_key_name,
1772 qcache_se_key_len, &engine_data))
1773 {
1774 DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
1775 table_list.db, table_list.alias));
1776 BLOCK_UNLOCK_RD(query_block);
1777 if (engine_data != table->engine_data())
1778 {
1779 DBUG_PRINT("qcache",
1780 ("Handler require invalidation queries of %s.%s %lu-%lu",
1781 table_list.db, table_list.alias,
1782 (ulong) engine_data, (ulong) table->engine_data()));
1783 invalidate_table_internal(thd, (uchar *) table->db(),
1784 table->key_length());
1785 }
1786 else
1787 thd->lex->safe_to_cache_query= 0; // Don't try to cache this
1788 /*
1789 End the statement transaction potentially started by engine.
1790 Currently our engines do not request rollback from callbacks.
1791 If this is going to change code needs to be reworked.
1792 */
1793 DBUG_ASSERT(! thd->transaction_rollback_request);
1794 trans_rollback_stmt(thd);
1795 goto err_unlock; // Parse query
1796 }
1797 }
1798 else
1799 DBUG_PRINT("qcache", ("handler allow caching %s,%s",
1800 table_list.db, table_list.alias));
1801 }
1802 move_to_query_list_end(query_block);
1803 hits++;
1804 unlock();
1805
1806 /*
1807 Send cached result to client
1808 */
1809 #ifndef EMBEDDED_LIBRARY
1810 THD_STAGE_INFO(thd, stage_sending_cached_result_to_client);
1811 do
1812 {
1813 DBUG_PRINT("qcache", ("Results (len: %lu used: %lu headers: %lu)",
1814 result_block->length, result_block->used,
1815 (ulong) (result_block->headers_len()+
1816 ALIGN_SIZE(sizeof(Query_cache_result)))));
1817
1818 Query_cache_result *result = result_block->result();
1819 if (send_data_in_chunks(&thd->net, result->data(),
1820 result_block->used -
1821 result_block->headers_len() -
1822 ALIGN_SIZE(sizeof(Query_cache_result))))
1823 break; // Client aborted
1824 result_block = result_block->next;
1825 thd->net.pkt_nr= query->last_pkt_nr; // Keep packet number updated
1826 } while (result_block != first_result_block);
1827 #else
1828 {
1829 Querycache_stream qs(result_block, result_block->headers_len() +
1830 ALIGN_SIZE(sizeof(Query_cache_result)));
1831 emb_load_querycache_result(thd, &qs);
1832 }
1833 #endif /*!EMBEDDED_LIBRARY*/
1834
1835 thd->limit_found_rows = query->found_rows();
1836 thd->status_var.last_query_cost= 0.0;
1837
1838 {
1839 Opt_trace_start ots(thd, NULL, SQLCOM_SELECT, NULL,
1840 thd->query(), thd->query_length(), NULL,
1841 thd->variables.character_set_client);
1842
1843 Opt_trace_object (&thd->opt_trace)
1844 .add("query_result_read_from_cache", true);
1845 }
1846
1847 /*
1848 End the statement transaction potentially started by an
1849 engine callback. We ignore the return value for now,
1850 since as long as EOF packet is part of the query cache
1851 response, we can't handle it anyway.
1852 */
1853 (void) trans_commit_stmt(thd);
1854 if (!thd->get_stmt_da()->is_set())
1855 thd->get_stmt_da()->disable_status();
1856
1857 BLOCK_UNLOCK_RD(query_block);
1858 MYSQL_QUERY_CACHE_HIT(thd->query(), (ulong) thd->limit_found_rows);
1859 DBUG_RETURN(1); // Result sent to client
1860
1861 err_unlock:
1862 unlock();
1863 err:
1864 MYSQL_QUERY_CACHE_MISS(thd->query());
1865 DBUG_RETURN(0); // Query was not cached
1866 }
1867
1868
1869 /*
1870 Remove all cached queries that uses any of the tables in the list
1871 */
1872
invalidate(THD * thd,TABLE_LIST * tables_used,my_bool using_transactions)1873 void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
1874 my_bool using_transactions)
1875 {
1876 DBUG_ENTER("Query_cache::invalidate (table list)");
1877 if (is_disabled())
1878 DBUG_VOID_RETURN;
1879
1880 using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
1881 for (; tables_used; tables_used= tables_used->next_local)
1882 {
1883 DBUG_ASSERT(!using_transactions || tables_used->table!=0);
1884 if (tables_used->derived)
1885 continue;
1886 if (using_transactions &&
1887 (tables_used->table->file->table_cache_type() ==
1888 HA_CACHE_TBL_TRANSACT))
1889 /*
1890 tables_used->table can't be 0 in transaction.
1891 Only 'drop' invalidate not opened table, but 'drop'
1892 force transaction finish.
1893 */
1894 thd->add_changed_table(tables_used->table);
1895 else
1896 invalidate_table(thd, tables_used);
1897 }
1898
1899 DEBUG_SYNC(thd, "wait_after_query_cache_invalidate");
1900
1901 DBUG_VOID_RETURN;
1902 }
1903
invalidate(CHANGED_TABLE_LIST * tables_used)1904 void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
1905 {
1906 DBUG_ENTER("Query_cache::invalidate (changed table list)");
1907 if (is_disabled())
1908 DBUG_VOID_RETURN;
1909
1910 THD *thd= current_thd;
1911 for (; tables_used; tables_used= tables_used->next)
1912 {
1913 THD_STAGE_INFO(thd, stage_invalidating_query_cache_entries_table_list);
1914 invalidate_table(thd, (uchar*) tables_used->key, tables_used->key_length);
1915 DBUG_PRINT("qcache", ("db: %s table: %s", tables_used->key,
1916 tables_used->key+
1917 strlen(tables_used->key)+1));
1918 }
1919 DBUG_VOID_RETURN;
1920 }
1921
1922
1923 /*
1924 Invalidate locked for write
1925
1926 SYNOPSIS
1927 Query_cache::invalidate_locked_for_write()
1928 tables_used - table list
1929
1930 NOTE
1931 can be used only for opened tables
1932 */
invalidate_locked_for_write(TABLE_LIST * tables_used)1933 void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used)
1934 {
1935 DBUG_ENTER("Query_cache::invalidate_locked_for_write");
1936 if (is_disabled())
1937 DBUG_VOID_RETURN;
1938
1939 THD *thd= current_thd;
1940 for (; tables_used; tables_used= tables_used->next_local)
1941 {
1942 THD_STAGE_INFO(thd, stage_invalidating_query_cache_entries_table);
1943 if (tables_used->lock_type >= TL_WRITE_ALLOW_WRITE &&
1944 tables_used->table)
1945 {
1946 invalidate_table(thd, tables_used->table);
1947 }
1948 }
1949 DBUG_VOID_RETURN;
1950 }
1951
1952 /*
1953 Remove all cached queries that uses the given table
1954 */
1955
invalidate(THD * thd,TABLE * table,my_bool using_transactions)1956 void Query_cache::invalidate(THD *thd, TABLE *table,
1957 my_bool using_transactions)
1958 {
1959 DBUG_ENTER("Query_cache::invalidate (table)");
1960 if (is_disabled())
1961 DBUG_VOID_RETURN;
1962
1963 using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
1964 if (using_transactions &&
1965 (table->file->table_cache_type() == HA_CACHE_TBL_TRANSACT))
1966 thd->add_changed_table(table);
1967 else
1968 invalidate_table(thd, table);
1969
1970
1971 DBUG_VOID_RETURN;
1972 }
1973
invalidate(THD * thd,const char * key,uint32 key_length,my_bool using_transactions)1974 void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
1975 my_bool using_transactions)
1976 {
1977 DBUG_ENTER("Query_cache::invalidate (key)");
1978 if (is_disabled())
1979 DBUG_VOID_RETURN;
1980
1981 using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
1982 if (using_transactions) // used for innodb => has_transactions() is TRUE
1983 thd->add_changed_table(key, key_length);
1984 else
1985 invalidate_table(thd, (uchar*)key, key_length);
1986
1987 DBUG_VOID_RETURN;
1988 }
1989
1990
1991 /**
1992 Remove all cached queries that uses the given database.
1993 */
1994
invalidate(char * db)1995 void Query_cache::invalidate(char *db)
1996 {
1997
1998 DBUG_ENTER("Query_cache::invalidate (db)");
1999 if (is_disabled())
2000 DBUG_VOID_RETURN;
2001
2002 bool restart= FALSE;
2003 /*
2004 Lock the query cache and queue all invalidation attempts to avoid
2005 the risk of a race between invalidation, cache inserts and flushes.
2006 */
2007 lock();
2008
2009 THD *thd= current_thd;
2010
2011 if (query_cache_size > 0)
2012 {
2013 if (tables_blocks)
2014 {
2015 Query_cache_block *table_block = tables_blocks;
2016 do {
2017 restart= FALSE;
2018 do
2019 {
2020 Query_cache_block *next= table_block->next;
2021 Query_cache_table *table = table_block->table();
2022 if (strcmp(table->db(),db) == 0)
2023 {
2024 Query_cache_block_table *list_root= table_block->table(0);
2025 invalidate_query_block_list(thd,list_root);
2026 }
2027
2028 table_block= next;
2029
2030 /*
2031 If our root node to used tables became null then the last element
2032 in the table list was removed when a query was invalidated;
2033 Terminate the search.
2034 */
2035 if (tables_blocks == 0)
2036 {
2037 table_block= tables_blocks;
2038 }
2039 /*
2040 If the iterated list has changed underlying structure;
2041 we need to restart the search.
2042 */
2043 else if (table_block->type == Query_cache_block::FREE)
2044 {
2045 restart= TRUE;
2046 table_block= tables_blocks;
2047 }
2048 /*
2049 The used tables are linked in a circular list;
2050 loop until we return to the begining.
2051 */
2052 } while (table_block != tables_blocks);
2053 /*
2054 Invalidating a table will also mean that all cached queries using
2055 this table also will be invalidated. This will in turn change the
2056 list of tables associated with these queries and the linked list of
2057 used table will be changed. Because of this we might need to restart
2058 the search when a table has been invalidated.
2059 */
2060 } while (restart);
2061 } // end if( tables_blocks )
2062 }
2063 unlock();
2064
2065 DBUG_VOID_RETURN;
2066 }
2067
2068
invalidate_by_MyISAM_filename(const char * filename)2069 void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
2070 {
2071 DBUG_ENTER("Query_cache::invalidate_by_MyISAM_filename");
2072
2073 /* Calculate the key outside the lock to make the lock shorter */
2074 char key[MAX_DBKEY_LENGTH];
2075 uint32 db_length;
2076 uint key_length= filename_2_table_key(key, filename, &db_length);
2077 THD *thd= current_thd;
2078 invalidate_table(thd,(uchar *)key, key_length);
2079 DBUG_VOID_RETURN;
2080 }
2081
2082 /* Remove all queries from cache */
2083
flush()2084 void Query_cache::flush()
2085 {
2086 DBUG_ENTER("Query_cache::flush");
2087 if (is_disabled())
2088 DBUG_VOID_RETURN;
2089
2090 QC_DEBUG_SYNC("wait_in_query_cache_flush1");
2091
2092 lock_and_suspend();
2093 if (query_cache_size > 0)
2094 {
2095 DUMP(this);
2096 flush_cache();
2097 DUMP(this);
2098 }
2099
2100 DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
2101 unlock();
2102 DBUG_VOID_RETURN;
2103 }
2104
2105
2106 /**
2107 Rearrange the memory blocks and join result in cache in 1 block (if
2108 result length > join_limit)
2109
2110 @param[in] join_limit If the minimum length of a result block to be joined.
2111 @param[in] iteration_limit The maximum number of packing and joining
2112 sequences.
2113
2114 */
2115
pack(ulong join_limit,uint iteration_limit)2116 void Query_cache::pack(ulong join_limit, uint iteration_limit)
2117 {
2118 DBUG_ENTER("Query_cache::pack");
2119
2120 if (is_disabled())
2121 DBUG_VOID_RETURN;
2122
2123 /*
2124 If the entire qc is being invalidated we can bail out early
2125 instead of waiting for the lock.
2126 */
2127 if (try_lock())
2128 DBUG_VOID_RETURN;
2129
2130 if (query_cache_size == 0)
2131 {
2132 unlock();
2133 DBUG_VOID_RETURN;
2134 }
2135
2136 uint i = 0;
2137 do
2138 {
2139 pack_cache();
2140 } while ((++i < iteration_limit) && join_results(join_limit));
2141
2142 unlock();
2143 DBUG_VOID_RETURN;
2144 }
2145
2146
destroy()2147 void Query_cache::destroy()
2148 {
2149 DBUG_ENTER("Query_cache::destroy");
2150 if (!initialized)
2151 {
2152 DBUG_PRINT("qcache", ("Query Cache not initialized"));
2153 }
2154 else
2155 {
2156 /* Underlying code expects the lock. */
2157 lock_and_suspend();
2158 free_cache();
2159 unlock();
2160
2161 mysql_cond_destroy(&COND_cache_status_changed);
2162 mysql_mutex_destroy(&structure_guard_mutex);
2163 initialized = 0;
2164 }
2165 DBUG_VOID_RETURN;
2166 }
2167
2168
2169 /*****************************************************************************
2170 init/destroy
2171 *****************************************************************************/
2172
init()2173 void Query_cache::init()
2174 {
2175 DBUG_ENTER("Query_cache::init");
2176 mysql_mutex_init(key_structure_guard_mutex,
2177 &structure_guard_mutex, MY_MUTEX_INIT_FAST);
2178 mysql_cond_init(key_COND_cache_status_changed,
2179 &COND_cache_status_changed, NULL);
2180 m_cache_lock_status= Query_cache::UNLOCKED;
2181 initialized = 1;
2182 /*
2183 If we explicitly turn off query cache from the command line query cache will
2184 be disabled for the reminder of the server life time. This is because we
2185 want to avoid locking the QC specific mutex if query cache isn't going to
2186 be used.
2187 */
2188 if (global_system_variables.query_cache_type == 0)
2189 query_cache.disable_query_cache();
2190
2191 DBUG_VOID_RETURN;
2192 }
2193
2194
init_cache()2195 ulong Query_cache::init_cache()
2196 {
2197 uint mem_bin_count, num, step;
2198 ulong mem_bin_size, prev_size, inc;
2199 ulong additional_data_size, max_mem_bin_size, approx_additional_data_size;
2200 int align;
2201
2202 DBUG_ENTER("Query_cache::init_cache");
2203
2204 approx_additional_data_size = (sizeof(Query_cache) +
2205 sizeof(uchar*)*(def_query_hash_size+
2206 def_table_hash_size));
2207 if (query_cache_size < approx_additional_data_size)
2208 goto err;
2209
2210 query_cache_size-= approx_additional_data_size;
2211 align= query_cache_size % ALIGN_SIZE(1);
2212 if (align)
2213 {
2214 query_cache_size-= align;
2215 approx_additional_data_size+= align;
2216 }
2217
2218 /*
2219 Count memory bins number.
2220 Check section 6. in start comment for the used algorithm.
2221 */
2222
2223 max_mem_bin_size = query_cache_size >> QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2;
2224 mem_bin_count = (uint) ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
2225 QUERY_CACHE_MEM_BIN_PARTS_MUL);
2226 mem_bin_num = 1;
2227 mem_bin_steps = 1;
2228 mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
2229 prev_size = 0;
2230 if (mem_bin_size <= min_allocation_unit)
2231 {
2232 DBUG_PRINT("qcache", ("too small query cache => query cache disabled"));
2233 // TODO here (and above) should be warning in 4.1
2234 goto err;
2235 }
2236 while (mem_bin_size > min_allocation_unit)
2237 {
2238 mem_bin_num += mem_bin_count;
2239 prev_size = mem_bin_size;
2240 mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
2241 mem_bin_steps++;
2242 mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
2243 mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
2244
2245 // Prevent too small bins spacing
2246 if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
2247 mem_bin_count= (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
2248 }
2249 inc = (prev_size - mem_bin_size) / mem_bin_count;
2250 mem_bin_num += (mem_bin_count - (min_allocation_unit - mem_bin_size)/inc);
2251 mem_bin_steps++;
2252 additional_data_size = ((mem_bin_num+1) *
2253 ALIGN_SIZE(sizeof(Query_cache_memory_bin))+
2254 (mem_bin_steps *
2255 ALIGN_SIZE(sizeof(Query_cache_memory_bin_step))));
2256
2257 if (query_cache_size < additional_data_size)
2258 goto err;
2259 query_cache_size -= additional_data_size;
2260
2261 if (!(cache= (uchar *)
2262 my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
2263 goto err;
2264
2265 DBUG_PRINT("qcache", ("cache length %lu, min unit %lu, %u bins",
2266 query_cache_size, min_allocation_unit, mem_bin_num));
2267
2268 steps = (Query_cache_memory_bin_step *) cache;
2269 bins = ((Query_cache_memory_bin *)
2270 (cache + mem_bin_steps *
2271 ALIGN_SIZE(sizeof(Query_cache_memory_bin_step))));
2272
2273 first_block = (Query_cache_block *) (cache + additional_data_size);
2274 first_block->init(query_cache_size);
2275 total_blocks++;
2276 first_block->pnext=first_block->pprev=first_block;
2277 first_block->next=first_block->prev=first_block;
2278
2279 /* Prepare bins */
2280
2281 bins[0].init(max_mem_bin_size);
2282 steps[0].init(max_mem_bin_size,0,0);
2283 mem_bin_count = (uint) ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
2284 QUERY_CACHE_MEM_BIN_PARTS_MUL);
2285 num= step= 1;
2286 mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
2287 while (mem_bin_size > min_allocation_unit)
2288 {
2289 ulong incr = (steps[step-1].size - mem_bin_size) / mem_bin_count;
2290 unsigned long size = mem_bin_size;
2291 for (uint i= mem_bin_count; i > 0; i--)
2292 {
2293 bins[num+i-1].init(size);
2294 size += incr;
2295 }
2296 num += mem_bin_count;
2297 steps[step].init(mem_bin_size, num-1, incr);
2298 mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
2299 step++;
2300 mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
2301 mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
2302 if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
2303 mem_bin_count=(mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
2304 }
2305 inc = (steps[step-1].size - mem_bin_size) / mem_bin_count;
2306
2307 /*
2308 num + mem_bin_count > mem_bin_num, but index never be > mem_bin_num
2309 because block with size < min_allocated_unit never will be requested
2310 */
2311
2312 steps[step].init(mem_bin_size, num + mem_bin_count - 1, inc);
2313 {
2314 uint skiped = (min_allocation_unit - mem_bin_size)/inc;
2315 ulong size = mem_bin_size + inc*skiped;
2316 uint i = mem_bin_count - skiped;
2317 while (i-- > 0)
2318 {
2319 bins[num+i].init(size);
2320 size += inc;
2321 }
2322 }
2323 bins[mem_bin_num].number = 1; // For easy end test in get_free_block
2324 free_memory = free_memory_blocks = 0;
2325 insert_into_free_memory_list(first_block);
2326
2327 DUMP(this);
2328
2329 (void) my_hash_init(&queries, &my_charset_bin, def_query_hash_size, 0, 0,
2330 query_cache_query_get_key, 0, 0);
2331 #ifndef FN_NO_CASE_SENSE
2332 /*
2333 If lower_case_table_names!=0 then db and table names are already
2334 converted to lower case and we can use binary collation for their
2335 comparison (no matter if file system case sensitive or not).
2336 If we have case-sensitive file system (like on most Unixes) and
2337 lower_case_table_names == 0 then we should distinguish my_table
2338 and MY_TABLE cases and so again can use binary collation.
2339 */
2340 (void) my_hash_init(&tables, &my_charset_bin, def_table_hash_size, 0, 0,
2341 query_cache_table_get_key, 0, 0);
2342 #else
2343 /*
2344 On windows, OS/2, MacOS X with HFS+ or any other case insensitive
2345 file system if lower_case_table_names!=0 we have same situation as
2346 in previous case, but if lower_case_table_names==0 then we should
2347 not distinguish cases (to be compatible in behavior with underlying
2348 file system) and so should use case insensitive collation for
2349 comparison.
2350 */
2351 (void) my_hash_init(&tables,
2352 lower_case_table_names ? &my_charset_bin :
2353 files_charset_info,
2354 def_table_hash_size, 0, 0,query_cache_table_get_key,
2355 0, 0);
2356 #endif
2357
2358 queries_in_cache = 0;
2359 queries_blocks = 0;
2360 DBUG_RETURN(query_cache_size +
2361 additional_data_size + approx_additional_data_size);
2362
2363 err:
2364 make_disabled();
2365 DBUG_RETURN(0);
2366 }
2367
2368
2369 /* Disable the use of the query cache */
2370
make_disabled()2371 void Query_cache::make_disabled()
2372 {
2373 DBUG_ENTER("Query_cache::make_disabled");
2374 query_cache_size= 0;
2375 queries_blocks= 0;
2376 free_memory= 0;
2377 free_memory_blocks= 0;
2378 bins= 0;
2379 steps= 0;
2380 cache= 0;
2381 mem_bin_num= mem_bin_steps= 0;
2382 queries_in_cache= 0;
2383 first_block= 0;
2384 total_blocks= 0;
2385 tables_blocks= 0;
2386 DBUG_VOID_RETURN;
2387 }
2388
2389
2390 /**
2391 @class Query_cache
2392 Free all resources allocated by the cache.
2393
2394 This function frees all resources allocated by the cache. You
2395 have to call init_cache() before using the cache again. This function
2396 requires the structure_guard_mutex to be locked.
2397 */
2398
free_cache()2399 void Query_cache::free_cache()
2400 {
2401 DBUG_ENTER("Query_cache::free_cache");
2402
2403 my_free(cache);
2404 make_disabled();
2405 my_hash_free(&queries);
2406 my_hash_free(&tables);
2407 DBUG_VOID_RETURN;
2408 }
2409
2410 /*****************************************************************************
2411 Free block data
2412 *****************************************************************************/
2413
2414
2415 /**
2416 Flush the cache.
2417
2418 This function will flush cache contents. It assumes we have
2419 'structure_guard_mutex' locked. The function sets the m_cache_status flag and
2420 releases the lock, so other threads may proceed skipping the cache as if it
2421 is disabled. Concurrent flushes are performed in turn.
2422 After flush_cache() call, the cache is flushed, all the freed memory is
2423 accumulated in bin[0], and the 'structure_guard_mutex' is locked. However,
2424 since we could release the mutex during execution, the rest of the cache
2425 state could have been changed, and should not be relied on.
2426 */
2427
flush_cache()2428 void Query_cache::flush_cache()
2429 {
2430 QC_DEBUG_SYNC("wait_in_query_cache_flush2");
2431
2432 my_hash_reset(&queries);
2433 while (queries_blocks != 0)
2434 {
2435 BLOCK_LOCK_WR(queries_blocks);
2436 free_query_internal(queries_blocks);
2437 }
2438 }
2439
2440 /*
2441 Free oldest query that is not in use by another thread.
2442 Returns 1 if we couldn't remove anything
2443 */
2444
free_old_query()2445 my_bool Query_cache::free_old_query()
2446 {
2447 DBUG_ENTER("Query_cache::free_old_query");
2448 if (queries_blocks)
2449 {
2450 /*
2451 try_lock_writing used to prevent client because here lock
2452 sequence is breached.
2453 Also we don't need remove locked queries at this point.
2454 */
2455 Query_cache_block *query_block= 0;
2456 if (queries_blocks != 0)
2457 {
2458 Query_cache_block *block = queries_blocks;
2459 /* Search until we find first query that we can remove */
2460 do
2461 {
2462 Query_cache_query *header = block->query();
2463 if (header->result() != 0 &&
2464 header->result()->type == Query_cache_block::RESULT &&
2465 block->query()->try_lock_writing())
2466 {
2467 query_block = block;
2468 break;
2469 }
2470 } while ((block=block->next) != queries_blocks );
2471 }
2472
2473 if (query_block != 0)
2474 {
2475 free_query(query_block);
2476 lowmem_prunes++;
2477 DBUG_RETURN(0);
2478 }
2479 }
2480 DBUG_RETURN(1); // Nothing to remove
2481 }
2482
2483
2484 /*
2485 free_query_internal() - free query from query cache.
2486
2487 SYNOPSIS
2488 free_query_internal()
2489 query_block Query_cache_block representing the query
2490
2491 DESCRIPTION
2492 This function will remove the query from a cache, and place its
2493 memory blocks to the list of free blocks. 'query_block' must be
2494 locked for writing, this function will release (and destroy) this
2495 lock.
2496
2497 NOTE
2498 'query_block' should be removed from 'queries' hash _before_
2499 calling this method, as the lock will be destroyed here.
2500 */
2501
free_query_internal(Query_cache_block * query_block)2502 void Query_cache::free_query_internal(Query_cache_block *query_block)
2503 {
2504 DBUG_ENTER("Query_cache::free_query_internal");
2505 DBUG_PRINT("qcache", ("free query 0x%lx %lu bytes result",
2506 (ulong) query_block,
2507 query_block->query()->length() ));
2508
2509 queries_in_cache--;
2510
2511 Query_cache_query *query= query_block->query();
2512
2513 if (query->writer() != 0)
2514 {
2515 /* Tell MySQL that this query should not be cached anymore */
2516 query->writer()->first_query_block= NULL;
2517 query->writer(0);
2518 }
2519 double_linked_list_exclude(query_block, &queries_blocks);
2520 Query_cache_block_table *table= query_block->table(0);
2521
2522 for (TABLE_COUNTER_TYPE i= 0; i < query_block->n_tables; i++)
2523 unlink_table(table++);
2524 Query_cache_block *result_block= query->result();
2525
2526 /*
2527 The following is true when query destruction was called and no results
2528 in query . (query just registered and then abort/pack/flush called)
2529 */
2530 if (result_block != 0)
2531 {
2532 if (result_block->type != Query_cache_block::RESULT)
2533 {
2534 // removing unfinished query
2535 refused++;
2536 inserts--;
2537 }
2538 Query_cache_block *block= result_block;
2539 do
2540 {
2541 Query_cache_block *current= block;
2542 block= block->next;
2543 free_memory_block(current);
2544 } while (block != result_block);
2545 }
2546 else
2547 {
2548 // removing unfinished query
2549 refused++;
2550 inserts--;
2551 }
2552
2553 query->unlock_n_destroy();
2554 free_memory_block(query_block);
2555
2556 DBUG_VOID_RETURN;
2557 }
2558
2559
2560 /*
2561 free_query() - free query from query cache.
2562
2563 SYNOPSIS
2564 free_query()
2565 query_block Query_cache_block representing the query
2566
2567 DESCRIPTION
2568 This function will remove 'query_block' from 'queries' hash, and
2569 then call free_query_internal(), which see.
2570 */
2571
free_query(Query_cache_block * query_block)2572 void Query_cache::free_query(Query_cache_block *query_block)
2573 {
2574 DBUG_ENTER("Query_cache::free_query");
2575 DBUG_PRINT("qcache", ("free query 0x%lx %lu bytes result",
2576 (ulong) query_block,
2577 query_block->query()->length() ));
2578
2579 my_hash_delete(&queries,(uchar *) query_block);
2580 free_query_internal(query_block);
2581
2582 DBUG_VOID_RETURN;
2583 }
2584
2585 /*****************************************************************************
2586 Query data creation
2587 *****************************************************************************/
2588
2589 Query_cache_block *
write_block_data(ulong data_len,uchar * data,ulong header_len,Query_cache_block::block_type type,TABLE_COUNTER_TYPE ntab)2590 Query_cache::write_block_data(ulong data_len, uchar* data,
2591 ulong header_len,
2592 Query_cache_block::block_type type,
2593 TABLE_COUNTER_TYPE ntab)
2594 {
2595 ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
2596 ALIGN_SIZE(ntab*sizeof(Query_cache_block_table)) +
2597 header_len);
2598 ulong len = data_len + all_headers_len;
2599 ulong align_len= ALIGN_SIZE(len);
2600 DBUG_ENTER("Query_cache::write_block_data");
2601 DBUG_PRINT("qcache", ("data: %ld, header: %ld, all header: %ld",
2602 data_len, header_len, all_headers_len));
2603 Query_cache_block *block= allocate_block(max(align_len,
2604 min_allocation_unit),1, 0);
2605 if (block != 0)
2606 {
2607 block->type = type;
2608 block->n_tables = ntab;
2609 block->used = len;
2610
2611 memcpy((uchar *) block+ all_headers_len, data, data_len);
2612 }
2613 DBUG_RETURN(block);
2614 }
2615
2616
2617 my_bool
append_result_data(Query_cache_block ** current_block,ulong data_len,uchar * data,Query_cache_block * query_block)2618 Query_cache::append_result_data(Query_cache_block **current_block,
2619 ulong data_len, uchar* data,
2620 Query_cache_block *query_block)
2621 {
2622 DBUG_ENTER("Query_cache::append_result_data");
2623 DBUG_PRINT("qcache", ("append %lu bytes to 0x%lx query",
2624 data_len, (long) query_block));
2625
2626 if (query_block->query()->add(data_len) > query_cache_limit)
2627 {
2628 DBUG_PRINT("qcache", ("size limit reached %lu > %lu",
2629 query_block->query()->length(),
2630 query_cache_limit));
2631 DBUG_RETURN(0);
2632 }
2633 if (*current_block == 0)
2634 {
2635 DBUG_PRINT("qcache", ("allocated first result data block %lu", data_len));
2636 DBUG_RETURN(write_result_data(current_block, data_len, data, query_block,
2637 Query_cache_block::RES_BEG));
2638 }
2639 Query_cache_block *last_block = (*current_block)->prev;
2640
2641 DBUG_PRINT("qcache", ("lastblock 0x%lx len %lu used %lu",
2642 (ulong) last_block, last_block->length,
2643 last_block->used));
2644 my_bool success = 1;
2645 ulong last_block_free_space= last_block->length - last_block->used;
2646
2647 /*
2648 We will first allocate and write the 'tail' of data, that doesn't fit
2649 in the 'last_block'. Only if this succeeds, we will fill the last_block.
2650 This saves us a memcpy if the query doesn't fit in the query cache.
2651 */
2652
2653 // Try join blocks if physically next block is free...
2654 ulong tail = data_len - last_block_free_space;
2655 ulong append_min = get_min_append_result_data_size();
2656 if (last_block_free_space < data_len &&
2657 append_next_free_block(last_block,
2658 max(tail, append_min)))
2659 last_block_free_space = last_block->length - last_block->used;
2660 // If no space in last block (even after join) allocate new block
2661 if (last_block_free_space < data_len)
2662 {
2663 DBUG_PRINT("qcache", ("allocate new block for %lu bytes",
2664 data_len-last_block_free_space));
2665 Query_cache_block *new_block = 0;
2666 success = write_result_data(&new_block, data_len-last_block_free_space,
2667 (uchar*)(((uchar*)data)+last_block_free_space),
2668 query_block,
2669 Query_cache_block::RES_CONT);
2670 /*
2671 new_block may be != 0 even !success (if write_result_data
2672 allocate a small block but failed to allocate continue)
2673 */
2674 if (new_block != 0)
2675 double_linked_list_join(last_block, new_block);
2676 }
2677 else
2678 {
2679 // It is success (nobody can prevent us write data)
2680 unlock();
2681 }
2682
2683 // Now finally write data to the last block
2684 if (success && last_block_free_space > 0)
2685 {
2686 ulong to_copy = min(data_len,last_block_free_space);
2687 DBUG_PRINT("qcache", ("use free space %lub at block 0x%lx to copy %lub",
2688 last_block_free_space, (ulong)last_block, to_copy));
2689 memcpy((uchar*) last_block + last_block->used, data, to_copy);
2690 last_block->used+=to_copy;
2691 }
2692 DBUG_RETURN(success);
2693 }
2694
2695
write_result_data(Query_cache_block ** result_block,ulong data_len,uchar * data,Query_cache_block * query_block,Query_cache_block::block_type type)2696 my_bool Query_cache::write_result_data(Query_cache_block **result_block,
2697 ulong data_len, uchar* data,
2698 Query_cache_block *query_block,
2699 Query_cache_block::block_type type)
2700 {
2701 DBUG_ENTER("Query_cache::write_result_data");
2702 DBUG_PRINT("qcache", ("data_len %lu",data_len));
2703
2704 /*
2705 Reserve block(s) for filling
2706 During data allocation we must have structure_guard_mutex locked.
2707 As data copy is not a fast operation, it's better if we don't have
2708 structure_guard_mutex locked during data coping.
2709 Thus we first allocate space and lock query, then unlock
2710 structure_guard_mutex and copy data.
2711 */
2712
2713 my_bool success = allocate_data_chain(result_block, data_len, query_block,
2714 type == Query_cache_block::RES_BEG);
2715 if (success)
2716 {
2717 // It is success (nobody can prevent us write data)
2718 unlock();
2719 uint headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
2720 ALIGN_SIZE(sizeof(Query_cache_result)));
2721 #ifndef EMBEDDED_LIBRARY
2722 Query_cache_block *block= *result_block;
2723 uchar *rest= data;
2724 // Now fill list of blocks that created by allocate_data_chain
2725 do
2726 {
2727 block->type = type;
2728 ulong length = block->used - headers_len;
2729 DBUG_PRINT("qcache", ("write %lu byte in block 0x%lx",length,
2730 (ulong)block));
2731 memcpy((uchar*) block+headers_len, rest, length);
2732 rest += length;
2733 block = block->next;
2734 type = Query_cache_block::RES_CONT;
2735 } while (block != *result_block);
2736 #else
2737 /*
2738 Set type of first block, emb_store_querycache_result() will handle
2739 the others.
2740 */
2741 (*result_block)->type= type;
2742 Querycache_stream qs(*result_block, headers_len);
2743 emb_store_querycache_result(&qs, (THD*)data);
2744 #endif /*!EMBEDDED_LIBRARY*/
2745 }
2746 else
2747 {
2748 if (*result_block != 0)
2749 {
2750 // Destroy list of blocks that was created & locked by lock_result_data
2751 Query_cache_block *block = *result_block;
2752 do
2753 {
2754 Query_cache_block *current = block;
2755 block = block->next;
2756 free_memory_block(current);
2757 } while (block != *result_block);
2758 *result_block = 0;
2759 /*
2760 It is not success => not unlock structure_guard_mutex (we need it to
2761 free query)
2762 */
2763 }
2764 }
2765 DBUG_PRINT("qcache", ("success %d", (int) success));
2766 DBUG_RETURN(success);
2767 }
2768
get_min_first_result_data_size()2769 inline ulong Query_cache::get_min_first_result_data_size()
2770 {
2771 if (queries_in_cache < QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER)
2772 return min_result_data_size;
2773 ulong avg_result = (query_cache_size - free_memory) / queries_in_cache;
2774 avg_result = min(avg_result, query_cache_limit);
2775 return max(min_result_data_size, avg_result);
2776 }
2777
get_min_append_result_data_size()2778 inline ulong Query_cache::get_min_append_result_data_size()
2779 {
2780 return min_result_data_size;
2781 }
2782
2783 /*
2784 Allocate one or more blocks to hold data
2785 */
allocate_data_chain(Query_cache_block ** result_block,ulong data_len,Query_cache_block * query_block,my_bool first_block_arg)2786 my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
2787 ulong data_len,
2788 Query_cache_block *query_block,
2789 my_bool first_block_arg)
2790 {
2791 ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
2792 ALIGN_SIZE(sizeof(Query_cache_result)));
2793 ulong min_size = (first_block_arg ?
2794 get_min_first_result_data_size():
2795 get_min_append_result_data_size());
2796 Query_cache_block *prev_block= NULL;
2797 Query_cache_block *new_block;
2798 DBUG_ENTER("Query_cache::allocate_data_chain");
2799 DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
2800 data_len, all_headers_len));
2801
2802 do
2803 {
2804 ulong len= data_len + all_headers_len;
2805 ulong align_len= ALIGN_SIZE(len);
2806
2807 if (!(new_block= allocate_block(max(min_size, align_len),
2808 min_result_data_size == 0,
2809 all_headers_len + min_result_data_size)))
2810 {
2811 DBUG_PRINT("warning", ("Can't allocate block for results"));
2812 DBUG_RETURN(FALSE);
2813 }
2814
2815 new_block->n_tables = 0;
2816 new_block->used = min(len, new_block->length);
2817 new_block->type = Query_cache_block::RES_INCOMPLETE;
2818 new_block->next = new_block->prev = new_block;
2819 Query_cache_result *header = new_block->result();
2820 header->parent(query_block);
2821
2822 DBUG_PRINT("qcache", ("Block len %lu used %lu",
2823 new_block->length, new_block->used));
2824
2825 if (prev_block)
2826 double_linked_list_join(prev_block, new_block);
2827 else
2828 *result_block= new_block;
2829 if (new_block->length >= len)
2830 break;
2831
2832 /*
2833 We got less memory then we need (no big memory blocks) =>
2834 Continue to allocated more blocks until we got everything we need.
2835 */
2836 data_len= len - new_block->length;
2837 prev_block= new_block;
2838 } while (1);
2839
2840 DBUG_RETURN(TRUE);
2841 }
2842
2843 /*****************************************************************************
2844 Tables management
2845 *****************************************************************************/
2846
2847 /*
2848 Invalidate the first table in the table_list
2849 */
2850
invalidate_table(THD * thd,TABLE_LIST * table_list)2851 void Query_cache::invalidate_table(THD *thd, TABLE_LIST *table_list)
2852 {
2853 if (table_list->table != 0)
2854 invalidate_table(thd, table_list->table); // Table is open
2855 else
2856 {
2857 const char *key;
2858 uint key_length;
2859 key_length= get_table_def_key(table_list, &key);
2860
2861 // We don't store temporary tables => no key_length+=4 ...
2862 invalidate_table(thd, (uchar *)key, key_length);
2863 }
2864 }
2865
invalidate_table(THD * thd,TABLE * table)2866 void Query_cache::invalidate_table(THD *thd, TABLE *table)
2867 {
2868 invalidate_table(thd, (uchar*) table->s->table_cache_key.str,
2869 table->s->table_cache_key.length);
2870 }
2871
invalidate_table(THD * thd,uchar * key,uint32 key_length)2872 void Query_cache::invalidate_table(THD *thd, uchar * key, uint32 key_length)
2873 {
2874 DEBUG_SYNC(thd, "wait_in_query_cache_invalidate1");
2875
2876 /*
2877 Lock the query cache and queue all invalidation attempts to avoid
2878 the risk of a race between invalidation, cache inserts and flushes.
2879 */
2880 lock();
2881
2882 DEBUG_SYNC(thd, "wait_in_query_cache_invalidate2");
2883
2884 if (query_cache_size > 0)
2885 invalidate_table_internal(thd, key, key_length);
2886
2887 unlock();
2888 }
2889
2890
2891 /**
2892 Try to locate and invalidate a table by name.
2893 The caller must ensure that no other thread is trying to work with
2894 the query cache when this function is executed.
2895
2896 @pre structure_guard_mutex is acquired or LOCKED is set.
2897 */
2898
2899 void
invalidate_table_internal(THD * thd,uchar * key,uint32 key_length)2900 Query_cache::invalidate_table_internal(THD *thd, uchar *key, uint32 key_length)
2901 {
2902 Query_cache_block *table_block=
2903 (Query_cache_block*)my_hash_search(&tables, key, key_length);
2904 if (table_block)
2905 {
2906 Query_cache_block_table *list_root= table_block->table(0);
2907 invalidate_query_block_list(thd, list_root);
2908 }
2909 }
2910
2911 /**
2912 Invalidate a linked list of query cache blocks.
2913
2914 Each block tries to acquire a block level lock before
2915 free_query is a called. This function will in turn affect
2916 related table- and result-blocks.
2917
2918 @param[in,out] thd Thread context.
2919 @param[in,out] list_root A pointer to a circular list of query blocks.
2920
2921 */
2922
2923 void
invalidate_query_block_list(THD * thd,Query_cache_block_table * list_root)2924 Query_cache::invalidate_query_block_list(THD *thd,
2925 Query_cache_block_table *list_root)
2926 {
2927 while (list_root->next != list_root)
2928 {
2929 Query_cache_block *query_block= list_root->next->block();
2930 BLOCK_LOCK_WR(query_block);
2931 free_query(query_block);
2932 }
2933 }
2934
2935 /*
2936 Register given table list begining with given position in tables table of
2937 block
2938
2939 SYNOPSIS
2940 Query_cache::register_tables_from_list
2941 tables_used given table list
2942 counter number current position in table of tables of block
2943 block_table pointer to current position in tables table of block
2944
2945 RETURN
2946 0 error
2947 number of next position of table entry in table of tables of block
2948 */
2949
2950 TABLE_COUNTER_TYPE
register_tables_from_list(TABLE_LIST * tables_used,TABLE_COUNTER_TYPE counter,Query_cache_block_table * block_table)2951 Query_cache::register_tables_from_list(TABLE_LIST *tables_used,
2952 TABLE_COUNTER_TYPE counter,
2953 Query_cache_block_table *block_table)
2954 {
2955 TABLE_COUNTER_TYPE n;
2956 DBUG_ENTER("Query_cache::register_tables_from_list");
2957 for (n= counter;
2958 tables_used;
2959 tables_used= tables_used->next_global, n++, block_table++)
2960 {
2961 if (tables_used->is_anonymous_derived_table())
2962 {
2963 DBUG_PRINT("qcache", ("derived table skipped"));
2964 n--;
2965 block_table--;
2966 continue;
2967 }
2968 block_table->n= n;
2969 if (tables_used->view)
2970 {
2971 const char *key;
2972 uint key_length;
2973 DBUG_PRINT("qcache", ("view: %s db: %s",
2974 tables_used->view_name.str,
2975 tables_used->view_db.str));
2976 key_length= get_table_def_key(tables_used, &key);
2977 /*
2978 There are not callback function for for VIEWs
2979 */
2980 if (!insert_table(key_length, key, block_table,
2981 tables_used->view_db.length + 1,
2982 HA_CACHE_TBL_NONTRANSACT, 0, 0))
2983 DBUG_RETURN(0);
2984 /*
2985 We do not need to register view tables here because they are already
2986 present in the global list.
2987 */
2988 }
2989 else
2990 {
2991 DBUG_PRINT("qcache",
2992 ("table: %s db: %s openinfo: 0x%lx keylen: %lu key: 0x%lx",
2993 tables_used->table->s->table_name.str,
2994 tables_used->table->s->table_cache_key.str,
2995 (ulong) tables_used->table,
2996 (ulong) tables_used->table->s->table_cache_key.length,
2997 (ulong) tables_used->table->s->table_cache_key.str));
2998
2999 if (!insert_table(tables_used->table->s->table_cache_key.length,
3000 tables_used->table->s->table_cache_key.str,
3001 block_table,
3002 tables_used->db_length,
3003 tables_used->table->file->table_cache_type(),
3004 tables_used->callback_func,
3005 tables_used->engine_data))
3006 DBUG_RETURN(0);
3007
3008 #ifdef WITH_MYISAMMRG_STORAGE_ENGINE
3009 /*
3010 XXX FIXME: Some generic mechanism is required here instead of this
3011 MYISAMMRG-specific implementation.
3012 */
3013 if (tables_used->table->s->db_type()->db_type == DB_TYPE_MRG_MYISAM)
3014 {
3015 ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
3016 MYRG_INFO *file = handler->myrg_info();
3017 for (MYRG_TABLE *table = file->open_tables;
3018 table != file->end_table ;
3019 table++)
3020 {
3021 char key[MAX_DBKEY_LENGTH];
3022 uint32 db_length;
3023 uint key_length= filename_2_table_key(key, table->table->filename,
3024 &db_length);
3025 (++block_table)->n= ++n;
3026 /*
3027 There are not callback function for for MyISAM, and engine data
3028 */
3029 if (!insert_table(key_length, key, block_table,
3030 db_length,
3031 tables_used->table->file->table_cache_type(),
3032 0, 0))
3033 DBUG_RETURN(0);
3034 }
3035 }
3036 #endif
3037 }
3038 }
3039 DBUG_RETURN(n - counter);
3040 }
3041
3042 /*
3043 Store all used tables
3044
3045 SYNOPSIS
3046 register_all_tables()
3047 block Store tables in this block
3048 tables_used List if used tables
3049 tables_arg Not used ?
3050 */
3051
register_all_tables(Query_cache_block * block,TABLE_LIST * tables_used,TABLE_COUNTER_TYPE tables_arg)3052 my_bool Query_cache::register_all_tables(Query_cache_block *block,
3053 TABLE_LIST *tables_used,
3054 TABLE_COUNTER_TYPE tables_arg)
3055 {
3056 TABLE_COUNTER_TYPE n;
3057 DBUG_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x",
3058 (ulong) block, (int) tables_arg,
3059 (int) ALIGN_SIZE(sizeof(Query_cache_block))));
3060
3061 Query_cache_block_table *block_table = block->table(0);
3062
3063 n= register_tables_from_list(tables_used, 0, block_table);
3064
3065 if (n==0)
3066 {
3067 /* Unlink the tables we allocated above */
3068 for (Query_cache_block_table *tmp = block->table(0) ;
3069 tmp != block_table;
3070 tmp++)
3071 unlink_table(tmp);
3072 }
3073 return MY_TEST(n);
3074 }
3075
3076
3077 /**
3078 Insert used table name into the cache.
3079
3080 @return Error status
3081 @retval FALSE On error
3082 @retval TRUE On success
3083 */
3084
3085 my_bool
insert_table(uint key_len,const char * key,Query_cache_block_table * node,uint32 db_length,uint8 cache_type,qc_engine_callback callback,ulonglong engine_data)3086 Query_cache::insert_table(uint key_len, const char *key,
3087 Query_cache_block_table *node,
3088 uint32 db_length, uint8 cache_type,
3089 qc_engine_callback callback,
3090 ulonglong engine_data)
3091 {
3092 DBUG_ENTER("Query_cache::insert_table");
3093 DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d",
3094 (ulong)node, key_len));
3095
3096 THD *thd= current_thd;
3097
3098 Query_cache_block *table_block=
3099 (Query_cache_block *) my_hash_search(&tables, (uchar*) key, key_len);
3100
3101 if (table_block &&
3102 table_block->table()->engine_data() != engine_data)
3103 {
3104 DBUG_PRINT("qcache",
3105 ("Handler require invalidation queries of %s.%s %lu-%lu",
3106 table_block->table()->db(),
3107 table_block->table()->table(),
3108 (ulong) engine_data,
3109 (ulong) table_block->table()->engine_data()));
3110 /*
3111 as far as we delete all queries with this table, table block will be
3112 deleted, too
3113 */
3114 {
3115 Query_cache_block_table *list_root= table_block->table(0);
3116 invalidate_query_block_list(thd, list_root);
3117 }
3118
3119 table_block= 0;
3120 }
3121
3122 if (table_block == 0)
3123 {
3124 DBUG_PRINT("qcache", ("new table block from 0x%lx (%u)",
3125 (ulong) key, (int) key_len));
3126 table_block= write_block_data(key_len, (uchar*) key,
3127 ALIGN_SIZE(sizeof(Query_cache_table)),
3128 Query_cache_block::TABLE, 1);
3129 if (table_block == 0)
3130 {
3131 DBUG_PRINT("qcache", ("Can't write table name to cache"));
3132 DBUG_RETURN(0);
3133 }
3134 Query_cache_table *header= table_block->table();
3135 double_linked_list_simple_include(table_block,
3136 &tables_blocks);
3137 /*
3138 First node in the Query_cache_block_table-chain is the table-type
3139 block. This block will only have one Query_cache_block_table (n=0).
3140 */
3141 Query_cache_block_table *list_root= table_block->table(0);
3142 list_root->n= 0;
3143
3144 /*
3145 The node list is circular in nature.
3146 */
3147 list_root->next= list_root->prev= list_root;
3148
3149 if (my_hash_insert(&tables, (const uchar *) table_block))
3150 {
3151 DBUG_PRINT("qcache", ("Can't insert table to hash"));
3152 // write_block_data return locked block
3153 free_memory_block(table_block);
3154 DBUG_RETURN(0);
3155 }
3156 char *db= header->db();
3157 header->table(db + db_length + 1);
3158 header->key_length(key_len);
3159 header->type(cache_type);
3160 header->callback(callback);
3161 header->engine_data(engine_data);
3162
3163 /*
3164 We insert this table without the assumption that it isn't refrenenced by
3165 any queries.
3166 */
3167 header->m_cached_query_count= 0;
3168 }
3169
3170 /*
3171 Table is now in the cache; link the table_block-node associated
3172 with the currently processed query into the chain of queries depending
3173 on the cached table.
3174 */
3175 Query_cache_block_table *list_root= table_block->table(0);
3176 node->next= list_root->next;
3177 list_root->next= node;
3178 node->next->prev= node;
3179 node->prev= list_root;
3180 node->parent= table_block->table();
3181 /*
3182 Increase the counter to keep track on how long this chain
3183 of queries is.
3184 */
3185 Query_cache_table *table_block_data= table_block->table();
3186 table_block_data->m_cached_query_count++;
3187 DBUG_RETURN(1);
3188 }
3189
3190
unlink_table(Query_cache_block_table * node)3191 void Query_cache::unlink_table(Query_cache_block_table *node)
3192 {
3193 DBUG_ENTER("Query_cache::unlink_table");
3194 node->prev->next= node->next;
3195 node->next->prev= node->prev;
3196 Query_cache_block_table *neighbour= node->next;
3197 Query_cache_table *table_block_data= node->parent;
3198 table_block_data->m_cached_query_count--;
3199
3200 DBUG_ASSERT(table_block_data->m_cached_query_count >= 0);
3201
3202 if (neighbour->next == neighbour)
3203 {
3204 DBUG_ASSERT(table_block_data->m_cached_query_count == 0);
3205 /*
3206 If neighbor is root of list, the list is empty.
3207 The root of the list is always a table-type block
3208 which contain exactly one Query_cache_block_table
3209 node object, thus we can use the block() method
3210 to calculate the Query_cache_block address.
3211 */
3212 Query_cache_block *table_block= neighbour->block();
3213 double_linked_list_exclude(table_block,
3214 &tables_blocks);
3215 my_hash_delete(&tables,(uchar *) table_block);
3216 free_memory_block(table_block);
3217 }
3218 DBUG_VOID_RETURN;
3219 }
3220
3221 /*****************************************************************************
3222 Free memory management
3223 *****************************************************************************/
3224
3225 Query_cache_block *
allocate_block(ulong len,my_bool not_less,ulong minimum)3226 Query_cache::allocate_block(ulong len, my_bool not_less, ulong minimum)
3227 {
3228 DBUG_ENTER("Query_cache::allocate_block");
3229 DBUG_PRINT("qcache", ("len %lu, not less %d, min %lu",
3230 len, not_less, minimum));
3231
3232 if (len >= min(query_cache_size, query_cache_limit))
3233 {
3234 DBUG_PRINT("qcache", ("Query cache hase only %lu memory and limit %lu",
3235 query_cache_size, query_cache_limit));
3236 DBUG_RETURN(0); // in any case we don't have such piece of memory
3237 }
3238
3239 /* Free old queries until we have enough memory to store this block */
3240 Query_cache_block *block;
3241 do
3242 {
3243 block= get_free_block(len, not_less, minimum);
3244 }
3245 while (block == 0 && !free_old_query());
3246
3247 if (block != 0) // If we found a suitable block
3248 {
3249 if (block->length >= ALIGN_SIZE(len) + min_allocation_unit)
3250 split_block(block,ALIGN_SIZE(len));
3251 }
3252
3253 DBUG_RETURN(block);
3254 }
3255
3256
3257 Query_cache_block *
get_free_block(ulong len,my_bool not_less,ulong min)3258 Query_cache::get_free_block(ulong len, my_bool not_less, ulong min)
3259 {
3260 Query_cache_block *block = 0, *first = 0;
3261 DBUG_ENTER("Query_cache::get_free_block");
3262 DBUG_PRINT("qcache",("length %lu, not_less %d, min %lu", len,
3263 (int)not_less, min));
3264
3265 /* Find block with minimal size > len */
3266 uint start = find_bin(len);
3267 // try matching bin
3268 if (bins[start].number != 0)
3269 {
3270 Query_cache_block *list = bins[start].free_blocks;
3271 if (list->prev->length >= len) // check block with max size
3272 {
3273 first = list;
3274 uint n = 0;
3275 while ( n < QUERY_CACHE_MEM_BIN_TRY &&
3276 first->length < len) //we don't need irst->next != list
3277 {
3278 first=first->next;
3279 n++;
3280 }
3281 if (first->length >= len)
3282 block=first;
3283 else // we don't need if (first->next != list)
3284 {
3285 n = 0;
3286 block = list->prev;
3287 while (n < QUERY_CACHE_MEM_BIN_TRY &&
3288 block->length > len)
3289 {
3290 block=block->prev;
3291 n++;
3292 }
3293 if (block->length < len)
3294 block=block->next;
3295 }
3296 }
3297 else
3298 first = list->prev;
3299 }
3300 if (block == 0 && start > 0)
3301 {
3302 DBUG_PRINT("qcache",("Try bins with bigger block size"));
3303 // Try more big bins
3304 int i = start - 1;
3305 while (i > 0 && bins[i].number == 0)
3306 i--;
3307 if (bins[i].number > 0)
3308 block = bins[i].free_blocks;
3309 }
3310
3311 // If no big blocks => try less size (if it is possible)
3312 if (block == 0 && ! not_less)
3313 {
3314 DBUG_PRINT("qcache",("Try to allocate a smaller block"));
3315 if (first != 0 && first->length > min)
3316 block = first;
3317 else
3318 {
3319 uint i = start + 1;
3320 /* bins[mem_bin_num].number contains 1 for easy end test */
3321 for (i= start+1 ; bins[i].number == 0 ; i++) ;
3322 if (i < mem_bin_num && bins[i].free_blocks->prev->length >= min)
3323 block = bins[i].free_blocks->prev;
3324 }
3325 }
3326 if (block != 0)
3327 exclude_from_free_memory_list(block);
3328
3329 DBUG_PRINT("qcache",("getting block 0x%lx", (ulong) block));
3330 DBUG_RETURN(block);
3331 }
3332
3333
free_memory_block(Query_cache_block * block)3334 void Query_cache::free_memory_block(Query_cache_block *block)
3335 {
3336 DBUG_ENTER("Query_cache::free_memory_block");
3337 block->used=0;
3338 block->type= Query_cache_block::FREE; // mark block as free in any case
3339 DBUG_PRINT("qcache",
3340 ("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx",
3341 (ulong) first_block, (ulong) block, (ulong) block->pnext,
3342 (ulong) block->pprev));
3343
3344 if (block->pnext != first_block && block->pnext->is_free())
3345 block = join_free_blocks(block, block->pnext);
3346 if (block != first_block && block->pprev->is_free())
3347 block = join_free_blocks(block->pprev, block->pprev);
3348 insert_into_free_memory_list(block);
3349 DBUG_VOID_RETURN;
3350 }
3351
3352
split_block(Query_cache_block * block,ulong len)3353 void Query_cache::split_block(Query_cache_block *block, ulong len)
3354 {
3355 DBUG_ENTER("Query_cache::split_block");
3356 Query_cache_block *new_block = (Query_cache_block*)(((uchar*) block)+len);
3357
3358 new_block->init(block->length - len);
3359 total_blocks++;
3360 block->length=len;
3361 new_block->pnext = block->pnext;
3362 block->pnext = new_block;
3363 new_block->pprev = block;
3364 new_block->pnext->pprev = new_block;
3365
3366 if (block->type == Query_cache_block::FREE)
3367 {
3368 // if block was free then it already joined with all free neighbours
3369 insert_into_free_memory_list(new_block);
3370 }
3371 else
3372 free_memory_block(new_block);
3373
3374 DBUG_PRINT("qcache", ("split 0x%lx (%lu) new 0x%lx",
3375 (ulong) block, len, (ulong) new_block));
3376 DBUG_VOID_RETURN;
3377 }
3378
3379
3380 Query_cache_block *
join_free_blocks(Query_cache_block * first_block_arg,Query_cache_block * block_in_list)3381 Query_cache::join_free_blocks(Query_cache_block *first_block_arg,
3382 Query_cache_block *block_in_list)
3383 {
3384 Query_cache_block *second_block;
3385 DBUG_ENTER("Query_cache::join_free_blocks");
3386 DBUG_PRINT("qcache",
3387 ("join first 0x%lx, pnext 0x%lx, in list 0x%lx",
3388 (ulong) first_block_arg, (ulong) first_block_arg->pnext,
3389 (ulong) block_in_list));
3390
3391 exclude_from_free_memory_list(block_in_list);
3392 second_block = first_block_arg->pnext;
3393 // May be was not free block
3394 second_block->used=0;
3395 second_block->destroy();
3396 total_blocks--;
3397
3398 first_block_arg->length += second_block->length;
3399 first_block_arg->pnext = second_block->pnext;
3400 second_block->pnext->pprev = first_block_arg;
3401
3402 DBUG_RETURN(first_block_arg);
3403 }
3404
3405
append_next_free_block(Query_cache_block * block,ulong add_size)3406 my_bool Query_cache::append_next_free_block(Query_cache_block *block,
3407 ulong add_size)
3408 {
3409 Query_cache_block *next_block = block->pnext;
3410 DBUG_ENTER("Query_cache::append_next_free_block");
3411 DBUG_PRINT("enter", ("block 0x%lx, add_size %lu", (ulong) block,
3412 add_size));
3413
3414 if (next_block != first_block && next_block->is_free())
3415 {
3416 ulong old_len = block->length;
3417 exclude_from_free_memory_list(next_block);
3418 next_block->destroy();
3419 total_blocks--;
3420
3421 block->length += next_block->length;
3422 block->pnext = next_block->pnext;
3423 next_block->pnext->pprev = block;
3424
3425 if (block->length > ALIGN_SIZE(old_len + add_size) + min_allocation_unit)
3426 split_block(block,ALIGN_SIZE(old_len + add_size));
3427 DBUG_PRINT("exit", ("block was appended"));
3428 DBUG_RETURN(1);
3429 }
3430 DBUG_RETURN(0);
3431 }
3432
3433
exclude_from_free_memory_list(Query_cache_block * free_block)3434 void Query_cache::exclude_from_free_memory_list(Query_cache_block *free_block)
3435 {
3436 DBUG_ENTER("Query_cache::exclude_from_free_memory_list");
3437 Query_cache_memory_bin *bin = *((Query_cache_memory_bin **)
3438 free_block->data());
3439 double_linked_list_exclude(free_block, &bin->free_blocks);
3440 bin->number--;
3441 free_memory-=free_block->length;
3442 free_memory_blocks--;
3443 DBUG_PRINT("qcache",("exclude block 0x%lx, bin 0x%lx", (ulong) free_block,
3444 (ulong) bin));
3445 DBUG_VOID_RETURN;
3446 }
3447
insert_into_free_memory_list(Query_cache_block * free_block)3448 void Query_cache::insert_into_free_memory_list(Query_cache_block *free_block)
3449 {
3450 DBUG_ENTER("Query_cache::insert_into_free_memory_list");
3451 uint idx = find_bin(free_block->length);
3452 insert_into_free_memory_sorted_list(free_block, &bins[idx].free_blocks);
3453 /*
3454 We have enough memory in block for storing bin reference due to
3455 min_allocation_unit choice
3456 */
3457 Query_cache_memory_bin **bin_ptr = ((Query_cache_memory_bin**)
3458 free_block->data());
3459 *bin_ptr = bins+idx;
3460 (*bin_ptr)->number++;
3461 DBUG_PRINT("qcache",("insert block 0x%lx, bin[%d] 0x%lx",
3462 (ulong) free_block, idx, (ulong) *bin_ptr));
3463 DBUG_VOID_RETURN;
3464 }
3465
find_bin(ulong size)3466 uint Query_cache::find_bin(ulong size)
3467 {
3468 DBUG_ENTER("Query_cache::find_bin");
3469 // Binary search
3470 int left = 0, right = mem_bin_steps;
3471 do
3472 {
3473 int middle = (left + right) / 2;
3474 if (steps[middle].size > size)
3475 left = middle+1;
3476 else
3477 right = middle;
3478 } while (left < right);
3479 if (left == 0)
3480 {
3481 // first bin not subordinate of common rules
3482 DBUG_PRINT("qcache", ("first bin (# 0), size %lu",size));
3483 DBUG_RETURN(0);
3484 }
3485 uint bin = steps[left].idx -
3486 (uint)((size - steps[left].size)/steps[left].increment);
3487
3488 DBUG_PRINT("qcache", ("bin %u step %u, size %lu step size %lu",
3489 bin, left, size, steps[left].size));
3490 DBUG_RETURN(bin);
3491 }
3492
3493
3494 /*****************************************************************************
3495 Lists management
3496 *****************************************************************************/
3497
move_to_query_list_end(Query_cache_block * query_block)3498 void Query_cache::move_to_query_list_end(Query_cache_block *query_block)
3499 {
3500 DBUG_ENTER("Query_cache::move_to_query_list_end");
3501 double_linked_list_exclude(query_block, &queries_blocks);
3502 double_linked_list_simple_include(query_block, &queries_blocks);
3503 DBUG_VOID_RETURN;
3504 }
3505
3506
insert_into_free_memory_sorted_list(Query_cache_block * new_block,Query_cache_block ** list)3507 void Query_cache::insert_into_free_memory_sorted_list(Query_cache_block *
3508 new_block,
3509 Query_cache_block **
3510 list)
3511 {
3512 DBUG_ENTER("Query_cache::insert_into_free_memory_sorted_list");
3513 /*
3514 list sorted by size in ascendant order, because we need small blocks
3515 more frequently than bigger ones
3516 */
3517
3518 new_block->used = 0;
3519 new_block->n_tables = 0;
3520 new_block->type = Query_cache_block::FREE;
3521
3522 if (*list == 0)
3523 {
3524 *list = new_block->next=new_block->prev=new_block;
3525 DBUG_PRINT("qcache", ("inserted into empty list"));
3526 }
3527 else
3528 {
3529 Query_cache_block *point = *list;
3530 if (point->length >= new_block->length)
3531 {
3532 point = point->prev;
3533 *list = new_block;
3534 }
3535 else
3536 {
3537 /* Find right position in sorted list to put block */
3538 while (point->next != *list &&
3539 point->next->length < new_block->length)
3540 point=point->next;
3541 }
3542 new_block->prev = point;
3543 new_block->next = point->next;
3544 new_block->next->prev = new_block;
3545 point->next = new_block;
3546 }
3547 free_memory+=new_block->length;
3548 free_memory_blocks++;
3549 DBUG_VOID_RETURN;
3550 }
3551
3552
3553 void
double_linked_list_simple_include(Query_cache_block * point,Query_cache_block ** list_pointer)3554 Query_cache::double_linked_list_simple_include(Query_cache_block *point,
3555 Query_cache_block **
3556 list_pointer)
3557 {
3558 DBUG_ENTER("Query_cache::double_linked_list_simple_include");
3559 DBUG_PRINT("qcache", ("including block 0x%lx", (ulong) point));
3560 if (*list_pointer == 0)
3561 *list_pointer=point->next=point->prev=point;
3562 else
3563 {
3564 // insert to the end of list
3565 point->next = (*list_pointer);
3566 point->prev = (*list_pointer)->prev;
3567 point->prev->next = point;
3568 (*list_pointer)->prev = point;
3569 }
3570 DBUG_VOID_RETURN;
3571 }
3572
3573 void
double_linked_list_exclude(Query_cache_block * point,Query_cache_block ** list_pointer)3574 Query_cache::double_linked_list_exclude(Query_cache_block *point,
3575 Query_cache_block **list_pointer)
3576 {
3577 DBUG_ENTER("Query_cache::double_linked_list_exclude");
3578 DBUG_PRINT("qcache", ("excluding block 0x%lx, list 0x%lx",
3579 (ulong) point, (ulong) list_pointer));
3580 if (point->next == point)
3581 *list_pointer = 0; // empty list
3582 else
3583 {
3584 point->next->prev = point->prev;
3585 point->prev->next = point->next;
3586 /*
3587 If the root is removed; select a new root
3588 */
3589 if (point == *list_pointer)
3590 *list_pointer= point->next;
3591 }
3592 DBUG_VOID_RETURN;
3593 }
3594
3595
double_linked_list_join(Query_cache_block * head_tail,Query_cache_block * tail_head)3596 void Query_cache::double_linked_list_join(Query_cache_block *head_tail,
3597 Query_cache_block *tail_head)
3598 {
3599 Query_cache_block *head_head = head_tail->next,
3600 *tail_tail = tail_head->prev;
3601 head_head->prev = tail_tail;
3602 head_tail->next = tail_head;
3603 tail_head->prev = head_tail;
3604 tail_tail->next = head_head;
3605 }
3606
3607 /*****************************************************************************
3608 Query
3609 *****************************************************************************/
3610
3611 /*
3612 Collect information about table types, check that tables are cachable and
3613 count them
3614
3615 SYNOPSIS
3616 process_and_count_tables()
3617 tables_used table list for processing
3618 tables_type pointer to variable for table types collection
3619
3620 RETURN
3621 0 error
3622 >0 number of tables
3623 */
3624
3625 TABLE_COUNTER_TYPE
process_and_count_tables(THD * thd,TABLE_LIST * tables_used,uint8 * tables_type)3626 Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used,
3627 uint8 *tables_type)
3628 {
3629 DBUG_ENTER("process_and_count_tables");
3630 TABLE_COUNTER_TYPE table_count = 0;
3631 for (; tables_used; tables_used= tables_used->next_global)
3632 {
3633 table_count++;
3634 #ifndef NO_EMBEDDED_ACCESS_CHECKS
3635 /*
3636 Disable any attempt to store this statement if there are
3637 column level grants on any referenced tables.
3638 The grant.want_privileges flag was set to 1 in the
3639 check_grant() function earlier if the TABLE_LIST object
3640 had any associated column privileges.
3641
3642 We need to check that the TABLE_LIST object isn't part
3643 of a VIEW definition because we want to be able to cache
3644 views.
3645
3646 TODO: Although it is possible to cache views, the privilege
3647 check on view tables always fall back on column privileges
3648 even if there are more generic table privileges. Thus it isn't
3649 currently possible to retrieve cached view-tables unless the
3650 client has the super user privileges.
3651 */
3652 if (tables_used->grant.want_privilege &&
3653 tables_used->belong_to_view == NULL)
3654 {
3655 DBUG_PRINT("qcache", ("Don't cache statement as it refers to "
3656 "tables with column privileges."));
3657 thd->lex->safe_to_cache_query= 0;
3658 DBUG_RETURN(0);
3659 }
3660 #endif
3661 if (tables_used->view)
3662 {
3663 DBUG_PRINT("qcache", ("view: %s db: %s",
3664 tables_used->view_name.str,
3665 tables_used->view_db.str));
3666 *tables_type|= HA_CACHE_TBL_NONTRANSACT;
3667 }
3668 else
3669 {
3670 DBUG_PRINT("qcache", ("table: %s db: %s type: %u",
3671 tables_used->table->s->table_name.str,
3672 tables_used->table->s->db.str,
3673 tables_used->table->s->db_type()->db_type));
3674 if (tables_used->derived)
3675 {
3676 table_count--;
3677 DBUG_PRINT("qcache", ("derived table skipped"));
3678 continue;
3679 }
3680 *tables_type|= tables_used->table->file->table_cache_type();
3681
3682 /*
3683 table_alias_charset used here because it depends of
3684 lower_case_table_names variable
3685 */
3686 if (tables_used->table->s->tmp_table != NO_TMP_TABLE ||
3687 (*tables_type & HA_CACHE_TBL_NOCACHE) ||
3688 (tables_used->db_length == 5 &&
3689 my_strnncoll(table_alias_charset,
3690 (uchar*)tables_used->table->s->table_cache_key.str, 6,
3691 (uchar*)"mysql",6) == 0))
3692 {
3693 DBUG_PRINT("qcache",
3694 ("select not cacheable: temporary, system or "
3695 "other non-cacheable table(s)"));
3696 DBUG_RETURN(0);
3697 }
3698 #ifdef WITH_MYISAMMRG_STORAGE_ENGINE
3699 /*
3700 XXX FIXME: Some generic mechanism is required here instead of this
3701 MYISAMMRG-specific implementation.
3702 */
3703 if (tables_used->table->s->db_type()->db_type == DB_TYPE_MRG_MYISAM)
3704 {
3705 ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
3706 MYRG_INFO *file = handler->myrg_info();
3707 table_count+= (file->end_table - file->open_tables);
3708 }
3709 #endif
3710 }
3711 }
3712 DBUG_RETURN(table_count);
3713 }
3714
3715
3716 /*
3717 If query is cacheable return number tables in query
3718 (query without tables are not cached)
3719 */
3720
3721 TABLE_COUNTER_TYPE
is_cacheable(THD * thd,size_t query_len,const char * query,LEX * lex,TABLE_LIST * tables_used,uint8 * tables_type)3722 Query_cache::is_cacheable(THD *thd, size_t query_len, const char *query,
3723 LEX *lex,
3724 TABLE_LIST *tables_used, uint8 *tables_type)
3725 {
3726 TABLE_COUNTER_TYPE table_count;
3727 DBUG_ENTER("Query_cache::is_cacheable");
3728
3729 if (query_cache_is_cacheable_query(lex) &&
3730 (thd->variables.query_cache_type == 1 ||
3731 (thd->variables.query_cache_type == 2 && (lex->select_lex.options &
3732 OPTION_TO_QUERY_CACHE))))
3733 {
3734 DBUG_PRINT("qcache", ("options: %lx %lx type: %u",
3735 (long) OPTION_TO_QUERY_CACHE,
3736 (long) lex->select_lex.options,
3737 (int) thd->variables.query_cache_type));
3738
3739 if (!(table_count= process_and_count_tables(thd, tables_used,
3740 tables_type)))
3741 DBUG_RETURN(0);
3742
3743 if (thd->in_multi_stmt_transaction_mode() &&
3744 ((*tables_type)&HA_CACHE_TBL_TRANSACT))
3745 {
3746 DBUG_PRINT("qcache", ("not in autocommin mode"));
3747 DBUG_RETURN(0);
3748 }
3749 DBUG_PRINT("qcache", ("select is using %d tables", table_count));
3750 DBUG_RETURN(table_count);
3751 }
3752
3753 DBUG_PRINT("qcache",
3754 ("not interesting query: %d or not cacheable, options %lx %lx type: %u",
3755 (int) lex->sql_command,
3756 (long) OPTION_TO_QUERY_CACHE,
3757 (long) lex->select_lex.options,
3758 (int) thd->variables.query_cache_type));
3759 DBUG_RETURN(0);
3760 }
3761
3762 /*
3763 Check handler allowance to cache query with these tables
3764
3765 SYNOPSYS
3766 Query_cache::ask_handler_allowance()
3767 thd - thread handlers
3768 tables_used - tables list used in query
3769
3770 RETURN
3771 0 - caching allowed
3772 1 - caching disallowed
3773 */
ask_handler_allowance(THD * thd,TABLE_LIST * tables_used)3774 my_bool Query_cache::ask_handler_allowance(THD *thd,
3775 TABLE_LIST *tables_used)
3776 {
3777 DBUG_ENTER("Query_cache::ask_handler_allowance");
3778
3779 for (; tables_used; tables_used= tables_used->next_global)
3780 {
3781 TABLE *table;
3782 handler *handler;
3783 if (!(table= tables_used->table))
3784 continue;
3785 handler= table->file;
3786 /* Allow caching of queries with derived tables. */
3787 if (tables_used->uses_materialization())
3788 {
3789 /*
3790 Skip the derived table itself, but process its underlying tables and
3791 other tables that follow.
3792 */
3793 continue;
3794 }
3795
3796 /*
3797 We're skipping a special case here (MERGE VIEW on top of a TEMPTABLE
3798 view). This is MyISAMly safe because we know it's not a user-created
3799 TEMPTABLE as those are guarded against in
3800 Query_cache::process_and_count_tables(), and schema-tables clear
3801 safe_to_cache_query. This implies that nobody else will change our
3802 TEMPTABLE while we're using it, so calling register_query_cache_table()
3803 in MyISAM to check on it is pointless. Finally, we should see the
3804 TEMPTABLE view again in a subsequent iteration, anyway.
3805 */
3806 if ((tables_used->effective_algorithm == VIEW_ALGORITHM_MERGE) &&
3807 (table->s->get_table_ref_type() == TABLE_REF_TMP_TABLE))
3808 continue;
3809
3810 if (!handler->register_query_cache_table(thd,
3811 table->s->normalized_path.str,
3812 table->s->normalized_path.length,
3813 &tables_used->callback_func,
3814 &tables_used->engine_data))
3815 {
3816 DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
3817 tables_used->db, tables_used->alias));
3818 thd->lex->safe_to_cache_query= 0; // Don't try to cache this
3819 DBUG_RETURN(1);
3820 }
3821 }
3822 DBUG_RETURN(0);
3823 }
3824
3825
3826 /*****************************************************************************
3827 Packing
3828 *****************************************************************************/
3829
3830
3831 /**
3832 Rearrange all memory blocks so that free memory joins at the
3833 'bottom' of the allocated memory block containing all cache data.
3834 @see Query_cache::pack(ulong join_limit, uint iteration_limit)
3835 */
3836
pack_cache()3837 void Query_cache::pack_cache()
3838 {
3839 DBUG_ENTER("Query_cache::pack_cache");
3840
3841 DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
3842
3843 uchar *border = 0;
3844 Query_cache_block *before = 0;
3845 ulong gap = 0;
3846 my_bool ok = 1;
3847 Query_cache_block *block = first_block;
3848 DUMP(this);
3849
3850 if (first_block)
3851 {
3852 do
3853 {
3854 Query_cache_block *next=block->pnext;
3855 ok = move_by_type(&border, &before, &gap, block);
3856 block = next;
3857 } while (ok && block != first_block);
3858
3859 if (border != 0)
3860 {
3861 Query_cache_block *new_block = (Query_cache_block *) border;
3862 new_block->init(gap);
3863 total_blocks++;
3864 new_block->pnext = before->pnext;
3865 before->pnext = new_block;
3866 new_block->pprev = before;
3867 new_block->pnext->pprev = new_block;
3868 insert_into_free_memory_list(new_block);
3869 }
3870 DUMP(this);
3871 }
3872
3873 DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
3874 DBUG_VOID_RETURN;
3875 }
3876
3877
move_by_type(uchar ** border,Query_cache_block ** before,ulong * gap,Query_cache_block * block)3878 my_bool Query_cache::move_by_type(uchar **border,
3879 Query_cache_block **before, ulong *gap,
3880 Query_cache_block *block)
3881 {
3882 DBUG_ENTER("Query_cache::move_by_type");
3883
3884 my_bool ok = 1;
3885 switch (block->type) {
3886 case Query_cache_block::FREE:
3887 {
3888 DBUG_PRINT("qcache", ("block 0x%lx FREE", (ulong) block));
3889 if (*border == 0)
3890 {
3891 *border = (uchar *) block;
3892 *before = block->pprev;
3893 DBUG_PRINT("qcache", ("gap beginning here"));
3894 }
3895 exclude_from_free_memory_list(block);
3896 *gap +=block->length;
3897 block->pprev->pnext=block->pnext;
3898 block->pnext->pprev=block->pprev;
3899 block->destroy();
3900 total_blocks--;
3901 DBUG_PRINT("qcache", ("added to gap (%lu)", *gap));
3902 break;
3903 }
3904 case Query_cache_block::TABLE:
3905 {
3906 HASH_SEARCH_STATE record_idx;
3907 DBUG_PRINT("qcache", ("block 0x%lx TABLE", (ulong) block));
3908 if (*border == 0)
3909 break;
3910 ulong len = block->length, used = block->used;
3911 Query_cache_block_table *list_root = block->table(0);
3912 Query_cache_block_table *tprev = list_root->prev,
3913 *tnext = list_root->next;
3914 Query_cache_block *prev = block->prev,
3915 *next = block->next,
3916 *pprev = block->pprev,
3917 *pnext = block->pnext,
3918 *new_block =(Query_cache_block *) *border;
3919 uint tablename_offset = block->table()->table() - block->table()->db();
3920 char *data = (char*) block->data();
3921 uchar *key;
3922 size_t key_length;
3923 key=query_cache_table_get_key((uchar*) block, &key_length, 0);
3924 my_hash_first(&tables, (uchar*) key, key_length, &record_idx);
3925
3926 block->destroy();
3927 new_block->init(len);
3928 new_block->type=Query_cache_block::TABLE;
3929 new_block->used=used;
3930 new_block->n_tables=1;
3931 memmove((char*) new_block->data(), data, len-new_block->headers_len());
3932 relink(block, new_block, next, prev, pnext, pprev);
3933 if (tables_blocks == block)
3934 tables_blocks = new_block;
3935
3936 Query_cache_block_table *nlist_root = new_block->table(0);
3937 nlist_root->n = 0;
3938 nlist_root->next = tnext;
3939 tnext->prev = nlist_root;
3940 nlist_root->prev = tprev;
3941 tprev->next = nlist_root;
3942 DBUG_PRINT("qcache",
3943 ("list_root: 0x%lx tnext 0x%lx tprev 0x%lx tprev->next 0x%lx tnext->prev 0x%lx",
3944 (ulong) list_root, (ulong) tnext, (ulong) tprev,
3945 (ulong)tprev->next, (ulong)tnext->prev));
3946 /*
3947 Go through all queries that uses this table and change them to
3948 point to the new table object
3949 */
3950 Query_cache_table *new_block_table=new_block->table();
3951 for (;tnext != nlist_root; tnext=tnext->next)
3952 tnext->parent= new_block_table;
3953 *border += len;
3954 *before = new_block;
3955 /* Fix pointer to table name */
3956 new_block->table()->table(new_block->table()->db() + tablename_offset);
3957 /* Fix hash to point at moved block */
3958 my_hash_replace(&tables, &record_idx, (uchar*) new_block);
3959
3960 DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
3961 len, (ulong) new_block, (ulong) *border));
3962 break;
3963 }
3964 case Query_cache_block::QUERY:
3965 {
3966 HASH_SEARCH_STATE record_idx;
3967 DBUG_PRINT("qcache", ("block 0x%lx QUERY", (ulong) block));
3968 if (*border == 0)
3969 break;
3970 BLOCK_LOCK_WR(block);
3971 ulong len = block->length, used = block->used;
3972 TABLE_COUNTER_TYPE n_tables = block->n_tables;
3973 Query_cache_block *prev = block->prev,
3974 *next = block->next,
3975 *pprev = block->pprev,
3976 *pnext = block->pnext,
3977 *new_block =(Query_cache_block*) *border;
3978 char *data = (char*) block->data();
3979 Query_cache_block *first_result_block = ((Query_cache_query *)
3980 block->data())->result();
3981 uchar *key;
3982 size_t key_length;
3983 key=query_cache_query_get_key((uchar*) block, &key_length, 0);
3984 my_hash_first(&queries, (uchar*) key, key_length, &record_idx);
3985 // Move table of used tables
3986 memmove((char*) new_block->table(0), (char*) block->table(0),
3987 ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
3988 block->query()->unlock_n_destroy();
3989 block->destroy();
3990 new_block->init(len);
3991 new_block->type=Query_cache_block::QUERY;
3992 new_block->used=used;
3993 new_block->n_tables=n_tables;
3994 memmove((char*) new_block->data(), data, len - new_block->headers_len());
3995 relink(block, new_block, next, prev, pnext, pprev);
3996 if (queries_blocks == block)
3997 queries_blocks = new_block;
3998 Query_cache_block_table *beg_of_table_table= block->table(0),
3999 *end_of_table_table= block->table(n_tables);
4000 uchar *beg_of_new_table_table= (uchar*) new_block->table(0);
4001
4002 for (TABLE_COUNTER_TYPE j=0; j < n_tables; j++)
4003 {
4004 Query_cache_block_table *block_table = new_block->table(j);
4005
4006 // use aligment from begining of table if 'next' is in same block
4007 if ((beg_of_table_table <= block_table->next) &&
4008 (block_table->next < end_of_table_table))
4009 ((Query_cache_block_table *)(beg_of_new_table_table +
4010 (((uchar*)block_table->next) -
4011 ((uchar*)beg_of_table_table))))->prev=
4012 block_table;
4013 else
4014 block_table->next->prev= block_table;
4015
4016 // use aligment from begining of table if 'prev' is in same block
4017 if ((beg_of_table_table <= block_table->prev) &&
4018 (block_table->prev < end_of_table_table))
4019 ((Query_cache_block_table *)(beg_of_new_table_table +
4020 (((uchar*)block_table->prev) -
4021 ((uchar*)beg_of_table_table))))->next=
4022 block_table;
4023 else
4024 block_table->prev->next = block_table;
4025 }
4026 DBUG_PRINT("qcache", ("after circle tt"));
4027 *border += len;
4028 *before = new_block;
4029 new_block->query()->result(first_result_block);
4030 if (first_result_block != 0)
4031 {
4032 Query_cache_block *result_block = first_result_block;
4033 do
4034 {
4035 result_block->result()->parent(new_block);
4036 result_block = result_block->next;
4037 } while ( result_block != first_result_block );
4038 }
4039 Query_cache_query *new_query= ((Query_cache_query *) new_block->data());
4040 mysql_rwlock_init(key_rwlock_query_cache_query_lock, &new_query->lock);
4041
4042 /*
4043 If someone is writing to this block, inform the writer that the block
4044 has been moved.
4045 */
4046 Query_cache_tls *query_cache_tls= new_block->query()->writer();
4047 if (query_cache_tls != NULL)
4048 {
4049 query_cache_tls->first_query_block= new_block;
4050 }
4051 /* Fix hash to point at moved block */
4052 my_hash_replace(&queries, &record_idx, (uchar*) new_block);
4053 DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
4054 len, (ulong) new_block, (ulong) *border));
4055 break;
4056 }
4057 case Query_cache_block::RES_INCOMPLETE:
4058 case Query_cache_block::RES_BEG:
4059 case Query_cache_block::RES_CONT:
4060 case Query_cache_block::RESULT:
4061 {
4062 DBUG_PRINT("qcache", ("block 0x%lx RES* (%d)", (ulong) block,
4063 (int) block->type));
4064 if (*border == 0)
4065 break;
4066 Query_cache_block *query_block= block->result()->parent();
4067 BLOCK_LOCK_WR(query_block);
4068 Query_cache_block *next= block->next, *prev= block->prev;
4069 Query_cache_block::block_type type= block->type;
4070 ulong len = block->length, used = block->used;
4071 Query_cache_block *pprev = block->pprev,
4072 *pnext = block->pnext,
4073 *new_block =(Query_cache_block*) *border;
4074 char *data = (char*) block->data();
4075 block->destroy();
4076 new_block->init(len);
4077 new_block->type=type;
4078 new_block->used=used;
4079 memmove((char*) new_block->data(), data, len - new_block->headers_len());
4080 relink(block, new_block, next, prev, pnext, pprev);
4081 new_block->result()->parent(query_block);
4082 Query_cache_query *query = query_block->query();
4083 if (query->result() == block)
4084 query->result(new_block);
4085 *border += len;
4086 *before = new_block;
4087 /* If result writing complete && we have free space in block */
4088 ulong free_space= new_block->length - new_block->used;
4089 free_space-= free_space % ALIGN_SIZE(1);
4090 if (query->result()->type == Query_cache_block::RESULT &&
4091 new_block->length > new_block->used &&
4092 *gap + free_space > min_allocation_unit &&
4093 new_block->length - free_space > min_allocation_unit)
4094 {
4095 *border-= free_space;
4096 *gap+= free_space;
4097 DBUG_PRINT("qcache",
4098 ("rest of result free space added to gap (%lu)", *gap));
4099 new_block->length -= free_space;
4100 }
4101 BLOCK_UNLOCK_WR(query_block);
4102 DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
4103 len, (ulong) new_block, (ulong) *border));
4104 break;
4105 }
4106 default:
4107 DBUG_PRINT("error", ("unexpected block type %d, block 0x%lx",
4108 (int)block->type, (ulong) block));
4109 ok = 0;
4110 }
4111 DBUG_RETURN(ok);
4112 }
4113
4114
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)4115 void Query_cache::relink(Query_cache_block *oblock,
4116 Query_cache_block *nblock,
4117 Query_cache_block *next, Query_cache_block *prev,
4118 Query_cache_block *pnext, Query_cache_block *pprev)
4119 {
4120 if (prev == oblock) //check pointer to himself
4121 {
4122 nblock->prev = nblock;
4123 nblock->next = nblock;
4124 }
4125 else
4126 {
4127 nblock->prev = prev;
4128 prev->next=nblock;
4129 }
4130 if (next != oblock)
4131 {
4132 nblock->next = next;
4133 next->prev=nblock;
4134 }
4135 nblock->pprev = pprev; // Physical pointer to himself have only 1 free block
4136 nblock->pnext = pnext;
4137 pprev->pnext=nblock;
4138 pnext->pprev=nblock;
4139 }
4140
4141
join_results(ulong join_limit)4142 my_bool Query_cache::join_results(ulong join_limit)
4143 {
4144 my_bool has_moving = 0;
4145 DBUG_ENTER("Query_cache::join_results");
4146
4147 if (queries_blocks != 0)
4148 {
4149 DBUG_ASSERT(query_cache_size > 0);
4150 Query_cache_block *block = queries_blocks;
4151 do
4152 {
4153 Query_cache_query *header = block->query();
4154 if (header->result() != 0 &&
4155 header->result()->type == Query_cache_block::RESULT &&
4156 header->length() > join_limit)
4157 {
4158 Query_cache_block *new_result_block =
4159 get_free_block(ALIGN_SIZE(header->length()) +
4160 ALIGN_SIZE(sizeof(Query_cache_block)) +
4161 ALIGN_SIZE(sizeof(Query_cache_result)), 1, 0);
4162 if (new_result_block != 0)
4163 {
4164 has_moving = 1;
4165 Query_cache_block *first_result = header->result();
4166 ulong new_len = (header->length() +
4167 ALIGN_SIZE(sizeof(Query_cache_block)) +
4168 ALIGN_SIZE(sizeof(Query_cache_result)));
4169 if (new_result_block->length >
4170 ALIGN_SIZE(new_len) + min_allocation_unit)
4171 split_block(new_result_block, ALIGN_SIZE(new_len));
4172 BLOCK_LOCK_WR(block);
4173 header->result(new_result_block);
4174 new_result_block->type = Query_cache_block::RESULT;
4175 new_result_block->n_tables = 0;
4176 new_result_block->used = new_len;
4177
4178 new_result_block->next = new_result_block->prev = new_result_block;
4179 DBUG_PRINT("qcache", ("new block %lu/%lu (%lu)",
4180 new_result_block->length,
4181 new_result_block->used,
4182 header->length()));
4183
4184 Query_cache_result *new_result = new_result_block->result();
4185 new_result->parent(block);
4186 uchar *write_to = (uchar*) new_result->data();
4187 Query_cache_block *result_block = first_result;
4188 do
4189 {
4190 ulong len = (result_block->used - result_block->headers_len() -
4191 ALIGN_SIZE(sizeof(Query_cache_result)));
4192 DBUG_PRINT("loop", ("add block %lu/%lu (%lu)",
4193 result_block->length,
4194 result_block->used,
4195 len));
4196 memcpy((char *) write_to,
4197 (char*) result_block->result()->data(),
4198 len);
4199 write_to += len;
4200 Query_cache_block *old_result_block = result_block;
4201 result_block = result_block->next;
4202 free_memory_block(old_result_block);
4203 } while (result_block != first_result);
4204 BLOCK_UNLOCK_WR(block);
4205 }
4206 }
4207 block = block->next;
4208 } while ( block != queries_blocks );
4209 }
4210 DBUG_RETURN(has_moving);
4211 }
4212
4213
filename_2_table_key(char * key,const char * path,uint32 * db_length)4214 uint Query_cache::filename_2_table_key (char *key, const char *path,
4215 uint32 *db_length)
4216 {
4217 char tablename[FN_REFLEN+2], *filename, *dbname;
4218 DBUG_ENTER("Query_cache::filename_2_table_key");
4219
4220 /* Safety if filename didn't have a directory name */
4221 tablename[0]= FN_LIBCHAR;
4222 tablename[1]= FN_LIBCHAR;
4223 /* Convert filename to this OS's format in tablename */
4224 fn_format(tablename + 2, path, "", "", MY_REPLACE_EXT);
4225 filename= tablename + dirname_length(tablename + 2) + 2;
4226 /* Find start of databasename */
4227 for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ;
4228 *db_length= (filename - dbname) - 1;
4229 DBUG_PRINT("qcache", ("table '%-.*s.%s'", *db_length, dbname, filename));
4230
4231 DBUG_RETURN(static_cast<uint>(strmake(strmake(key, dbname,
4232 min<uint32>(*db_length,
4233 NAME_LEN)) + 1,
4234 filename, NAME_LEN) - key) + 1);
4235 }
4236
4237 /****************************************************************************
4238 Functions to be used when debugging
4239 ****************************************************************************/
4240
4241 #if defined(DBUG_OFF) && !defined(USE_QUERY_CACHE_INTEGRITY_CHECK)
4242
wreck(uint line,const char * message)4243 void wreck(uint line, const char *message) { query_cache_size = 0; }
bins_dump()4244 void bins_dump() {}
cache_dump()4245 void cache_dump() {}
queries_dump()4246 void queries_dump() {}
tables_dump()4247 void tables_dump() {}
check_integrity(bool not_locked)4248 my_bool check_integrity(bool not_locked) { return 0; }
in_list(Query_cache_block * root,Query_cache_block * point,const char * name)4249 my_bool in_list(Query_cache_block * root, Query_cache_block * point,
4250 const char *name) { return 0;}
in_blocks(Query_cache_block * point)4251 my_bool in_blocks(Query_cache_block * point) { return 0; }
4252
4253 #else
4254
4255
4256 /*
4257 Debug method which switch query cache off but left content for
4258 investigation.
4259
4260 SYNOPSIS
4261 Query_cache::wreck()
4262 line line of the wreck() call
4263 message message for logging
4264 */
4265
wreck(uint line,const char * message)4266 void Query_cache::wreck(uint line, const char *message)
4267 {
4268 THD *thd=current_thd;
4269 DBUG_ENTER("Query_cache::wreck");
4270 query_cache_size = 0;
4271 if (*message)
4272 DBUG_PRINT("error", (" %s", message));
4273 DBUG_PRINT("warning", ("=================================="));
4274 DBUG_PRINT("warning", ("%5d QUERY CACHE WRECK => DISABLED",line));
4275 DBUG_PRINT("warning", ("=================================="));
4276 if (thd)
4277 thd->killed= THD::KILL_CONNECTION;
4278 cache_dump();
4279 /* check_integrity(0); */ /* Can't call it here because of locks */
4280 bins_dump();
4281 DBUG_VOID_RETURN;
4282 }
4283
4284
bins_dump()4285 void Query_cache::bins_dump()
4286 {
4287 uint i;
4288
4289 if (!initialized || query_cache_size == 0)
4290 {
4291 DBUG_PRINT("qcache", ("Query Cache not initialized"));
4292 return;
4293 }
4294
4295 DBUG_PRINT("qcache", ("mem_bin_num=%u, mem_bin_steps=%u",
4296 mem_bin_num, mem_bin_steps));
4297 DBUG_PRINT("qcache", ("-------------------------"));
4298 DBUG_PRINT("qcache", (" size idx step"));
4299 DBUG_PRINT("qcache", ("-------------------------"));
4300 for (i=0; i < mem_bin_steps; i++)
4301 {
4302 DBUG_PRINT("qcache", ("%10lu %3d %10lu", steps[i].size, steps[i].idx,
4303 steps[i].increment));
4304 }
4305 DBUG_PRINT("qcache", ("-------------------------"));
4306 DBUG_PRINT("qcache", (" size num"));
4307 DBUG_PRINT("qcache", ("-------------------------"));
4308 for (i=0; i < mem_bin_num; i++)
4309 {
4310 DBUG_PRINT("qcache", ("%10lu %3d 0x%lx", bins[i].size, bins[i].number,
4311 (ulong)&(bins[i])));
4312 if (bins[i].free_blocks)
4313 {
4314 Query_cache_block *block = bins[i].free_blocks;
4315 do{
4316 DBUG_PRINT("qcache", ("\\-- %lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
4317 block->length, (ulong)block,
4318 (ulong)block->next, (ulong)block->prev,
4319 (ulong)block->pnext, (ulong)block->pprev));
4320 block = block->next;
4321 } while ( block != bins[i].free_blocks );
4322 }
4323 }
4324 DBUG_PRINT("qcache", ("-------------------------"));
4325 }
4326
4327
cache_dump()4328 void Query_cache::cache_dump()
4329 {
4330 if (!initialized || query_cache_size == 0)
4331 {
4332 DBUG_PRINT("qcache", ("Query Cache not initialized"));
4333 return;
4334 }
4335
4336 DBUG_PRINT("qcache", ("-------------------------------------"));
4337 DBUG_PRINT("qcache", (" length used t nt"));
4338 DBUG_PRINT("qcache", ("-------------------------------------"));
4339 Query_cache_block *i = first_block;
4340 do
4341 {
4342 DBUG_PRINT("qcache",
4343 ("%10lu %10lu %1d %2d 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
4344 i->length, i->used, (int)i->type,
4345 i->n_tables, (ulong)i,
4346 (ulong)i->next, (ulong)i->prev, (ulong)i->pnext,
4347 (ulong)i->pprev));
4348 i = i->pnext;
4349 } while ( i != first_block );
4350 DBUG_PRINT("qcache", ("-------------------------------------"));
4351 }
4352
4353
queries_dump()4354 void Query_cache::queries_dump()
4355 {
4356
4357 if (!initialized)
4358 {
4359 DBUG_PRINT("qcache", ("Query Cache not initialized"));
4360 return;
4361 }
4362
4363 DBUG_PRINT("qcache", ("------------------"));
4364 DBUG_PRINT("qcache", (" QUERIES"));
4365 DBUG_PRINT("qcache", ("------------------"));
4366 if (queries_blocks != 0)
4367 {
4368 Query_cache_block *block = queries_blocks;
4369 do
4370 {
4371 size_t len;
4372 char *str = (char*) query_cache_query_get_key((uchar*) block, &len, 0);
4373 len-= QUERY_CACHE_FLAGS_SIZE; // Point at flags
4374 Query_cache_query_flags flags;
4375 memcpy(&flags, str+len, QUERY_CACHE_FLAGS_SIZE);
4376 str[len]= 0; // make zero ending DB name
4377 DBUG_PRINT("qcache", ("F: %u C: %u L: %lu T: '%s' (%lu) '%s' '%s'",
4378 flags.client_long_flag,
4379 flags.character_set_client_num,
4380 (ulong)flags.limit,
4381 flags.time_zone->get_name()->ptr(),
4382 (ulong) len, str, strend(str)+1));
4383 DBUG_PRINT("qcache", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong) block,
4384 (ulong) block->next, (ulong) block->prev,
4385 (ulong)block->pnext, (ulong)block->pprev));
4386 memcpy(str + len, &flags, QUERY_CACHE_FLAGS_SIZE); // restore flags
4387 for (TABLE_COUNTER_TYPE t= 0; t < block->n_tables; t++)
4388 {
4389 Query_cache_table *table= block->table(t)->parent;
4390 DBUG_PRINT("qcache", ("-t- '%s' '%s'", table->db(), table->table()));
4391 }
4392 Query_cache_query *header = block->query();
4393 if (header->result())
4394 {
4395 Query_cache_block *result_block = header->result();
4396 Query_cache_block *result_beg = result_block;
4397 do
4398 {
4399 DBUG_PRINT("qcache", ("-r- %u %lu/%lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
4400 (uint) result_block->type,
4401 result_block->length, result_block->used,
4402 (ulong) result_block,
4403 (ulong) result_block->next,
4404 (ulong) result_block->prev,
4405 (ulong) result_block->pnext,
4406 (ulong) result_block->pprev));
4407 result_block = result_block->next;
4408 } while ( result_block != result_beg );
4409 }
4410 } while ((block=block->next) != queries_blocks);
4411 }
4412 else
4413 {
4414 DBUG_PRINT("qcache", ("no queries in list"));
4415 }
4416 DBUG_PRINT("qcache", ("------------------"));
4417 }
4418
4419
tables_dump()4420 void Query_cache::tables_dump()
4421 {
4422 if (!initialized || query_cache_size == 0)
4423 {
4424 DBUG_PRINT("qcache", ("Query Cache not initialized"));
4425 return;
4426 }
4427
4428 DBUG_PRINT("qcache", ("--------------------"));
4429 DBUG_PRINT("qcache", ("TABLES"));
4430 DBUG_PRINT("qcache", ("--------------------"));
4431 if (tables_blocks != 0)
4432 {
4433 Query_cache_block *table_block = tables_blocks;
4434 do
4435 {
4436 Query_cache_table *table = table_block->table();
4437 DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table()));
4438 table_block = table_block->next;
4439 } while (table_block != tables_blocks);
4440 }
4441 else
4442 DBUG_PRINT("qcache", ("no tables in list"));
4443 DBUG_PRINT("qcache", ("--------------------"));
4444 }
4445
4446
4447 /**
4448 Checks integrity of the various linked lists
4449
4450 @return Error status code
4451 @retval FALSE Query cache is operational.
4452 @retval TRUE Query cache is broken.
4453 */
4454
check_integrity(bool locked)4455 my_bool Query_cache::check_integrity(bool locked)
4456 {
4457 my_bool result = 0;
4458 uint i;
4459 DBUG_ENTER("check_integrity");
4460
4461 if (!locked)
4462 lock_and_suspend();
4463
4464 if (my_hash_check(&queries))
4465 {
4466 DBUG_PRINT("error", ("queries hash is damaged"));
4467 result = 1;
4468 }
4469
4470 if (my_hash_check(&tables))
4471 {
4472 DBUG_PRINT("error", ("tables hash is damaged"));
4473 result = 1;
4474 }
4475
4476 DBUG_PRINT("qcache", ("physical address check ..."));
4477 ulong free=0, used=0;
4478 Query_cache_block * block = first_block;
4479 do
4480 {
4481 /* When checking at system start, there is no block. */
4482 if (!block)
4483 break;
4484
4485 DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
4486 (ulong) block, (uint) block->type));
4487 // Check allignment
4488 if ((((long)block) % (long) ALIGN_SIZE(1)) !=
4489 (((long)first_block) % (long)ALIGN_SIZE(1)))
4490 {
4491 DBUG_PRINT("error",
4492 ("block 0x%lx do not aligned by %d", (ulong) block,
4493 (int) ALIGN_SIZE(1)));
4494 result = 1;
4495 }
4496 // Check memory allocation
4497 if (block->pnext == first_block) // Is it last block?
4498 {
4499 if (((uchar*)block) + block->length !=
4500 ((uchar*)first_block) + query_cache_size)
4501 {
4502 DBUG_PRINT("error",
4503 ("block 0x%lx, type %u, ended at 0x%lx, but cache ended at 0x%lx",
4504 (ulong) block, (uint) block->type,
4505 (ulong) (((uchar*)block) + block->length),
4506 (ulong) (((uchar*)first_block) + query_cache_size)));
4507 result = 1;
4508 }
4509 }
4510 else
4511 if (((uchar*)block) + block->length != ((uchar*)block->pnext))
4512 {
4513 DBUG_PRINT("error",
4514 ("block 0x%lx, type %u, ended at 0x%lx, but next block begining at 0x%lx",
4515 (ulong) block, (uint) block->type,
4516 (ulong) (((uchar*)block) + block->length),
4517 (ulong) ((uchar*)block->pnext)));
4518 }
4519 if (block->type == Query_cache_block::FREE)
4520 free+= block->length;
4521 else
4522 used+= block->length;
4523 switch(block->type) {
4524 case Query_cache_block::FREE:
4525 {
4526 Query_cache_memory_bin *bin = *((Query_cache_memory_bin **)
4527 block->data());
4528 //is it correct pointer?
4529 if (((uchar*)bin) < ((uchar*)bins) ||
4530 ((uchar*)bin) >= ((uchar*)first_block))
4531 {
4532 DBUG_PRINT("error",
4533 ("free block 0x%lx have bin pointer 0x%lx beyaond of bins array bounds [0x%lx,0x%lx]",
4534 (ulong) block,
4535 (ulong) bin,
4536 (ulong) bins,
4537 (ulong) first_block));
4538 result = 1;
4539 }
4540 else
4541 {
4542 int idx = (((uchar*)bin) - ((uchar*)bins)) /
4543 sizeof(Query_cache_memory_bin);
4544 if (in_list(bins[idx].free_blocks, block, "free memory"))
4545 result = 1;
4546 }
4547 break;
4548 }
4549 case Query_cache_block::TABLE:
4550 if (in_list(tables_blocks, block, "tables"))
4551 result = 1;
4552 if (in_table_list(block->table(0), block->table(0), "table list root"))
4553 result = 1;
4554 break;
4555 case Query_cache_block::QUERY:
4556 {
4557 if (in_list(queries_blocks, block, "query"))
4558 result = 1;
4559 for (TABLE_COUNTER_TYPE j=0; j < block->n_tables; j++)
4560 {
4561 Query_cache_block_table *block_table = block->table(j);
4562 Query_cache_block_table *block_table_root =
4563 (Query_cache_block_table *)
4564 (((uchar*)block_table->parent) -
4565 ALIGN_SIZE(sizeof(Query_cache_block_table)));
4566
4567 if (in_table_list(block_table, block_table_root, "table list"))
4568 result = 1;
4569 }
4570 break;
4571 }
4572 case Query_cache_block::RES_INCOMPLETE:
4573 // This type of block can be not lincked yet (in multithread environment)
4574 break;
4575 case Query_cache_block::RES_BEG:
4576 case Query_cache_block::RES_CONT:
4577 case Query_cache_block::RESULT:
4578 {
4579 Query_cache_block * query_block = block->result()->parent();
4580 if (((uchar*)query_block) < ((uchar*)first_block) ||
4581 ((uchar*)query_block) >= (((uchar*)first_block) + query_cache_size))
4582 {
4583 DBUG_PRINT("error",
4584 ("result block 0x%lx have query block pointer 0x%lx beyaond of block pool bounds [0x%lx,0x%lx]",
4585 (ulong) block,
4586 (ulong) query_block,
4587 (ulong) first_block,
4588 (ulong) (((uchar*)first_block) + query_cache_size)));
4589 result = 1;
4590 }
4591 else
4592 {
4593 BLOCK_LOCK_RD(query_block);
4594 if (in_list(queries_blocks, query_block, "query from results"))
4595 result = 1;
4596 if (in_list(query_block->query()->result(), block,
4597 "results"))
4598 result = 1;
4599 BLOCK_UNLOCK_RD(query_block);
4600 }
4601 break;
4602 }
4603 default:
4604 DBUG_PRINT("error", ("block 0x%lx have incorrect type %u",
4605 (long) block, block->type));
4606 result = 1;
4607 }
4608
4609 block = block->pnext;
4610 } while (block != first_block);
4611
4612 if (used + free != query_cache_size)
4613 {
4614 DBUG_PRINT("error",
4615 ("used memory (%lu) + free memory (%lu) != query_cache_size (%lu)",
4616 used, free, query_cache_size));
4617 result = 1;
4618 }
4619
4620 if (free != free_memory)
4621 {
4622 DBUG_PRINT("error",
4623 ("free memory (%lu) != free_memory (%lu)",
4624 free, free_memory));
4625 result = 1;
4626 }
4627
4628 DBUG_PRINT("qcache", ("check queries ..."));
4629 if ((block = queries_blocks))
4630 {
4631 do
4632 {
4633 DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
4634 (ulong) block, (uint) block->type));
4635 size_t length;
4636 uchar *key = query_cache_query_get_key((uchar*) block, &length, 0);
4637 uchar* val = my_hash_search(&queries, key, length);
4638 if (((uchar*)block) != val)
4639 {
4640 DBUG_PRINT("error", ("block 0x%lx found in queries hash like 0x%lx",
4641 (ulong) block, (ulong) val));
4642 }
4643 if (in_blocks(block))
4644 result = 1;
4645 Query_cache_block * results = block->query()->result();
4646 if (results)
4647 {
4648 Query_cache_block * result_block = results;
4649 do
4650 {
4651 DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
4652 (ulong) block, (uint) block->type));
4653 if (in_blocks(result_block))
4654 result = 1;
4655
4656 result_block = result_block->next;
4657 } while (result_block != results);
4658 }
4659 block = block->next;
4660 } while (block != queries_blocks);
4661 }
4662
4663 DBUG_PRINT("qcache", ("check tables ..."));
4664 if ((block = tables_blocks))
4665 {
4666 do
4667 {
4668 DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
4669 (ulong) block, (uint) block->type));
4670 size_t length;
4671 uchar *key = query_cache_table_get_key((uchar*) block, &length, 0);
4672 uchar* val = my_hash_search(&tables, key, length);
4673 if (((uchar*)block) != val)
4674 {
4675 DBUG_PRINT("error", ("block 0x%lx found in tables hash like 0x%lx",
4676 (ulong) block, (ulong) val));
4677 }
4678
4679 if (in_blocks(block))
4680 result = 1;
4681 block=block->next;
4682 } while (block != tables_blocks);
4683 }
4684
4685 DBUG_PRINT("qcache", ("check free blocks"));
4686 for (i = 0; i < mem_bin_num; i++)
4687 {
4688 if ((block = bins[i].free_blocks))
4689 {
4690 uint count = 0;
4691 do
4692 {
4693 DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
4694 (ulong) block, (uint) block->type));
4695 if (in_blocks(block))
4696 result = 1;
4697
4698 count++;
4699 block=block->next;
4700 } while (block != bins[i].free_blocks);
4701 if (count != bins[i].number)
4702 {
4703 DBUG_PRINT("error", ("bins[%d].number= %d, but bin have %d blocks",
4704 i, bins[i].number, count));
4705 result = 1;
4706 }
4707 }
4708 }
4709 DBUG_ASSERT(result == 0);
4710 if (!locked)
4711 unlock();
4712 DBUG_RETURN(result);
4713 }
4714
4715
in_blocks(Query_cache_block * point)4716 my_bool Query_cache::in_blocks(Query_cache_block * point)
4717 {
4718 my_bool result = 0;
4719 Query_cache_block *block = point;
4720 //back
4721 do
4722 {
4723 if (block->pprev->pnext != block)
4724 {
4725 DBUG_PRINT("error",
4726 ("block 0x%lx in physical list is incorrect linked, prev block 0x%lx refered as next to 0x%lx (check from 0x%lx)",
4727 (ulong) block, (ulong) block->pprev,
4728 (ulong) block->pprev->pnext,
4729 (ulong) point));
4730 //back trace
4731 for (; block != point; block = block->pnext)
4732 DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
4733 result = 1;
4734 goto err1;
4735 }
4736 block = block->pprev;
4737 } while (block != first_block && block != point);
4738 if (block != first_block)
4739 {
4740 DBUG_PRINT("error",
4741 ("block 0x%lx (0x%lx<-->0x%lx) not owned by pysical list",
4742 (ulong) block, (ulong) block->pprev, (ulong )block->pnext));
4743 return 1;
4744 }
4745
4746 err1:
4747 //forward
4748 block = point;
4749 do
4750 {
4751 if (block->pnext->pprev != block)
4752 {
4753 DBUG_PRINT("error",
4754 ("block 0x%lx in physicel list is incorrect linked, next block 0x%lx refered as prev to 0x%lx (check from 0x%lx)",
4755 (ulong) block, (ulong) block->pnext,
4756 (ulong) block->pnext->pprev,
4757 (ulong) point));
4758 //back trace
4759 for (; block != point; block = block->pprev)
4760 DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
4761 result = 1;
4762 goto err2;
4763 }
4764 block = block->pnext;
4765 } while (block != first_block);
4766 err2:
4767 return result;
4768 }
4769
4770
in_list(Query_cache_block * root,Query_cache_block * point,const char * name)4771 my_bool Query_cache::in_list(Query_cache_block * root,
4772 Query_cache_block * point,
4773 const char *name)
4774 {
4775 my_bool result = 0;
4776 Query_cache_block *block = point;
4777 //back
4778 do
4779 {
4780 if (block->prev->next != block)
4781 {
4782 DBUG_PRINT("error",
4783 ("block 0x%lx in list '%s' 0x%lx is incorrect linked, prev block 0x%lx refered as next to 0x%lx (check from 0x%lx)",
4784 (ulong) block, name, (ulong) root, (ulong) block->prev,
4785 (ulong) block->prev->next,
4786 (ulong) point));
4787 //back trace
4788 for (; block != point; block = block->next)
4789 DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
4790 result = 1;
4791 goto err1;
4792 }
4793 block = block->prev;
4794 } while (block != root && block != point);
4795 if (block != root)
4796 {
4797 DBUG_PRINT("error",
4798 ("block 0x%lx (0x%lx<-->0x%lx) not owned by list '%s' 0x%lx",
4799 (ulong) block,
4800 (ulong) block->prev, (ulong) block->next,
4801 name, (ulong) root));
4802 return 1;
4803 }
4804 err1:
4805 // forward
4806 block = point;
4807 do
4808 {
4809 if (block->next->prev != block)
4810 {
4811 DBUG_PRINT("error",
4812 ("block 0x%lx in list '%s' 0x%lx is incorrect linked, next block 0x%lx refered as prev to 0x%lx (check from 0x%lx)",
4813 (ulong) block, name, (ulong) root, (ulong) block->next,
4814 (ulong) block->next->prev,
4815 (ulong) point));
4816 //back trace
4817 for (; block != point; block = block->prev)
4818 DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
4819 result = 1;
4820 goto err2;
4821 }
4822 block = block->next;
4823 } while (block != root);
4824 err2:
4825 return result;
4826 }
4827
dump_node(Query_cache_block_table * node,const char * call,const char * descr)4828 void dump_node(Query_cache_block_table * node,
4829 const char * call, const char * descr)
4830 {
4831 DBUG_PRINT("qcache", ("%s: %s: node: 0x%lx", call, descr, (ulong) node));
4832 DBUG_PRINT("qcache", ("%s: %s: node block: 0x%lx",
4833 call, descr, (ulong) node->block()));
4834 DBUG_PRINT("qcache", ("%s: %s: next: 0x%lx", call, descr,
4835 (ulong) node->next));
4836 DBUG_PRINT("qcache", ("%s: %s: prev: 0x%lx", call, descr,
4837 (ulong) node->prev));
4838 }
4839
in_table_list(Query_cache_block_table * root,Query_cache_block_table * point,const char * name)4840 my_bool Query_cache::in_table_list(Query_cache_block_table * root,
4841 Query_cache_block_table * point,
4842 const char *name)
4843 {
4844 my_bool result = 0;
4845 Query_cache_block_table *table = point;
4846 dump_node(root, name, "parameter root");
4847 //back
4848 do
4849 {
4850 dump_node(table, name, "list element << ");
4851 if (table->prev->next != table)
4852 {
4853 DBUG_PRINT("error",
4854 ("table 0x%lx(0x%lx) in list '%s' 0x%lx(0x%lx) is incorrect linked, prev table 0x%lx(0x%lx) refered as next to 0x%lx(0x%lx) (check from 0x%lx(0x%lx))",
4855 (ulong) table, (ulong) table->block(), name,
4856 (ulong) root, (ulong) root->block(),
4857 (ulong) table->prev, (ulong) table->prev->block(),
4858 (ulong) table->prev->next,
4859 (ulong) table->prev->next->block(),
4860 (ulong) point, (ulong) point->block()));
4861 //back trace
4862 for (; table != point; table = table->next)
4863 DBUG_PRINT("error", ("back trace 0x%lx(0x%lx)",
4864 (ulong) table, (ulong) table->block()));
4865 result = 1;
4866 goto err1;
4867 }
4868 table = table->prev;
4869 } while (table != root && table != point);
4870 if (table != root)
4871 {
4872 DBUG_PRINT("error",
4873 ("table 0x%lx(0x%lx) (0x%lx(0x%lx)<-->0x%lx(0x%lx)) not owned by list '%s' 0x%lx(0x%lx)",
4874 (ulong) table, (ulong) table->block(),
4875 (ulong) table->prev, (ulong) table->prev->block(),
4876 (ulong) table->next, (ulong) table->next->block(),
4877 name, (ulong) root, (ulong) root->block()));
4878 return 1;
4879 }
4880 err1:
4881 // forward
4882 table = point;
4883 do
4884 {
4885 dump_node(table, name, "list element >> ");
4886 if (table->next->prev != table)
4887 {
4888 DBUG_PRINT("error",
4889 ("table 0x%lx(0x%lx) in list '%s' 0x%lx(0x%lx) is incorrect linked, next table 0x%lx(0x%lx) refered as prev to 0x%lx(0x%lx) (check from 0x%lx(0x%lx))",
4890 (ulong) table, (ulong) table->block(),
4891 name, (ulong) root, (ulong) root->block(),
4892 (ulong) table->next, (ulong) table->next->block(),
4893 (ulong) table->next->prev,
4894 (ulong) table->next->prev->block(),
4895 (ulong) point, (ulong) point->block()));
4896 //back trace
4897 for (; table != point; table = table->prev)
4898 DBUG_PRINT("error", ("back trace 0x%lx(0x%lx)",
4899 (ulong) table, (ulong) table->block()));
4900 result = 1;
4901 goto err2;
4902 }
4903 table = table->next;
4904 } while (table != root);
4905 err2:
4906 return result;
4907 }
4908
4909 #endif /* DBUG_OFF */
4910
4911 #endif /*HAVE_QUERY_CACHE*/
4912
4913