~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to sql/sql_cache.h

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

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