1 /* -*-pgsql-c-*- */
2 /*
3  *
4  * $Header$
5  *
6  * pgpool: a language independent connection pool server for PostgreSQL
7  * written by Tatsuo Ishii
8  *
9  * Copyright (c) 2003-2019	PgPool Global Development Group
10  *
11  * Permission to use, copy, modify, and distribute this software and
12  * its documentation for any purpose and without fee is hereby
13  * granted, provided that the above copyright notice appear in all
14  * copies and that both that copyright notice and this permission
15  * notice appear in supporting documentation, and that the name of the
16  * author not be used in advertising or publicity pertaining to
17  * distribution of the software without specific, written prior
18  * permission. The author makes no representations about the
19  * suitability of this software for any purpose.  It is provided "as
20  * is" without express or implied warranty.
21  *
22  * pool_process_context.h.: process context information
23  *
24  */
25 
26 #ifndef POOL_SESSION_CONTEXT_H
27 #define POOL_SESSION_CONTEXT_H
28 #define INIT_LIST_SIZE 8
29 
30 #include "pool.h"
31 #include "pool_process_context.h"
32 #include "pool_session_context.h"
33 #include "pool_query_context.h"
34 #include "query_cache/pool_memqcache.h"
35 
36 /*
37  * Transaction isolation mode
38  */
39 typedef enum
40 {
41 	POOL_UNKNOWN,				/* Unknown. Need to ask backend */
42 	POOL_READ_UNCOMMITTED,		/* Read uncommitted */
43 	POOL_READ_COMMITTED,		/* Read committed */
44 	POOL_REPEATABLE_READ,		/* Rpeatable read */
45 	POOL_SERIALIZABLE			/* Serializable */
46 }			POOL_TRANSACTION_ISOLATION;
47 
48 /*
49  * Return values for pool_use_sync_map
50  */
51 typedef enum
52 {
53 	POOL_IGNORE_SYNC_MAP,		/* Please ignore sync map */
54 	POOL_SYNC_MAP_IS_VALID,		/* Sync map is valid */
55 	POOL_SYNC_MAP_EMPTY,		/* Sync map is empty */
56 }			POOL_SYNC_MAP_STATE;
57 
58 /*
59  * Status of sent message
60  */
61 typedef enum
62 {
63 	POOL_SENT_MESSAGE_CREATED,	/* initial state of sent meesage */
64 	POOL_SENT_MESSAGE_CLOSED	/* sent meesage closed but close complete
65 								 * message has not arrived yet */
66 }			POOL_SENT_MESSAGE_STATE;
67 
68 /*
69  * Message content of extended query
70  */
71 typedef struct
72 {
73 	/*
74 	 * One of 'P':Parse, 'B':Bind or 'Q':Query (PREPARE).  If kind = 'B', it
75 	 * is assumed that the message is a portal.
76 	 */
77 	char		kind;
78 
79 	int			len;			/* message length in host byte order */
80 	char	   *contents;
81 	POOL_SENT_MESSAGE_STATE state;	/* message state */
82 	int			num_tsparams;
83 	char	   *name;			/* object name of prepared statement or portal */
84 	POOL_QUERY_CONTEXT *query_context;
85 
86 	/*
87 	 * Following members are only used when memcache is enabled.
88 	 */
89 	bool		is_cache_safe;	/* true if the query can be cached */
90 	int			param_offset;	/* Offset from contents where actual bind
91 								 * parameters are stored. This is meaningful
92 								 * only when is_cache_safe is true. */
93 }			POOL_SENT_MESSAGE;
94 
95 /*
96  * List of POOL_SENT_MESSAGE (XXX this should have been implemented using a
97  * list, rather than an array)
98  */
99 typedef struct
100 {
101 	int			capacity;		/* capacity of list */
102 	int			size;			/* number of elements */
103 	POOL_SENT_MESSAGE **sent_messages;
104 }			POOL_SENT_MESSAGE_LIST;
105 
106 /*
107  * Received message queue used in extended query/streaming replication mode.
108  * The queue is an FIFO.  When Parse/Bind/Describe/Execute/Close message are
109  * received, each message is en-queued.  The information is used to process
110  * those response messages, when Parse complete/Bind completes, Parameter
111  * description, row description, command complete and close compete message
112  * are received because they don't have any information regarding
113  * statement/portal.
114  *
115  * The memory used for the queue lives in the session context mememory.
116  */
117 
118 typedef enum
119 {
120 	POOL_PARSE = 0,
121 	POOL_BIND,
122 	POOL_EXECUTE,
123 	POOL_DESCRIBE,
124 	POOL_CLOSE,
125 	POOL_SYNC
126 }			POOL_MESSAGE_TYPE;
127 
128 typedef struct
129 {
130 	POOL_MESSAGE_TYPE type;
131 	char	   *contents;		/* message packet contents excluding message
132 								 * kind */
133 	int			contents_len;	/* message packet length */
134 	char		query[QUERY_STRING_BUFFER_LEN]; /* copy of original query */
135 	char		statement[MAX_IDENTIFIER_LEN];	/* prepared statment name if
136 												 * any */
137 	char		portal[MAX_IDENTIFIER_LEN]; /* portal name if any */
138 	bool		is_rows_returned;	/* true if the message could produce row
139 									 * data */
140 	bool		not_forward_to_frontend;	/* Do not forward response from
141 											 * backend to frontend. This is
142 											 * used by parse_before_bind() */
143 	int			node_ids[2];	/* backend node ids this message was sent to.
144 								 * -1 means no message was sent. */
145 	POOL_QUERY_CONTEXT *query_context;	/* query context */
146 }			POOL_PENDING_MESSAGE;
147 
148 /* Return true if node_id is one of node_ids */
149 #define IS_SENT_NODE_ID(msg, node_id)	(msg->node_ids[0] == node_id || msg->node_ids[1] == node_id)
150 
151 /*
152  * Per session context:
153  */
154 typedef struct
155 {
156 	POOL_PROCESS_CONTEXT *process_context;	/* belonging process */
157 	POOL_CONNECTION *frontend;	/* connection to frontend */
158 	POOL_CONNECTION_POOL *backend;	/* connection to backends */
159 
160 	/*
161 	 * If true, we are waiting for backend response.  For SELECT this flags
162 	 * should be kept until all responses are returned from backend. i.e.
163 	 * until "Read for Query" packet.
164 	 */
165 	bool		in_progress;
166 
167 	/* If true, we are doing extended query message */
168 	bool		doing_extended_query_message;
169 
170 	/*
171 	 * If true, we have rewritten where_to_send map in the current query
172 	 * context. pool_unset_query_in_progress() should restore the data from
173 	 * where_to_send_save.  For now, this is only necessary while doing
174 	 * extended query protocol and in streaming replication mode.
175 	 */
176 	bool		need_to_restore_where_to_send;
177 	bool		where_to_send_save[MAX_NUM_BACKENDS];
178 
179 	/* If true, the command in progress has finished successfully. */
180 	bool		command_success;
181 
182 	/* If true, write query has been appeared in this transaction */
183 	bool		writing_transaction;
184 
185 	/* If true, error occurred in this transaction */
186 	bool		failed_transaction;
187 
188 	/* If true, we skip reading from backends */
189 	bool		skip_reading_from_backends;
190 
191 	/* ignore any command until Sync message */
192 	bool		ignore_till_sync;
193 
194 	/*
195 	 * Transaction isolation mode.
196 	 */
197 	POOL_TRANSACTION_ISOLATION transaction_isolation;
198 
199 	/*
200 	 * Associated query context, only used for non-extended protocol. In
201 	 * extended protocol, the query context resides in "PreparedStatementList
202 	 * *pstmt_list" (see below).
203 	 */
204 	POOL_QUERY_CONTEXT *query_context;
205 #ifdef NOT_USED
206 	/* where to send map for PREPARE/EXECUTE/DEALLOCATE */
207 	POOL_PREPARED_SEND_MAP prep_where;
208 #endif							/* NOT_USED */
209 	MemoryContext memory_context;	/* memory context for session */
210 
211 	/* message which doesn't receive complete message */
212 	POOL_SENT_MESSAGE *uncompleted_message;
213 
214 	POOL_SENT_MESSAGE_LIST message_list;
215 
216 	int			load_balance_node_id;	/* selected load balance node id */
217 
218 	/*
219 	 * If true, UPDATE/DELETE caused difference in number of affected tuples
220 	 * in backends.
221 	 */
222 	bool		mismatch_ntuples;
223 
224 	/*
225 	 * If mismatch_ntuples true, this array holds the number of affected
226 	 * tuples of each node. -1 for down nodes.
227 	 */
228 	int			ntuples[MAX_NUM_BACKENDS];
229 
230 	/*
231 	 * If true, we are executing reset query list.
232 	 */
233 	bool		reset_context;
234 
235 	/*
236 	 * Query cache management area
237 	 */
238 	POOL_QUERY_CACHE_ARRAY *query_cache_array;	/* pending SELECT results */
239 	long long int num_selects;	/* number of successful SELECTs in this
240 								 * transaction */
241 
242 	/*
243 	 * Parse/Bind/Decribe/Execute/Close message queue.
244 	 */
245 	List	   *pending_messages;
246 
247 	/*
248 	 * The last pending message. Reset at Ready for query.  Note that this is
249 	 * a shallow copy of pending message.  Once the are is reset,
250 	 * previos_message_exists is set to false.
251 	 */
252 	bool		previous_message_exists;
253 	POOL_PENDING_MESSAGE previous_message;
254 
255 	/* Protocol major version number */
256 	int			major;
257 	/* Protocol minor version number */
258 	int			minor;
259 
260 	/*
261 	 * Do not read messages from frontend. Used in extended protocol +
262 	 * streaming replication.  If sync message is received from frontend, this
263 	 * flag prevent from reading any message from frontend until read for
264 	 * query message arrives from backend.
265 	 */
266 	bool		suspend_reading_from_frontend;
267 
268 #ifdef NOT_USED
269 	/* Preferred "master" node id. Only used for SimpleForwardToFrontend. */
270 	int			preferred_master_node_id;
271 #endif
272 }			POOL_SESSION_CONTEXT;
273 
274 extern void pool_init_session_context(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend);
275 extern void pool_session_context_destroy(void);
276 extern POOL_SESSION_CONTEXT * pool_get_session_context(bool noerror);
277 extern int	pool_get_local_session_id(void);
278 extern bool pool_is_query_in_progress(void);
279 extern void pool_set_query_in_progress(void);
280 extern void pool_unset_query_in_progress(void);
281 extern bool pool_is_skip_reading_from_backends(void);
282 extern void pool_set_skip_reading_from_backends(void);
283 extern void pool_unset_skip_reading_from_backends(void);
284 extern bool pool_is_doing_extended_query_message(void);
285 extern void pool_set_doing_extended_query_message(void);
286 extern void pool_unset_doing_extended_query_message(void);
287 extern bool pool_is_ignore_till_sync(void);
288 extern void pool_set_ignore_till_sync(void);
289 extern void pool_unset_ignore_till_sync(void);
290 extern POOL_SENT_MESSAGE * pool_create_sent_message(char kind, int len, char *contents,
291 													int num_tsparams, const char *name,
292 													POOL_QUERY_CONTEXT * query_context);
293 extern void pool_add_sent_message(POOL_SENT_MESSAGE * message);
294 extern bool pool_remove_sent_message(char kind, const char *name);
295 extern void pool_remove_sent_messages(char kind);
296 extern void pool_clear_sent_message_list(void);
297 extern void pool_sent_message_destroy(POOL_SENT_MESSAGE * message);
298 extern POOL_SENT_MESSAGE * pool_get_sent_message(char kind, const char *name, POOL_SENT_MESSAGE_STATE state);
299 extern void pool_set_sent_message_state(POOL_SENT_MESSAGE * message);
300 extern void pool_zap_query_context_in_sent_messages(POOL_QUERY_CONTEXT *query_context);
301 extern POOL_SENT_MESSAGE * pool_get_sent_message_by_query_context(POOL_QUERY_CONTEXT * query_context);
302 extern void pool_unset_writing_transaction(void);
303 extern void pool_set_writing_transaction(void);
304 extern bool pool_is_writing_transaction(void);
305 extern void pool_unset_failed_transaction(void);
306 extern void pool_set_failed_transaction(void);
307 extern bool pool_is_failed_transaction(void);
308 extern void pool_unset_transaction_isolation(void);
309 extern void pool_set_transaction_isolation(POOL_TRANSACTION_ISOLATION isolation_level);
310 extern POOL_TRANSACTION_ISOLATION pool_get_transaction_isolation(void);
311 extern void pool_unset_command_success(void);
312 extern void pool_set_command_success(void);
313 extern bool pool_is_command_success(void);
314 extern void pool_copy_prep_where(bool *src, bool *dest);
315 extern bool can_query_context_destroy(POOL_QUERY_CONTEXT * qc);
316 extern void pool_pending_messages_init(void);
317 extern void pool_pending_messages_destroy(void);
318 extern POOL_PENDING_MESSAGE * pool_pending_message_create(char kind, int len, char *contents);
319 extern void pool_pending_message_free_pending_message(POOL_PENDING_MESSAGE * message);
320 extern void pool_pending_message_dest_set(POOL_PENDING_MESSAGE * message, POOL_QUERY_CONTEXT * query_context);
321 extern void pool_pending_message_query_context_dest_set(POOL_PENDING_MESSAGE * message, POOL_QUERY_CONTEXT * query_context);
322 extern void pool_pending_message_query_set(POOL_PENDING_MESSAGE * message, POOL_QUERY_CONTEXT * query_context);
323 extern void pool_pending_message_add(POOL_PENDING_MESSAGE * message);
324 extern POOL_PENDING_MESSAGE * pool_pending_message_head_message(void);
325 extern POOL_PENDING_MESSAGE * pool_pending_message_pull_out(void);
326 extern POOL_PENDING_MESSAGE * pool_pending_message_get(POOL_MESSAGE_TYPE type);
327 extern char pool_get_close_message_spec(POOL_PENDING_MESSAGE * msg);
328 extern char *pool_get_close_message_name(POOL_PENDING_MESSAGE * msg);
329 extern void pool_pending_message_reset_previous_message(void);
330 extern void pool_pending_message_set_previous_message(POOL_PENDING_MESSAGE * message);
331 extern POOL_PENDING_MESSAGE * pool_pending_message_get_previous_message(void);
332 extern bool pool_pending_message_exists(void);
333 extern const char *pool_pending_message_type_to_string(POOL_MESSAGE_TYPE type);
334 extern void pool_check_pending_message_and_reply(POOL_MESSAGE_TYPE type, char kind);
335 extern POOL_PENDING_MESSAGE * pool_pending_message_find_lastest_by_query_context(POOL_QUERY_CONTEXT * qc);
336 extern int	pool_pending_message_get_target_backend_id(POOL_PENDING_MESSAGE * msg);
337 extern int	pool_pending_message_get_message_num_by_backend_id(int backend_id);
338 extern void dump_pending_message(void);
339 extern void pool_set_major_version(int major);
340 extern void pool_set_minor_version(int minor);
341 extern int	pool_get_minor_version(void);
342 extern bool pool_is_suspend_reading_from_frontend(void);
343 extern void pool_set_suspend_reading_from_frontend(void);
344 extern void pool_unset_suspend_reading_from_frontend(void);
345 
346 #ifdef NOT_USED
347 extern void pool_set_preferred_master_node_id(int node_id);
348 extern int	pool_get_preferred_master_node_id(void);
349 extern void pool_reset_preferred_master_node_id(void);
350 #endif
351 
352 #ifdef NOT_USED
353 extern void pool_add_prep_where(char *name, bool *map);
354 extern bool *pool_get_prep_where(char *name);
355 extern void pool_delete_prep_where(char *name);
356 #endif							/* NOT_USED */
357 #endif							/* POOL_SESSION_CONTEXT_H */
358