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