#ifndef _QUERYCACHE_H_ #define _QUERYCACHE_H_ /*------------------------------------------------------------------------- * * querycache.h * Query Cache for PostgreSQL * * License Free *------------------------------------------------------------------------- */ #ifndef _UNIT_TEST_ #include "postgres.h" #include "storage/shmem.h" #include "libpq/pqcomm.h" #else typedef unsigned int Oid; typedef char bool; #define true ((bool) 1) #define false ((bool) 0) #include #include #include #include #endif #include #include #include #ifndef offsetof #define offsetof(type, mem) ((size_t) \ ((char *)&((type *)0)->mem - (char *)(type *)0)) #endif /*============================================ * constant declaration /===========================================*/ /* Choose prime number. */ #define HASH_SIZE 509 #define PQ_QUERY_LEN 512 #define MAX_QUERY_LEN PQ_QUERY_LEN #define PQ_BUFFER_SIZE 8192 #define Nil 0 #define MAX_OID 32 #define MAX_DATA 30 /* PQ_BUFFER_PAR_QBLOCK_DATA = 1 or 2 or 4 or 8 */ #define PQ_BUFFER_PAR_QBLOCK_DATA 2 #define QBLOCK_DATA_SIZE PQ_BUFFER_SIZE / PQ_BUFFER_PAR_QBLOCK_DATA #define PQ_USER_NAME_LEN 64 #define PQ_DB_NAME_LEN 64 #ifdef _UNIT_TEST_ #define MAX_OBLOCKS 4096 #define MAX_QBLOCKS 2048 #define MAX_TOTAL_DATA 10 #endif /*============================================ * data structure declaration /===========================================*/ typedef unsigned int hkey; /* hash key */ typedef unsigned int bid; /* block id */ typedef struct QueryCache_Header QueryCache_Header; /* */ typedef struct hash_tbl hash_tbl; /* */ typedef struct oblock oblock; /* Element of Table QueryCache Shmem Space */ typedef struct qblock qblock; /* Element of Query QueryCache Shmem Space */ typedef struct qc_space_header qc_space_header; /*-------------------------------------------- * query cache header (postmaster) /-------------------------------------------*/ struct hash_tbl { int num; /* */ bid next; /* */ }; struct qc_space_header { bid block_num; /* the number of blocks which are used. */ bid max_block_num; /* the number of blocks which it prepares. */ hash_tbl ht[HASH_SIZE]; /* hash table. */ bid next_free_block; /* link to the next free block. */ /* if (bid)Nil is that there is not free blocks. */ }; struct QueryCache_Header { /* * */ unsigned long int qc_all_query; /* Number of all queries, include delete, update, insert ... */ unsigned long int qc_store; /* Number of select queries which are stored data to the cache. */ unsigned long int qc_not_cached; unsigned long int qc_hits; /* Number of select queries which hit to data on the cache. */ /* * */ qc_space_header qc_oid_space; /* QueryCache Table Shmem Space Section */ qc_space_header qc_query_space; /* QueryCache Query Shmem Space Section */ }; /*-------------------------------------------- * table / query qc_space (postmaster) /-------------------------------------------*/ typedef enum { FREE, /* 0: Free block */ /* QueryCache Table Shmem Space */ TID, /* 1: */ TQID, /* 2: */ /* QueryCache Query Shmem Space */ QID, /* 3: Query */ DID /* 4: Data */ } block_type; /*------------------------- * table qc_space (postmaster) /------------------------*/ struct oblock { // bid toid; /* virtual index */ block_type type; /* */ union data { struct Tid { /* */ Oid oid; /* relation ( = table ) number of PostgreSQL. */ } tid; struct TQid { /* */ hkey key; /* to search for query_qc_space. */ bid tqid; /* link to query id at query_qc_space. */ bid prev, next; } qid; }; bid prev, next; /* for Free Block List */ }; #define offset_oblock_type offsetof (oblock, type) #define offset_oblock_tid_oid offsetof (oblock, tid.oid) #define offset_oblock_qid_key offsetof (oblock, qid.key) #define offset_oblock_qid_tqid offsetof (oblock, qid.tqid) #define offset_oblock_qid_prev offsetof (oblock, qid.prev) #define offset_oblock_qid_next offsetof (oblock, qid.next) #define offset_oblock_prev offsetof (oblock, prev) #define offset_oblock_next offsetof (oblock, next) /*------------------------- * query qc_space (postmaster) /------------------------*/ typedef enum query_atr { QC_QATR_NORMAL, /* 0: Normal query */ QC_QATR_HUGE /* 1: Result was Too Huge */ } query_atr; struct qblock { // bid qid; /* virtual index */ block_type type; /* */ union unit { struct Qid { hkey key; /* */ unsigned char query[PQ_QUERY_LEN]; query_atr attr; /* */ char user_name[PQ_USER_NAME_LEN]; /* */ char db_name[PQ_DB_NAME_LEN]; /* */ bid toid[MAX_OID]; /* */ bid tqid[MAX_OID]; /* */ int tid_num; /* */ int data_num; bid next; bid last; } qid; struct Did { unsigned char data[QBLOCK_DATA_SIZE]; int data_len; bid next; } did; }; bid prev, next; /* */ }; #define offset_qblock_type offsetof (qblock, type) #define offset_qblock_qid_key offsetof (qblock, qid.key) #define offset_qblock_qid_query offsetof (qblock, qid.query) #define offset_qblock_qid_attr offsetof (qblock, qid.attr) #define offset_qblock_qid_user_name offsetof (qblock, qid.user_name) #define offset_qblock_qid_db_name offsetof (qblock, qid.db_name) #define offset_qblock_qid_toid offsetof (qblock, qid.toid) #define offset_qblock_qid_tqid offsetof (qblock, qid.tqid) #define offset_qblock_qid_tid_num offsetof (qblock, qid.tid_num) #define offset_qblock_qid_data_num offsetof (qblock, qid.data_num) #define offset_qblock_qid_next offsetof (qblock, qid.next) #define offset_qblock_qid_last offsetof (qblock, qid.last) #define offset_qblock_did_data offsetof (qblock, did.data) #define offset_qblock_did_data_len offsetof (qblock, did.data_len) #define offset_qblock_did_next offsetof (qblock, did.next) #define offset_qblock_prev offsetof (qblock, prev) #define offset_qblock_next offsetof (qblock, next) /*-------------------------------------------- * current_query (postgres) /-------------------------------------------*/ typedef enum query_cond { QC_NULL, /* 0: null */ QC_STORE_DATA, /* 1: SELECT and No-Cahce */ QC_SEND_CACHE, /* 2: SELECT and Cached */ QC_DELETE_CACHE, /* 3: Drop Cache Data */ QC_THROUGH, /* 4: Drop Cache Data */ QC_END, /* 5: */ QC_INVALID, /* 6: Query Cache InValisd */ QC_TOO_HUGE, /* 7: Result is Too Huge */ QC_NO_CACHE, /* 8: Don't cache! */ QC_COMMIT /* 9: Transaction -> COMMIT */ } query_cond; typedef struct data_cell { int data_num; unsigned char data[MAX_DATA][PQ_BUFFER_SIZE]; int data_len[MAX_DATA]; struct data_cell *next; } data_cell; typedef struct query { bid qid; /* query string section */ hkey key; unsigned char query_string[PQ_QUERY_LEN]; char commandTag[32]; char user_name[PQ_USER_NAME_LEN]; char db_name[PQ_DB_NAME_LEN]; /* codition */ query_cond cond; /* attribute */ query_atr attr; /* related tables */ Oid oid[MAX_OID]; int oid_num; /* result data section */ int total_data_num; struct data_cell *next; struct data_cell *last; } query; /*-------------------------------------------- * (postgres) /-------------------------------------------*/ struct oid_cell oid_cell; struct oid_cell { Oid oid; struct oid_cell *next; } oid_cell; typedef struct Tx_info { struct oid_cell *next; } Tx_info; /*============================================ * Prototype declaration /===========================================*/ /* */ int QueryCacheShmemSize (void); void InitQueryCacheShmem(void); /* */ void qc_init (void); void qc_reset (void); /* */ bool qc_check_query (const char *commandTag, const char *query_string); bool qc_operate_cache (void); /* */ bool qc_set_oid (Oid oid); /* */ enum query_cond qc_get_cond_from_current_query (void); bid qc_get_qid_from_current_query (void); /* */ bool qc_set_data (bid qid, const unsigned char *data, int len); int qc_get_data (bid qid, unsigned char *data); void qc_get_data_from_buffer_to_current_query (const unsigned char *data, int len); /* */ void _check_query_cache (const char *statement); #ifndef _UNIT_TEST_ /* for debug */ /* original -> libpq/pqcomm.c */ int qc_pq_flush (const unsigned char *data, int len); int pq_flush (void); #endif #endif //EOF