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]