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