summaryrefslogtreecommitdiff
path: root/sql/sql_cache.h
diff options
context:
space:
mode:
authorunknown <monty@hundin.mysql.fi>2001-12-02 14:34:01 +0200
committerunknown <monty@hundin.mysql.fi>2001-12-02 14:34:01 +0200
commit7c999bb03223114a4d07f23db2842363d32d1859 (patch)
tree8e30a64d5c7aaa0ba8554c4c316cc9b76a6724ca /sql/sql_cache.h
parent95e94560eac0ee72bbc566517ca70f14128a01e8 (diff)
downloadmariadb-git-7c999bb03223114a4d07f23db2842363d32d1859.tar.gz
Query cache.
Remove some warnings Docs/manual.texi: Solaris and gcc include/ft_global.h: Remove warnings include/myisam.h: Query cache include/myisammrg.h: Query cache include/mysql_com.h: Query cache libmysqld/lib_sql.cc: Query cache myisam/ft_boolean_search.c: Remove warnings myisam/ft_dump.c: Remove warnings myisam/ft_parser.c: Remove warnings myisam/ft_static.c: Remove warnings myisam/ft_update.c: Remove warnings myisam/ftdefs.h: Remove warnings myisam/mi_delete.c: Query cache myisam/mi_locking.c: Query cache myisam/mi_update.c: Query cache myisam/myisamdef.h: Optimize for Ia64 myisammrg/myrg_extra.c: Query cache mysys/mf_keycache.c: DBUG statements regex/cclass.h: Remove warnings regex/cname.h: Remove warnings regex/main.c: Remove warnings regex/regcomp.c: Remove warnings regex/regcomp.ih: Remove warnings regex/regerror.c: Remove warnings regex/reginit.c: Remove warnings regex/split.c: Remove warnings sql-bench/test-connect.sh: Make tests query-cache safe. sql-bench/test-transactions.sh: Fix for old perl versions sql/convert.cc: Query cache sql/ha_myisammrg.cc: Query cache sql/ha_myisammrg.h: Query cache sql/handler.cc: Query cache sql/item_create.cc: Query cache sql/item_func.cc: Remove warnings sql/item_func.h: Remove warnings sql/lex.h: Query cache sql/mysql_priv.h: Query cache sql/mysqld.cc: Query cache sql/net_serv.cc: Query cache sql/sql_cache.cc: Query cache sql/sql_class.cc: Query cache sql/sql_class.h: Query cache sql/sql_db.cc: Query cache sql/sql_delete.cc: Query cache sql/sql_insert.cc: Query cache sql/sql_parse.cc: Query cache sql/sql_select.cc: Query cache sql/sql_table.cc: Query cache sql/sql_update.cc: Query cache sql/sql_yacc.yy: Query cache
Diffstat (limited to 'sql/sql_cache.h')
-rw-r--r--sql/sql_cache.h402
1 files changed, 402 insertions, 0 deletions
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
new file mode 100644
index 00000000000..0b786fb1560
--- /dev/null
+++ b/sql/sql_cache.h
@@ -0,0 +1,402 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef _SQL_CACHE_H
+#define _SQL_CACHE_H
+
+#include <semaphore.h>
+
+/* Query cache */
+
+/*
+ Can't create new free memory block if unused memory in block less
+ then QUERY_CACHE_MIN_ALLOCATION_UNIT.
+ if QUERY_CACHE_MIN_ALLOCATION_UNIT == 0 then
+ QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automaticaly
+*/
+#define QUERY_CACHE_MIN_ALLOCATION_UNIT 0
+
+/* inittial size of hashes */
+#define QUERY_CACHE_DEF_QUERY_HASH_SIZE 1024
+#define QUERY_CACHE_DEF_TABLE_HASH_SIZE 1024
+
+/* minimal result data size when data allocated */
+#define QUERY_CACHE_MIN_RESULT_DATA_SIZE 1024
+
+/* memory bins size spacing (see at Query_cache::init_cache (sql_cache.cc)) */
+#define QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 4
+#define QUERY_CACHE_MEM_BIN_STEP_PWR2 2
+#define QUERY_CACHE_MEM_BIN_PARTS_INC 1
+#define QUERY_CACHE_MEM_BIN_PARTS_MUL 1.2
+#define QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2 3
+
+/* query flags masks */
+#define QUERY_CACHE_CLIENT_LONG_FLAG_MASK 0x80
+#define QUERY_CACHE_CHARSET_CONVERT_MASK 0x7F
+
+/* packing parameters */
+#define QUERY_CACHE_PACK_ITERATION 2
+#define QUERY_CACHE_PACK_LIMIT (512*1024L)
+
+#define TABLE_COUNTER_TYPE uint8
+
+struct Query_cache_block;
+struct Query_cache_block_table;
+struct Query_cache_table;
+struct Query_cache_query;
+struct Query_cache_result;
+class Query_cache;
+
+
+struct Query_cache_block_table
+{
+ TABLE_COUNTER_TYPE n; // numbr in table (from 0)
+ Query_cache_block_table *next, *prev;
+ Query_cache_table *parent;
+ inline Query_cache_block * block();
+};
+
+
+struct Query_cache_block
+{
+ enum block_type {FREE, QUERY, RESULT, RES_CONT, RES_BEG,
+ RES_INCOMPLETE, TABLE, INCOMPLETE};
+
+ ulong length; // length of all block
+ ulong used; // length of data
+ /*
+ Not used **pprev, **prev because really needed access to pervious block:
+ *pprev to join free blocks
+ *prev to access to opposite side of list in cyclic sorted list
+ */
+ Query_cache_block
+ *pnext,*pprev, // physical next/previous block
+ *next,*prev; // logical next/previous block
+ block_type type;
+ TABLE_COUNTER_TYPE n_tables; // number of tables in query
+
+ inline my_bool is_free(void) { return type == FREE; }
+
+ void init(ulong length);
+ void destroy();
+ inline uint headers_len();
+ inline gptr data(void);
+ inline Query_cache_query * query();
+ inline Query_cache_table * table();
+ inline Query_cache_result * result();
+ inline Query_cache_block_table * table(TABLE_COUNTER_TYPE n);
+};
+
+
+struct Query_cache_query
+{
+ ulonglong limit_found_rows;
+ Query_cache_block * res;
+ NET * wri;
+ ulong len;
+ sem_t lock; // R/W lock of block
+ pthread_mutex_t clients_guard;
+ uint clients;
+
+ inline void init_n_lock();
+ void unlock_n_destroy();
+ inline ulonglong found_rows() { return limit_found_rows; }
+ inline void found_rows(ulonglong rows) { limit_found_rows = rows; }
+ inline Query_cache_block * result() { return res; }
+ inline void result(Query_cache_block *p) { res=p; }
+ inline NET * writer() { return wri; }
+ inline void writer(NET *p) { wri=p; }
+ inline ulong length() { return len; }
+ inline ulong add(ulong packet_len) { return(len += packet_len); }
+ inline void length(ulong length) { len = length; }
+ inline gptr query()
+ {
+ return (gptr)(((byte*)this)+
+ ALIGN_SIZE(sizeof(Query_cache_query)));
+ }
+ void lock_writing();
+ void lock_reading();
+ my_bool try_lock_writing();
+ void unlock_writing();
+ void unlock_reading();
+ static byte * cache_key(const byte *record, uint *length,
+ my_bool not_used);
+ static void free_cache(void *entry);
+};
+
+
+struct Query_cache_table
+{
+ enum query_cache_table_type {OTHER=0, INNODB=1, TYPES_NUMBER=2};
+ inline static query_cache_table_type type_convertion(db_type type)
+ {
+ return (type == DB_TYPE_INNODB ? INNODB : OTHER);
+ }
+
+ char * tbl;
+ query_cache_table_type tp;
+
+ inline query_cache_table_type type() { return tp; }
+ inline void type(query_cache_table_type t) { tp = t;}
+ inline char * db() { return (char *) data(); }
+ inline char * table() { return tbl; }
+ inline void table(char * table) { tbl = table; }
+ inline gptr data()
+ {
+ return (gptr)(((byte*)this)+
+ ALIGN_SIZE(sizeof(Query_cache_table)));
+ }
+
+ static byte * cache_key(const byte *record, uint *length,
+ my_bool not_used);
+ static void free_cache(void *entry);
+};
+
+
+struct Query_cache_result
+{
+ Query_cache_block *query;
+
+ inline gptr data(){return (gptr)(((byte*)this)+
+ ALIGN_SIZE(sizeof(Query_cache_result)));}
+
+ /* data_continue (if not whole packet contained by this block) */
+ inline Query_cache_block * parent() { return query; }
+ inline void parent (Query_cache_block *p) { query=p; }
+};
+
+
+extern "C" {
+ void query_cache_insert(THD *thd, const char *packet, ulong length);
+ void query_cache_end_of_result(THD *thd);
+ void query_cache_abort(THD *thd);
+ void query_cache_invalidate_by_MyISAM_filename(char* filename);
+}
+
+struct Query_cache_memory_bin
+{
+#ifndef DBUG_OFF
+ ulong size;
+#endif
+ uint number;
+ Query_cache_block * free_blocks;
+
+ inline void init(ulong size)
+ {
+#ifndef DBUG_OFF
+ this->size = size;
+#endif
+ number = 0;
+ free_blocks = 0;
+ }
+};
+
+struct Query_cache_memory_bin_step
+{
+ ulong size;
+ ulong increment;
+ uint idx;
+ inline void init(ulong size, uint idx, ulong increment)
+ {
+ this->size = size;
+ this->idx = idx;
+ this->increment = increment;
+ }
+};
+
+class Query_cache
+{
+ protected:
+ byte * cache; // cache memory
+ Query_cache_block *first_block; // physical location block list
+ Query_cache_block *queries_blocks; // query list (LIFO)
+ Query_cache_block *tables_blocks[Query_cache_table::TYPES_NUMBER];
+
+ Query_cache_memory_bin * bins; // free block lists
+ Query_cache_memory_bin_step * steps; // bins spacing info
+ uint mem_bin_num, mem_bin_steps; // See at init_cache & find_bin
+
+ /* options */
+ ulong query_cache_size, query_cache_limit,
+ min_allocation_unit, min_result_data_size;
+ uint def_query_hash_size, def_table_hash_size;
+
+ /* statistics */
+public:
+ ulong free_memory, queries_in_cache, hits, inserts, refused;
+protected:
+ my_bool initialized;
+
+ /*
+ Locked when searched or changed global query or
+ tables lists or hashes. When operate inside
+ query structure locked own query block mutex
+ LOCK SEQUENCE (to prevent clinch):
+ 1. structure_guard_mutex
+ 2. query block / table block / free block
+ 3. results blocks (only when must become free).
+ */
+ pthread_mutex_t structure_guard_mutex;
+
+ HASH queries, tables;
+
+ /* Exclude/include from cyclic double linked list */
+ static void double_linked_list_exclude(Query_cache_block * point,
+ Query_cache_block * &list_pointer);
+ static void double_linked_list_simple_include(Query_cache_block * point,
+ Query_cache_block *
+ &list_pointer);
+ static void double_linked_list_join(Query_cache_block *head_tail,
+ Query_cache_block *tail_head);
+
+ /* Table key generation */
+ static uint filename_2_table_key (char * key, char *filename);
+
+ /* Following function work properly only when structure_guard_mutex locked */
+ void flush_cache();
+ my_bool free_old_query();
+ void free_query(Query_cache_block * point);
+ my_bool allocate_data_chain(Query_cache_block * &result_block,
+ ulong data_len,
+ Query_cache_block * query_block);
+ void invalidate_table(TABLE_LIST *table);
+ void invalidate_table(TABLE *table);
+ void invalidate_table_in_db(Query_cache_block *table_block,
+ char * db);
+ void invalidate_table(Query_cache_block *table_block);
+ my_bool register_all_tables(Query_cache_block * block,
+ TABLE_LIST * tables_used,
+ TABLE_COUNTER_TYPE tables);
+ my_bool insert_table(uint key_len, char * key,
+ Query_cache_block_table * node,
+ Query_cache_table::query_cache_table_type type);
+ void unlink_table(Query_cache_block_table * node);
+ Query_cache_block * get_free_block (ulong len, my_bool not_less,
+ ulong min);
+ void free_memory_block(Query_cache_block * point);
+ void split_block(Query_cache_block *block, ulong len);
+ Query_cache_block * join_free_blocks(Query_cache_block *first_block,
+ Query_cache_block * block_in_list);
+ my_bool append_next_free_block(Query_cache_block * block,
+ ulong add_size);
+ void exclude_from_free_memory_list(Query_cache_block * free_block);
+ void insert_into_free_memory_list(Query_cache_block * new_block);
+ my_bool move_by_type(byte * &border, Query_cache_block * &before,
+ ulong &gap, Query_cache_block * i);
+ uint find_bin(ulong size);
+ void move_to_query_list_end(Query_cache_block * block);
+ void insert_into_free_memory_sorted_list(Query_cache_block * new_block,
+ Query_cache_block * &list);
+ void pack_cache();
+ void relink(Query_cache_block * oblock,
+ Query_cache_block * nblock,
+ Query_cache_block * next,
+ Query_cache_block * prev,
+ Query_cache_block * pnext,
+ Query_cache_block * pprev);
+ my_bool join_results(ulong join_limit);
+
+ /*
+ Following function control structure_guard_mutex
+ by themself or don't need structure_guard_mutex
+ */
+ void init();
+ ulong init_cache();
+ void make_disabled();
+ void free_cache(my_bool destruction);
+ Query_cache_block * write_block_data(ulong data_len, gptr data,
+ ulong header_len,
+ Query_cache_block::block_type type,
+ TABLE_COUNTER_TYPE ntab = 0,
+ my_bool under_guard=0);
+ my_bool append_result_data(Query_cache_block * &result,
+ ulong data_len, gptr data,
+ Query_cache_block * parent,
+ Query_cache_block * first_data_block);
+ my_bool write_result_data(Query_cache_block * &result,
+ ulong data_len, gptr data,
+ Query_cache_block * parent,
+ Query_cache_block::block_type
+ type=Query_cache_block::RESULT);
+ Query_cache_block * allocate_block(ulong len, my_bool not_less,
+ ulong min,
+ my_bool under_guard=0);
+ /*
+ If query is cachable return numder tables in query
+ (query without tables not cached)
+ */
+ TABLE_COUNTER_TYPE is_cachable(THD *thd, uint query_len, char *query,
+ LEX *lex,
+ TABLE_LIST *tables_used);
+ public:
+
+ Query_cache(ulong query_cache_limit = ULONG_MAX,
+ ulong min_allocation_unit = QUERY_CACHE_MIN_ALLOCATION_UNIT,
+ ulong min_result_data_size = QUERY_CACHE_MIN_RESULT_DATA_SIZE,
+ uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE,
+ uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE
+ );
+
+ /* resize query cache (return real query size, 0 if disabled) */
+ ulong resize(ulong query_cache_size);
+ inline void result_size_limit(ulong limit){query_cache_limit=limit;}
+
+ /* register query in cache */
+ void store_query(THD *thd, TABLE_LIST *used_tables);
+
+ /*
+ Check if the query is in the cache and if this is true send the
+ data to client.
+ */
+ my_bool send_result_to_client(THD *thd, char *query, uint query_length);
+
+ /* Remove all queries that uses any of the listed following tables */
+ void invalidate(TABLE_LIST *tables_used);
+ void invalidate(TABLE *table);
+
+ /* Remove all queries that uses tables of pointed type*/
+ void invalidate(Query_cache_table::query_cache_table_type type);
+
+ /* Remove all queries that uses any of the tables in following database */
+ void invalidate(char * db);
+
+ /* Remove all queries that uses any of the listed following table */
+ void invalidate_by_MyISAM_filename(char * filename);
+
+ /* Remove all queries from cache */
+ void flush();
+
+ /* Join result in cache in 1 block (if result length > join_limit) */
+ void pack(ulong join_limit = QUERY_CACHE_PACK_LIMIT,
+ uint iteration_limit = QUERY_CACHE_PACK_ITERATION);
+
+ void destroy();
+
+#ifndef DBUG_OFF
+ void wreck(uint line, const char * message);
+ void bins_dump();
+ void cache_dump();
+ void queries_dump();
+ void tables_dump();
+#endif
+ friend void query_cache_insert(NET *net, const char *packet, ulong length);
+ friend void query_cache_end_of_result(NET *net);
+ friend void query_cache_abort(NET *net);
+};
+
+extern Query_cache query_cache;
+
+#endif