pgpool2.git / summary / log / commit / refs

commit    9910020dda1ccfa7b6e96893b0b008b13296fd41
Author:   Nozomi Anzai <anzai@sraoss.co.jp>
Date:     Fri Apr 27 07:55:10 2012 +0000

    Fix memqcache to recognize extended query.
    - In Parse() set flag that the extended query is cache safe or not.
    - In Bind() save the offset of a bind message contents in which are
      portal name, prepared statement's name, params count, etc.
    - In Execute() try to fetch its result from caches.
    - In ReadyForQuery() save its result into cache.


pool_memqcache.c | 28 +++++++---- pool_proto_modules.c | 130 +++++++++++++++++++++++++++++++++++++++++++++------ pool_query_context.h | 1 + 3 files changed, 138 insertions(+), 21 deletions(-) diff --git a/pool_memqcache.c b/pool_memqcache.c index 8e17e7f5f..c5d51960e 100644 --- a/pool_memqcache.c +++ b/pool_memqcache.c @@ -1,3 +1,4 @@ +#define DEBUG /* -*-pgsql-c-*- */ /* * pgpool: a language independent connection pool server for PostgreSQL @@ -463,6 +464,7 @@ static int send_cached_messages(POOL_CONNECTION *frontend, const char *qcache, i char tmpbuf[MAX_VALUE]; tmpkind = qcache[i]; + i += 1; memcpy(&tmplen, qcache+i, sizeof(tmplen)); @@ -490,6 +492,7 @@ static int send_cached_messages(POOL_CONNECTION *frontend, const char *qcache, i } /* send message to frontend */ + pool_log("send_cached_messages: %c len: %d", tmpkind, tmplen); send_message(frontend, tmpkind, tmplen, tmpbuf); msg++; @@ -1389,13 +1392,22 @@ static void pool_reset_memqcache_buffer(void) pool_discard_query_cache_array(session_context->query_cache_array); session_context->query_cache_array = pool_create_query_cache_array(); - cache = pool_get_current_cache(); - pool_discard_temp_query_cache(cache); /* - * Reset temp_cache pointer in the current query context - * so that we don't double free memory. + * if the query context is still under use, we cannot discard + * temporary cache. */ - session_context->query_context->temp_cache = NULL; + if (can_query_context_destroy(session_context->query_context)) + { + pool_debug("pool_reset_memqcache_buffer: discard temp buffer of %p (%s)", + session_context->query_context, session_context->query_context->original_query); + cache = pool_get_current_cache(); + pool_discard_temp_query_cache(cache); + /* + * Reset temp_cache pointer in the current query context + * so that we don't double free memory. + */ + session_context->query_context->temp_cache = NULL; + } } pool_discard_dml_table_oid(); pool_tmp_stats_reset_num_selects(); @@ -2456,10 +2468,10 @@ static void pool_add_temp_query_cache(POOL_TEMP_QUERY_CACHE *temp_cache, char ki } /* - * We only store T(Table Description), D(Data row), C(Command - * Complete) + * We only store T(Table Description), D(Data row), C(Command Complete), + * 1(ParseComplete), 2(BindComplete) */ - if (kind != 'T' && kind != 'D' && kind != 'C') + if (kind != 'T' && kind != 'D' && kind != 'C' && kind != '1' && kind != '2') { return; } diff --git a/pool_proto_modules.c b/pool_proto_modules.c index de1452d83..25c59b7a2 100644 --- a/pool_proto_modules.c +++ b/pool_proto_modules.c @@ -624,7 +624,7 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, int specific_error = 0; POOL_SESSION_CONTEXT *session_context; POOL_QUERY_CONTEXT *query_context; - POOL_SENT_MESSAGE *msg; + POOL_SENT_MESSAGE *bind_msg; /* Get session context */ session_context = pool_get_session_context(); @@ -636,32 +636,33 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, pool_debug("Execute: portal name <%s>", contents); - msg = pool_get_sent_message('B', contents); - if (!msg) + bind_msg = pool_get_sent_message('B', contents); + if (!bind_msg) { pool_error("Execute: cannot get bind message"); return POOL_END; } - if(!msg->query_context) + if(!bind_msg->query_context) { pool_error("Execute: cannot get query context"); return POOL_END; } - if (!msg->query_context->original_query) + if (!bind_msg->query_context->original_query) { pool_error("Execute: cannot get original query"); return POOL_END; } - if (!msg->query_context->parse_tree) + if (!bind_msg->query_context->parse_tree) { pool_error("Execute: cannot get parse tree"); return POOL_END; } - query_context = msg->query_context; - node = msg->query_context->parse_tree; - query = msg->query_context->original_query; + query_context = bind_msg->query_context; + node = bind_msg->query_context->parse_tree; + query = bind_msg->query_context->original_query; pool_debug("Execute: query: %s", query); + strlcpy(query_string_buffer, query, sizeof(query_string_buffer)); pool_debug("Execute: query string = <%s>", query); @@ -673,8 +674,50 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, { bool foundp; POOL_STATUS status; + char *search_query = NULL; - status = pool_fetch_from_memory_cache(frontend,backend, query, &foundp); + search_query = (char *)malloc(sizeof(char) * strlen(query) + 1); + if (search_query == NULL) + { + return POOL_END; + } + strcpy(search_query, query); + + /* + * Add bind message's info to query to search. + */ + if (bind_msg->param_offset && bind_msg->contents) + { + /* Extract binary contents from bind message */ + char *query_in_bind_msg = bind_msg->contents + bind_msg->param_offset; + char hex_str[4]; // 02X chars + white space + null end + int max_search_query_size = 0; + int i = 0; + char *tmp; + + for (i = 0; i < bind_msg->len - bind_msg->param_offset; i++) + { + while (max_search_query_size <= sizeof(char) * strlen(search_query)) + { + max_search_query_size += 1024; + tmp =(char *)realloc(search_query, sizeof(char) * max_search_query_size); + if (tmp == NULL) + { + return POOL_END; + } + search_query = tmp; + tmp = NULL; + } + + sprintf(hex_str, (i == 0) ? " %02X" : "%02X", (unsigned int)query_in_bind_msg[i]); + strcat(search_query, hex_str); + } + + query_context->query_w_hex = search_query; + } + + /* If the query is SELECT from table to cache, try to fetch cached result. */ + status = pool_fetch_from_memory_cache(frontend, backend, search_query, &foundp); if (status != POOL_CONTINUE) return status; @@ -710,7 +753,6 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, return POOL_END; } - /* Check specific errors */ specific_error = check_errors(backend, MASTER_NODE_ID); if (specific_error) @@ -860,6 +902,52 @@ POOL_STATUS Parse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, return POOL_END; } + /* + * If the table is to be cached, set is_cache_safe TRUE and register table oids. + */ + if (pool_config->memory_cache_enabled) + { + bool is_likely_select = false; + bool is_select_query = false; + int num_oids; + int *oids; + int i; + + /* Check if the query is actually SELECT */ + is_likely_select = pool_is_likely_select(query_context->original_query); + if (is_likely_select && IsA(node, SelectStmt)) + { + is_select_query = true; + } + + /* Switch the flag of is_cache_safe in session_context */ + if (is_select_query && + pool_is_allow_to_cache(query_context->parse_tree, + query_context->original_query)) + { + pool_set_cache_safe(); + } + else + { + pool_unset_cache_safe(); + } + + /* If table is to be cached and the query is DML, save the table oid */ + if (!is_select_query) + { + num_oids = pool_extract_table_oids(node, &oids); + + if (num_oids > 0) + { + /* Save to oid buffer */ + for (i=0;i<num_oids;i++) + { + pool_add_dml_table_oid(oids[i]); + } + } + } + } + /* * Decide where to send query */ @@ -1117,6 +1205,14 @@ POOL_STATUS Bind(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, return POOL_END; } + /* + * If the query can ce cached, save its offset of query text in bind message's content. + */ + if (query_context->is_cache_safe) + { + bind_msg->param_offset = sizeof(int) + sizeof(char) * (strlen(portal_name) + strlen(pstmt_name)); + } + session_context->uncompleted_message = bind_msg; /* rewrite bind message */ @@ -1133,7 +1229,7 @@ POOL_STATUS Bind(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, if (pool_config->load_balance_mode && pool_is_writing_transaction()) { - if(parse_before_bind(frontend, backend, parse_msg) != POOL_CONTINUE) + if (parse_before_bind(frontend, backend, parse_msg) != POOL_CONTINUE) return POOL_END; } @@ -1568,7 +1664,15 @@ POOL_STATUS ReadyForQuery(POOL_CONNECTION *frontend, /* Memory cache enabled? */ if (pool_config->memory_cache_enabled) { - pool_handle_query_cache(backend, query, node, state); + if (pool_is_doing_extended_query_message()) + { + pool_handle_query_cache(backend, session_context->query_context->query_w_hex, node, state); + free(session_context->query_context->query_w_hex); // malloced in Execute(). + } + else + { + pool_handle_query_cache(backend, query, node, state); + } } } /* diff --git a/pool_query_context.h b/pool_query_context.h index b4ea397f2..6f6e99a45 100644 --- a/pool_query_context.h +++ b/pool_query_context.h @@ -64,6 +64,7 @@ typedef struct { POOL_TEMP_QUERY_CACHE *temp_cache; /* temporary cache */ bool is_multi_statement; /* true if multi statement query */ int dboid; /* DB oid which is used at DROP DATABASE */ + char *query_w_hex; /* original_query with bind message hex which used for committing cache of extended query */ } POOL_QUERY_CONTEXT; extern POOL_QUERY_CONTEXT *pool_init_query_context(void); [parent: a5af7bd88174]