sql_cache.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:116k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /*
  14.   Description of the query cache:
  15. 1. Query_cache object consists of
  16. - query cache memory pool (cache)
  17. - queries hash (queries)
  18. - tables hash (tables)
  19. - list of blocks ordered as they allocated in memory
  20. (first_block)
  21. - list of queries block (queries_blocks)
  22. - list of used tables (tables_blocks)
  23. 2. Query cache memory pool (cache) consists of
  24. - table of steps of memory bins allocation
  25. - table of free memory bins
  26. - blocks of memory
  27. 3. Memory blocks
  28. Every memory block has the following structure:
  29. +----------------------------------------------------------+
  30. |      Block header (Query_cache_block structure)    |
  31. +----------------------------------------------------------+
  32. |Table of database table lists (used for queries & tables) |
  33. +----------------------------------------------------------+
  34. |   Type depended header    |
  35. |(Query_cache_query, Query_cache_table, Query_cache_result)|
  36. +----------------------------------------------------------+
  37. | Data ...    |
  38. +----------------------------------------------------------+
  39. Block header consists of:
  40. - type:
  41.   FREE Free memory block
  42.   QUERY Query block
  43.   RESULT Ready to send result
  44.   RES_CONT Result's continuation
  45.   RES_BEG First block of results, that is not yet complete,
  46. written to cache
  47.   RES_INCOMPLETE  Allocated for results data block
  48.   TABLE Block with database table description
  49.   INCOMPLETE The destroyed block
  50. - length of block (length)
  51. - length of data & headers (used)
  52. - physical list links (pnext/pprev) - used for the list of
  53.   blocks ordered as they are allocated in physical memory
  54. - logical list links (next/prev) - used for queries block list, tables block
  55.   list, free memory block lists and list of results block in query
  56. - number of elements in table of database table list (n_tables)
  57. 4. Query & results blocks
  58. Query stored in cache consists of following blocks:
  59. more       more
  60. recent+-------------+ old
  61. <-----|Query block 1|------> double linked list of queries block
  62.  prev |     | next
  63.       +-------------+
  64.     <-|  table 0    |-> (see "Table of database table lists" description)
  65.     <-|  table 1    |->
  66.       |  ...     | +--------------------------+
  67.       +-------------+  +-------------------------+    |
  68. NET   |     |  | V    V    |
  69. struct|     |  +-+------------+   +------------+ |
  70. <-----|query header |----->|Result block|-->|Result block|-+ doublelinked
  71. writer|     |result| |<--|  |   list of results
  72.       +-------------+    +------------+   +------------+
  73.       |charset     |    +------------+   +------------+ no table of dbtables
  74.       |encoding +   |    |   result |   | result  |
  75.       |query text   |<-----|   header |   | header  |------+
  76.       +-------------+parent| |   |  |parent|
  77.     ^    +------------+   +------------+ |
  78.     |    |result data |   |result data | |
  79.     |    +------------+   +------------+ |
  80.     +---------------------------------------------------+
  81. First query is registered. During the registration query block is
  82. allocated. This query block is included in query hash and is linked
  83. with appropriate database tables lists (if there is no appropriate
  84. list exists it will be created).
  85. Later when query has performed results is written into the result blocks.
  86. A result block cannot be smaller then QUERY_CACHE_MIN_RESULT_DATA_SIZE.
  87. When new result is written to cache it is appended to the last result
  88. block, if no more  free space left in the last block, new block is
  89. allocated.
  90. 5. Table of database table lists.
  91. For quick invalidation of queries all query are linked in lists on used
  92. database tables basis (when table will be changed (insert/delete/...)
  93. this queries will be removed from cache).
  94. Root of such list is table block:
  95.      +------------+   list of used tables (used while invalidation of
  96. <----| Table   |-----> whole database)
  97.  prev| block   |next      +-----------+
  98.      |   |   +-----------+      |Query block|
  99.      |   |   |Query block|      +-----------+
  100.      +------------+   +-----------+      | ...  |
  101.   +->| table 0   |------>|table 0    |----->| table N  |---+
  102.   |+-|   |<------|       |<-----|  |<-+|
  103.   || +------------+   | ...       |      | ...  |  ||
  104.   || |table header|   +-----------+      +-----------+  ||
  105.   || +------------+   | ...       |      | ...  |  ||
  106.   || |db name +   |   +-----------+      +-----------+  ||
  107.   || |table name  |     ||
  108.   || +------------+     ||
  109.   |+--------------------------------------------------------+|
  110.   +----------------------------------------------------------+
  111. Table block is included into the tables hash (tables).
  112. 6. Free blocks, free blocks bins & steps of freeblock bins.
  113. When we just started only one free memory block  existed. All query
  114. cache memory (that will be used for block allocation) were
  115. containing in this block.
  116. When a new block is allocated we find most suitable memory block
  117. (minimal of >= required size). If such a block can not be found, we try
  118. to find max block < required size (if we allocate block for results).
  119. If there is no free memory, oldest query is removed from cache, and then
  120. we try to allocate memory. Last step should be repeated until we find
  121. suitable block or until there is no unlocked query found.
  122. If the block is found and its length more then we need, it should be
  123. split into 2 blocks.
  124. New blocks cannot be smaller then min_allocation_unit_bytes.
  125. When a block becomes free, its neighbor-blocks should be tested and if
  126. there are free blocks among them, they should be joined into one block.
  127. Free memory blocks are stored in bins according to their sizes.
  128. The bins are stored in size-descending order.
  129. These bins are distributed (by size) approximately logarithmically.
  130. First bin (number 0) stores free blocks with
  131. size <= query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2.
  132. It is first (number 0) step.
  133. On the next step distributed (1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
  134. QUERY_CACHE_MEM_BIN_PARTS_MUL bins. This bins allocated in interval from
  135. query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 to
  136. query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 >>
  137. QUERY_CACHE_MEM_BIN_STEP_PWR2
  138. ...
  139. On each step interval decreases in 2 power of
  140. QUERY_CACHE_MEM_BIN_STEP_PWR2
  141. times, number of bins (that distributed on this step) increases. If on
  142. the previous step there were N bins distributed , on the current there
  143. would be distributed
  144. (N + QUERY_CACHE_MEM_BIN_PARTS_INC) * QUERY_CACHE_MEM_BIN_PARTS_MUL
  145. bins.
  146. Last distributed bin stores blocks with size near min_allocation_unit
  147. bytes.
  148. For example:
  149. query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 = 100,
  150. min_allocation_unit = 17,
  151. QUERY_CACHE_MEM_BIN_STEP_PWR2 = 1,
  152. QUERY_CACHE_MEM_BIN_PARTS_INC = 1,
  153. QUERY_CACHE_MEM_BIN_PARTS_MUL = 1
  154. (in followed picture showed right (low) bound of bin):
  155.       |       100>>1  50>>1       |25>>1|
  156.       |  |    |       |  |  |
  157.       | 100  75 50  41 33 25  21 18 15| 12  | -  bins right (low) bounds
  158.       |---/-----/--------/--------|---/ |
  159.       |  0     1 2    3  |     | - steps
  160.        -----------------------------/ ---/
  161. bins that we store in cache this bin showed for example only
  162. Calculation of steps/bins distribution is performed only when query cache
  163. is resized.
  164. When we need to find appropriate bin, first we should find appropriate
  165. step, then we should calculate number of bins that are using data
  166. stored in Query_cache_memory_bin_step structure.
  167. Free memory blocks are sorted in bins in lists with size-ascending order
  168. (more small blocks needed frequently then bigger one).
  169. 7. Packing cache.
  170. Query cache packing is divided into two operation:
  171. - pack_cache
  172. - join_results
  173. pack_cache moved all blocks to "top" of cache and create one block of free
  174. space at the "bottom":
  175.  before pack_cache    after pack_cache
  176.  +-------------+      +-------------+
  177.  | query 1     |      | query 1     |
  178.  +-------------+      +-------------+
  179.  | table 1     |      | table 1     |
  180.  +-------------+      +-------------+
  181.  | results 1.1 |      | results 1.1 |
  182.  +-------------+      +-------------+
  183.  | free        |      | query 2     |
  184.  +-------------+      +-------------+
  185.  | query 2     |      | table 2     |
  186.  +-------------+ ---> +-------------+
  187.  | table 2     |      | results 1.2 |
  188.  +-------------+      +-------------+
  189.  | results 1.2 |      | results 2   |
  190.  +-------------+      +-------------+
  191.  | free        |      | free        |
  192.  +-------------+      |             |
  193.  | results 2   |      |             |
  194.  +-------------+      |             |
  195.  | free        |      |             |
  196.  +-------------+      +-------------+
  197. pack_cache scan blocks in physical address order and move every non-free
  198. block "higher".
  199. pack_cach remove every free block it finds. The length of the deleted block
  200. is accumulated to the "gap". All non free blocks should be shifted with the
  201. "gap" step.
  202. join_results scans all complete queries. If the results of query are not
  203. stored in the same block, join_results tries to move results so, that they
  204. are stored in one block.
  205.  before join_results  after join_results
  206.  +-------------+      +-------------+
  207.  | query 1     |      | query 1     |
  208.  +-------------+      +-------------+
  209.  | table 1     |      | table 1     |
  210.  +-------------+      +-------------+
  211.  | results 1.1 |      | free        |
  212.  +-------------+      +-------------+
  213.  | query 2     |      | query 2     |
  214.  +-------------+      +-------------+
  215.  | table 2     |      | table 2     |
  216.  +-------------+ ---> +-------------+
  217.  | results 1.2 |      | free        |
  218.  +-------------+      +-------------+
  219.  | results 2   |      | results 2   |
  220.  +-------------+      +-------------+
  221.  | free        |      | results 1   |
  222.  |             |      |             |
  223.  |             |      +-------------+
  224.  |             |      | free        |
  225.  |             |      |             |
  226.  +-------------+      +-------------+
  227. If join_results allocated new block(s) then we need call pack_cache again.
  228. TODO list:
  229.   - Delayed till after-parsing qache answer (for column rights processing)
  230.   - Optimize cache resizing
  231.       - if new_size < old_size then pack & shrink
  232.       - if new_size > old_size copy cached query to new cache
  233.   - Move MRG_MYISAM table type processing to handlers, something like:
  234.         tables_used->table->file->register_used_filenames(callback,
  235.                                                           first_argument);
  236.   - Make derived tables cachable.
  237.   - QC improvement suggested by Monty:
  238.     - Add a counter in open_table() for how many MERGE (ISAM or MyISAM)
  239.       tables are cached in the table cache.
  240.       (This will be trivial when we have the new table cache in place I
  241.       have been working on)
  242.     - After this we can add the following test around the for loop in
  243.       is_cacheable::
  244.       if (thd->temp_tables || global_merge_table_count)
  245.     - Another option would be to set thd->lex->safe_to_cache_query to 0
  246.       in 'get_lock_data' if any of the tables was a tmp table or a
  247.       MRG_ISAM table.
  248.       (This could be done with almost no speed penalty)
  249. */
  250. #include "mysql_priv.h"
  251. #ifdef HAVE_QUERY_CACHE
  252. #include <m_ctype.h>
  253. #include <my_dir.h>
  254. #include <hash.h>
  255. #include "ha_myisammrg.h"
  256. #ifndef MASTER
  257. #include "../srclib/myisammrg/myrg_def.h"
  258. #else
  259. #include "../myisammrg/myrg_def.h"
  260. #endif
  261. #ifdef EMBEDDED_LIBRARY
  262. #include "emb_qcache.h"
  263. #endif
  264. #if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
  265. #define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); 
  266.   pthread_mutex_lock(M);}
  267. #define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",
  268.   (ulong)(M))); pthread_mutex_unlock(M);}
  269. #define RW_WLOCK(M) {DBUG_PRINT("lock", ("rwlock wlock 0x%lx",(ulong)(M))); 
  270.   if (!rw_wrlock(M)) DBUG_PRINT("lock", ("rwlock wlock ok")) 
  271.   else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); }
  272. #define RW_RLOCK(M) {DBUG_PRINT("lock", ("rwlock rlock 0x%lx", (ulong)(M))); 
  273.   if (!rw_rdlock(M)) DBUG_PRINT("lock", ("rwlock rlock ok")) 
  274.   else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); }
  275. #define RW_UNLOCK(M) {DBUG_PRINT("lock", ("rwlock unlock 0x%lx",(ulong)(M))); 
  276.   if (!rw_unlock(M)) DBUG_PRINT("lock", ("rwlock unlock ok")) 
  277.   else DBUG_PRINT("lock", ("rwlock unlock FAILED %d", errno)); }
  278. #define STRUCT_LOCK(M) {DBUG_PRINT("lock", ("%d struct lock...",__LINE__)); 
  279.   pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));}
  280. #define STRUCT_UNLOCK(M) { 
  281.   DBUG_PRINT("lock", ("%d struct unlock...",__LINE__)); 
  282.   pthread_mutex_unlock(M);DBUG_PRINT("lock", ("struct unlock OK"));}
  283. #define BLOCK_LOCK_WR(B) {DBUG_PRINT("lock", ("%d LOCK_WR 0x%lx",
  284.   __LINE__,(ulong)(B))); 
  285.   B->query()->lock_writing();}
  286. #define BLOCK_LOCK_RD(B) {DBUG_PRINT("lock", ("%d LOCK_RD 0x%lx",
  287.   __LINE__,(ulong)(B))); 
  288.   B->query()->lock_reading();}
  289. #define BLOCK_UNLOCK_WR(B) { 
  290.   DBUG_PRINT("lock", ("%d UNLOCK_WR 0x%lx",
  291.   __LINE__,(ulong)(B)));B->query()->unlock_writing();}
  292. #define BLOCK_UNLOCK_RD(B) { 
  293.   DBUG_PRINT("lock", ("%d UNLOCK_RD 0x%lx",
  294.   __LINE__,(ulong)(B)));B->query()->unlock_reading();}
  295. #define DUMP(C) DBUG_EXECUTE("qcache", {
  296.   (C)->cache_dump(); (C)->queries_dump();(C)->tables_dump();})
  297. #else
  298. #define MUTEX_LOCK(M) pthread_mutex_lock(M)
  299. #define MUTEX_UNLOCK(M) pthread_mutex_unlock(M)
  300. #define RW_WLOCK(M) rw_wrlock(M)
  301. #define RW_RLOCK(M) rw_rdlock(M)
  302. #define RW_UNLOCK(M) rw_unlock(M)
  303. #define STRUCT_LOCK(M) pthread_mutex_lock(M)
  304. #define STRUCT_UNLOCK(M) pthread_mutex_unlock(M)
  305. #define BLOCK_LOCK_WR(B) B->query()->lock_writing()
  306. #define BLOCK_LOCK_RD(B) B->query()->lock_reading()
  307. #define BLOCK_UNLOCK_WR(B) B->query()->unlock_writing()
  308. #define BLOCK_UNLOCK_RD(B) B->query()->unlock_reading()
  309. #define DUMP(C)
  310. #endif
  311. const char *query_cache_type_names[]= { "OFF", "ON", "DEMAND",NullS };
  312. TYPELIB query_cache_type_typelib=
  313. {
  314.   array_elements(query_cache_type_names)-1,"", query_cache_type_names, NULL
  315. };
  316. /*****************************************************************************
  317.  Query_cache_block_table method(s)
  318. *****************************************************************************/
  319. inline Query_cache_block * Query_cache_block_table::block()
  320. {
  321.   return (Query_cache_block *)(((byte*)this) -
  322.        ALIGN_SIZE(sizeof(Query_cache_block_table)*n) -
  323.        ALIGN_SIZE(sizeof(Query_cache_block)));
  324. }
  325. /*****************************************************************************
  326.    Query_cache_block method(s)
  327. *****************************************************************************/
  328. void Query_cache_block::init(ulong block_length)
  329. {
  330.   DBUG_ENTER("Query_cache_block::init");
  331.   DBUG_PRINT("qcache", ("init block 0x%lx  length: %lu", (ulong) this,
  332. block_length));
  333.   length = block_length;
  334.   used = 0;
  335.   type = Query_cache_block::FREE;
  336.   n_tables = 0;
  337.   DBUG_VOID_RETURN;
  338. }
  339. void Query_cache_block::destroy()
  340. {
  341.   DBUG_ENTER("Query_cache_block::destroy");
  342.   DBUG_PRINT("qcache", ("destroy block 0x%lx, type %d",
  343. (ulong) this, type));
  344.   type = INCOMPLETE;
  345.   DBUG_VOID_RETURN;
  346. }
  347. inline uint Query_cache_block::headers_len()
  348. {
  349.   return (ALIGN_SIZE(sizeof(Query_cache_block_table)*n_tables) +
  350.   ALIGN_SIZE(sizeof(Query_cache_block)));
  351. }
  352. inline gptr Query_cache_block::data(void)
  353. {
  354.   return (gptr)( ((byte*)this) + headers_len() );
  355. }
  356. inline Query_cache_query * Query_cache_block::query()
  357. {
  358. #ifndef DBUG_OFF
  359.   if (type != QUERY)
  360.     query_cache.wreck(__LINE__, "incorrect block type");
  361. #endif
  362.   return (Query_cache_query *) data();
  363. }
  364. inline Query_cache_table * Query_cache_block::table()
  365. {
  366. #ifndef DBUG_OFF
  367.   if (type != TABLE)
  368.     query_cache.wreck(__LINE__, "incorrect block type");
  369. #endif
  370.   return (Query_cache_table *) data();
  371. }
  372. inline Query_cache_result * Query_cache_block::result()
  373. {
  374. #ifndef DBUG_OFF
  375.   if (type != RESULT && type != RES_CONT && type != RES_BEG &&
  376.       type != RES_INCOMPLETE)
  377.     query_cache.wreck(__LINE__, "incorrect block type");
  378. #endif
  379.   return (Query_cache_result *) data();
  380. }
  381. inline Query_cache_block_table * Query_cache_block::table(TABLE_COUNTER_TYPE n)
  382. {
  383.   return ((Query_cache_block_table *)
  384.   (((byte*)this)+ALIGN_SIZE(sizeof(Query_cache_block)) +
  385.    n*sizeof(Query_cache_block_table)));
  386. }
  387. /*****************************************************************************
  388.  *   Query_cache_table method(s)
  389.  *****************************************************************************/
  390. extern "C"
  391. {
  392. byte *query_cache_table_get_key(const byte *record, uint *length,
  393. my_bool not_used __attribute__((unused)))
  394. {
  395.   Query_cache_block* table_block = (Query_cache_block*) record;
  396.   *length = (table_block->used - table_block->headers_len() -
  397.      ALIGN_SIZE(sizeof(Query_cache_table)));
  398.   return (((byte *) table_block->data()) +
  399.   ALIGN_SIZE(sizeof(Query_cache_table)));
  400. }
  401. }
  402. /*****************************************************************************
  403.     Query_cache_query methods
  404. *****************************************************************************/
  405. /*
  406.    Following methods work for block read/write locking only in this
  407.    particular case and in interaction with structure_guard_mutex.
  408.    Lock for write prevents any other locking. (exclusive use)
  409.    Lock for read prevents only locking for write.
  410. */
  411. inline void Query_cache_query::lock_writing()
  412. {
  413.   RW_WLOCK(&lock);
  414. }
  415. /*
  416.   Needed for finding queries, that we may delete from cache.
  417.   We don't want to wait while block become unlocked. In addition,
  418.   block locking means that query is now used and we don't need to
  419.   remove it.
  420. */
  421. my_bool Query_cache_query::try_lock_writing()
  422. {
  423.   DBUG_ENTER("Query_cache_block::try_lock_writing");
  424.   if (rw_trywrlock(&lock)!=0)
  425.   {
  426.     DBUG_PRINT("info", ("can't lock rwlock"));
  427.     DBUG_RETURN(0);
  428.   }
  429.   DBUG_PRINT("info", ("rwlock 0x%lx locked", (ulong) &lock));
  430.   DBUG_RETURN(1);
  431. }
  432. inline void Query_cache_query::lock_reading()
  433. {
  434.   RW_RLOCK(&lock);
  435. }
  436. inline void Query_cache_query::unlock_writing()
  437. {
  438.   RW_UNLOCK(&lock);
  439. }
  440. inline void Query_cache_query::unlock_reading()
  441. {
  442.   RW_UNLOCK(&lock);
  443. }
  444. void Query_cache_query::init_n_lock()
  445. {
  446.   DBUG_ENTER("Query_cache_query::init_n_lock");
  447.   res=0; wri = 0; len = 0;
  448.   my_rwlock_init(&lock, NULL);
  449.   lock_writing();
  450.   DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx",
  451. ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
  452.   DBUG_VOID_RETURN;
  453. }
  454. void Query_cache_query::unlock_n_destroy()
  455. {
  456.   DBUG_ENTER("Query_cache_query::unlock_n_destroy");
  457.   DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
  458. ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
  459.   /*
  460.     The following call is not needed on system where one can destroy an
  461.     active semaphore
  462.   */
  463.   this->unlock_writing();
  464.   rwlock_destroy(&lock);
  465.   DBUG_VOID_RETURN;
  466. }
  467. extern "C"
  468. {
  469. byte *query_cache_query_get_key(const byte *record, uint *length,
  470. my_bool not_used)
  471. {
  472.   Query_cache_block *query_block = (Query_cache_block*) record;
  473.   *length = (query_block->used - query_block->headers_len() -
  474.      ALIGN_SIZE(sizeof(Query_cache_query)));
  475.   return (((byte *) query_block->data()) +
  476.   ALIGN_SIZE(sizeof(Query_cache_query)));
  477. }
  478. }
  479. /*****************************************************************************
  480.   Functions to store things into the query cache
  481. *****************************************************************************/
  482. /*
  483.   Insert the packet into the query cache.
  484.   This should only be called if net->query_cache_query != 0
  485. */
  486. void query_cache_insert(NET *net, const char *packet, ulong length)
  487. {
  488.   DBUG_ENTER("query_cache_insert");
  489.   STRUCT_LOCK(&query_cache.structure_guard_mutex);
  490.   /*
  491.     It is very unlikely that following condition is TRUE (it is possible
  492.     only if other thread is resizing cache), so we check it only after guard
  493.     mutex lock
  494.   */
  495.   if (unlikely(query_cache.query_cache_size == 0))
  496.   {
  497.     STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
  498.     DBUG_VOID_RETURN;
  499.   }
  500.   Query_cache_block *query_block = ((Query_cache_block*)
  501.     net->query_cache_query);
  502.   if (query_block)
  503.   {
  504.     Query_cache_query *header = query_block->query();
  505.     Query_cache_block *result = header->result();
  506.     DUMP(&query_cache);
  507.     BLOCK_LOCK_WR(query_block);
  508.     DBUG_PRINT("qcache", ("insert packet %lu bytes long",length));
  509.     /*
  510.       On success STRUCT_UNLOCK(&query_cache.structure_guard_mutex) will be
  511.       done by query_cache.append_result_data if success (if not we need
  512.       query_cache.structure_guard_mutex locked to free query)
  513.     */
  514.     if (!query_cache.append_result_data(&result, length, (gptr) packet,
  515. query_block))
  516.     {
  517.       DBUG_PRINT("warning", ("Can't append data"));
  518.       header->result(result);
  519.       DBUG_PRINT("qcache", ("free query 0x%lx", (ulong) query_block));
  520.       // The following call will remove the lock on query_block
  521.       query_cache.free_query(query_block);
  522.       // append_result_data no success => we need unlock
  523.       STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
  524.       DBUG_VOID_RETURN;
  525.     }
  526.     header->result(result);
  527.     BLOCK_UNLOCK_WR(query_block);
  528.   }
  529.   else
  530.     STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
  531.   DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
  532.   DBUG_VOID_RETURN;
  533. }
  534. void query_cache_abort(NET *net)
  535. {
  536.   DBUG_ENTER("query_cache_abort");
  537.   if (net->query_cache_query != 0) // Quick check on unlocked structure
  538.   {
  539.     STRUCT_LOCK(&query_cache.structure_guard_mutex);
  540.     /*
  541.       It is very unlikely that following condition is TRUE (it is possible
  542.       only if other thread is resizing cache), so we check it only after guard
  543.       mutex lock
  544.     */
  545.     if (unlikely(query_cache.query_cache_size == 0))
  546.     {
  547.       STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
  548.       DBUG_VOID_RETURN;
  549.     }
  550.     Query_cache_block *query_block = ((Query_cache_block*)
  551.        net->query_cache_query);
  552.     if (query_block) // Test if changed by other thread
  553.     {
  554.       DUMP(&query_cache);
  555.       BLOCK_LOCK_WR(query_block);
  556.       // The following call will remove the lock on query_block
  557.       query_cache.free_query(query_block);
  558.     }
  559.     net->query_cache_query=0;
  560.     DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
  561.     STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
  562.   }
  563.   DBUG_VOID_RETURN;
  564. }
  565. void query_cache_end_of_result(THD *thd)
  566. {
  567.   DBUG_ENTER("query_cache_end_of_result");
  568.   if (thd->net.query_cache_query != 0) // Quick check on unlocked structure
  569.   {
  570. #ifdef EMBEDDED_LIBRARY
  571.     query_cache_insert(&thd->net, (char*)thd, 
  572.        emb_count_querycache_size(thd));
  573. #endif
  574.     STRUCT_LOCK(&query_cache.structure_guard_mutex);
  575.     /*
  576.       It is very unlikely that following condition is TRUE (it is possible
  577.       only if other thread is resizing cache), so we check it only after guard
  578.       mutex lock
  579.     */
  580.     if (unlikely(query_cache.query_cache_size == 0))
  581.     {
  582.       STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
  583.       DBUG_VOID_RETURN;
  584.     }
  585.     Query_cache_block *query_block = ((Query_cache_block*)
  586.       thd->net.query_cache_query);
  587.     if (query_block)
  588.     {
  589.       DUMP(&query_cache);
  590.       BLOCK_LOCK_WR(query_block);
  591.       Query_cache_query *header = query_block->query();
  592.       Query_cache_block *last_result_block = header->result()->prev;
  593.       ulong allign_size = ALIGN_SIZE(last_result_block->used);
  594.       ulong len = max(query_cache.min_allocation_unit, allign_size);
  595.       if (last_result_block->length >= query_cache.min_allocation_unit + len)
  596. query_cache.split_block(last_result_block,len);
  597.       STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
  598. #ifndef DBUG_OFF
  599.       if (header->result() == 0)
  600.       {
  601. DBUG_PRINT("error", ("end of data whith no result. query '%s'",
  602.      header->query()));
  603. query_cache.wreck(__LINE__, "");
  604. DBUG_VOID_RETURN;
  605.       }
  606. #endif
  607.       header->found_rows(current_thd->limit_found_rows);
  608.       header->result()->type = Query_cache_block::RESULT;
  609.       header->writer(0);
  610.       BLOCK_UNLOCK_WR(query_block);
  611.     }
  612.     else
  613.     {
  614.       // Cache was flushed or resized and query was deleted => do nothing
  615.       STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
  616.     }
  617.     thd->net.query_cache_query=0;
  618.     DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
  619.   }
  620.   DBUG_VOID_RETURN;
  621. }
  622. void query_cache_invalidate_by_MyISAM_filename(const char *filename)
  623. {
  624.   query_cache.invalidate_by_MyISAM_filename(filename);
  625.   DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
  626. }
  627. /*****************************************************************************
  628.    Query_cache methods
  629. *****************************************************************************/
  630. Query_cache::Query_cache(ulong query_cache_limit_arg,
  631.  ulong min_allocation_unit_arg,
  632.  ulong min_result_data_size_arg,
  633.  uint def_query_hash_size_arg,
  634.  uint def_table_hash_size_arg)
  635.   :query_cache_size(0),
  636.    query_cache_limit(query_cache_limit_arg),
  637.    queries_in_cache(0), hits(0), inserts(0), refused(0),
  638.    total_blocks(0), lowmem_prunes(0),
  639.    min_allocation_unit(ALIGN_SIZE(min_allocation_unit_arg)),
  640.    min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)),
  641.    def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)),
  642.    def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)),
  643.    initialized(0)
  644. {
  645.   ulong min_needed= (ALIGN_SIZE(sizeof(Query_cache_block)) +
  646.      ALIGN_SIZE(sizeof(Query_cache_block_table)) +
  647.      ALIGN_SIZE(sizeof(Query_cache_query)) + 3);
  648.   set_if_bigger(min_allocation_unit,min_needed);
  649.   this->min_allocation_unit= ALIGN_SIZE(min_allocation_unit);
  650.   set_if_bigger(this->min_result_data_size,min_allocation_unit);
  651. }
  652. ulong Query_cache::resize(ulong query_cache_size_arg)
  653. {
  654.   DBUG_ENTER("Query_cache::resize");
  655.   DBUG_PRINT("qcache", ("from %lu to %lu",query_cache_size,
  656. query_cache_size_arg));
  657.   DBUG_ASSERT(initialized);
  658.   STRUCT_LOCK(&structure_guard_mutex);
  659.   if (query_cache_size > 0)
  660.     free_cache();
  661.   query_cache_size= query_cache_size_arg;
  662.   ::query_cache_size= init_cache();
  663.   STRUCT_UNLOCK(&structure_guard_mutex);
  664.   DBUG_RETURN(::query_cache_size);
  665. }
  666. ulong Query_cache::set_min_res_unit(ulong size)
  667. {
  668.   if (size < min_allocation_unit)
  669.     size= min_allocation_unit;
  670.   return (min_result_data_size= ALIGN_SIZE(size));
  671. }
  672. void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
  673. {
  674.   TABLE_COUNTER_TYPE local_tables;
  675.   ulong tot_length;
  676.   DBUG_ENTER("Query_cache::store_query");
  677.   if (query_cache_size == 0 || thd->locked_tables)
  678.     DBUG_VOID_RETURN;
  679.   uint8 tables_type= 0;
  680.   if ((local_tables= is_cacheable(thd, thd->query_length,
  681.   thd->query, thd->lex, tables_used,
  682.   &tables_type)))
  683.   {
  684.     NET *net= &thd->net;
  685.     Query_cache_query_flags flags;
  686.     // fill all gaps between fields with 0 to get repeatable key
  687.     bzero(&flags, QUERY_CACHE_FLAGS_SIZE);
  688.     flags.client_long_flag= (thd->client_capabilities & CLIENT_LONG_FLAG ?
  689.      1 : 0);
  690.     flags.client_protocol_41= (thd->client_capabilities & CLIENT_PROTOCOL_41 ?
  691.      1 : 0);
  692.     flags.character_set_client_num=
  693.       thd->variables.character_set_client->number;
  694.     flags.character_set_results_num=
  695.       (thd->variables.character_set_results ?
  696.        thd->variables.character_set_results->number :
  697.        UINT_MAX);
  698.     flags.collation_connection_num=
  699.       thd->variables.collation_connection->number;
  700.     flags.limit= thd->variables.select_limit;
  701.     flags.time_zone= thd->variables.time_zone;
  702.     flags.sql_mode= thd->variables.sql_mode;
  703.     flags.max_sort_length= thd->variables.max_sort_length;
  704.     flags.group_concat_max_len= thd->variables.group_concat_max_len;
  705.     STRUCT_LOCK(&structure_guard_mutex);
  706.     if (query_cache_size == 0)
  707.     {
  708.       STRUCT_UNLOCK(&structure_guard_mutex);
  709.       DBUG_VOID_RETURN;
  710.     }
  711.     DUMP(this);
  712.     if (ask_handler_allowance(thd, tables_used))
  713.     {
  714.       refused++;
  715.       STRUCT_UNLOCK(&structure_guard_mutex);
  716.       DBUG_VOID_RETURN;
  717.     }
  718.     /* Key is query + database + flag */
  719.     if (thd->db_length)
  720.     {
  721.       memcpy(thd->query+thd->query_length+1, thd->db, thd->db_length);
  722.       DBUG_PRINT("qcache", ("database : %s length %u",
  723.     thd->db, thd->db_length)); 
  724.     }
  725.     else
  726.     {
  727.       DBUG_PRINT("qcache", ("No active database"));
  728.     }
  729.     tot_length= thd->query_length + thd->db_length + 1 +
  730.       QUERY_CACHE_FLAGS_SIZE;
  731.     /*
  732.       We should only copy structure (don't use it location directly)
  733.       because of alignment issue
  734.     */
  735.     memcpy((void *)(thd->query + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
  736.    &flags, QUERY_CACHE_FLAGS_SIZE);
  737.     /* Check if another thread is processing the same query? */
  738.     Query_cache_block *competitor = (Query_cache_block *)
  739.       hash_search(&queries, (byte*) thd->query, tot_length);
  740.     DBUG_PRINT("qcache", ("competitor 0x%lx", (ulong) competitor));
  741.     if (competitor == 0)
  742.     {
  743.       /* Query is not in cache and no one is working with it; Store it */
  744.       Query_cache_block *query_block;
  745.       query_block= write_block_data(tot_length, (gptr) thd->query,
  746.     ALIGN_SIZE(sizeof(Query_cache_query)),
  747.     Query_cache_block::QUERY, local_tables, 1);
  748.       if (query_block != 0)
  749.       {
  750. DBUG_PRINT("qcache", ("query block 0x%lx allocated, %lu",
  751.     (ulong) query_block, query_block->used));
  752. Query_cache_query *header = query_block->query();
  753. header->init_n_lock();
  754. if (my_hash_insert(&queries, (byte*) query_block))
  755. {
  756.   refused++;
  757.   DBUG_PRINT("qcache", ("insertion in query hash"));
  758.   header->unlock_n_destroy();
  759.   free_memory_block(query_block);
  760.   STRUCT_UNLOCK(&structure_guard_mutex);
  761.   goto end;
  762. }
  763. if (!register_all_tables(query_block, tables_used, local_tables))
  764. {
  765.   refused++;
  766.   DBUG_PRINT("warning", ("tables list including failed"));
  767.   hash_delete(&queries, (byte *) query_block);
  768.   header->unlock_n_destroy();
  769.   free_memory_block(query_block);
  770.   STRUCT_UNLOCK(&structure_guard_mutex);
  771.   goto end;
  772. }
  773. double_linked_list_simple_include(query_block, &queries_blocks);
  774. inserts++;
  775. queries_in_cache++;
  776. STRUCT_UNLOCK(&structure_guard_mutex);
  777. net->query_cache_query= (gptr) query_block;
  778. header->writer(net);
  779. header->tables_type(tables_type);
  780. // init_n_lock make query block locked
  781. BLOCK_UNLOCK_WR(query_block);
  782.       }
  783.       else
  784.       {
  785. // We have not enough memory to store query => do nothing
  786. refused++;
  787. STRUCT_UNLOCK(&structure_guard_mutex);
  788. DBUG_PRINT("warning", ("Can't allocate query"));
  789.       }
  790.     }
  791.     else
  792.     {
  793.       // Another thread is processing the same query => do nothing
  794.       refused++;
  795.       STRUCT_UNLOCK(&structure_guard_mutex);
  796.       DBUG_PRINT("qcache", ("Another thread process same query"));
  797.     }
  798.   }
  799.   else if (thd->lex->sql_command == SQLCOM_SELECT)
  800.     statistic_increment(refused, &structure_guard_mutex);
  801. end:
  802.   DBUG_VOID_RETURN;
  803. }
  804. /*
  805.   Check if the query is in the cache. If it was cached, send it
  806.   to the user.
  807.   RESULTS
  808.         1 Query was not cached.
  809. 0 The query was cached and user was sent the result.
  810. -1 The query was cached but we didn't have rights to use it.
  811. No error is sent to the client yet.
  812. */
  813. int
  814. Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
  815. {
  816.   Query_cache_query *query;
  817.   Query_cache_block *first_result_block, *result_block;
  818.   Query_cache_block_table *block_table, *block_table_end;
  819.   ulong tot_length;
  820.   Query_cache_query_flags flags;
  821.   bool check_tables;
  822.   DBUG_ENTER("Query_cache::send_result_to_client");
  823.   if (query_cache_size == 0 || thd->locked_tables ||
  824.       thd->variables.query_cache_type == 0)
  825.     goto err;
  826.   /* Check that we haven't forgot to reset the query cache variables */
  827.   DBUG_ASSERT(thd->net.query_cache_query == 0);
  828.   if (!thd->lex->safe_to_cache_query)
  829.   {
  830.     DBUG_PRINT("qcache", ("SELECT is non-cacheable"));
  831.     goto err;
  832.   }
  833.   /*
  834.     Test if the query is a SELECT
  835.     (pre-space is removed in dispatch_command)
  836.   */
  837.   if (my_toupper(system_charset_info, sql[0]) != 'S' || 
  838.       my_toupper(system_charset_info, sql[1]) != 'E' ||
  839.       my_toupper(system_charset_info,sql[2]) !='L')
  840.   {
  841.     DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
  842.     goto err;
  843.   }
  844.   STRUCT_LOCK(&structure_guard_mutex);
  845.   if (query_cache_size == 0)
  846.   {
  847.     DBUG_PRINT("qcache", ("query cache disabled"));
  848.     goto err_unlock;
  849.   }
  850.   Query_cache_block *query_block;
  851.   tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
  852.   if (thd->db_length)
  853.   {
  854.     memcpy(sql+query_length+1, thd->db, thd->db_length);
  855.     DBUG_PRINT("qcache", ("database: '%s' length %u",
  856.   thd->db, thd->db_length));
  857.   }
  858.   else
  859.   {
  860.     DBUG_PRINT("qcache", ("No active database"));
  861.   }
  862.   // fill all gaps between fields with 0 to get repeatable key
  863.   bzero(&flags, QUERY_CACHE_FLAGS_SIZE);
  864.   flags.client_long_flag= (thd->client_capabilities & CLIENT_LONG_FLAG ?
  865.    1 : 0);
  866.   flags.client_protocol_41= (thd->client_capabilities & CLIENT_PROTOCOL_41 ?
  867.                            1 : 0);
  868.   flags.character_set_client_num= thd->variables.character_set_client->number;
  869.   flags.character_set_results_num=
  870.     (thd->variables.character_set_results ?
  871.      thd->variables.character_set_results->number :
  872.      UINT_MAX);
  873.   flags.collation_connection_num= thd->variables.collation_connection->number;
  874.   flags.limit= thd->variables.select_limit;
  875.   flags.time_zone= thd->variables.time_zone;
  876.   flags.sql_mode= thd->variables.sql_mode;
  877.   flags.max_sort_length= thd->variables.max_sort_length;
  878.   flags.group_concat_max_len= thd->variables.group_concat_max_len;
  879.   memcpy((void *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
  880.  &flags, QUERY_CACHE_FLAGS_SIZE);
  881.   query_block = (Query_cache_block *)  hash_search(&queries, (byte*) sql,
  882.    tot_length);
  883.   /* Quick abort on unlocked data */
  884.   if (query_block == 0 ||
  885.       query_block->query()->result() == 0 ||
  886.       query_block->query()->result()->type != Query_cache_block::RESULT)
  887.   {
  888.     DBUG_PRINT("qcache", ("No query in query hash or no results"));
  889.     goto err_unlock;
  890.   }
  891.   DBUG_PRINT("qcache", ("Query in query hash 0x%lx", (ulong)query_block));
  892.   /* Now lock and test that nothing changed while blocks was unlocked */
  893.   BLOCK_LOCK_RD(query_block);
  894.   query = query_block->query();
  895.   result_block= first_result_block= query->result();
  896.   if (result_block == 0 || result_block->type != Query_cache_block::RESULT)
  897.   {
  898.     /* The query is probably yet processed */
  899.     DBUG_PRINT("qcache", ("query found, but no data or data incomplete"));
  900.     BLOCK_UNLOCK_RD(query_block);
  901.     goto err_unlock;
  902.   }
  903.   DBUG_PRINT("qcache", ("Query have result 0x%lx", (ulong) query));
  904.   if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
  905.       (query->tables_type() & HA_CACHE_TBL_TRANSACT))
  906.   {
  907.     DBUG_PRINT("qcache",
  908.        ("we are in transaction and have transaction tables in query"));
  909.     BLOCK_UNLOCK_RD(query_block);
  910.     goto err_unlock;
  911.   }
  912.       
  913.   check_tables= query->tables_type() & HA_CACHE_TBL_ASKTRANSACT;
  914.   // Check access;
  915.   block_table= query_block->table(0);
  916.   block_table_end= block_table+query_block->n_tables;
  917.   for (; block_table != block_table_end; block_table++)
  918.   {
  919.     TABLE_LIST table_list;
  920.     TABLE *tmptable;
  921.     Query_cache_table *table = block_table->parent;
  922.     /*
  923.       Check that we have not temporary tables with same names of tables
  924.       of this query. If we have such tables, we will not send data from
  925.       query cache, because temporary tables hide real tables by which
  926.       query in query cache was made.
  927.     */
  928.     for (tmptable= thd->temporary_tables; tmptable ; tmptable= tmptable->next)
  929.     {
  930.       if (tmptable->key_length - TMP_TABLE_KEY_EXTRA == table->key_length() &&
  931.           !memcmp(tmptable->table_cache_key, table->data(),
  932.                   table->key_length()))
  933.       {
  934.         DBUG_PRINT("qcache",
  935.                    ("Temporary table detected: '%s.%s'",
  936.                     table_list.db, table_list.alias));
  937.         STRUCT_UNLOCK(&structure_guard_mutex);
  938.         /*
  939.           We should not store result of this query because it contain
  940.           temporary tables => assign following variable to make check
  941.           faster.
  942.         */
  943.         thd->lex->safe_to_cache_query=0;
  944.         BLOCK_UNLOCK_RD(query_block);
  945.         DBUG_RETURN(-1);
  946.       }
  947.     }
  948.     bzero((char*) &table_list,sizeof(table_list));
  949.     table_list.db = table->db();
  950.     table_list.alias= table_list.real_name= table->table();
  951. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  952.     if (check_table_access(thd,SELECT_ACL,&table_list,1))
  953.     {
  954.       DBUG_PRINT("qcache",
  955.  ("probably no SELECT access to %s.%s =>  return to normal processing",
  956.   table_list.db, table_list.alias));
  957.       STRUCT_UNLOCK(&structure_guard_mutex);
  958.       thd->lex->safe_to_cache_query=0; // Don't try to cache this
  959.       BLOCK_UNLOCK_RD(query_block);
  960.       DBUG_RETURN(-1); // Privilege error
  961.     }
  962.     if (table_list.grant.want_privilege)
  963.     {
  964.       DBUG_PRINT("qcache", ("Need to check column privileges for %s.%s",
  965.     table_list.db, table_list.alias));
  966.       BLOCK_UNLOCK_RD(query_block);
  967.       thd->lex->safe_to_cache_query= 0; // Don't try to cache this
  968.       goto err_unlock; // Parse query
  969.     }
  970. #endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
  971.     if (check_tables && !ha_caching_allowed(thd, table->db(), 
  972.                                          table->key_length(),
  973.                                          table->type()))
  974.     {
  975.       DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
  976.     table_list.db, table_list.alias));
  977.       BLOCK_UNLOCK_RD(query_block);
  978.       thd->lex->safe_to_cache_query= 0;          // Don't try to cache this
  979.       goto err_unlock; // Parse query
  980.     }
  981.     else
  982.       DBUG_PRINT("qcache", ("handler allow caching (%d) %s,%s",
  983.     check_tables, table_list.db, table_list.alias));
  984.   }
  985.   move_to_query_list_end(query_block);
  986.   hits++;
  987.   STRUCT_UNLOCK(&structure_guard_mutex);
  988.   /*
  989.     Send cached result to client
  990.   */
  991. #ifndef EMBEDDED_LIBRARY
  992.   do
  993.   {
  994.     DBUG_PRINT("qcache", ("Results  (len %lu, used %lu, headers %lu)",
  995.   result_block->length, result_block->used,
  996.   result_block->headers_len()+
  997.   ALIGN_SIZE(sizeof(Query_cache_result))));
  998.     
  999.     Query_cache_result *result = result_block->result();
  1000.     if (net_real_write(&thd->net, result->data(),
  1001.        result_block->used -
  1002.        result_block->headers_len() -
  1003.        ALIGN_SIZE(sizeof(Query_cache_result))))
  1004.       break; // Client aborted
  1005.     result_block = result_block->next;
  1006.   } while (result_block != first_result_block);
  1007. #else
  1008.   {
  1009.     Querycache_stream qs(result_block, result_block->headers_len() +
  1010.  ALIGN_SIZE(sizeof(Query_cache_result)));
  1011.     emb_load_querycache_result(thd, &qs);
  1012.   }
  1013. #endif /*!EMBEDDED_LIBRARY*/
  1014.   thd->limit_found_rows = query->found_rows();
  1015.   BLOCK_UNLOCK_RD(query_block);
  1016.   DBUG_RETURN(1); // Result sent to client
  1017. err_unlock:
  1018.   STRUCT_UNLOCK(&structure_guard_mutex);
  1019. err:
  1020.   DBUG_RETURN(0); // Query was not cached
  1021. }
  1022. /*
  1023.   Remove all cached queries that uses any of the tables in the list
  1024. */
  1025. void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
  1026.      my_bool using_transactions)
  1027. {
  1028.   DBUG_ENTER("Query_cache::invalidate (table list)");
  1029.   if (query_cache_size > 0)
  1030.   {
  1031.     STRUCT_LOCK(&structure_guard_mutex);
  1032.     if (query_cache_size > 0)
  1033.     {
  1034.       DUMP(this);
  1035.       using_transactions = using_transactions &&
  1036. (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
  1037.       for (; tables_used; tables_used=tables_used->next)
  1038.       {
  1039. DBUG_ASSERT(!using_transactions || tables_used->table!=0);
  1040. if (tables_used->derived)
  1041.   continue;
  1042. if (using_transactions &&
  1043.    (tables_used->table->file->table_cache_type() ==
  1044.     HA_CACHE_TBL_TRANSACT))
  1045.   /*
  1046.      Tables_used->table can't be 0 in transaction.
  1047.      Only 'drop' invalidate not opened table, but 'drop'
  1048.      force transaction finish.
  1049.   */
  1050.   thd->add_changed_table(tables_used->table);
  1051. else
  1052.   invalidate_table(tables_used);
  1053.       }
  1054.     }
  1055.     STRUCT_UNLOCK(&structure_guard_mutex);
  1056.   }
  1057.   DBUG_VOID_RETURN;
  1058. }
  1059. void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
  1060. {
  1061.   DBUG_ENTER("Query_cache::invalidate (changed table list)");
  1062.   if (query_cache_size > 0 && tables_used)
  1063.   {
  1064.     STRUCT_LOCK(&structure_guard_mutex);
  1065.     if (query_cache_size > 0)
  1066.     {
  1067.       DUMP(this);
  1068.       for (; tables_used; tables_used=tables_used->next)
  1069.       {
  1070. invalidate_table((byte*) tables_used->key, tables_used->key_length);
  1071. DBUG_PRINT("qcache", (" db %s, table %s", tables_used->key,
  1072.       tables_used->key+
  1073.       strlen(tables_used->key)+1));
  1074.       }
  1075.     }
  1076.     STRUCT_UNLOCK(&structure_guard_mutex);
  1077.   }
  1078.   DBUG_VOID_RETURN;
  1079. }
  1080. /*
  1081.   Invalidate locked for write
  1082.   SYNOPSIS
  1083.     Query_cache::invalidate_locked_for_write()
  1084.     tables_used - table list
  1085.   NOTE
  1086.     can be used only for opened tables
  1087. */
  1088. void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used)
  1089. {
  1090.   DBUG_ENTER("Query_cache::invalidate_locked_for_write");
  1091.   if (query_cache_size > 0 && tables_used)
  1092.   {
  1093.     STRUCT_LOCK(&structure_guard_mutex);
  1094.     if (query_cache_size > 0)
  1095.     {
  1096.       DUMP(this);
  1097.       for (; tables_used; tables_used= tables_used->next)
  1098.       {
  1099. if (tables_used->lock_type & (TL_WRITE_LOW_PRIORITY | TL_WRITE))
  1100.   invalidate_table(tables_used->table);
  1101.       }
  1102.     }
  1103.     STRUCT_UNLOCK(&structure_guard_mutex);
  1104.   }
  1105.   DBUG_VOID_RETURN;
  1106. }
  1107. /*
  1108.   Remove all cached queries that uses the given table
  1109. */
  1110. void Query_cache::invalidate(THD *thd, TABLE *table, 
  1111.      my_bool using_transactions)
  1112. {
  1113.   DBUG_ENTER("Query_cache::invalidate (table)");
  1114.   
  1115.   if (query_cache_size > 0)
  1116.   {
  1117.     STRUCT_LOCK(&structure_guard_mutex);
  1118.     if (query_cache_size > 0)
  1119.     {
  1120.       using_transactions = using_transactions &&
  1121. (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
  1122.       if (using_transactions && 
  1123.   (table->file->table_cache_type() == HA_CACHE_TBL_TRANSACT))
  1124. thd->add_changed_table(table);
  1125.       else
  1126. invalidate_table(table);
  1127.     }
  1128.     STRUCT_UNLOCK(&structure_guard_mutex);
  1129.   }
  1130.   DBUG_VOID_RETURN;
  1131. }
  1132. void Query_cache::invalidate(THD *thd, const char *key, uint32  key_length,
  1133.      my_bool using_transactions)
  1134. {
  1135.   DBUG_ENTER("Query_cache::invalidate (key)");
  1136.   
  1137.   if (query_cache_size > 0)
  1138.   {
  1139.     using_transactions = using_transactions &&
  1140.       (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
  1141.     if (using_transactions) // used for innodb => has_transactions() is TRUE
  1142.       thd->add_changed_table(key, key_length);
  1143.     else
  1144.     {
  1145.       STRUCT_LOCK(&structure_guard_mutex);
  1146.       if (query_cache_size > 0)
  1147. invalidate_table((byte*)key, key_length);
  1148.       STRUCT_UNLOCK(&structure_guard_mutex);  
  1149.     }
  1150.   }
  1151.   DBUG_VOID_RETURN;
  1152. }
  1153. /*
  1154.   Remove all cached queries that uses the given database
  1155. */
  1156. void Query_cache::invalidate(char *db)
  1157. {
  1158.   DBUG_ENTER("Query_cache::invalidate (db)");
  1159.   if (query_cache_size > 0)
  1160.   {
  1161.     STRUCT_LOCK(&structure_guard_mutex);
  1162.     if (query_cache_size > 0)
  1163.     {
  1164.       DUMP(this);
  1165.   restart_search:
  1166.       if (tables_blocks)
  1167.       {
  1168. Query_cache_block *curr= tables_blocks;
  1169. Query_cache_block *next;
  1170. do
  1171. {
  1172.   next= curr->next;
  1173.   if (strcmp(db, (char*)(curr->table()->db())) == 0)
  1174.     invalidate_table(curr);
  1175.   /*
  1176.     invalidate_table can freed block on which point 'next' (if
  1177.     table of this block used only in queries which was deleted
  1178.     by invalidate_table). As far as we do not allocate new blocks
  1179.     and mark all headers of freed blocks as 'FREE' (even if they are
  1180.     merged with other blocks) we can just test type of block
  1181.     to be sure that block is not deleted
  1182.   */
  1183.   if (next->type == Query_cache_block::FREE)
  1184.     goto restart_search;
  1185.   curr= next;
  1186. } while (curr != tables_blocks);
  1187.       }
  1188.     }
  1189.     STRUCT_UNLOCK(&structure_guard_mutex);
  1190.   }
  1191.   DBUG_VOID_RETURN;
  1192. }
  1193. void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
  1194. {
  1195.   DBUG_ENTER("Query_cache::invalidate_by_MyISAM_filename");
  1196.   if (query_cache_size > 0)
  1197.   {
  1198.     /* Calculate the key outside the lock to make the lock shorter */
  1199.     char key[MAX_DBKEY_LENGTH];
  1200.     uint32 db_length;
  1201.     uint key_length= filename_2_table_key(key, filename, &db_length);
  1202.     STRUCT_LOCK(&structure_guard_mutex);
  1203.     if (query_cache_size > 0) // Safety if cache removed
  1204.     {
  1205.       Query_cache_block *table_block;
  1206.       if ((table_block = (Query_cache_block*) hash_search(&tables,
  1207.   (byte*) key,
  1208.   key_length)))
  1209. invalidate_table(table_block);
  1210.     }
  1211.     STRUCT_UNLOCK(&structure_guard_mutex);
  1212.   }
  1213.   DBUG_VOID_RETURN;
  1214. }
  1215.   /* Remove all queries from cache */
  1216. void Query_cache::flush()
  1217. {
  1218.   DBUG_ENTER("Query_cache::flush");
  1219.   STRUCT_LOCK(&structure_guard_mutex);
  1220.   if (query_cache_size > 0)
  1221.   {
  1222.     DUMP(this);
  1223.     flush_cache();
  1224.     DUMP(this);
  1225.   }
  1226.   DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
  1227.   STRUCT_UNLOCK(&structure_guard_mutex);
  1228.   DBUG_VOID_RETURN;
  1229. }
  1230.   /* Join result in cache in 1 block (if result length > join_limit) */
  1231. void Query_cache::pack(ulong join_limit, uint iteration_limit)
  1232. {
  1233.   DBUG_ENTER("Query_cache::pack");
  1234.   uint i = 0;
  1235.   do
  1236.   {
  1237.     pack_cache();
  1238.   } while ((++i < iteration_limit) && join_results(join_limit));
  1239.   DBUG_VOID_RETURN;
  1240. }
  1241. void Query_cache::destroy()
  1242. {
  1243.   DBUG_ENTER("Query_cache::destroy");
  1244.   if (!initialized)
  1245.   {
  1246.     DBUG_PRINT("qcache", ("Query Cache not initialized"));
  1247.   }
  1248.   else
  1249.   {
  1250.     free_cache();
  1251.     pthread_mutex_destroy(&structure_guard_mutex);
  1252.     initialized = 0;
  1253.   }
  1254.   DBUG_VOID_RETURN;
  1255. }
  1256. /*****************************************************************************
  1257.   init/destroy
  1258. *****************************************************************************/
  1259. void Query_cache::init()
  1260. {
  1261.   DBUG_ENTER("Query_cache::init");
  1262.   pthread_mutex_init(&structure_guard_mutex,MY_MUTEX_INIT_FAST);
  1263.   initialized = 1;
  1264.   DBUG_VOID_RETURN;
  1265. }
  1266. ulong Query_cache::init_cache()
  1267. {
  1268.   uint mem_bin_count, num, step;
  1269.   ulong mem_bin_size, prev_size, inc;
  1270.   ulong additional_data_size, max_mem_bin_size, approx_additional_data_size;
  1271.   int align;
  1272.   DBUG_ENTER("Query_cache::init_cache");
  1273.   approx_additional_data_size = (sizeof(Query_cache) +
  1274.  sizeof(gptr)*(def_query_hash_size+
  1275.        def_table_hash_size));
  1276.   if (query_cache_size < approx_additional_data_size)
  1277.     goto err;
  1278.   query_cache_size-= approx_additional_data_size;
  1279.   align= query_cache_size % ALIGN_SIZE(1);
  1280.   if (align)
  1281.   {
  1282.     query_cache_size-= align;
  1283.     approx_additional_data_size+= align;
  1284.   }
  1285.   /*
  1286.     Count memory bins number.
  1287.     Check section 6. in start comment for the used algorithm.
  1288.   */
  1289.   max_mem_bin_size = query_cache_size >> QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2;
  1290.   mem_bin_count = (uint)  ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
  1291.    QUERY_CACHE_MEM_BIN_PARTS_MUL);
  1292.   mem_bin_num = 1;
  1293.   mem_bin_steps = 1;
  1294.   mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
  1295.   prev_size = 0;
  1296.   if (mem_bin_size <= min_allocation_unit)
  1297.   {
  1298.     DBUG_PRINT("qcache", ("too small query cache => query cache disabled"));
  1299.     // TODO here (and above) should be warning in 4.1
  1300.     goto err;
  1301.   }
  1302.   while (mem_bin_size > min_allocation_unit)
  1303.   {
  1304.     mem_bin_num += mem_bin_count;
  1305.     prev_size = mem_bin_size;
  1306.     mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
  1307.     mem_bin_steps++;
  1308.     mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
  1309.     mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
  1310.     // Prevent too small bins spacing
  1311.     if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
  1312.       mem_bin_count= (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
  1313.   }
  1314.   inc = (prev_size - mem_bin_size) / mem_bin_count;
  1315.   mem_bin_num += (mem_bin_count - (min_allocation_unit - mem_bin_size)/inc);
  1316.   mem_bin_steps++;
  1317.   additional_data_size = ((mem_bin_num+1) *
  1318.   ALIGN_SIZE(sizeof(Query_cache_memory_bin))+
  1319.   (mem_bin_steps *
  1320.    ALIGN_SIZE(sizeof(Query_cache_memory_bin_step))));
  1321.   if (query_cache_size < additional_data_size)
  1322.     goto err;
  1323.   query_cache_size -= additional_data_size;
  1324.   if (!(cache= (byte *)
  1325.         my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
  1326.     goto err;
  1327.   DBUG_PRINT("qcache", ("cache length %lu, min unit %lu, %u bins",
  1328.       query_cache_size, min_allocation_unit, mem_bin_num));
  1329.   steps = (Query_cache_memory_bin_step *) cache;
  1330.   bins = ((Query_cache_memory_bin *)
  1331.   (cache + mem_bin_steps *
  1332.    ALIGN_SIZE(sizeof(Query_cache_memory_bin_step))));
  1333.   first_block = (Query_cache_block *) (cache + additional_data_size);
  1334.   first_block->init(query_cache_size);
  1335.   total_blocks++;
  1336.   first_block->pnext=first_block->pprev=first_block;
  1337.   first_block->next=first_block->prev=first_block;
  1338.   /* Prepare bins */
  1339.   bins[0].init(max_mem_bin_size);
  1340.   steps[0].init(max_mem_bin_size,0,0);
  1341.   mem_bin_count = (uint) ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
  1342.   QUERY_CACHE_MEM_BIN_PARTS_MUL);
  1343.   num= step= 1;
  1344.   mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
  1345.   while (mem_bin_size > min_allocation_unit)
  1346.   {
  1347.     ulong incr = (steps[step-1].size - mem_bin_size) / mem_bin_count;
  1348.     unsigned long size = mem_bin_size;
  1349.     for (uint i= mem_bin_count; i > 0; i--)
  1350.     {
  1351.       bins[num+i-1].init(size);
  1352.       size += incr;
  1353.     }
  1354.     num += mem_bin_count;
  1355.     steps[step].init(mem_bin_size, num-1, incr);
  1356.     mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
  1357.     step++;
  1358.     mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
  1359.     mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
  1360.     if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
  1361.       mem_bin_count=(mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
  1362.   }
  1363.   inc = (steps[step-1].size - mem_bin_size) / mem_bin_count;
  1364.   /*
  1365.     num + mem_bin_count > mem_bin_num, but index never be > mem_bin_num
  1366.     because block with size < min_allocated_unit never will be requested
  1367.   */
  1368.   steps[step].init(mem_bin_size, num + mem_bin_count - 1, inc);
  1369.   {
  1370.     uint skiped = (min_allocation_unit - mem_bin_size)/inc;
  1371.     ulong size = mem_bin_size + inc*skiped;
  1372.     uint i = mem_bin_count - skiped;
  1373.     while (i-- > 0)
  1374.     {
  1375.       bins[num+i].init(size);
  1376.       size += inc;
  1377.     }
  1378.   }
  1379.   bins[mem_bin_num].number = 1; // For easy end test in get_free_block
  1380.   free_memory = free_memory_blocks = 0;
  1381.   insert_into_free_memory_list(first_block);
  1382.   DUMP(this);
  1383.   VOID(hash_init(&queries, &my_charset_bin, def_query_hash_size, 0, 0,
  1384.  query_cache_query_get_key, 0, 0));
  1385. #ifndef FN_NO_CASE_SENCE
  1386.   /*
  1387.     If lower_case_table_names!=0 then db and table names are already 
  1388.     converted to lower case and we can use binary collation for their 
  1389.     comparison (no matter if file system case sensitive or not).
  1390.     If we have case-sensitive file system (like on most Unixes) and
  1391.     lower_case_table_names == 0 then we should distinguish my_table
  1392.     and MY_TABLE cases and so again can use binary collation.
  1393.   */
  1394.   VOID(hash_init(&tables, &my_charset_bin, def_table_hash_size, 0, 0,
  1395.  query_cache_table_get_key, 0, 0));
  1396. #else
  1397.   /*
  1398.     On windows, OS/2, MacOS X with HFS+ or any other case insensitive
  1399.     file system if lower_case_table_names!=0 we have same situation as
  1400.     in previous case, but if lower_case_table_names==0 then we should
  1401.     not distinguish cases (to be compatible in behavior with underlying
  1402.     file system) and so should use case insensitive collation for
  1403.     comparison.
  1404.   */
  1405.   VOID(hash_init(&tables,
  1406.  lower_case_table_names ? &my_charset_bin :
  1407.  files_charset_info,
  1408.  def_table_hash_size, 0, 0,query_cache_table_get_key, 0, 0));
  1409. #endif
  1410.   queries_in_cache = 0;
  1411.   queries_blocks = 0;
  1412.   DBUG_RETURN(query_cache_size +
  1413.       additional_data_size + approx_additional_data_size);
  1414. err:
  1415.   make_disabled();
  1416.   DBUG_RETURN(0);
  1417. }
  1418. /* Disable the use of the query cache */
  1419. void Query_cache::make_disabled()
  1420. {
  1421.   DBUG_ENTER("Query_cache::make_disabled");
  1422.   query_cache_size= 0;
  1423.   queries_blocks= 0;
  1424.   free_memory= 0;
  1425.   bins= 0;
  1426.   steps= 0;
  1427.   cache= 0;
  1428.   mem_bin_num= mem_bin_steps= 0;
  1429.   queries_in_cache= 0;
  1430.   first_block= 0;
  1431.   DBUG_VOID_RETURN;
  1432. }
  1433. void Query_cache::free_cache()
  1434. {
  1435.   DBUG_ENTER("Query_cache::free_cache");
  1436.   if (query_cache_size > 0)
  1437.   {
  1438.     flush_cache();
  1439. #ifndef DBUG_OFF
  1440.     if (bins[0].free_blocks == 0)
  1441.     {
  1442.       wreck(__LINE__,"no free memory found in (bins[0].free_blocks");
  1443.       DBUG_VOID_RETURN;
  1444.     }
  1445. #endif
  1446.     /* Becasue we did a flush, all cache memory must be in one this block */
  1447.     bins[0].free_blocks->destroy();
  1448.     total_blocks--;
  1449. #ifndef DBUG_OFF
  1450.     if (free_memory != query_cache_size)
  1451.       DBUG_PRINT("qcache", ("free memory %lu (should be %lu)",
  1452.     free_memory , query_cache_size));
  1453. #endif
  1454.     my_free((gptr) cache, MYF(MY_ALLOW_ZERO_PTR));
  1455.     make_disabled();
  1456.     hash_free(&queries);
  1457.     hash_free(&tables);
  1458.   }
  1459.   DBUG_VOID_RETURN;
  1460. }
  1461. /*****************************************************************************
  1462.   Free block data
  1463. *****************************************************************************/
  1464. /*
  1465.   The following assumes we have a lock on the cache
  1466. */
  1467. void Query_cache::flush_cache()
  1468. {
  1469.   while (queries_blocks != 0)
  1470.   {
  1471.     BLOCK_LOCK_WR(queries_blocks);
  1472.     free_query(queries_blocks);
  1473.   }
  1474. }
  1475. /*
  1476.   Free oldest query that is not in use by another thread.
  1477.   Returns 1 if we couldn't remove anything
  1478. */
  1479. my_bool Query_cache::free_old_query()
  1480. {
  1481.   DBUG_ENTER("Query_cache::free_old_query");
  1482.   if (queries_blocks)
  1483.   {
  1484.     /*
  1485.       try_lock_writing used to prevent client because here lock
  1486.       sequence is breached.
  1487.       Also we don't need remove locked queries at this point.
  1488.     */
  1489.     Query_cache_block *query_block = 0;
  1490.     if (queries_blocks != 0)
  1491.     {
  1492.       Query_cache_block *block = queries_blocks;
  1493.       /* Search until we find first query that we can remove */
  1494.       do
  1495.       {
  1496. Query_cache_query *header = block->query();
  1497. if (header->result() != 0 &&
  1498.     header->result()->type == Query_cache_block::RESULT &&
  1499.     block->query()->try_lock_writing())
  1500. {
  1501.   query_block = block;
  1502.   break;
  1503. }
  1504.       } while ((block=block->next) != queries_blocks );
  1505.     }
  1506.     if (query_block != 0)
  1507.     {
  1508.       free_query(query_block);
  1509.       lowmem_prunes++;
  1510.       DBUG_RETURN(0);
  1511.     }
  1512.   }
  1513.   DBUG_RETURN(1); // Nothing to remove
  1514. }
  1515. /*
  1516.   Free query from query cache.
  1517.   query_block must be locked for writing.
  1518.   This function will remove (and destroy) the lock for the query.
  1519. */
  1520. void Query_cache::free_query(Query_cache_block *query_block)
  1521. {
  1522.   DBUG_ENTER("Query_cache::free_query");
  1523.   DBUG_PRINT("qcache", ("free query 0x%lx %lu bytes result",
  1524.       (ulong) query_block,
  1525.       query_block->query()->length() ));
  1526.   queries_in_cache--;
  1527.   hash_delete(&queries,(byte *) query_block);
  1528.   Query_cache_query *query = query_block->query();
  1529.   if (query->writer() != 0)
  1530.   {
  1531.     /* Tell MySQL that this query should not be cached anymore */
  1532.     query->writer()->query_cache_query = 0;
  1533.     query->writer(0);
  1534.   }
  1535.   double_linked_list_exclude(query_block, &queries_blocks);
  1536.   Query_cache_block_table *table=query_block->table(0);
  1537.   for (TABLE_COUNTER_TYPE i=0; i < query_block->n_tables; i++)
  1538.     unlink_table(table++);
  1539.   Query_cache_block *result_block = query->result();
  1540.   /*
  1541.     The following is true when query destruction was called and no results
  1542.     in query . (query just registered and then abort/pack/flush called)
  1543.   */
  1544.   if (result_block != 0)
  1545.   {
  1546.     if (result_block->type != Query_cache_block::RESULT)
  1547.     {
  1548.       // removing unfinished query
  1549.       refused++;
  1550.       inserts--;
  1551.     }
  1552.     Query_cache_block *block = result_block;
  1553.     do
  1554.     {
  1555.       Query_cache_block *current = block;
  1556.       block = block->next;
  1557.       free_memory_block(current);
  1558.     } while (block != result_block);
  1559.   }
  1560.   else
  1561.   {
  1562.     // removing unfinished query
  1563.     refused++;
  1564.     inserts--;
  1565.   }
  1566.   query->unlock_n_destroy();
  1567.   free_memory_block(query_block);
  1568.   DBUG_VOID_RETURN;
  1569. }
  1570. /*****************************************************************************
  1571.  Query data creation
  1572. *****************************************************************************/
  1573. Query_cache_block *
  1574. Query_cache::write_block_data(ulong data_len, gptr data,
  1575.       ulong header_len,
  1576.       Query_cache_block::block_type type,
  1577.       TABLE_COUNTER_TYPE ntab,
  1578.       my_bool under_guard)
  1579. {
  1580.   ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
  1581.    ALIGN_SIZE(ntab*sizeof(Query_cache_block_table)) +
  1582.    header_len);
  1583.   ulong len = data_len + all_headers_len;
  1584.   ulong align_len= ALIGN_SIZE(len);
  1585.   DBUG_ENTER("Query_cache::write_block_data");
  1586.   DBUG_PRINT("qcache", ("data: %ld, header: %ld, all header: %ld",
  1587.       data_len, header_len, all_headers_len));
  1588.   Query_cache_block *block = allocate_block(max(align_len, 
  1589. min_allocation_unit),
  1590.     1, 0, under_guard);
  1591.   if (block != 0)
  1592.   {
  1593.     block->type = type;
  1594.     block->n_tables = ntab;
  1595.     block->used = len;
  1596.     memcpy((void*) (((byte *) block)+ all_headers_len),
  1597.    (void*) data, data_len);
  1598.   }
  1599.   DBUG_RETURN(block);
  1600. }
  1601. /*
  1602.   On success STRUCT_UNLOCK(&query_cache.structure_guard_mutex) will be done.
  1603. */
  1604. my_bool
  1605. Query_cache::append_result_data(Query_cache_block **current_block,
  1606. ulong data_len, gptr data,
  1607. Query_cache_block *query_block)
  1608. {
  1609.   DBUG_ENTER("Query_cache::append_result_data");
  1610.   DBUG_PRINT("qcache", ("append %lu bytes to 0x%lx query",
  1611.       data_len, query_block));
  1612.   if (query_block->query()->add(data_len) > query_cache_limit)
  1613.   {
  1614.     DBUG_PRINT("qcache", ("size limit reached %lu > %lu",
  1615. query_block->query()->length(),
  1616. query_cache_limit));
  1617.     DBUG_RETURN(0);
  1618.   }
  1619.   if (*current_block == 0)
  1620.   {
  1621.     DBUG_PRINT("qcache", ("allocated first result data block %lu", data_len));
  1622.     /*
  1623.       STRUCT_UNLOCK(&structure_guard_mutex) Will be done by
  1624.       write_result_data if success;
  1625.     */
  1626.     DBUG_RETURN(write_result_data(current_block, data_len, data, query_block,
  1627.   Query_cache_block::RES_BEG));
  1628.   }
  1629.   Query_cache_block *last_block = (*current_block)->prev;
  1630.   DBUG_PRINT("qcache", ("lastblock 0x%lx len %lu used %lu",
  1631.       (ulong) last_block, last_block->length,
  1632.       last_block->used));
  1633.   my_bool success = 1;
  1634.   ulong last_block_free_space= last_block->length - last_block->used;
  1635.   /*
  1636.     We will first allocate and write the 'tail' of data, that doesn't fit
  1637.     in the 'last_block'.  Only if this succeeds, we will fill the last_block.
  1638.     This saves us a memcpy if the query doesn't fit in the query cache.
  1639.   */
  1640.   // Try join blocks if physically next block is free...
  1641.   ulong tail = data_len - last_block_free_space;
  1642.   ulong append_min = get_min_append_result_data_size();
  1643.   if (last_block_free_space < data_len &&
  1644.       append_next_free_block(last_block,
  1645.      max(tail, append_min)))
  1646.     last_block_free_space = last_block->length - last_block->used;
  1647.   // If no space in last block (even after join) allocate new block
  1648.   if (last_block_free_space < data_len)
  1649.   {
  1650.     DBUG_PRINT("qcache", ("allocate new block for %lu bytes",
  1651. data_len-last_block_free_space));
  1652.     Query_cache_block *new_block = 0;
  1653.     /*
  1654.       On success STRUCT_UNLOCK(&structure_guard_mutex) will be done
  1655.       by the next call
  1656.     */
  1657.     success = write_result_data(&new_block, data_len-last_block_free_space,
  1658. (gptr)(((byte*)data)+last_block_free_space),
  1659. query_block,
  1660. Query_cache_block::RES_CONT);
  1661.     /*
  1662.        new_block may be != 0 even !success (if write_result_data
  1663.        allocate a small block but failed to allocate continue)
  1664.     */
  1665.     if (new_block != 0)
  1666.       double_linked_list_join(last_block, new_block);
  1667.   }
  1668.   else
  1669.   {
  1670.     // It is success (nobody can prevent us write data)
  1671.     STRUCT_UNLOCK(&structure_guard_mutex);
  1672.   }
  1673.   // Now finally write data to the last block
  1674.   if (success && last_block_free_space > 0)
  1675.   {
  1676.     ulong to_copy = min(data_len,last_block_free_space);
  1677.     DBUG_PRINT("qcache", ("use free space %lub at block 0x%lx to copy %lub",
  1678. last_block_free_space, (ulong)last_block, to_copy));
  1679.     memcpy((void*) (((byte*) last_block) + last_block->used), (void*) data,
  1680.    to_copy);
  1681.     last_block->used+=to_copy;
  1682.   }
  1683.   DBUG_RETURN(success);
  1684. }
  1685. my_bool Query_cache::write_result_data(Query_cache_block **result_block,
  1686.        ulong data_len, gptr data,
  1687.        Query_cache_block *query_block,
  1688.        Query_cache_block::block_type type)
  1689. {
  1690.   DBUG_ENTER("Query_cache::write_result_data");
  1691.   DBUG_PRINT("qcache", ("data_len %lu",data_len));
  1692.   /*
  1693.     Reserve block(s) for filling
  1694.     During data allocation we must have structure_guard_mutex locked.
  1695.     As data copy is not a fast operation, it's better if we don't have
  1696.     structure_guard_mutex locked during data coping.
  1697.     Thus we first allocate space and lock query, then unlock
  1698.     structure_guard_mutex and copy data.
  1699.   */
  1700.   my_bool success = allocate_data_chain(result_block, data_len, query_block,
  1701. type == Query_cache_block::RES_BEG);
  1702.   if (success)
  1703.   {
  1704.     // It is success (nobody can prevent us write data)
  1705.     STRUCT_UNLOCK(&structure_guard_mutex);
  1706.     uint headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
  1707. ALIGN_SIZE(sizeof(Query_cache_result)));
  1708. #ifndef EMBEDDED_LIBRARY
  1709.     Query_cache_block *block= *result_block;
  1710.     byte *rest= (byte*) data;
  1711.     // Now fill list of blocks that created by allocate_data_chain
  1712.     do
  1713.     {
  1714.       block->type = type;
  1715.       ulong length = block->used - headers_len;
  1716.       DBUG_PRINT("qcache", ("write %lu byte in block 0x%lx",length,
  1717.     (ulong)block));
  1718.       memcpy((void*)(((byte*) block)+headers_len), (void*) rest, length);
  1719.       rest += length;
  1720.       block = block->next;
  1721.       type = Query_cache_block::RES_CONT;
  1722.     } while (block != *result_block);
  1723. #else
  1724.     /*
  1725.       Set type of first block, emb_store_querycache_result() will handle
  1726.       the others.
  1727.     */
  1728.     (*result_block)->type= type;
  1729.     Querycache_stream qs(*result_block, headers_len);
  1730.     emb_store_querycache_result(&qs, (THD*)data);
  1731. #endif /*!EMBEDDED_LIBRARY*/
  1732.   }
  1733.   else
  1734.   {
  1735.     if (*result_block != 0)
  1736.     {
  1737.       // Destroy list of blocks that was created & locked by lock_result_data
  1738.       Query_cache_block *block = *result_block;
  1739.       do
  1740.       {
  1741. Query_cache_block *current = block;
  1742. block = block->next;
  1743. free_memory_block(current);
  1744.       } while (block != *result_block);
  1745.       *result_block = 0;
  1746.       /*
  1747. It is not success => not unlock structure_guard_mutex (we need it to
  1748. free query)
  1749.       */
  1750.     }
  1751.   }
  1752.   DBUG_PRINT("qcache", ("success %d", (int) success));
  1753.   DBUG_RETURN(success);
  1754. }
  1755. inline ulong Query_cache::get_min_first_result_data_size()
  1756. {
  1757.   if (queries_in_cache < QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER)
  1758.     return min_result_data_size;
  1759.   ulong avg_result = (query_cache_size - free_memory) / queries_in_cache;
  1760.   avg_result = min(avg_result, query_cache_limit);
  1761.   return max(min_result_data_size, avg_result);
  1762. }
  1763. inline ulong Query_cache::get_min_append_result_data_size()
  1764. {
  1765.   return min_result_data_size;
  1766. }
  1767. /*
  1768.   Allocate one or more blocks to hold data
  1769. */
  1770. my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
  1771.  ulong data_len,
  1772.  Query_cache_block *query_block,
  1773.  my_bool first_block_arg)
  1774. {
  1775.   ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
  1776.    ALIGN_SIZE(sizeof(Query_cache_result)));
  1777.   ulong min_size = (first_block_arg ?
  1778.     get_min_first_result_data_size():
  1779.     get_min_append_result_data_size());
  1780.   Query_cache_block *prev_block= NULL;
  1781.   Query_cache_block *new_block;
  1782.   DBUG_ENTER("Query_cache::allocate_data_chain");
  1783.   DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
  1784. data_len, all_headers_len));
  1785.   do
  1786.   {
  1787.     ulong len= data_len + all_headers_len;
  1788.     ulong align_len= ALIGN_SIZE(len);
  1789.     if (!(new_block= allocate_block(max(min_size, align_len),
  1790.     min_result_data_size == 0,
  1791.     all_headers_len + min_result_data_size,
  1792.     1)))
  1793.     {
  1794.       DBUG_PRINT("warning", ("Can't allocate block for results"));
  1795.       DBUG_RETURN(FALSE);
  1796.     }
  1797.     new_block->n_tables = 0;
  1798.     new_block->used = min(len, new_block->length);
  1799.     new_block->type = Query_cache_block::RES_INCOMPLETE;
  1800.     new_block->next = new_block->prev = new_block;
  1801.     Query_cache_result *header = new_block->result();
  1802.     header->parent(query_block);
  1803.     DBUG_PRINT("qcache", ("Block len %lu used %lu",
  1804.   new_block->length, new_block->used));
  1805.     if (prev_block)
  1806.       double_linked_list_join(prev_block, new_block);
  1807.     else
  1808.       *result_block= new_block;
  1809.     if (new_block->length >= len)
  1810.       break;
  1811.     /*
  1812.       We got less memory then we need (no big memory blocks) =>
  1813.       Continue to allocated more blocks until we got everything we need.
  1814.     */
  1815.     data_len= len - new_block->length;
  1816.     prev_block= new_block;
  1817.   } while(1);
  1818.   DBUG_RETURN(TRUE);
  1819. }
  1820. /*****************************************************************************
  1821.   Tables management
  1822. *****************************************************************************/
  1823. /*
  1824.   Invalidate the first table in the table_list
  1825. */
  1826. void Query_cache::invalidate_table(TABLE_LIST *table_list)
  1827. {
  1828.   if (table_list->table != 0)
  1829.     invalidate_table(table_list->table); // Table is open
  1830.   else
  1831.   {
  1832.     char key[MAX_DBKEY_LENGTH];
  1833.     uint key_length;
  1834.     Query_cache_block *table_block;
  1835.     key_length=(uint) (strmov(strmov(key,table_list->db)+1,
  1836.       table_list->real_name) -key)+ 1;
  1837.     // We don't store temporary tables => no key_length+=4 ...
  1838.     if ((table_block = (Query_cache_block*)
  1839.  hash_search(&tables,(byte*) key,key_length)))
  1840.       invalidate_table(table_block);
  1841.   }
  1842. }
  1843. void Query_cache::invalidate_table(TABLE *table)
  1844. {
  1845.   invalidate_table((byte*) table->table_cache_key, table->key_length);
  1846. }
  1847. void Query_cache::invalidate_table(byte * key, uint32  key_length)
  1848. {
  1849.   Query_cache_block *table_block;
  1850.   if ((table_block = ((Query_cache_block*)
  1851.       hash_search(&tables, key, key_length))))
  1852.     invalidate_table(table_block);
  1853. }
  1854. void Query_cache::invalidate_table(Query_cache_block *table_block)
  1855. {
  1856.   Query_cache_block_table *list_root = table_block->table(0);
  1857.   while (list_root->next != list_root)
  1858.   {
  1859.     Query_cache_block *query_block = list_root->next->block();
  1860.     BLOCK_LOCK_WR(query_block);
  1861.     free_query(query_block);
  1862.   }
  1863. }
  1864. /*
  1865.   Store all used tables
  1866.   SYNOPSIS
  1867.     register_all_tables()
  1868.     block Store tables in this block
  1869.     tables_used List if used tables
  1870.     tables_arg Not used ?
  1871. */
  1872. my_bool Query_cache::register_all_tables(Query_cache_block *block,
  1873.  TABLE_LIST *tables_used,
  1874.  TABLE_COUNTER_TYPE tables_arg)
  1875. {
  1876.   TABLE_COUNTER_TYPE n;
  1877.   DBUG_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x",
  1878.       (ulong) block, (int) tables_arg,
  1879.       (int) ALIGN_SIZE(sizeof(Query_cache_block))));
  1880.   Query_cache_block_table *block_table = block->table(0);
  1881.   for (n=0; tables_used; tables_used=tables_used->next, n++, block_table++)
  1882.   {
  1883.     if (tables_used->derived)
  1884.     {
  1885.       DBUG_PRINT("qcache", ("derived table skipped"));
  1886.       n--;
  1887.       block_table--;
  1888.       continue;
  1889.     }
  1890.     DBUG_PRINT("qcache",
  1891.        ("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx",
  1892. tables_used->real_name, tables_used->db,
  1893. (ulong) tables_used->table,
  1894. tables_used->table->key_length,
  1895. (ulong) tables_used->table->table_cache_key));
  1896.     block_table->n=n;
  1897.     if (!insert_table(tables_used->table->key_length,
  1898.       tables_used->table->table_cache_key, block_table,
  1899.       tables_used->db_length,
  1900.       tables_used->table->file->table_cache_type()))
  1901.       break;
  1902.     if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
  1903.     {
  1904.       ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
  1905.       MYRG_INFO *file = handler->myrg_info();
  1906.       for (MYRG_TABLE *table = file->open_tables;
  1907.    table != file->end_table ;
  1908.    table++)
  1909.       {
  1910. char key[MAX_DBKEY_LENGTH];
  1911. uint32 db_length;
  1912. uint key_length= filename_2_table_key(key, table->table->filename,
  1913.       &db_length);
  1914. (++block_table)->n= ++n;
  1915. if (!insert_table(key_length, key, block_table,
  1916.   db_length,
  1917.   tables_used->table->file->table_cache_type()))
  1918.   goto err;
  1919.       }
  1920.     }
  1921.   }
  1922. err:
  1923.   if (tables_used)
  1924.   {
  1925.     DBUG_PRINT("qcache", ("failed at table %d", (int) n));
  1926.     /* Unlink the tables we allocated above */
  1927.     for (Query_cache_block_table *tmp = block->table(0) ;
  1928.  tmp != block_table;
  1929.  tmp++)
  1930.       unlink_table(tmp);
  1931.   }
  1932.   return (tables_used == 0);
  1933. }
  1934. /*
  1935.   Insert used tablename in cache
  1936.   Returns 0 on error
  1937. */
  1938. my_bool
  1939. Query_cache::insert_table(uint key_len, char *key,
  1940.   Query_cache_block_table *node,
  1941.   uint32 db_length, uint8 cache_type)
  1942. {
  1943.   DBUG_ENTER("Query_cache::insert_table");
  1944.   DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d",
  1945.       (ulong)node, key_len));
  1946.   Query_cache_block *table_block = ((Query_cache_block *)
  1947.     hash_search(&tables, (byte*) key,
  1948. key_len));
  1949.   if (table_block == 0)
  1950.   {
  1951.     DBUG_PRINT("qcache", ("new table block from 0x%lx (%u)",
  1952. (ulong) key, (int) key_len));
  1953.     table_block = write_block_data(key_len, (gptr) key,
  1954.    ALIGN_SIZE(sizeof(Query_cache_table)),
  1955.    Query_cache_block::TABLE,
  1956.    1, 1);
  1957.     if (table_block == 0)
  1958.     {
  1959.       DBUG_PRINT("qcache", ("Can't write table name to cache"));
  1960.       DBUG_RETURN(0);
  1961.     }
  1962.     Query_cache_table *header = table_block->table();
  1963.     double_linked_list_simple_include(table_block,
  1964.       &tables_blocks);
  1965.     Query_cache_block_table *list_root = table_block->table(0);
  1966.     list_root->n = 0;
  1967.     list_root->next = list_root->prev = list_root;
  1968.     if (my_hash_insert(&tables, (const byte *) table_block))
  1969.     {
  1970.       DBUG_PRINT("qcache", ("Can't insert table to hash"));
  1971.       // write_block_data return locked block
  1972.       free_memory_block(table_block);
  1973.       DBUG_RETURN(0);
  1974.     }
  1975.     char *db = header->db();
  1976.     header->table(db + db_length + 1);
  1977.     header->key_length(key_len);
  1978.     header->type(cache_type);
  1979.   }
  1980.   Query_cache_block_table *list_root = table_block->table(0);
  1981.   node->next = list_root->next;
  1982.   list_root->next = node;
  1983.   node->next->prev = node;
  1984.   node->prev = list_root;
  1985.   node->parent = table_block->table();
  1986.   DBUG_RETURN(1);
  1987. }
  1988. void Query_cache::unlink_table(Query_cache_block_table *node)
  1989. {
  1990.   DBUG_ENTER("Query_cache::unlink_table");
  1991.   node->prev->next = node->next;
  1992.   node->next->prev = node->prev;
  1993.   Query_cache_block_table *neighbour = node->next;
  1994.   if (neighbour->next == neighbour)
  1995.   {
  1996.     // list is empty (neighbor is root of list)
  1997.     Query_cache_block *table_block = neighbour->block();
  1998.     double_linked_list_exclude(table_block,
  1999.        &tables_blocks);
  2000.     hash_delete(&tables,(byte *) table_block);
  2001.     free_memory_block(table_block);
  2002.   }
  2003.   DBUG_VOID_RETURN;
  2004. }
  2005. /*****************************************************************************
  2006.   Free memory management
  2007. *****************************************************************************/
  2008. Query_cache_block *
  2009. Query_cache::allocate_block(ulong len, my_bool not_less, ulong min,
  2010.     my_bool under_guard)
  2011. {
  2012.   DBUG_ENTER("Query_cache::allocate_block");
  2013.   DBUG_PRINT("qcache", ("len %lu, not less %d, min %lu, uder_guard %d",
  2014.       len, not_less,min,under_guard));
  2015.   if (len >= min(query_cache_size, query_cache_limit))
  2016.   {
  2017.     DBUG_PRINT("qcache", ("Query cache hase only %lu memory and limit %lu",
  2018. query_cache_size, query_cache_limit));
  2019.     DBUG_RETURN(0); // in any case we don't have such piece of memory
  2020.   }
  2021.   if (!under_guard)
  2022.   {
  2023.     STRUCT_LOCK(&structure_guard_mutex);
  2024.     /*
  2025.       It is very unlikely that following condition is TRUE (it is possible
  2026.       only if other thread is resizing cache), so we check it only after
  2027.       guard mutex lock
  2028.     */
  2029.     if (unlikely(query_cache.query_cache_size == 0))
  2030.     {
  2031.       STRUCT_UNLOCK(&structure_guard_mutex);
  2032.       DBUG_RETURN(0);
  2033.     }
  2034.   }
  2035.   /* Free old queries until we have enough memory to store this block */
  2036.   Query_cache_block *block;
  2037.   do
  2038.   {
  2039.     block= get_free_block(len, not_less, min);
  2040.   }
  2041.   while (block == 0 && !free_old_query());
  2042.   if (block != 0) // If we found a suitable block
  2043.   {
  2044.     if (block->length >= ALIGN_SIZE(len) + min_allocation_unit)
  2045.       split_block(block,ALIGN_SIZE(len));
  2046.   }
  2047.   if (!under_guard)
  2048.     STRUCT_UNLOCK(&structure_guard_mutex);
  2049.   DBUG_RETURN(block);
  2050. }
  2051. Query_cache_block *
  2052. Query_cache::get_free_block(ulong len, my_bool not_less, ulong min)
  2053. {
  2054.   Query_cache_block *block = 0, *first = 0;
  2055.   DBUG_ENTER("Query_cache::get_free_block");
  2056.   DBUG_PRINT("qcache",("length %lu, not_less %d, min %lu", len,
  2057.      (int)not_less, min));
  2058.   /* Find block with minimal size > len  */
  2059.   uint start = find_bin(len);
  2060.   // try matching bin
  2061.   if (bins[start].number != 0)
  2062.   {
  2063.     Query_cache_block *list = bins[start].free_blocks;
  2064.     if (list->prev->length >= len) // check block with max size 
  2065.     { 
  2066.       first = list;
  2067.       uint n = 0;
  2068.       while ( n < QUERY_CACHE_MEM_BIN_TRY &&
  2069.       first->length < len) //we don't need irst->next != list
  2070.       {
  2071. first=first->next;
  2072. n++;
  2073.       }
  2074.       if (first->length >= len)
  2075. block=first;
  2076.       else // we don't need if (first->next != list)
  2077.       {
  2078. n = 0;
  2079. block = list->prev;
  2080. while (n < QUERY_CACHE_MEM_BIN_TRY &&
  2081.        block->length > len)
  2082. {
  2083.   block=block->prev;
  2084.   n++;
  2085. }
  2086. if (block->length < len)
  2087.   block=block->next;
  2088.       }
  2089.     }
  2090.     else
  2091.       first = list->prev;
  2092.   }
  2093.   if (block == 0 && start > 0)
  2094.   {
  2095.     DBUG_PRINT("qcache",("Try bins with bigger block size"));
  2096.     // Try more big bins
  2097.     int i = start - 1;
  2098.     while (i > 0 && bins[i].number == 0)
  2099.       i--;
  2100.     if (bins[i].number > 0)
  2101.       block = bins[i].free_blocks;
  2102.   }
  2103.   // If no big blocks => try less size (if it is possible)
  2104.   if (block == 0 && ! not_less)
  2105.   {
  2106.     DBUG_PRINT("qcache",("Try to allocate a smaller block"));
  2107.     if (first != 0 && first->length > min)
  2108.       block = first;
  2109.     else
  2110.     {
  2111.       uint i = start + 1;
  2112.       /* bins[mem_bin_num].number contains 1 for easy end test */
  2113.       for (i= start+1 ; bins[i].number == 0 ; i++) ;
  2114.       if (i < mem_bin_num && bins[i].free_blocks->prev->length >= min)
  2115. block = bins[i].free_blocks->prev;
  2116.     }
  2117.   }
  2118.   if (block != 0)
  2119.     exclude_from_free_memory_list(block);
  2120.   DBUG_PRINT("qcache",("getting block 0x%lx", (ulong) block));
  2121.   DBUG_RETURN(block);
  2122. }
  2123. void Query_cache::free_memory_block(Query_cache_block *block)
  2124. {
  2125.   DBUG_ENTER("Query_cache::free_memory_block");
  2126.   block->used=0;
  2127.   block->type= Query_cache_block::FREE; // mark block as free in any case
  2128.   DBUG_PRINT("qcache",
  2129.      ("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx",
  2130.       (ulong) first_block, (ulong) block, (ulong) block->pnext,
  2131.       (ulong) block->pprev));
  2132.   if (block->pnext != first_block && block->pnext->is_free())
  2133.     block = join_free_blocks(block, block->pnext);
  2134.   if (block != first_block && block->pprev->is_free())
  2135.     block = join_free_blocks(block->pprev, block->pprev);
  2136.   insert_into_free_memory_list(block);
  2137.   DBUG_VOID_RETURN;
  2138. }
  2139. void Query_cache::split_block(Query_cache_block *block, ulong len)
  2140. {
  2141.   DBUG_ENTER("Query_cache::split_block");
  2142.   Query_cache_block *new_block = (Query_cache_block*)(((byte*) block)+len);
  2143.   new_block->init(block->length - len);
  2144.   total_blocks++;
  2145.   block->length=len;
  2146.   new_block->pnext = block->pnext;
  2147.   block->pnext = new_block;
  2148.   new_block->pprev = block;
  2149.   new_block->pnext->pprev = new_block;
  2150.   if (block->type == Query_cache_block::FREE)
  2151.   {
  2152.     // if block was free then it already joined with all free neighbours
  2153.     insert_into_free_memory_list(new_block);
  2154.   }
  2155.   else
  2156.     free_memory_block(new_block);
  2157.   DBUG_PRINT("qcache", ("split 0x%lx (%lu) new 0x%lx",
  2158.       (ulong) block, len, (ulong) new_block));
  2159.   DBUG_VOID_RETURN;
  2160. }
  2161. Query_cache_block *
  2162. Query_cache::join_free_blocks(Query_cache_block *first_block_arg,
  2163.       Query_cache_block *block_in_list)
  2164. {
  2165.   Query_cache_block *second_block;
  2166.   DBUG_ENTER("Query_cache::join_free_blocks");
  2167.   DBUG_PRINT("qcache",
  2168.      ("join first 0x%lx, pnext 0x%lx, in list 0x%lx",
  2169.       (ulong) first_block_arg, (ulong) first_block_arg->pnext,
  2170.       (ulong) block_in_list));
  2171.   exclude_from_free_memory_list(block_in_list);
  2172.   second_block = first_block_arg->pnext;
  2173.   // May be was not free block
  2174.   second_block->used=0;
  2175.   second_block->destroy();
  2176.   total_blocks--;
  2177.   first_block_arg->length += second_block->length;
  2178.   first_block_arg->pnext = second_block->pnext;
  2179.   second_block->pnext->pprev = first_block_arg;
  2180.   DBUG_RETURN(first_block_arg);
  2181. }
  2182. my_bool Query_cache::append_next_free_block(Query_cache_block *block,
  2183.     ulong add_size)
  2184. {
  2185.   Query_cache_block *next_block = block->pnext;
  2186.   DBUG_ENTER("Query_cache::append_next_free_block");
  2187.   DBUG_PRINT("enter", ("block 0x%lx, add_size %lu", (ulong) block,
  2188.        add_size));
  2189.   if (next_block != first_block && next_block->is_free())
  2190.   {
  2191.     ulong old_len = block->length;
  2192.     exclude_from_free_memory_list(next_block);
  2193.     next_block->destroy();
  2194.     total_blocks--;
  2195.     block->length += next_block->length;
  2196.     block->pnext = next_block->pnext;
  2197.     next_block->pnext->pprev = block;
  2198.     if (block->length > ALIGN_SIZE(old_len + add_size) + min_allocation_unit)
  2199.       split_block(block,ALIGN_SIZE(old_len + add_size));
  2200.     DBUG_PRINT("exit", ("block was appended"));
  2201.     DBUG_RETURN(1);
  2202.   }
  2203.   DBUG_RETURN(0);
  2204. }
  2205. void Query_cache::exclude_from_free_memory_list(Query_cache_block *free_block)
  2206. {
  2207.   DBUG_ENTER("Query_cache::exclude_from_free_memory_list");
  2208.   Query_cache_memory_bin *bin = *((Query_cache_memory_bin **)
  2209.   free_block->data());
  2210.   double_linked_list_exclude(free_block, &bin->free_blocks);
  2211.   bin->number--;
  2212.   free_memory-=free_block->length;
  2213.   free_memory_blocks--;
  2214.   DBUG_PRINT("qcache",("exclude block 0x%lx, bin 0x%lx", (ulong) free_block,
  2215.      (ulong) bin));
  2216.   DBUG_VOID_RETURN;
  2217. }
  2218. void Query_cache::insert_into_free_memory_list(Query_cache_block *free_block)
  2219. {
  2220.   DBUG_ENTER("Query_cache::insert_into_free_memory_list");
  2221.   uint idx = find_bin(free_block->length);
  2222.   insert_into_free_memory_sorted_list(free_block, &bins[idx].free_blocks);
  2223.   /*
  2224.     We have enough memory in block for storing bin reference due to
  2225.     min_allocation_unit choice
  2226.   */
  2227.   Query_cache_memory_bin **bin_ptr = ((Query_cache_memory_bin**)
  2228.       free_block->data());
  2229.   *bin_ptr = bins+idx;
  2230.   (*bin_ptr)->number++;
  2231.   DBUG_PRINT("qcache",("insert block 0x%lx, bin[%d] 0x%lx",
  2232.      (ulong) free_block, idx, (ulong) *bin_ptr));
  2233.   DBUG_VOID_RETURN;
  2234. }
  2235. uint Query_cache::find_bin(ulong size)
  2236. {
  2237.   DBUG_ENTER("Query_cache::find_bin");
  2238.   // Binary search
  2239.   int left = 0, right = mem_bin_steps;
  2240.   do
  2241.   {
  2242.     int middle = (left + right) / 2;
  2243.     if (steps[middle].size > size)
  2244.       left = middle+1;
  2245.     else
  2246.       right = middle;
  2247.   } while (left < right);
  2248.   if (left == 0)
  2249.   {
  2250.     // first bin not subordinate of common rules
  2251.     DBUG_PRINT("qcache", ("first bin (# 0), size %lu",size));
  2252.     DBUG_RETURN(0);
  2253.   }
  2254.   uint bin =  steps[left].idx - 
  2255.     (uint)((size - steps[left].size)/steps[left].increment);
  2256. #ifndef DBUG_OFF
  2257.   bins_dump();
  2258. #endif
  2259.   DBUG_PRINT("qcache", ("bin %u step %u, size %lu step size %lu",
  2260. bin, left, size, steps[left].size));
  2261.   DBUG_RETURN(bin);
  2262. }
  2263. /*****************************************************************************
  2264.  Lists management
  2265. *****************************************************************************/
  2266. void Query_cache::move_to_query_list_end(Query_cache_block *query_block)
  2267. {
  2268.   DBUG_ENTER("Query_cache::move_to_query_list_end");
  2269.   double_linked_list_exclude(query_block, &queries_blocks);
  2270.   double_linked_list_simple_include(query_block, &queries_blocks);
  2271.   DBUG_VOID_RETURN;
  2272. }
  2273. void Query_cache::insert_into_free_memory_sorted_list(Query_cache_block *
  2274.       new_block,
  2275.       Query_cache_block **
  2276.       list)
  2277. {
  2278.   DBUG_ENTER("Query_cache::insert_into_free_memory_sorted_list");
  2279.   /*
  2280.      list sorted by size in ascendant order, because we need small blocks
  2281.      more frequently than bigger ones
  2282.   */
  2283.   new_block->used = 0;
  2284.   new_block->n_tables = 0;
  2285.   new_block->type = Query_cache_block::FREE;
  2286.   if (*list == 0)
  2287.   {
  2288.     *list = new_block->next=new_block->prev=new_block;
  2289.     DBUG_PRINT("qcache", ("inserted into empty list"));
  2290.   }
  2291.   else
  2292.   {
  2293.     Query_cache_block *point = *list;
  2294.     if (point->length >= new_block->length)
  2295.     {
  2296.       point = point->prev;
  2297.       *list = new_block;
  2298.     }
  2299.     else
  2300.     {
  2301.       /* Find right position in sorted list to put block */
  2302.       while (point->next != *list &&
  2303.      point->next->length < new_block->length)
  2304. point=point->next;
  2305.     }
  2306.     new_block->prev = point;
  2307.     new_block->next = point->next;
  2308.     new_block->next->prev = new_block;
  2309.     point->next = new_block;
  2310.   }
  2311.   free_memory+=new_block->length;
  2312.   free_memory_blocks++;
  2313.   DBUG_VOID_RETURN;
  2314. }
  2315. void
  2316. Query_cache::double_linked_list_simple_include(Query_cache_block *point,
  2317. Query_cache_block **
  2318. list_pointer)
  2319. {
  2320.   DBUG_ENTER("Query_cache::double_linked_list_simple_include");
  2321.   DBUG_PRINT("qcache", ("including block 0x%lx", (ulong) point));
  2322.   if (*list_pointer == 0)
  2323.     *list_pointer=point->next=point->prev=point;
  2324.   else
  2325.   {
  2326.     // insert to the end of list
  2327.     point->next = (*list_pointer);
  2328.     point->prev = (*list_pointer)->prev;
  2329.     point->prev->next = point;
  2330.     (*list_pointer)->prev = point;
  2331.   }
  2332.   DBUG_VOID_RETURN;
  2333. }
  2334. void
  2335. Query_cache::double_linked_list_exclude(Query_cache_block *point,
  2336. Query_cache_block **list_pointer)
  2337. {
  2338.   DBUG_ENTER("Query_cache::double_linked_list_exclude");
  2339.   DBUG_PRINT("qcache", ("excluding block 0x%lx, list 0x%lx",
  2340.       (ulong) point, (ulong) list_pointer));
  2341.   if (point->next == point)
  2342.     *list_pointer = 0; // empty list
  2343.   else
  2344.   {
  2345.     point->next->prev = point->prev;
  2346.     point->prev->next = point->next;
  2347.     if (point == *list_pointer)
  2348.       *list_pointer = point->next;
  2349.   }
  2350.   DBUG_VOID_RETURN;
  2351. }
  2352. void Query_cache::double_linked_list_join(Query_cache_block *head_tail,
  2353.   Query_cache_block *tail_head)
  2354. {
  2355.   Query_cache_block *head_head = head_tail->next,
  2356.     *tail_tail = tail_head->prev;
  2357.   head_head->prev = tail_tail;
  2358.   head_tail->next = tail_head;
  2359.   tail_head->prev = head_tail;
  2360.   tail_tail->next = head_head;
  2361. }
  2362. /*****************************************************************************
  2363.  Query
  2364. *****************************************************************************/
  2365. /*
  2366.   If query is cacheable return number tables in query
  2367.   (query without tables are not cached)
  2368. */
  2369. TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
  2370.      char *query,
  2371.      LEX *lex,
  2372.      TABLE_LIST *tables_used,
  2373.      uint8 *tables_type)
  2374. {
  2375.   TABLE_COUNTER_TYPE table_count = 0;
  2376.   DBUG_ENTER("Query_cache::is_cacheable");
  2377.   if (lex->sql_command == SQLCOM_SELECT &&
  2378.       (thd->variables.query_cache_type == 1 ||
  2379.        (thd->variables.query_cache_type == 2 && (lex->select_lex.options &
  2380.  OPTION_TO_QUERY_CACHE))) &&
  2381.       lex->safe_to_cache_query)
  2382.   {
  2383.     DBUG_PRINT("qcache", ("options %lx %lx, type %u",
  2384. OPTION_TO_QUERY_CACHE,
  2385. lex->select_lex.options,
  2386. (int) thd->variables.query_cache_type));
  2387.     for (; tables_used; tables_used= tables_used->next)
  2388.     {
  2389.       table_count++;
  2390.       DBUG_PRINT("qcache", ("table %s, db %s, type %u",
  2391.   tables_used->real_name,
  2392.   tables_used->db, tables_used->table->db_type));
  2393.       *tables_type|= tables_used->table->file->table_cache_type();
  2394.       /*
  2395. table_alias_charset used here because it depends of
  2396. lower_case_table_names variable
  2397.       */
  2398.       if ((tables_used->table->tmp_table != NO_TMP_TABLE &&
  2399.            !tables_used->derived) ||
  2400.   (*tables_type & HA_CACHE_TBL_NOCACHE) ||
  2401.   (tables_used->db_length == 5 &&
  2402.    my_strnncoll(table_alias_charset, (uchar*)tables_used->db, 6,
  2403. (uchar*)"mysql",6) == 0))
  2404.       {
  2405. DBUG_PRINT("qcache", 
  2406.    ("select not cacheable: temporary, system or 
  2407. other non-cacheable table(s)"));
  2408. DBUG_RETURN(0);
  2409.       }
  2410.       if (tables_used->derived)
  2411.       {
  2412.         table_count--;
  2413.         DBUG_PRINT("qcache", ("derived table skipped"));
  2414.       }
  2415.       else if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
  2416.       {
  2417. ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
  2418. MYRG_INFO *file = handler->myrg_info();
  2419. table_count+= (file->end_table - file->open_tables);
  2420.       }
  2421.     }
  2422.     if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
  2423. ((*tables_type)&HA_CACHE_TBL_TRANSACT))
  2424.     {
  2425.       DBUG_PRINT("qcache", ("not in autocommin mode"));
  2426.       DBUG_RETURN(0);
  2427.     }
  2428.     DBUG_PRINT("qcache", ("select is using %d tables", table_count));
  2429.     DBUG_RETURN(table_count);
  2430.   }
  2431.   DBUG_PRINT("qcache",
  2432.      ("not interesting query: %d or not cacheable, options %lx %lx, type %u",
  2433.       (int) lex->sql_command,
  2434.       OPTION_TO_QUERY_CACHE,
  2435.       lex->select_lex.options,
  2436.       (int) thd->variables.query_cache_type));
  2437.   DBUG_RETURN(0);
  2438. }
  2439. /*
  2440.   Check handler allowance to cache query with these tables
  2441.   SYNOPSYS
  2442.     Query_cache::ask_handler_allowance()
  2443.     thd - thread handlers
  2444.     tables_used - tables list used in query
  2445.   RETURN
  2446.     0 - caching allowed
  2447.     1 - caching disallowed
  2448. */
  2449. my_bool Query_cache::ask_handler_allowance(THD *thd,
  2450.    TABLE_LIST *tables_used)
  2451. {
  2452.   DBUG_ENTER("Query_cache::ask_handler_allowance");
  2453.   for (; tables_used; tables_used= tables_used->next)
  2454.   {
  2455.     TABLE *table= tables_used->table;
  2456.     if (!ha_caching_allowed(thd, table->table_cache_key,
  2457.                          table->key_length,
  2458.                          table->file->table_cache_type()))
  2459.     {
  2460.       DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
  2461.     tables_used->db, tables_used->alias));
  2462.       thd->lex->safe_to_cache_query= 0;          // Don't try to cache this
  2463.       DBUG_RETURN(1);
  2464.     }
  2465.   }
  2466.   DBUG_RETURN(0);
  2467. }
  2468. /*****************************************************************************
  2469.   Packing
  2470. *****************************************************************************/
  2471. void Query_cache::pack_cache()
  2472. {
  2473.   DBUG_ENTER("Query_cache::pack_cache");
  2474.   STRUCT_LOCK(&structure_guard_mutex);
  2475.   /*
  2476.     It is very unlikely that following condition is TRUE (it is possible
  2477.     only if other thread is resizing cache), so we check it only after
  2478.     guard mutex lock
  2479.   */
  2480.   if (unlikely(query_cache_size == 0))
  2481.   {
  2482.     STRUCT_UNLOCK(&structure_guard_mutex);
  2483.     DBUG_VOID_RETURN;
  2484.   }
  2485.   DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
  2486.   byte *border = 0;
  2487.   Query_cache_block *before = 0;
  2488.   ulong gap = 0;
  2489.   my_bool ok = 1;
  2490.   Query_cache_block *block = first_block;
  2491.   DUMP(this);
  2492.   if (first_block)
  2493.   {
  2494.     do
  2495.     {
  2496.       Query_cache_block *next=block->pnext;
  2497.       ok = move_by_type(&border, &before, &gap, block);
  2498.       block = next;
  2499.     } while (ok && block != first_block);
  2500.     if (border != 0)
  2501.     {
  2502.       Query_cache_block *new_block = (Query_cache_block *) border;
  2503.       new_block->init(gap);
  2504.       total_blocks++;
  2505.       new_block->pnext = before->pnext;
  2506.       before->pnext = new_block;
  2507.       new_block->pprev = before;
  2508.       new_block->pnext->pprev = new_block;
  2509.       insert_into_free_memory_list(new_block);
  2510.     }
  2511.     DUMP(this);
  2512.   }
  2513.   DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
  2514.   STRUCT_UNLOCK(&structure_guard_mutex);
  2515.   DBUG_VOID_RETURN;
  2516. }
  2517. my_bool Query_cache::move_by_type(byte **border,
  2518.   Query_cache_block **before, ulong *gap,
  2519.   Query_cache_block *block)
  2520. {
  2521.   DBUG_ENTER("Query_cache::move_by_type");
  2522.   my_bool ok = 1;
  2523.   switch (block->type) {
  2524.   case Query_cache_block::FREE:
  2525.   {
  2526.     DBUG_PRINT("qcache", ("block 0x%lx FREE", (ulong) block));
  2527.     if (*border == 0)
  2528.     {
  2529.       *border = (byte *) block;
  2530.       *before = block->pprev;
  2531.       DBUG_PRINT("qcache", ("gap beginning here"));
  2532.     }
  2533.     exclude_from_free_memory_list(block);
  2534.     *gap +=block->length;
  2535.     block->pprev->pnext=block->pnext;
  2536.     block->pnext->pprev=block->pprev;
  2537.     block->destroy();
  2538.     total_blocks--;
  2539.     DBUG_PRINT("qcache", ("added to gap (%lu)", *gap));
  2540.     break;
  2541.   }
  2542.   case Query_cache_block::TABLE:
  2543.   {
  2544.     DBUG_PRINT("qcache", ("block 0x%lx TABLE", (ulong) block));
  2545.     if (*border == 0)
  2546.       break;
  2547.     ulong len = block->length, used = block->used;
  2548.     Query_cache_block_table *list_root = block->table(0);
  2549.     Query_cache_block_table *tprev = list_root->prev,
  2550.     *tnext = list_root->next;
  2551.     Query_cache_block *prev = block->prev,
  2552.       *next = block->next,
  2553.       *pprev = block->pprev,
  2554.       *pnext = block->pnext,
  2555.       *new_block =(Query_cache_block *) *border;
  2556.     uint tablename_offset = block->table()->table() - block->table()->db();
  2557.     char *data = (char*) block->data();
  2558.     byte *key;
  2559.     uint key_length;
  2560.     key=query_cache_table_get_key((byte*) block, &key_length, 0);
  2561.     hash_search(&tables, (byte*) key, key_length);
  2562.     block->destroy();
  2563.     new_block->init(len);
  2564.     new_block->type=Query_cache_block::TABLE;
  2565.     new_block->used=used;
  2566.     new_block->n_tables=1;
  2567.     memmove((char*) new_block->data(), data, len-new_block->headers_len());
  2568.     relink(block, new_block, next, prev, pnext, pprev);
  2569.     if (tables_blocks == block)
  2570.       tables_blocks = new_block;
  2571.     Query_cache_block_table *nlist_root = new_block->table(0);
  2572.     nlist_root->n = 0;
  2573.     nlist_root->next = tnext;
  2574.     tnext->prev = nlist_root;
  2575.     nlist_root->prev = tprev;
  2576.     tprev->next = nlist_root;
  2577.     DBUG_PRINT("qcache",
  2578.        ("list_root: 0x%lx tnext 0x%lx tprev 0x%lx tprev->next 0x%lx tnext->prev 0x%lx",
  2579. (ulong) list_root, (ulong) tnext, (ulong) tprev,
  2580. (ulong)tprev->next, (ulong)tnext->prev));
  2581.     /*
  2582.       Go through all queries that uses this table and change them to
  2583.       point to the new table object
  2584.     */
  2585.     Query_cache_table *new_block_table=new_block->table();
  2586.     for (;tnext != nlist_root; tnext=tnext->next)
  2587.       tnext->parent= new_block_table;
  2588.     *border += len;
  2589.     *before = new_block;
  2590.     /* Fix pointer to table name */
  2591.     new_block->table()->table(new_block->table()->db() + tablename_offset);
  2592.     /* Fix hash to point at moved block */
  2593.     hash_replace(&tables, tables.current_record, (byte*) new_block);
  2594.     DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
  2595. len, (ulong) new_block, (ulong) *border));
  2596.     break;
  2597.   }
  2598.   case Query_cache_block::QUERY:
  2599.   {
  2600.     DBUG_PRINT("qcache", ("block 0x%lx QUERY", (ulong) block));
  2601.     if (*border == 0)
  2602.       break;
  2603.     BLOCK_LOCK_WR(block);
  2604.     ulong len = block->length, used = block->used;
  2605.     TABLE_COUNTER_TYPE n_tables = block->n_tables;
  2606.     Query_cache_block *prev = block->prev,
  2607. *next = block->next,
  2608. *pprev = block->pprev,
  2609. *pnext = block->pnext,
  2610. *new_block =(Query_cache_block*) *border;
  2611.     char *data = (char*) block->data();
  2612.     Query_cache_block *first_result_block = ((Query_cache_query *)
  2613.      block->data())->result();
  2614.     byte *key;
  2615.     uint key_length;
  2616.     key=query_cache_query_get_key((byte*) block, &key_length, 0);
  2617.     hash_search(&queries, (byte*) key, key_length);
  2618.     // Move table of used tables 
  2619.     memmove((char*) new_block->table(0), (char*) block->table(0),
  2620.    ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
  2621.     block->query()->unlock_n_destroy();
  2622.     block->destroy();
  2623.     new_block->init(len);
  2624.     new_block->type=Query_cache_block::QUERY;
  2625.     new_block->used=used;
  2626.     new_block->n_tables=n_tables;
  2627.     memmove((char*) new_block->data(), data, len - new_block->headers_len());
  2628.     relink(block, new_block, next, prev, pnext, pprev);
  2629.     if (queries_blocks == block)
  2630.       queries_blocks = new_block;
  2631.     Query_cache_block_table *beg_of_table_table= block->table(0),
  2632.       *end_of_table_table= block->table(n_tables);
  2633.     byte *beg_of_new_table_table= (byte*) new_block->table(0);
  2634.       
  2635.     for (TABLE_COUNTER_TYPE j=0; j < n_tables; j++)
  2636.     {
  2637.       Query_cache_block_table *block_table = new_block->table(j);
  2638.       // use aligment from begining of table if 'next' is in same block
  2639.       if ((beg_of_table_table <= block_table->next) &&
  2640.   (block_table->next < end_of_table_table))
  2641. ((Query_cache_block_table *)(beg_of_new_table_table + 
  2642.      (((byte*)block_table->next) -
  2643.       ((byte*)beg_of_table_table))))->prev=
  2644.  block_table;
  2645.       else
  2646. block_table->next->prev= block_table;
  2647.       // use aligment from begining of table if 'prev' is in same block
  2648.       if ((beg_of_table_table <= block_table->prev) &&
  2649.   (block_table->prev < end_of_table_table))
  2650. ((Query_cache_block_table *)(beg_of_new_table_table + 
  2651.      (((byte*)block_table->prev) -
  2652.       ((byte*)beg_of_table_table))))->next=
  2653.   block_table;
  2654.       else
  2655. block_table->prev->next = block_table;
  2656.     }
  2657.     DBUG_PRINT("qcache", ("after circle tt"));
  2658.     *border += len;
  2659.     *before = new_block;
  2660.     new_block->query()->result(first_result_block);
  2661.     if (first_result_block != 0)
  2662.     {
  2663.       Query_cache_block *result_block = first_result_block;
  2664.       do
  2665.       {
  2666. result_block->result()->parent(new_block);
  2667. result_block = result_block->next;
  2668.       } while ( result_block != first_result_block );
  2669.     }
  2670.     Query_cache_query *new_query= ((Query_cache_query *) new_block->data());
  2671.     my_rwlock_init(&new_query->lock, NULL);
  2672.     /* 
  2673.       If someone is writing to this block, inform the writer that the block
  2674.       has been moved.
  2675.     */
  2676.     NET *net = new_block->query()->writer();
  2677.     if (net != 0)
  2678.     {
  2679.       net->query_cache_query= (gptr) new_block;
  2680.     }
  2681.     /* Fix hash to point at moved block */
  2682.     hash_replace(&queries, queries.current_record, (byte*) new_block);
  2683.     DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
  2684. len, (ulong) new_block, (ulong) *border));
  2685.     break;
  2686.   }
  2687.   case Query_cache_block::RES_INCOMPLETE:
  2688.   case Query_cache_block::RES_BEG:
  2689.   case Query_cache_block::RES_CONT:
  2690.   case Query_cache_block::RESULT:
  2691.   {
  2692.     DBUG_PRINT("qcache", ("block 0x%lx RES* (%d)", (ulong) block,
  2693. (int) block->type));
  2694.     if (*border == 0)
  2695.       break;
  2696.     Query_cache_block *query_block = block->result()->parent(),
  2697.       *next = block->next,
  2698.       *prev = block->prev;
  2699.     Query_cache_block::block_type type = block->type;
  2700.     BLOCK_LOCK_WR(query_block);
  2701.     ulong len = block->length, used = block->used;
  2702.     Query_cache_block *pprev = block->pprev,
  2703.       *pnext = block->pnext,
  2704.       *new_block =(Query_cache_block*) *border;
  2705.     char *data = (char*) block->data();
  2706.     block->destroy();
  2707.     new_block->init(len);
  2708.     new_block->type=type;
  2709.     new_block->used=used;
  2710.     memmove((char*) new_block->data(), data, len - new_block->headers_len());
  2711.     relink(block, new_block, next, prev, pnext, pprev);
  2712.     new_block->result()->parent(query_block);
  2713.     Query_cache_query *query = query_block->query();
  2714.     if (query->result() == block)
  2715.       query->result(new_block);
  2716.     *border += len;
  2717.     *before = new_block;
  2718.     /* If result writing complete && we have free space in block */
  2719.     ulong free_space= new_block->length - new_block->used;
  2720.     free_space-= free_space % ALIGN_SIZE(1);
  2721.     if (query->result()->type == Query_cache_block::RESULT &&
  2722. new_block->length > new_block->used &&
  2723. *gap + free_space > min_allocation_unit &&
  2724. new_block->length - free_space > min_allocation_unit)
  2725.     {
  2726.       *border-= free_space;
  2727.       *gap+= free_space;
  2728.       DBUG_PRINT("qcache",
  2729.  ("rest of result free space added to gap (%lu)", *gap));
  2730.       new_block->length -= free_space;
  2731.     }
  2732.     BLOCK_UNLOCK_WR(query_block);
  2733.     DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
  2734. len, (ulong) new_block, (ulong) *border));
  2735.     break;
  2736.   }
  2737.   default:
  2738.     DBUG_PRINT("error", ("unexpected block type %d, block 0x%lx",
  2739.  (int)block->type, (ulong) block));
  2740.     ok = 0;
  2741.   }
  2742.   DBUG_RETURN(ok);
  2743. }
  2744. void Query_cache::relink(Query_cache_block *oblock,
  2745.  Query_cache_block *nblock,
  2746.  Query_cache_block *next, Query_cache_block *prev,
  2747.  Query_cache_block *pnext, Query_cache_block *pprev)
  2748. {
  2749.   if (prev == oblock) //check pointer to himself
  2750.   {
  2751.     nblock->prev = nblock;
  2752.     nblock->next = nblock;
  2753.   }
  2754.   else
  2755.   {
  2756.     nblock->prev = prev;
  2757.     prev->next=nblock;
  2758.   }
  2759.   if (next != oblock)
  2760.   {
  2761.     nblock->next = next;
  2762.     next->prev=nblock;
  2763.   }
  2764.   nblock->pprev = pprev; // Physical pointer to himself have only 1 free block
  2765.   nblock->pnext = pnext;
  2766.   pprev->pnext=nblock;
  2767.   pnext->pprev=nblock;
  2768. }
  2769. my_bool Query_cache::join_results(ulong join_limit)
  2770. {
  2771.   my_bool has_moving = 0;
  2772.   DBUG_ENTER("Query_cache::join_results");
  2773.   STRUCT_LOCK(&structure_guard_mutex);
  2774.   if (queries_blocks != 0)
  2775.   {
  2776.     DBUG_ASSERT(query_cache_size > 0);
  2777.     Query_cache_block *block = queries_blocks;
  2778.     do
  2779.     {
  2780.       Query_cache_query *header = block->query();
  2781.       if (header->result() != 0 &&
  2782.   header->result()->type == Query_cache_block::RESULT &&
  2783.   header->length() > join_limit)
  2784.       {
  2785. Query_cache_block *new_result_block =
  2786.   get_free_block(ALIGN_SIZE(header->length()) +
  2787.  ALIGN_SIZE(sizeof(Query_cache_block)) +
  2788.  ALIGN_SIZE(sizeof(Query_cache_result)), 1, 0);
  2789. if (new_result_block != 0)
  2790. {
  2791.   has_moving = 1;
  2792.   Query_cache_block *first_result = header->result();
  2793.   ulong new_len = (header->length() +
  2794.    ALIGN_SIZE(sizeof(Query_cache_block)) +
  2795.    ALIGN_SIZE(sizeof(Query_cache_result)));
  2796.   if (new_result_block->length >
  2797.       ALIGN_SIZE(new_len) + min_allocation_unit)
  2798.     split_block(new_result_block, ALIGN_SIZE(new_len));
  2799.   BLOCK_LOCK_WR(block);
  2800.   header->result(new_result_block);
  2801.   new_result_block->type = Query_cache_block::RESULT;
  2802.   new_result_block->n_tables = 0;
  2803.   new_result_block->used = new_len;
  2804.   new_result_block->next = new_result_block->prev = new_result_block;
  2805.   DBUG_PRINT("qcache", ("new block %lu/%lu (%lu)",
  2806.       new_result_block->length,
  2807.       new_result_block->used,
  2808.       header->length()));
  2809.   Query_cache_result *new_result = new_result_block->result();
  2810.   new_result->parent(block);
  2811.   byte *write_to = (byte*) new_result->data();
  2812.   Query_cache_block *result_block = first_result;
  2813.   do
  2814.   {
  2815.     ulong len = (result_block->used - result_block->headers_len() -
  2816.  ALIGN_SIZE(sizeof(Query_cache_result)));
  2817.     DBUG_PRINT("loop", ("add block %lu/%lu (%lu)",
  2818. result_block->length,
  2819. result_block->used,
  2820. len));
  2821.     memcpy((char *) write_to,
  2822.    (char*) result_block->result()->data(),
  2823.    len);
  2824.     write_to += len;
  2825.     Query_cache_block *old_result_block = result_block;
  2826.     result_block = result_block->next;
  2827.     free_memory_block(old_result_block);
  2828.   } while (result_block != first_result);
  2829.   BLOCK_UNLOCK_WR(block);
  2830. }
  2831.       }
  2832.       block = block->next;
  2833.     } while ( block != queries_blocks );
  2834.   }
  2835.   STRUCT_UNLOCK(&structure_guard_mutex);
  2836.   DBUG_RETURN(has_moving);
  2837. }
  2838. uint Query_cache::filename_2_table_key (char *key, const char *path,
  2839. uint32 *db_length)
  2840. {
  2841.   char tablename[FN_REFLEN+2], *filename, *dbname;
  2842.   DBUG_ENTER("Query_cache::filename_2_table_key");
  2843.   /* Safety if filename didn't have a directory name */
  2844.   tablename[0]= FN_LIBCHAR;
  2845.   tablename[1]= FN_LIBCHAR;
  2846.   /* Convert filename to this OS's format in tablename */
  2847.   fn_format(tablename + 2, path, "", "", MY_REPLACE_EXT);
  2848.   filename=  tablename + dirname_length(tablename + 2) + 2;
  2849.   /* Find start of databasename */
  2850.   for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ;
  2851.   *db_length= (filename - dbname) - 1;
  2852.   DBUG_PRINT("qcache", ("table '%-.*s.%s'", *db_length, dbname, filename));
  2853.   DBUG_RETURN((uint) (strmov(strmake(key, dbname, *db_length) + 1,
  2854.      filename) -key) + 1);
  2855. }
  2856. /****************************************************************************
  2857.   Functions to be used when debugging
  2858. ****************************************************************************/
  2859. #if defined(DBUG_OFF) && !defined(USE_QUERY_CACHE_INTEGRITY_CHECK)
  2860. void wreck(uint line, const char *message) {}
  2861. void bins_dump() {}
  2862. void cache_dump() {}
  2863. void queries_dump() {}
  2864. void tables_dump() {}
  2865. my_bool check_integrity(bool not_locked) { return 0; }
  2866. my_bool in_list(Query_cache_block * root, Query_cache_block * point,
  2867. const char *name) { return 0;}
  2868. my_bool in_blocks(Query_cache_block * point) { return 0; }
  2869. #else
  2870. void Query_cache::wreck(uint line, const char *message)
  2871. {
  2872.   THD *thd=current_thd;
  2873.   DBUG_ENTER("Query_cache::wreck");
  2874.   query_cache_size = 0;
  2875.   if (*message)
  2876.     DBUG_PRINT("error", (" %s", message));
  2877.   DBUG_PRINT("warning", ("=================================="));
  2878.   DBUG_PRINT("warning", ("%5d QUERY CACHE WRECK => DISABLED",line));
  2879.   DBUG_PRINT("warning", ("=================================="));
  2880.   if (thd)
  2881.     thd->killed = 1;
  2882.   cache_dump();
  2883.   /* check_integrity(0); */ /* Can't call it here because of locks */
  2884.   bins_dump();
  2885.   DBUG_VOID_RETURN;
  2886. }
  2887. void Query_cache::bins_dump()
  2888. {
  2889.   uint i;
  2890.   
  2891.   if (!initialized || query_cache_size == 0)
  2892.   {
  2893.     DBUG_PRINT("qcache", ("Query Cache not initialized"));
  2894.     return;
  2895.   }
  2896.   DBUG_PRINT("qcache", ("mem_bin_num=%u, mem_bin_steps=%u",
  2897.       mem_bin_num, mem_bin_steps));
  2898.   DBUG_PRINT("qcache", ("-------------------------"));
  2899.   DBUG_PRINT("qcache", ("      size idx       step"));
  2900.   DBUG_PRINT("qcache", ("-------------------------"));
  2901.   for (i=0; i < mem_bin_steps; i++)
  2902.   {
  2903.     DBUG_PRINT("qcache", ("%10lu %3d %10lu", steps[i].size, steps[i].idx,
  2904. steps[i].increment));
  2905.   }
  2906.   DBUG_PRINT("qcache", ("-------------------------"));
  2907.   DBUG_PRINT("qcache", ("      size num"));
  2908.   DBUG_PRINT("qcache", ("-------------------------"));
  2909.   for (i=0; i < mem_bin_num; i++)
  2910.   {
  2911.     DBUG_PRINT("qcache", ("%10lu %3d 0x%lx", bins[i].size, bins[i].number,
  2912. (ulong)&(bins[i])));
  2913.     if (bins[i].free_blocks)
  2914.     {
  2915.       Query_cache_block *block = bins[i].free_blocks;
  2916.       do{
  2917. DBUG_PRINT("qcache", ("\-- %lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
  2918.     block->length, (ulong)block,
  2919.     (ulong)block->next, (ulong)block->prev,
  2920.     (ulong)block->pnext, (ulong)block->pprev));
  2921. block = block->next;
  2922.       } while ( block != bins[i].free_blocks );
  2923.     }
  2924.   }
  2925.   DBUG_PRINT("qcache", ("-------------------------"));
  2926. }
  2927. void Query_cache::cache_dump()
  2928. {
  2929.   if (!initialized || query_cache_size == 0)
  2930.   {
  2931.     DBUG_PRINT("qcache", ("Query Cache not initialized"));
  2932.     return;
  2933.   }
  2934.   DBUG_PRINT("qcache", ("-------------------------------------"));
  2935.   DBUG_PRINT("qcache", ("    length       used t nt"));
  2936.   DBUG_PRINT("qcache", ("-------------------------------------"));
  2937.   Query_cache_block *i = first_block;
  2938.   do
  2939.   {
  2940.     DBUG_PRINT("qcache",
  2941.        ("%10lu %10lu %1d %2d 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
  2942. i->length, i->used, (int)i->type,
  2943. i->n_tables, (ulong)i,
  2944. (ulong)i->next, (ulong)i->prev, (ulong)i->pnext,
  2945. (ulong)i->pprev));
  2946.     i = i->pnext;
  2947.   } while ( i != first_block );
  2948.   DBUG_PRINT("qcache", ("-------------------------------------"));
  2949. }
  2950. void Query_cache::queries_dump()
  2951. {
  2952.   if (!initialized)
  2953.   {
  2954.     DBUG_PRINT("qcache", ("Query Cache not initialized"));
  2955.     return;
  2956.   }
  2957.   DBUG_PRINT("qcache", ("------------------"));
  2958.   DBUG_PRINT("qcache", (" QUERIES"));
  2959.   DBUG_PRINT("qcache", ("------------------"));
  2960.   if (queries_blocks != 0)
  2961.   {
  2962.     Query_cache_block *block = queries_blocks;
  2963.     do
  2964.     {
  2965.       uint len;
  2966.       char *str = (char*) query_cache_query_get_key((byte*) block, &len, 0);
  2967.       len-= QUERY_CACHE_FLAGS_SIZE;   // Point at flags
  2968.       Query_cache_query_flags flags;
  2969.       memcpy(&flags, str+len, QUERY_CACHE_FLAGS_SIZE);
  2970.       str[len]= 0; // make zero ending DB name
  2971.       DBUG_PRINT("qcache", ("F:%u C:%u L:%lu T:'%s' (%u) '%s' '%s'",
  2972.     flags.client_long_flag,
  2973.     flags.character_set_client_num, 
  2974.                             (ulong)flags.limit, flags.time_zone->get_name(),
  2975.     len, str, strend(str)+1));
  2976.       DBUG_PRINT("qcache", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong) block,
  2977.     (ulong) block->next, (ulong) block->prev,
  2978.     (ulong)block->pnext, (ulong)block->pprev));
  2979.       memcpy(str + len, &flags, QUERY_CACHE_FLAGS_SIZE); // restore flags
  2980.       for (TABLE_COUNTER_TYPE t= 0; t < block->n_tables; t++)
  2981.       {
  2982. Query_cache_table *table= block->table(t)->parent;
  2983. DBUG_PRINT("qcache", ("-t- '%s' '%s'", table->db(), table->table()));
  2984.       }
  2985.       Query_cache_query *header = block->query();
  2986.       if (header->result())
  2987.       {
  2988. Query_cache_block *result_block = header->result();
  2989. Query_cache_block *result_beg = result_block;
  2990. do
  2991. {
  2992.   DBUG_PRINT("qcache", ("-r- %u %lu/%lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
  2993.       (uint) result_block->type,
  2994.       result_block->length, result_block->used,
  2995.       (ulong) result_block,
  2996.       (ulong) result_block->next,
  2997.       (ulong) result_block->prev,
  2998.       (ulong) result_block->pnext,
  2999.       (ulong) result_block->pprev));
  3000.   result_block = result_block->next;
  3001. } while ( result_block != result_beg );
  3002.       }
  3003.     } while ((block=block->next) != queries_blocks);
  3004.   }
  3005.   else
  3006.   {
  3007.     DBUG_PRINT("qcache", ("no queries in list"));
  3008.   }
  3009.   DBUG_PRINT("qcache", ("------------------"));
  3010. }
  3011. void Query_cache::tables_dump()
  3012. {
  3013.   if (!initialized || query_cache_size == 0)
  3014.   {
  3015.     DBUG_PRINT("qcache", ("Query Cache not initialized"));
  3016.     return;
  3017.   }
  3018.   DBUG_PRINT("qcache", ("--------------------"));
  3019.   DBUG_PRINT("qcache", ("TABLES"));
  3020.   DBUG_PRINT("qcache", ("--------------------"));
  3021.   if (tables_blocks != 0)
  3022.   {
  3023.     Query_cache_block *table_block = tables_blocks;
  3024.     do
  3025.     {
  3026.       Query_cache_table *table = table_block->table();
  3027.       DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table()));
  3028.       table_block = table_block->next;
  3029.     } while ( table_block != tables_blocks);
  3030.   }
  3031.   else
  3032.     DBUG_PRINT("qcache", ("no tables in list"));
  3033.   DBUG_PRINT("qcache", ("--------------------"));
  3034. }
  3035. my_bool Query_cache::check_integrity(bool not_locked)
  3036. {
  3037.   my_bool result = 0;
  3038.   uint i;
  3039.   DBUG_ENTER("check_integrity");
  3040.   if (query_cache_size == 0)
  3041.   {
  3042.     DBUG_PRINT("qcache", ("Query Cache not initialized"));
  3043.     DBUG_RETURN(0);
  3044.   }
  3045.   if (!not_locked)
  3046.   {
  3047.     STRUCT_LOCK(&structure_guard_mutex);
  3048.     /*
  3049.       It is very unlikely that following condition is TRUE (it is possible
  3050.       only if other thread is resizing cache), so we check it only after
  3051.       guard mutex lock
  3052.     */
  3053.     if (unlikely(query_cache_size == 0))
  3054.     {
  3055.       STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
  3056.       DBUG_RETURN(0);
  3057.     }
  3058.   }
  3059.   if (hash_check(&queries))
  3060.   {
  3061.     DBUG_PRINT("error", ("queries hash is damaged"));
  3062.     result = 1;
  3063.   }
  3064.   if (hash_check(&tables))
  3065.   {
  3066.     DBUG_PRINT("error", ("tables hash is damaged"));
  3067.     result = 1;
  3068.   }
  3069.   DBUG_PRINT("qcache", ("physical address check ..."));
  3070.   ulong free=0, used=0;
  3071.   Query_cache_block * block = first_block;
  3072.   do
  3073.   {
  3074.     DBUG_PRINT("qcache", ("block 0x%lx, type %u...", 
  3075.   (ulong) block, (uint) block->type));  
  3076.     // Check allignment
  3077.     if ((((long)block) % (long) ALIGN_SIZE(1)) !=
  3078. (((long)first_block) % (long)ALIGN_SIZE(1)))
  3079.     {
  3080.       DBUG_PRINT("error",
  3081.  ("block 0x%lx do not aligned by %d", (ulong) block,
  3082.   ALIGN_SIZE(1)));
  3083.       result = 1;
  3084.     }
  3085.     // Check memory allocation
  3086.     if (block->pnext == first_block) // Is it last block?
  3087.     {
  3088.       if (((byte*)block) + block->length != 
  3089.   ((byte*)first_block) + query_cache_size)
  3090.       {
  3091. DBUG_PRINT("error", 
  3092.    ("block 0x%lx, type %u, ended at 0x%lx, but cache ended at 0x%lx",
  3093.     (ulong) block, (uint) block->type, 
  3094.     (ulong) (((byte*)block) + block->length),
  3095.     (ulong) (((byte*)first_block) + query_cache_size)));
  3096. result = 1;
  3097.       }
  3098.     }
  3099.     else
  3100.       if (((byte*)block) + block->length != ((byte*)block->pnext))
  3101.       {
  3102. DBUG_PRINT("error", 
  3103.    ("block 0x%lx, type %u, ended at 0x%lx, but next block begining at 0x%lx",
  3104.     (ulong) block, (uint) block->type, 
  3105.     (ulong) (((byte*)block) + block->length),
  3106.     (ulong) ((byte*)block->pnext)));
  3107.       }
  3108.     if (block->type == Query_cache_block::FREE)
  3109.       free+= block->length;
  3110.     else
  3111.       used+= block->length;
  3112.     switch(block->type) {
  3113.     case Query_cache_block::FREE:
  3114.     {
  3115.       Query_cache_memory_bin *bin = *((Query_cache_memory_bin **)
  3116.       block->data());
  3117.       //is it correct pointer?
  3118.       if (((byte*)bin) < ((byte*)bins) ||
  3119.   ((byte*)bin) >= ((byte*)first_block))
  3120.       {
  3121. DBUG_PRINT("error", 
  3122.    ("free block 0x%lx have bin pointer 0x%lx beyaond of bins array bounds [0x%lx,0x%lx]",
  3123.     (ulong) block, 
  3124.     (ulong) bin,
  3125.     (ulong) bins,
  3126.     (ulong) first_block));
  3127. result = 1;
  3128.       }
  3129.       else
  3130.       {
  3131. int idx = (((byte*)bin) - ((byte*)bins)) /
  3132.   sizeof(Query_cache_memory_bin);
  3133. if (in_list(bins[idx].free_blocks, block, "free memory"))
  3134.   result = 1;
  3135.       }
  3136.       break;
  3137.     }
  3138.     case Query_cache_block::TABLE:
  3139.       if (in_list(tables_blocks, block, "tables"))
  3140. result = 1;
  3141.       if (in_table_list(block->table(0),  block->table(0), "table list root"))
  3142. result = 1;
  3143.       break;
  3144.     case Query_cache_block::QUERY:
  3145.     {
  3146.       if (in_list(queries_blocks, block, "query"))
  3147. result = 1;
  3148.       for (TABLE_COUNTER_TYPE j=0; j < block->n_tables; j++)
  3149.       {
  3150. Query_cache_block_table *block_table = block->table(j);
  3151. Query_cache_block_table *block_table_root = 
  3152.   (Query_cache_block_table *) 
  3153.   (((byte*)block_table->parent) -
  3154.    ALIGN_SIZE(sizeof(Query_cache_block_table)));
  3155.      if (in_table_list(block_table, block_table_root, "table list"))
  3156.        result = 1;
  3157.       }
  3158.       break;
  3159.     }
  3160.     case Query_cache_block::RES_INCOMPLETE:
  3161.       // This type of block can be not lincked yet (in multithread environment)
  3162.       break;
  3163.     case Query_cache_block::RES_BEG:
  3164.     case Query_cache_block::RES_CONT:
  3165.     case Query_cache_block::RESULT:
  3166.     {
  3167.       Query_cache_block * query_block = block->result()->parent();
  3168.       if (((byte*)query_block) < ((byte*)first_block) ||
  3169.   ((byte*)query_block) >= (((byte*)first_block) + query_cache_size))
  3170.       {
  3171. DBUG_PRINT("error", 
  3172.    ("result block 0x%lx have query block pointer 0x%lx beyaond of block pool bounds [0x%lx,0x%lx]",
  3173.     (ulong) block,
  3174.     (ulong) query_block,
  3175.     (ulong) first_block,
  3176.     (ulong) (((byte*)first_block) + query_cache_size)));
  3177. result = 1;
  3178.       }
  3179.       else
  3180.       {
  3181. BLOCK_LOCK_RD(query_block);
  3182. if (in_list(queries_blocks, query_block, "query from results"))
  3183.   result = 1;
  3184. if (in_list(query_block->query()->result(), block,
  3185.     "results"))
  3186.   result = 1;
  3187. BLOCK_UNLOCK_RD(query_block);
  3188.       }
  3189.       break;
  3190.     }
  3191.     default:
  3192.       DBUG_PRINT("error",
  3193.  ("block 0x%lx have incorrect type %u",
  3194.   block, block->type));
  3195.       result = 1;
  3196.     }
  3197.     
  3198.     block = block->pnext;
  3199.   } while (block != first_block);
  3200.   
  3201.   if (used + free != query_cache_size)
  3202.   {
  3203.     DBUG_PRINT("error",
  3204.        ("used memory (%lu) + free memory (%lu) !=  query_cache_size (%lu)",
  3205. used, free, query_cache_size));
  3206.     result = 1;
  3207.   }
  3208.   
  3209.   if (free != free_memory)
  3210.   {
  3211.     DBUG_PRINT("error",
  3212.        ("free memory (%lu) != free_memory (%lu)",
  3213. free, free_memory));
  3214.     result = 1;
  3215.   }
  3216.   DBUG_PRINT("qcache", ("check queries ..."));
  3217.   if ((block = queries_blocks))
  3218.   {
  3219.     do
  3220.     {
  3221.       DBUG_PRINT("qcache", ("block 0x%lx, type %u...", 
  3222.     (ulong) block, (uint) block->type));
  3223.       uint length;
  3224.       byte *key = query_cache_query_get_key((byte*) block, &length, 0);
  3225.       gptr val = hash_search(&queries, key, length);
  3226.       if (((gptr)block) != val)
  3227.       {
  3228. DBUG_PRINT("error", ("block 0x%lx found in queries hash like 0x%lx",
  3229.      (ulong) block, (ulong) val));
  3230.       }
  3231.       if (in_blocks(block))
  3232. result = 1;
  3233.       Query_cache_block * results = block->query()->result();
  3234.       if (results)
  3235.       {
  3236. Query_cache_block * result_block = results;
  3237. do
  3238. {
  3239.   DBUG_PRINT("qcache", ("block 0x%lx, type %u...", 
  3240. (ulong) block, (uint) block->type));
  3241.   if (in_blocks(result_block))
  3242.     result = 1;
  3243.   result_block = result_block->next;
  3244. } while (result_block != results);
  3245.       }
  3246.       block = block->next;
  3247.     } while (block != queries_blocks);
  3248.   }
  3249.   DBUG_PRINT("qcache", ("check tables ..."));
  3250.   if ((block = tables_blocks))
  3251.   {
  3252.     do
  3253.     {
  3254.       DBUG_PRINT("qcache", ("block 0x%lx, type %u...", 
  3255.     (ulong) block, (uint) block->type));
  3256.       uint length;
  3257.       byte *key = query_cache_table_get_key((byte*) block, &length, 0);
  3258.       gptr val = hash_search(&tables, key, length);
  3259.       if (((gptr)block) != val)
  3260.       {
  3261. DBUG_PRINT("error", ("block 0x%lx found in tables hash like 0x%lx",
  3262.      (ulong) block, (ulong) val));
  3263.       }
  3264.       
  3265.       if (in_blocks(block))
  3266. result = 1;
  3267.       block=block->next;
  3268.     } while (block != tables_blocks);
  3269.   }
  3270.   DBUG_PRINT("qcache", ("check free blocks"));
  3271.   for (i = 0; i < mem_bin_num; i++)
  3272.   {
  3273.     if ((block = bins[i].free_blocks))
  3274.     {
  3275.       uint count = 0;
  3276.       do
  3277.       {
  3278. DBUG_PRINT("qcache", ("block 0x%lx, type %u...", 
  3279.       (ulong) block, (uint) block->type));
  3280. if (in_blocks(block))
  3281.   result = 1;
  3282. count++;
  3283. block=block->next;
  3284.       } while (block != bins[i].free_blocks);
  3285.       if (count != bins[i].number)
  3286.       {
  3287. DBUG_PRINT("error", ("bin[%d].number is %d, but bin have %d blocks",
  3288.      bins[i].number,  count));
  3289. result = 1;
  3290.       }
  3291.     }
  3292.   }
  3293.   DBUG_ASSERT(result == 0);
  3294.   if (!not_locked)
  3295.     STRUCT_UNLOCK(&structure_guard_mutex);
  3296.   DBUG_RETURN(result);
  3297. }
  3298. my_bool Query_cache::in_blocks(Query_cache_block * point)
  3299. {
  3300.   my_bool result = 0;
  3301.   Query_cache_block *block = point;
  3302.   //back
  3303.   do
  3304.   {
  3305.     if (block->pprev->pnext != block)
  3306.     {
  3307.       DBUG_PRINT("error",
  3308.  ("block 0x%lx in physical list is incorrect linked, prev block 0x%lx refered as next to 0x%lx (check from 0x%lx)",
  3309.   (ulong) block, (ulong) block->pprev,
  3310.   (ulong) block->pprev->pnext,
  3311.   (ulong) point));
  3312.       //back trace
  3313.       for (; block != point; block = block->pnext)
  3314.     DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
  3315.       result = 1;
  3316.       goto err1;
  3317.     }
  3318.     block = block->pprev;
  3319.   } while (block != first_block && block != point);
  3320.   if (block != first_block)
  3321.   {
  3322.     DBUG_PRINT("error",
  3323.        ("block 0x%lx (0x%lx<-->0x%lx) not owned by pysical list",
  3324. (ulong) block, (ulong) block->pprev, (ulong )block->pnext));
  3325.     return 1;
  3326.   }
  3327. err1:
  3328.   //forward
  3329.   block = point;
  3330.   do
  3331.   {
  3332.     if (block->pnext->pprev != block)
  3333.     {
  3334.       DBUG_PRINT("error",
  3335.  ("block 0x%lx in physicel list is incorrect linked, next block 0x%lx refered as prev to 0x%lx (check from 0x%lx)",
  3336.   (ulong) block, (ulong) block->pnext,
  3337.   (ulong) block->pnext->pprev,
  3338.   (ulong) point));
  3339.       //back trace
  3340.       for (; block != point; block = block->pprev)
  3341.     DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
  3342.       result = 1;
  3343.       goto err2;
  3344.     }
  3345.     block = block->pnext;
  3346.   } while (block != first_block);
  3347. err2:
  3348.   return result;
  3349. }
  3350. my_bool Query_cache::in_list(Query_cache_block * root,
  3351.      Query_cache_block * point,
  3352.      const char *name)
  3353. {
  3354.   my_bool result = 0;
  3355.   Query_cache_block *block = point;
  3356.   //back
  3357.   do
  3358.   {
  3359.     if (block->prev->next != block)
  3360.     {
  3361.       DBUG_PRINT("error",
  3362.  ("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)",
  3363.   (ulong) block, name, (ulong) root, (ulong) block->prev,
  3364.   (ulong) block->prev->next,
  3365.   (ulong) point));
  3366.       //back trace
  3367.       for (; block != point; block = block->next)
  3368.     DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
  3369.       result = 1;
  3370.       goto err1;
  3371.     }
  3372.     block = block->prev;
  3373.   } while (block != root && block != point);
  3374.   if (block != root)
  3375.   {
  3376.     DBUG_PRINT("error",
  3377.        ("block 0x%lx (0x%lx<-->0x%lx) not owned by list '%s' 0x%lx",
  3378. (ulong) block, 
  3379. (ulong) block->prev, (ulong) block->next,
  3380. name, (ulong) root));
  3381.     return 1;
  3382.   }
  3383. err1:
  3384.   // forward
  3385.   block = point;
  3386.   do
  3387.   {
  3388.     if (block->next->prev != block)
  3389.     {
  3390.       DBUG_PRINT("error",
  3391.  ("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)",
  3392.   (ulong) block, name, (ulong) root, (ulong) block->next,
  3393.   (ulong) block->next->prev,
  3394.   (ulong) point));
  3395.       //back trace
  3396.       for (; block != point; block = block->prev)
  3397.     DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
  3398.       result = 1;
  3399.       goto err2;
  3400.     }
  3401.     block = block->next;
  3402.   } while (block != root);
  3403. err2:
  3404.   return result;
  3405. }
  3406. void dump_node(Query_cache_block_table * node, 
  3407.        const char * call, const char * descr)
  3408. {
  3409.   DBUG_PRINT("qcache", ("%s: %s: node: 0x%lx", call, descr, (ulong) node));
  3410.   DBUG_PRINT("qcache", ("%s: %s: node block: 0x%lx",
  3411. call, descr, (ulong) node->block()));
  3412.   DBUG_PRINT("qcache", ("%s: %s: next: 0x%lx", call, descr,
  3413. (ulong) node->next));
  3414.   DBUG_PRINT("qcache", ("%s: %s: prev: 0x%lx", call, descr,
  3415. (ulong) node->prev));
  3416. }
  3417. my_bool Query_cache::in_table_list(Query_cache_block_table * root,
  3418.    Query_cache_block_table * point,
  3419.    const char *name)
  3420. {
  3421.   my_bool result = 0;
  3422.   Query_cache_block_table *table = point;
  3423.   dump_node(root, name, "parameter root");
  3424.   //back
  3425.   do
  3426.   {
  3427.     dump_node(table, name, "list element << ");
  3428.     if (table->prev->next != table)
  3429.     {
  3430.       DBUG_PRINT("error",
  3431.  ("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))",
  3432.   (ulong) table, (ulong) table->block(), name, 
  3433.   (ulong) root, (ulong) root->block(),
  3434.   (ulong) table->prev, (ulong) table->prev->block(),
  3435.   (ulong) table->prev->next, 
  3436.   (ulong) table->prev->next->block(),
  3437.   (ulong) point, (ulong) point->block()));
  3438.       //back trace
  3439.       for (; table != point; table = table->next)
  3440.     DBUG_PRINT("error", ("back trace 0x%lx(0x%lx)", 
  3441.  (ulong) table, (ulong) table->block()));
  3442.       result = 1;
  3443.       goto err1;
  3444.     }
  3445.     table = table->prev;
  3446.   } while (table != root && table != point);
  3447.   if (table != root)
  3448.   {
  3449.     DBUG_PRINT("error",
  3450.        ("table 0x%lx(0x%lx) (0x%lx(0x%lx)<-->0x%lx(0x%lx)) not owned by list '%s' 0x%lx(0x%lx)",
  3451. (ulong) table, (ulong) table->block(),
  3452. (ulong) table->prev, (ulong) table->prev->block(),
  3453. (ulong) table->next, (ulong) table->next->block(),
  3454. name, (ulong) root, (ulong) root->block()));
  3455.     return 1;
  3456.   }
  3457. err1:
  3458.   // forward
  3459.   table = point;
  3460.   do
  3461.   {
  3462.     dump_node(table, name, "list element >> ");
  3463.     if (table->next->prev != table)
  3464.     {
  3465.       DBUG_PRINT("error",
  3466.  ("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))",
  3467.   (ulong) table, (ulong) table->block(),
  3468.   name, (ulong) root, (ulong) root->block(),
  3469.   (ulong) table->next, (ulong) table->next->block(),
  3470.   (ulong) table->next->prev,
  3471.   (ulong) table->next->prev->block(),
  3472.   (ulong) point, (ulong) point->block()));
  3473.       //back trace
  3474.       for (; table != point; table = table->prev)
  3475.     DBUG_PRINT("error", ("back trace 0x%lx(0x%lx)",
  3476.  (ulong) table, (ulong) table->block()));
  3477.       result = 1;
  3478.       goto err2;
  3479.     }
  3480.     table = table->next;
  3481.   } while (table != root);
  3482. err2:
  3483.   return result;
  3484. }
  3485. #endif /* DBUG_OFF */
  3486. #endif /*HAVE_QUERY_CACHE*/