From 47d85d7b90ebb19b4eb63467d8c87d40241d3244 Mon Sep 17 00:00:00 2001 From: Toshihiro Kitagawa Date: Wed, 30 Jun 2010 00:31:55 +0000 Subject: [PATCH] Add structures: PreparedStatement, Portal, PreparedStatementList and PortalList. Add functions to operate these structures. --- pool_session_context.c | 492 +++++++++++++++++++++++++++++++++++++++++ pool_session_context.h | 65 +++++- 2 files changed, 549 insertions(+), 8 deletions(-) diff --git a/pool_session_context.c b/pool_session_context.c index 7f5188590..6f20e07d8 100644 --- a/pool_session_context.c +++ b/pool_session_context.c @@ -20,6 +20,9 @@ * is" without express or implied warranty. * */ +#include +#include +#include #include "pool.h" #include "pool_config.h" @@ -28,6 +31,44 @@ static POOL_SESSION_CONTEXT session_context_d; static POOL_SESSION_CONTEXT *session_context; +/* + * Initialize prepared statement list + */ +static void init_prepared_statement_list(void) +{ + PreparedStatementList *pslist = NULL; + + session_context->pstmt_list = malloc(sizeof(PreparedStatementList)); + pslist = session_context->pstmt_list; + pslist->pstmts = malloc(sizeof(PreparedStatement *) * INIT_LIST_SIZE); + if (pslist == NULL || pslist->pstmts == NULL) + { + pool_error("init_prepared_statement_list: malloc failed: %s", strerror(errno)); + exit(1); + } + pslist->size = 0; + pslist->capacity = INIT_LIST_SIZE; +} + +/* + * Initialize portal list + */ +static void init_portal_list(void) +{ + PortalList *plist; + + session_context->portal_list = malloc(sizeof(PortalList)); + plist = session_context->portal_list; + plist->portals = malloc(sizeof(Portal *) * INIT_LIST_SIZE); + if (plist == NULL || plist->portals == NULL) + { + pool_error("init_portal_list: malloc failed: %s", strerror(errno)); + exit(1); + } + plist->size = 0; + plist->capacity = INIT_LIST_SIZE; +} + /* * Initialize per session context */ @@ -53,6 +94,15 @@ void pool_init_session_context(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL * /* Initialize transaction state to idle */ session_context->transaction_state = 'I'; + /* Initialize prepared statement list */ + init_prepared_statement_list(); + + /* Initialize portal list */ + init_portal_list(); + + /* Create memory context */ + session_context->memory_context = pool_memory_create(PREPARE_BLOCK_SIZE); + /* Choose load balancing node if neccessary */ if (pool_config->load_balance_mode) { @@ -139,3 +189,445 @@ void pool_unset_query_in_progress(void) session_context->in_progress = false; } + +/* + * Remove a portal by portal name + */ +static void pool_remove_portal_by_portal_name(const char *name) +{ + int i; + PortalList *plist; + + if (*name == '\0') + { + if (session_context->unnamed_portal) + { + pool_memory_free(session_context->memory_context, + session_context->unnamed_portal); + session_context->unnamed_portal = NULL; + } + return; + } + + plist = session_context->portal_list; + + for (i = 0; i < plist->size; i++) + { + if (strcmp(plist->portals[i]->name, name) == 0) + { + pool_memory_free(session_context->memory_context, plist->portals[i]); + break; + } + } + + /* portal not found */ + if (i == plist->size) + return; + + if (i != plist->size - 1) + { + memmove(&plist->portals[i], &plist->portals[i+1], + sizeof(Portal *) * (plist->size - i - 1)); + } + plist->size--; +} + +/* + * Remove portals by prepared statement name + * prepared statement : portal = 1 : N + */ +static void pool_remove_portal_by_pstmt_name(const char *name) +{ + int i; + PortalList *plist; + + if (*name == '\0') + { + if (session_context->unnamed_portal) + { + pool_memory_free(session_context->memory_context, + session_context->unnamed_portal); + session_context->unnamed_portal = NULL; + } + return; + } + + plist = session_context->portal_list; + + for (i = 0; i < plist->size; i++) + { + if (strcmp(plist->portals[i]->pstmt->name, name) == 0) + pool_remove_portal_by_portal_name(plist->portals[i]->name); + } +} + +/* + * Remove a prepared statement by prepared statement name + */ +void pool_remove_prepared_statement_by_pstmt_name(const char *name) +{ + int i; + PreparedStatementList *pslist; + + if (!session_context) + { + pool_error("pool_remove_prepared_statement_by_pstmt_name: session context is not initialized"); + return; + } + + if (*name == '\0') + { + if (session_context->unnamed_pstmt) + { + pool_query_context_destroy(session_context->unnamed_pstmt->qctxt); + pool_memory_free(session_context->memory_context, + session_context->unnamed_pstmt); + session_context->unnamed_pstmt = NULL; + } + return; + } + + pslist = session_context->pstmt_list; + + for (i = 0; i < pslist->size; i++) + { + if (strcmp(pslist->pstmts[i]->name, name) == 0) + { + pool_query_context_destroy(pslist->pstmts[i]->qctxt); + pool_memory_free(session_context->memory_context, pslist->pstmts[i]); + break; + } + } + + /* prepared statement not found */ + if (i == pslist->size) + return; + + if (i != pslist->size - 1) + { + memmove(&pslist->pstmts[i], &pslist->pstmts[i+1], + sizeof(PreparedStatement *) * (pslist->size - i - 1)); + } + pslist->size--; + + pool_remove_portal_by_pstmt_name(name); +} + +/* + * Remove a pending prepared statement from prepared statement list + */ +void pool_remove_prepared_statement(void) +{ + char *name; + + if (!session_context) + { + pool_error("pool_remove_prepared_statement: session context is not initialized"); + return; + } + + if (session_context->pending_pstmt) + { + name = session_context->pending_pstmt->name; + pool_remove_prepared_statement_by_pstmt_name(name); + } + else + { + pool_error("pool_remove_prepared_statement: pending prepared statement is NULL"); + } +} + + +/* + * Remove a pending portal from portal list + */ +void pool_remove_portal(void) +{ + char *name; + + if (!session_context) + { + pool_error("pool_remove_portal: session context is not initialized"); + return; + } + + if (session_context->pending_portal) + { + name = session_context->pending_portal->name; + pool_remove_portal_by_portal_name(name); + } +} + +/* + * Remove pending objects + */ +void pool_remove_pending_objects(void) +{ + PreparedStatement *ps; + Portal *p; + + ps = session_context->pending_pstmt; + + if (ps && ps->name) + pool_memory_free(session_context->memory_context, ps->name); + + if (ps && ps->qctxt) + pool_query_context_destroy(ps->qctxt); + + if (ps) + pool_memory_free(session_context->memory_context, ps); + + p = session_context->pending_portal; + + if (p && p->name) + pool_memory_free(session_context->memory_context, p->name); + + if (p && p->pstmt) + pool_memory_free(session_context->memory_context, p->pstmt); + + if (p) + pool_memory_free(session_context->memory_context, p); + + session_context->pending_pstmt = NULL; + session_context->pending_portal = NULL; + session_context->pending_function = NULL; +} + +/* + * Clear prepared statement list and portal list + */ +void pool_clear_prepared_statement_list(void) +{ + int i; + PreparedStatementList *pslist; + + if (!session_context) + { + pool_error("pool_clear_prepared_statement_list: session context is not initialized"); + return; + } + + pslist = session_context->pstmt_list; + + for (i = 0; i < pslist->size; i++) + { + pool_remove_prepared_statement_by_pstmt_name(pslist->pstmts[i]->name); + } +} + +/* + * Create a prepared statement + */ +void *pool_create_prepared_statement(const char *name, int num_tsparams, POOL_QUERY_CONTEXT *qc) +{ + PreparedStatement *ps; + + if (!session_context) + { + pool_error("pool_create_prepared_statement: session context is not initialized"); + return NULL; + } + + ps = pool_memory_alloc(session_context->memory_context, + sizeof(PreparedStatement)); + ps->name = pool_memory_strdup(session_context->memory_context, name); + ps->num_tsparams = num_tsparams; + ps->qctxt = qc; + + return ps; +} + +/* + * Create a portal + */ +void *pool_create_portal(const char *name, int num_tsparams, PreparedStatement *pstmt) +{ + Portal *portal; + + if (!session_context) + { + pool_error("pool_create_portal: session context is not initialized"); + return NULL; + } + + portal = pool_memory_alloc(session_context->memory_context, sizeof(Portal)); + portal->name = pool_memory_strdup(session_context->memory_context, name); + portal->num_tsparams = num_tsparams; + portal->pstmt = pstmt; + + return portal; +} + +/* + * Add a prepared statement to prepared statement list + */ +void pool_add_prepared_statement(void) +{ + PreparedStatement *ps; + PreparedStatementList *pslist; + + if (!session_context) + { + pool_error("pool_add_prepared_statement: session context is not initialized"); + return; + } + + if (!session_context->pending_pstmt) + { + pool_error("pool_add_prepared_statement: pending prepared statement is NULL"); + return; + } + + ps = pool_get_prepared_statement_by_pstmt_name(session_context->pending_pstmt->name); + pslist = session_context->pstmt_list; + + if (ps) + { + pool_remove_prepared_statement_by_pstmt_name(ps->name); + if (*session_context->pending_pstmt->name == '\0') + { + session_context->unnamed_pstmt = session_context->pending_pstmt; + } + else + { + pool_error("pool_add_prepared_statement: prepared statement \"%s\" already exists", + session_context->pending_pstmt->name); + } + } + else + { + if (*session_context->pending_pstmt->name == '\0') + { + session_context->unnamed_pstmt = session_context->pending_pstmt; + } + else + { + if (pslist->size == pslist->capacity) + { + pslist->capacity *= 2; + pslist->pstmts = realloc(pslist->pstmts, sizeof(PreparedStatement *) * pslist->capacity); + if (pslist->pstmts == NULL) + { + pool_error("pool_add_prepared_statement: realloc failed: %s", strerror(errno)); + exit(1); + } + } + pslist->pstmts[pslist->size++] = session_context->pending_pstmt; + } + } +} + +/* + * Add a portal to portal list + */ +void pool_add_portal(void) +{ + Portal *p; + PortalList *plist; + + if (!session_context) + { + pool_error("pool_add_portal: session context is not initialized"); + return; + } + + if (!session_context->pending_portal) + { + pool_error("pool_add_portal: pending portal is NULL"); + return; + } + + p = pool_get_portal_by_portal_name(session_context->pending_portal->name); + plist = session_context->portal_list; + + if (p) + { + pool_remove_portal_by_portal_name(p->name); + if (*session_context->pending_portal->name == '\0') + { + session_context->unnamed_portal = session_context->pending_portal; + } + else + { + pool_error("pool_add_portal: portal \"%s\" already exists", + session_context->pending_portal->name); + } + } + else + { + if (*session_context->pending_portal->name == '\0') + { + session_context->unnamed_portal = session_context->pending_portal; + } + else + { + if (plist->size == plist->capacity) + { + plist->capacity *= 2; + plist->portals = realloc(plist->portals, sizeof(Portal *) * plist->capacity); + if (plist->portals == NULL) + { + pool_error("pool_add_portal: realloc failed: %s", strerror(errno)); + exit(1); + } + } + plist->portals[plist->size++] = session_context->pending_portal; + } + } +} + +/* + * Get a prepared statement by prepared statement name + */ +PreparedStatement *pool_get_prepared_statement_by_pstmt_name(const char *name) +{ + int i; + PreparedStatementList *pslist; + + if (!session_context) + { + pool_error("pool_get_prepared_statement_by_pstmt_name: session context is not initialized"); + return NULL; + } + + if (*name == '\0') + return session_context->unnamed_pstmt; + + pslist = session_context->pstmt_list; + + for (i = 0; i < pslist->size; i++) + { + if (strcmp(pslist->pstmts[i]->name, name) == 0) + return pslist->pstmts[i]; + } + + return NULL; +} + +/* + * Get a portal by portal name + */ +Portal *pool_get_portal_by_portal_name(const char *name) +{ + int i; + PortalList *plist; + + if (!session_context) + { + pool_error("pool_get_portal_by_portal_name: session context is not initialized"); + return NULL; + } + + if (*name == '\0') + return session_context->unnamed_portal; + + plist = session_context->portal_list; + + for (i = 0; i < plist->size; i++) + { + if (strcmp(plist->portals[i]->name, name) == 0) + return plist->portals[i]; + } + + return NULL; +} diff --git a/pool_session_context.h b/pool_session_context.h index c64ef0c97..e3f4a36d4 100644 --- a/pool_session_context.h +++ b/pool_session_context.h @@ -25,11 +25,49 @@ #ifndef POOL_SESSION_CONTEXT_H #define POOL_SESSION_CONTEXT_H +#define INIT_LIST_SIZE 8 #include "pool.h" #include "pool_process_context.h" #include "pool_session_context.h" #include "pool_query_context.h" +#include "parser/pool_memory.h" + +/* + * Prepared Statement: + */ +typedef struct { + char *name; /* prepared statement name */ + int num_tsparams; + POOL_QUERY_CONTEXT *qctxt; +} PreparedStatement; + +/* + * Prepared statement list: + */ +typedef struct { + int capacity; /* capacity of list */ + int size; /* number of PreparedStatement */ + PreparedStatement **pstmts; /* prepared statement list */ +} PreparedStatementList; + +/* + * Portal: + */ +typedef struct { + char *name; /* portal name */ + int num_tsparams; + PreparedStatement *pstmt; +} Portal; + +/* + * Portal list: + */ +typedef struct { + int capacity; /* capacity of list */ + int size; /* number of portal */ + Portal **portals; /* portal list */ +} PortalList; /* * Per session context: @@ -44,6 +82,14 @@ typedef struct { * all responses are returned from backend */ POOL_QUERY_CONTEXT *query_context; /* associated query context */ + POOL_MEMORY_POOL *memory_context; /* memory context for session */ + PreparedStatement *unnamed_pstmt; /* unnamed statement */ + PreparedStatement *pending_pstmt; /* used until receive backend response */ + Portal *unnamed_portal; /* unnamed portal */ + Portal *pending_portal; /* used until receive backend response */ + PreparedStatementList *pstmt_list; /* named statement list */ + PortalList *portal_list; /* named portal list */ + void (*pending_function)(void); /* switched function by backend response */ int load_balance_node_id; /* selected load balance node id */ #ifdef NOT_USED @@ -58,10 +104,6 @@ typedef struct { char *copy_schema = NULL; /* copy table name */ char copy_delimiter; /* copy delimiter char */ char *copy_null = NULL; /* copy null string */ - void (*pending_function)(PreparedStatementList *p, Portal *portal) = NULL; - Portal *pending_prepared_portal = NULL; - Portal *unnamed_statement = NULL; - Portal *unnamed_portal = NULL; int select_in_transaction = 0; /* non 0 if select query is in transaction */ int execute_select = 0; /* non 0 if select query is in transaction */ @@ -99,10 +141,6 @@ typedef struct { bool send_ready_for_query; /* ok to send ReadyForQuery */ bool igore_till_sync; /* ignore any command until Sync message */ LOAD_BALANCE_STATUS load_balance_status[MAX_NUM_BACKENDS]; /* to remember which DB node is selected for load balancing */ - /* unnamed statement */ - /* unnamed portal */ - /* named statement list */ - /* named portal list */ #endif } POOL_SESSION_CONTEXT; @@ -113,5 +151,16 @@ extern int pool_get_local_session_id(void); extern bool pool_is_query_in_progress(void); extern void pool_set_query_in_progress(void); extern void pool_unset_query_in_progress(void); +extern void pool_remove_prepared_statement_by_pstmt_name(const char *name); +extern void pool_remove_prepared_statement(void); +extern void pool_remove_portal(void); +extern void pool_remove_pending_objects(void); +extern void pool_clear_prepared_statement_list(void); +extern void *pool_create_prepared_statement(const char *name, int num_tsparams, POOL_QUERY_CONTEXT *qc); +extern void *pool_create_portal(const char *name, int num_tsparams, PreparedStatement *pstmt); +extern void pool_add_prepared_statement(void); +extern void pool_add_portal(void); +extern PreparedStatement *pool_get_prepared_statement_by_pstmt_name(const char *name); +extern Portal *pool_get_portal_by_portal_name(const char *name); #endif /* POOL_SESSION_CONTEXT_H */ -- 2.39.5