CUBRID Engine  latest
connection_sr.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * connection_sr.c - Client/Server connection list management
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #if defined (WINDOWS)
28 #include <io.h>
29 #endif
30 #include <filesystem>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #include <assert.h>
37 
38 #if defined(WINDOWS)
39 #include <winsock2.h>
40 #include <windows.h>
41 #else /* WINDOWS */
42 #include <sys/time.h>
43 #include <sys/ioctl.h>
44 #include <sys/uio.h>
45 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #endif /* WINDOWS */
48 
49 #if defined(_AIX)
50 #include <sys/select.h>
51 #endif /* _AIX */
52 
53 #if defined(SOLARIS)
54 #include <sys/filio.h>
55 #include <netdb.h>
56 #endif /* SOLARIS */
57 
58 #if defined(SOLARIS) || defined(LINUX)
59 #include <unistd.h>
60 #endif /* SOLARIS || LINUX */
61 
62 #include "porting.h"
63 #include "error_manager.h"
64 #include "connection_globals.h"
65 #include "filesys.hpp"
66 #include "filesys_temp.hpp"
67 #include "memory_alloc.h"
68 #include "environment_variable.h"
69 #include "system_parameter.h"
70 #include "critical_section.h"
71 #include "log_manager.h"
72 #include "object_representation.h"
73 #include "connection_error.h"
74 #include "log_impl.h"
75 #include "session.h"
76 #if defined(WINDOWS)
77 #include "wintcp.h"
78 #else /* WINDOWS */
79 #include "tcp.h"
80 #endif /* WINDOWS */
81 #include "connection_sr.h"
82 #include "server_support.h"
83 #include "thread_manager.hpp" // for thread_get_thread_entry_info
84 
85 #ifdef PACKET_TRACE
86 #define TRACE(string, arg) \
87  do { \
88  er_log_debug(ARG_FILE_LINE, string, arg); \
89  } \
90  while(0);
91 #else /* PACKET_TRACE */
92 #define TRACE(string, arg)
93 #endif /* PACKET_TRACE */
94 
95 /* data wait queue */
96 typedef struct css_wait_queue_entry
97 {
98  char **buffer;
99  int *size;
100  int *rc;
101  THREAD_ENTRY *thrd_entry; /* thread waiting for data */
103  unsigned int key;
105 
106 typedef struct queue_search_arg
107 {
109  int key;
112 
113 typedef struct wait_queue_search_arg
114 {
116  unsigned int key;
119 
120 #define NUM_NORMAL_CLIENTS (prm_get_integer_value(PRM_ID_CSS_MAX_CLIENTS))
121 
122 #define RMUTEX_NAME_CONN_ENTRY "CONN_ENTRY"
123 
124 static const int CSS_MAX_CLIENT_ID = INT_MAX - 1;
125 
126 static int css_Client_id = 0;
127 static pthread_mutex_t css_Client_id_lock = PTHREAD_MUTEX_INITIALIZER;
128 static pthread_mutex_t css_Conn_rule_lock = PTHREAD_MUTEX_INITIALIZER;
130 static int css_Num_free_conn = 0;
131 static int css_Num_max_conn = 101; /* default max_clients + 1 for conn with master */
132 
135 static int css_Num_active_conn = 0;
136 
139 
142 
143 /* This will handle new connections */
145 
146 /* This will handle new requests per connection */
148 
149 /* This will handle closed connection errors */
151 
152 #define CSS_CONN_IDX(conn_arg) ((conn_arg) - css_Conn_array)
153 
154 #define CSS_FREE_CONN_MSG "Free count = %d, head = %d"
155 #define CSS_FREE_CONN_ARGS css_Num_free_conn, CSS_CONN_IDX (css_Free_conn_anchor)
156 
157 #define CSS_ACTIVE_CONN_MSG "Active count = %d, head = %d"
158 #define CSS_ACTIVE_CONN_ARGS css_Num_active_conn, CSS_CONN_IDX (css_Active_conn_anchor)
159 
160 static int css_get_next_client_id (void);
161 static CSS_CONN_ENTRY *css_common_connect (CSS_CONN_ENTRY * conn, unsigned short *rid, const char *host_name,
162  int connect_type, const char *server_name, int server_name_length, int port);
163 
164 static int css_abort_request (CSS_CONN_ENTRY * conn, unsigned short rid);
165 static void css_dealloc_conn (CSS_CONN_ENTRY * conn);
166 
167 static unsigned int css_make_eid (unsigned short entry_id, unsigned short rid);
168 
170 static void css_retire_queue_entry (CSS_CONN_ENTRY * conn, CSS_QUEUE_ENTRY * entry);
171 static void css_free_queue_entry_list (CSS_CONN_ENTRY * conn);
172 
175 static void css_free_wait_queue_list (CSS_CONN_ENTRY * conn);
176 
178 static void css_retire_net_header_entry (CSS_CONN_ENTRY * conn, NET_HEADER * entry);
179 static void css_free_net_header_list (CSS_CONN_ENTRY * conn);
180 
181 static CSS_QUEUE_ENTRY *css_make_queue_entry (CSS_CONN_ENTRY * conn, unsigned int key, char *buffer,
182  int size, int rc, int transid, int invalidate_snapshot, int db_error);
183 static void css_free_queue_entry (CSS_CONN_ENTRY * conn, CSS_QUEUE_ENTRY * entry);
184 static css_error_code css_add_queue_entry (CSS_CONN_ENTRY * conn, CSS_LIST * list, unsigned short request_id,
185  char *buffer, int buffer_size, int rc, int transid, int invalidate_snapshot,
186  int db_error);
187 static CSS_QUEUE_ENTRY *css_find_queue_entry (CSS_LIST * list, unsigned int key);
188 static CSS_QUEUE_ENTRY *css_find_and_remove_queue_entry (CSS_LIST * list, unsigned int key);
189 static CSS_WAIT_QUEUE_ENTRY *css_make_wait_queue_entry (CSS_CONN_ENTRY * conn, unsigned int key, char **buffer,
190  int *size, int *rc);
193  unsigned short request_id, char **buffer, int *buffer_size,
194  int *rc);
196 
197 static void css_process_close_packet (CSS_CONN_ENTRY * conn);
198 static void css_process_abort_packet (CSS_CONN_ENTRY * conn, unsigned short request_id);
199 static bool css_is_request_aborted (CSS_CONN_ENTRY * conn, unsigned short request_id);
200 static void clear_wait_queue_entry_and_free_buffer (THREAD_ENTRY * thrdp, CSS_CONN_ENTRY * conn, unsigned short rid,
201  char **bufferp);
202 static int css_return_queued_data_timeout (CSS_CONN_ENTRY * conn, unsigned short rid, char **buffer, int *bufsize,
203  int *rc, int waitsec);
204 
205 static void css_queue_data_packet (CSS_CONN_ENTRY * conn, unsigned short request_id, const NET_HEADER * header,
206  THREAD_ENTRY ** wait_thrd);
207 static void css_queue_error_packet (CSS_CONN_ENTRY * conn, unsigned short request_id, const NET_HEADER * header);
208 static css_error_code css_queue_command_packet (CSS_CONN_ENTRY * conn, unsigned short request_id,
209  const NET_HEADER * header, int size);
210 static bool css_is_valid_request_id (CSS_CONN_ENTRY * conn, unsigned short request_id);
211 static void css_remove_unexpected_packets (CSS_CONN_ENTRY * conn, unsigned short request_id);
212 
213 static css_error_code css_queue_packet (CSS_CONN_ENTRY * conn, int type, unsigned short request_id,
214  const NET_HEADER * header, int size);
215 static int css_remove_and_free_queue_entry (void *data, void *arg);
216 static int css_remove_and_free_wait_queue_entry (void *data, void *arg);
217 
218 static int css_increment_num_conn_internal (CSS_CONN_RULE_INFO * conn_rule_info);
219 static void css_decrement_num_conn_internal (CSS_CONN_RULE_INFO * conn_rule_info);
220 
221 /*
222  * get_next_client_id() -
223  * return: client id
224  */
225 static int
227 {
228  static bool overflow = false;
229  int next_client_id, rv, i;
230  bool retry;
231 
233  if (rv != 0)
234  {
236  return ER_FAILED;
237  }
238 
239  do
240  {
241  css_Client_id++;
243  {
244  css_Client_id = 1;
245  overflow = true;
246  }
247 
248  retry = false;
249  for (i = 0; overflow && i < css_Num_max_conn; i++)
250  {
251  if (css_Conn_array[i].client_id == css_Client_id)
252  {
253  retry = true;
254  break;
255  }
256  }
257  }
258  while (retry);
259 
260  next_client_id = css_Client_id;
261 
263  if (rv != 0)
264  {
266  return ER_FAILED;
267  }
268 
269  return next_client_id;
270 }
271 
272 /*
273  * css_initialize_conn() - initialize connection entry
274  * return: void
275  * conn(in):
276  * fd(in):
277  */
278 int
280 {
281  int err;
282 
283  conn->fd = fd;
284  conn->request_id = 0;
285  conn->status = CONN_OPEN;
286  conn->set_tran_index (NULL_TRAN_INDEX);
287  conn->init_pending_request ();
288  conn->invalidate_snapshot = 1;
289  err = css_get_next_client_id ();
290  if (err < 0)
291  {
292  return ER_CSS_CONN_INIT;
293  }
294  conn->client_id = err;
295  conn->db_error = 0;
296  conn->in_transaction = false;
297  conn->reset_on_commit = false;
298  conn->stop_talk = false;
299  conn->ignore_repl_delay = false;
300  conn->stop_phase = THREAD_STOP_WORKERS_EXCEPT_LOGWR;
301  conn->version_string = NULL;
302  /* ignore connection handler thread */
303  conn->free_queue_list = NULL;
304  conn->free_queue_count = 0;
305 
306  conn->free_wait_queue_list = NULL;
307  conn->free_wait_queue_count = 0;
308 
309  conn->free_net_header_list = NULL;
310  conn->free_net_header_count = 0;
311 
313 #if defined(SERVER_MODE)
314  conn->session_p = NULL;
315  conn->client_type = DB_CLIENT_TYPE_UNKNOWN;
316 #endif
317 
318  err = css_initialize_list (&conn->request_queue, 0);
319  if (err != NO_ERROR)
320  {
321  return ER_CSS_CONN_INIT;
322  }
323  err = css_initialize_list (&conn->data_queue, 0);
324  if (err != NO_ERROR)
325  {
326  return ER_CSS_CONN_INIT;
327  }
328  err = css_initialize_list (&conn->data_wait_queue, 0);
329  if (err != NO_ERROR)
330  {
331  return ER_CSS_CONN_INIT;
332  }
333  err = css_initialize_list (&conn->abort_queue, 0);
334  if (err != NO_ERROR)
335  {
336  return ER_CSS_CONN_INIT;
337  }
338  err = css_initialize_list (&conn->buffer_queue, 0);
339  if (err != NO_ERROR)
340  {
341  return ER_CSS_CONN_INIT;
342  }
343  err = css_initialize_list (&conn->error_queue, 0);
344  if (err != NO_ERROR)
345  {
346  return ER_CSS_CONN_INIT;
347  }
348  return NO_ERROR;
349 }
350 
351 /*
352  * css_shutdown_conn() - close connection entry
353  * return: void
354  * conn(in):
355  */
356 void
358 {
359  int r;
360 
361  r = rmutex_lock (NULL, &conn->rmutex);
362  assert (r == NO_ERROR);
363 
364  if (!IS_INVALID_SOCKET (conn->fd))
365  {
366  /* if this is the PC, it also shuts down Winsock */
367  css_shutdown_socket (conn->fd);
368  conn->fd = INVALID_SOCKET;
369  }
370 
371  if (conn->status == CONN_OPEN || conn->status == CONN_CLOSING)
372  {
373  conn->status = CONN_CLOSED;
374  conn->stop_talk = false;
375  conn->stop_phase = THREAD_STOP_WORKERS_EXCEPT_LOGWR;
376 
377  if (conn->version_string)
378  {
379  free_and_init (conn->version_string);
380  }
381 
383 
385  css_finalize_list (&conn->data_queue);
386  css_finalize_list (&conn->data_wait_queue);
390  }
391 
392  if (conn->free_queue_list != NULL)
393  {
394  assert (conn->free_queue_count > 0);
396  }
397 
398  if (conn->free_wait_queue_list != NULL)
399  {
400  assert (conn->free_wait_queue_count > 0);
402  }
403 
404  if (conn->free_net_header_list != NULL)
405  {
406  assert (conn->free_net_header_count > 0);
408  }
409 
410 #if defined(SERVER_MODE)
411  if (conn->session_p)
412  {
413  session_state_decrease_ref_count (NULL, conn->session_p);
414  conn->session_p = NULL;
416  }
417 #endif
418 
419  r = rmutex_unlock (NULL, &conn->rmutex);
420  assert (r == NO_ERROR);
421 }
422 
423 /*
424  * css_init_conn_list() - initialize connection list
425  * return: NO_ERROR if success, or error code
426  */
427 int
429 {
430  int i, err;
431  CSS_CONN_ENTRY *conn;
432 
434 
436 
437  if (css_Conn_array != NULL)
438  {
439  return NO_ERROR;
440  }
441 
443  if (err != NO_ERROR)
444  {
445  ASSERT_ERROR ();
446  return err;
447  }
448 
450  if (err != NO_ERROR)
451  {
452  ASSERT_ERROR ();
454  return err;
455  }
456 
457  /*
458  * allocate NUM_MASTER_CHANNEL + the total number of
459  * conn entries
460  */
461  css_Conn_array = (CSS_CONN_ENTRY *) malloc (sizeof (CSS_CONN_ENTRY) * (css_Num_max_conn));
462  if (css_Conn_array == NULL)
463  {
465  sizeof (CSS_CONN_ENTRY) * (css_Num_max_conn));
467  goto error;
468  }
469 
470  /* initialize all CSS_CONN_ENTRY */
471  for (i = 0; i < css_Num_max_conn; i++)
472  {
473  conn = &css_Conn_array[i];
474  conn->idx = i;
475  err = css_initialize_conn (conn, -1);
476  if (err != NO_ERROR)
477  {
479  err = ER_CSS_CONN_INIT;
480  goto error;
481  }
482 
483  err = rmutex_initialize (&conn->rmutex, RMUTEX_NAME_CONN_ENTRY);
484  if (err != NO_ERROR)
485  {
487  err = ER_CSS_CONN_INIT;
488  goto error;
489  }
490 
491  if (i < css_Num_max_conn - 1)
492  {
493  conn->next = &css_Conn_array[i + 1];
494  }
495  else
496  {
497  conn->next = NULL;
498  }
499  }
500 
501  /* initialize active conn list, used for stopping all threads */
502  css_Active_conn_anchor = NULL;
503  css_Free_conn_anchor = &css_Conn_array[0];
505 
506  return NO_ERROR;
507 
508 error:
511 
512  if (css_Conn_array != NULL)
513  {
514  free_and_init (css_Conn_array);
515  }
516 
517  return err;
518 }
519 
520 /*
521  * css_final_conn_list() - free connection list
522  * return: void
523  */
524 void
526 {
527  CSS_CONN_ENTRY *conn, *next;
528  int i;
529 
530  if (css_Active_conn_anchor != NULL)
531  {
532  for (conn = css_Active_conn_anchor; conn != NULL; conn = next)
533  {
534  next = conn->next;
535  css_shutdown_conn (conn);
536  css_dealloc_conn (conn);
537 
540  }
541 
542  css_Active_conn_anchor = NULL;
543  }
544 
546  assert (css_Active_conn_anchor == NULL);
547 
548  if (css_Conn_array != NULL)
549  {
550  for (i = 0; i < css_Num_max_conn; i++)
551  {
552  conn = &css_Conn_array[i];
553 
554 #if defined(SERVER_MODE)
555  assert (conn->idx == i);
556 #endif
557  (void) rmutex_finalize (&conn->rmutex);
558  }
559 
560  free_and_init (css_Conn_array);
561 
564  }
565 }
566 
567 /*
568  * css_make_conn() - make new connection entry, but not insert into active
569  * conn list
570  * return: new connection entry
571  * fd(in): socket discriptor
572  */
575 {
576  CSS_CONN_ENTRY *conn = NULL;
577  int r;
578 
580 
581  if (css_Free_conn_anchor != NULL)
582  {
583  conn = css_Free_conn_anchor;
584  css_Free_conn_anchor = css_Free_conn_anchor->next;
585  conn->next = NULL;
586 
588  assert (css_Num_free_conn >= 0);
589  }
590  CSS_LOG_STACK ("css_make_conn: conn = %d, " CSS_FREE_CONN_MSG, CSS_CONN_IDX (conn), CSS_FREE_CONN_ARGS);
591 
593 
594  if (conn != NULL)
595  {
596  if (css_initialize_conn (conn, fd) != NO_ERROR)
597  {
599  return NULL;
600  }
601  }
602 
603  return conn;
604 }
605 
606 /*
607  * css_insert_into_active_conn_list() - insert/remove into/from active conn
608  * list. this operation must be called
609  * after/before css_free_conn etc.
610  * return: void
611  * conn(in): connection entry will be inserted
612  */
613 void
615 {
616  int r;
617 
619 
620  CSS_LOG_STACK ("css_insert_into_active_conn_list conn = %d, prev " CSS_ACTIVE_CONN_MSG, CSS_CONN_IDX (conn),
622 
624  css_Active_conn_anchor = conn;
625 
627 
630 
632 }
633 
634 /*
635  * css_dealloc_conn_rmutex() - free rmutex of connection entry
636  * return: void
637  * conn(in): connection entry
638  */
639 void
641 {
642  (void) rmutex_finalize (&conn->rmutex);
643 }
644 
645 /*
646  * css_dealloc_conn() - free connection entry
647  * return: void
648  * conn(in): connection entry will be free
649  */
650 static void
652 {
653  int r;
654 
656 
657  CSS_LOG_STACK ("css_dealloc_conn conn = %d, prev " CSS_FREE_CONN_MSG, CSS_CONN_IDX (conn), CSS_FREE_CONN_ARGS);
658 
659  conn->next = css_Free_conn_anchor;
660  css_Free_conn_anchor = conn;
661 
663 
666 
668 }
669 
670 /*
671  * css_get_num_free_conn -
672  */
673 int
675 {
676  return css_Num_free_conn;
677 }
678 
679 /*
680  * css_increment_num_conn_internal() - increments conn counter
681  * based on client type
682  * return: error code
683  * client_type(in): a type of a client trying
684  * to release the connection
685  */
686 static int
688 {
689  int error = NO_ERROR;
690 
691  switch (conn_rule_info->rule)
692  {
693  case CR_NORMAL_ONLY:
694  if (conn_rule_info->num_curr_conn == conn_rule_info->max_num_conn)
695  {
696  error = ER_CSS_CLIENTS_EXCEEDED;
697  }
698  else
699  {
700  conn_rule_info->num_curr_conn++;
701  }
702  break;
703  case CR_NORMAL_FIRST:
704  /* tries to use a normal conn first */
706  {
707  /* if normal conns are all occupied, uses a reserved conn */
708  if (conn_rule_info->num_curr_conn == conn_rule_info->max_num_conn)
709  {
710  error = ER_CSS_CLIENTS_EXCEEDED;
711  }
712  else
713  {
714  conn_rule_info->num_curr_conn++;
715  assert (conn_rule_info->num_curr_conn <= conn_rule_info->max_num_conn);
716  }
717  }
718  break;
719  case CR_RESERVED_FIRST:
720  /* tries to use a reserved conn first */
721  if (conn_rule_info->num_curr_conn < conn_rule_info->max_num_conn)
722  {
723  conn_rule_info->num_curr_conn++;
724  }
725  else /* uses a normal conn if no reserved conn is available */
726  {
727  if (css_increment_num_conn_internal (&css_Conn_rules[CSS_CR_NORMAL_ONLY_IDX]) != NO_ERROR)
728  {
729  error = ER_CSS_CLIENTS_EXCEEDED;
730  }
731  else
732  {
733  /* also increments its own conn counter */
734  conn_rule_info->num_curr_conn++;
735  assert (conn_rule_info->num_curr_conn <=
736  (css_Conn_rules[CSS_CR_NORMAL_ONLY_IDX].max_num_conn + conn_rule_info->max_num_conn));
737  }
738  }
739  break;
740  default:
741  assert (false);
742  break;
743  }
744 
745  return error;
746 }
747 
748 /*
749  * css_decrement_num_conn_internal() - decrements conn counter
750  * based on client type
751  * return:
752  * client_type(in): a type of a client trying
753  * to release the connection
754  */
755 static void
757 {
758  int i;
759 
760  switch (conn_rule_info->rule)
761  {
762  case CR_NORMAL_ONLY:
763  /* When a normal client decrements the counter, it should first check that other normal-first-reserved-last
764  * clients need to take the released connection first. */
765  for (i = 1; i < css_Conn_rules_size; i++)
766  {
767  if (css_Conn_rules[i].rule == CR_NORMAL_FIRST && css_Conn_rules[i].num_curr_conn > 0)
768  {
770 
771  return;
772  }
773  }
774  conn_rule_info->num_curr_conn--;
775  break;
776 
777  case CR_NORMAL_FIRST:
778  /* decrements reserved conn counter first if exists */
779  if (conn_rule_info->num_curr_conn > 0)
780  {
781  conn_rule_info->num_curr_conn--;
782  }
783  else /* decrements normal conn counter if no reserved conn is in use */
784  {
786  }
787  break;
788 
789  case CR_RESERVED_FIRST:
790  /* decrements normal conn counter if exists */
791  if (conn_rule_info->num_curr_conn > conn_rule_info->max_num_conn)
792  {
794  }
795  /* also decrements its own conn counter */
796  conn_rule_info->num_curr_conn--;
797  break;
798 
799  default:
800  assert (false);
801  break;
802  }
803 
804  assert (conn_rule_info->num_curr_conn >= 0);
805 
806  return;
807 }
808 
809 /*
810  * css_increment_num_conn() - increment a connection counter
811  * and check if a client can take its connection
812  * return: error code
813  * client_type(in): a type of a client trying
814  * to take the connection
815  */
816 int
818 {
819  int i;
820  int error = NO_ERROR;
821 
822  for (i = 0; i < css_Conn_rules_size; i++)
823  {
824  if (css_Conn_rules[i].check_client_type_fn (client_type))
825  {
829  break;
830  }
831  }
832 
833  return error;
834 }
835 
836 /*
837  * css_decrement_num_conn() - decrement a connection counter
838  * return:
839  * client_type(in): a type of a client trying
840  * to release the connection
841  */
842 void
844 {
845  int i;
846 
847  if (client_type == DB_CLIENT_TYPE_UNKNOWN)
848  {
849  return;
850  }
851 
852  for (i = 0; i < css_Conn_rules_size; i++)
853  {
854  if (css_Conn_rules[i].check_client_type_fn (client_type))
855  {
859  break;
860  }
861  }
862 
863  return;
864 }
865 
866 /*
867  * css_free_conn() - destroy all connection related structures, and free conn
868  * entry, delete from css_Active_conn_anchor list
869  * return: void
870  * conn(in): connection entry will be free
871  */
872 void
874 {
875  CSS_CONN_ENTRY *p, *prev = NULL, *next;
876  int r;
877 
879 
880  /* find and remove from active conn list */
881  for (p = css_Active_conn_anchor; p != NULL; p = next)
882  {
883  next = p->next;
884 
885  if (p == conn)
886  {
887  if (prev == NULL)
888  {
889  css_Active_conn_anchor = next;
890  }
891  else
892  {
893  prev->next = next;
894  }
895 
897 
900 
901  CSS_LOG_STACK ("css_free_conn - removed conn = %d from " CSS_ACTIVE_CONN_MSG, CSS_CONN_IDX (conn),
903 
904  break;
905  }
906 
907  prev = p;
908  }
909 
910  if (p == NULL)
911  {
912  CSS_LOG_STACK ("css_free_conn - not found conn = %p in " CSS_ACTIVE_CONN_MSG, conn, CSS_ACTIVE_CONN_ARGS);
913  }
914 
915  css_shutdown_conn (conn);
916  css_dealloc_conn (conn);
917  css_decrement_num_conn (conn->client_type);
918 
920 }
921 
922 /*
923  * css_print_conn_entry_info() - print connection entry information to stderr
924  * return: void
925  * conn(in): connection entry
926  */
927 void
929 {
930  fprintf (stderr,
931  "CONN_ENTRY: %p, next(%p), idx(%d),fd(%lld),request_id(%d),transaction_id(%d),client_id(%d)\n",
932  conn, conn->next, conn->idx, (long long) conn->fd, conn->request_id, conn->get_tran_index (),
933  conn->client_id);
934 }
935 
936 /*
937  * css_print_conn_list() - print active connection list to stderr
938  * return: void
939  */
940 void
942 {
943  CSS_CONN_ENTRY *conn, *next;
944  int i, r;
945 
946  if (css_Active_conn_anchor != NULL)
947  {
949 
950  fprintf (stderr, "active conn list (%d)\n", css_Num_active_conn);
951 
952  for (conn = css_Active_conn_anchor, i = 0; conn != NULL; conn = next, i++)
953  {
954  next = conn->next;
956  }
957 
959 
961  }
962 }
963 
964 /*
965  * css_print_free_conn_list() - print free connection list to stderr
966  * return: void
967  */
968 void
970 {
971  CSS_CONN_ENTRY *conn, *next;
972  int i, r;
973 
974  if (css_Free_conn_anchor != NULL)
975  {
977 
978  fprintf (stderr, "free conn list (%d)\n", css_Num_free_conn);
979 
980  for (conn = css_Free_conn_anchor, i = 0; conn != NULL; conn = next, i++)
981  {
982  next = conn->next;
984  }
985 
986  assert (i == css_Num_free_conn);
987 
989  }
990 }
991 
992 /*
993  * css_register_handler_routines() - enroll handler routines
994  * return: void
995  * connect_handler(in): connection handler function pointer
996  * conn(in): connection entry
997  * request_handler(in): request handler function pointer
998  * connection_error_handler(in): error handler function pointer
999  *
1000  * Note: This is the routine that will enroll various handler routines
1001  * that the client/server interface software may use. Any of these
1002  * routines may be given a NULL value in which case a default routine
1003  * will be used, or nothing will be done.
1004  *
1005  * The connect handler is called when a new connection is made.
1006  *
1007  * The request handler is called to handle a new request. This must
1008  * return non zero, otherwise, the server will halt.
1009  *
1010  * The abort handler is called by the server when an abort command
1011  * is sent from the client.
1012  *
1013  * The alloc function is called instead of malloc when new buffers
1014  * are to be created.
1015  *
1016  * The free function is called when a buffer is to be released.
1017  *
1018  * The error handler function is called when the client/server system
1019  * detects an error it considers to be fatal.
1020  */
1021 void
1023  CSS_THREAD_FN request_handler, CSS_THREAD_FN connection_error_handler)
1024 {
1025  css_Connect_handler = connect_handler;
1026  css_Request_handler = request_handler;
1027 
1028  if (connection_error_handler)
1029  {
1030  css_Connection_error_handler = connection_error_handler;
1031  }
1032 }
1033 
1034 /*
1035  * css_common_connect() - actually try to make a connection to a server.
1036  * return: connection entry if success, or NULL
1037  * conn(in): connection entry will be connected
1038  * rid(out): request id
1039  * host_name(in): host name of server
1040  * connect_type(in):
1041  * server_name(in):
1042  * server_name_length(in):
1043  * port(in):
1044  */
1045 static CSS_CONN_ENTRY *
1046 css_common_connect (CSS_CONN_ENTRY * conn, unsigned short *rid,
1047  const char *host_name, int connect_type, const char *server_name, int server_name_length, int port)
1048 {
1049  SOCKET fd;
1050 
1051  fd = css_tcp_client_open ((char *) host_name, port);
1052 
1053  if (!IS_INVALID_SOCKET (fd))
1054  {
1055  conn->fd = fd;
1056 
1057  if (css_send_magic (conn) != NO_ERRORS)
1058  {
1059  return NULL;
1060  }
1061 
1062  if (css_send_request (conn, connect_type, rid, server_name, server_name_length) == NO_ERRORS)
1063  {
1064  return conn;
1065  }
1066  }
1067 
1068  return NULL;
1069 }
1070 
1071 /*
1072  * css_connect_to_master_server() - Connect to the master from the server.
1073  * return: connection entry if success, or NULL
1074  * master_port_id(in):
1075  * server_name(in): name + version
1076  * name_length(in):
1077  */
1079 css_connect_to_master_server (int master_port_id, const char *server_name, int name_length)
1080 {
1081  char hname[CUB_MAXHOSTNAMELEN];
1082  CSS_CONN_ENTRY *conn;
1083  unsigned short rid;
1084  int response, response_buff;
1085  int server_port_id;
1086  int connection_protocol;
1087 #if !defined(WINDOWS)
1088  std::string pname;
1089  int datagram_fd, socket_fd;
1090 #endif
1091 
1092  css_Service_id = master_port_id;
1093  if (GETHOSTNAME (hname, CUB_MAXHOSTNAMELEN) != 0)
1094  {
1095  return NULL;
1096  }
1097 
1098  conn = css_make_conn (0);
1099  if (conn == NULL)
1100  {
1102  return NULL;
1103  }
1104 
1105  /* select the connection protocol */
1107  {
1108  // Windows
1109  connection_protocol = SERVER_REQUEST_NEW;
1110  }
1111  else
1112  {
1113  // Linux and Unix
1114  connection_protocol = SERVER_REQUEST;
1115  }
1116 
1117  if (css_common_connect (conn, &rid, hname, connection_protocol, server_name, name_length, master_port_id) == NULL)
1118  {
1119  goto fail_end;
1120  }
1121 
1122  if (css_readn (conn->fd, (char *) &response_buff, sizeof (int), -1) != sizeof (int))
1123  {
1124  goto fail_end;
1125  }
1126 
1127  response = ntohl (response_buff);
1128  TRACE ("css_connect_to_master_server received %d as response from master\n", response);
1129 
1130  switch (response)
1131  {
1132  case SERVER_ALREADY_EXISTS:
1134  goto fail_end;
1135 
1137  /*
1138  * Master requests a new-style connect, must go get
1139  * our port id and set up our connection socket.
1140  * For drivers, we don't need a connection socket and we
1141  * don't want to allocate a bunch of them. Let a flag variable
1142  * control whether or not we actually create one of these.
1143  */
1145  {
1146  server_port_id = -1;
1147  }
1148  else
1149  {
1150  server_port_id = css_open_server_connection_socket ();
1151  }
1152 
1153  response = htonl (server_port_id);
1154  css_net_send (conn, (char *) &response, sizeof (int), -1);
1155  /* this connection remains our only contact with the master */
1156  return conn;
1157 
1159 #if defined(WINDOWS)
1160  /* PC's can't handle this style of connection at all */
1162  goto fail_end;
1163 #else /* WINDOWS */
1164  /* send the "pathname" for the datagram */
1165  /* be sure to open the datagram first. */
1166  pname = std::filesystem::temp_directory_path ();
1167  pname += "/cubrid_tcp_setup_server" + std::to_string (getpid ());
1168  (void) unlink (pname.c_str ()); // make sure file is deleted
1169 
1170  if (!css_tcp_setup_server_datagram (pname.c_str (), &socket_fd))
1171  {
1172  (void) unlink (pname.c_str ());
1174  goto fail_end;
1175  }
1176  if (css_send_data (conn, rid, pname.c_str (), pname.length () + 1) != NO_ERRORS)
1177  {
1178  (void) unlink (pname.c_str ());
1179  close (socket_fd);
1181  goto fail_end;
1182  }
1183  if (!css_tcp_listen_server_datagram (socket_fd, &datagram_fd))
1184  {
1185  (void) unlink (pname.c_str ());
1186  close (socket_fd);
1188  goto fail_end;
1189  }
1190  // success
1191  (void) unlink (pname.c_str ());
1192  css_free_conn (conn);
1193  close (socket_fd);
1194  return (css_make_conn (datagram_fd));
1195 #endif /* WINDOWS */
1196  }
1197 
1198 fail_end:
1199  css_free_conn (conn);
1200  return NULL;
1201 }
1202 
1203 /*
1204  * css_find_conn_by_tran_index() - find connection entry having given
1205  * transaction id
1206  * return: connection entry if find, or NULL
1207  * tran_index(in): transaction id
1208  */
1211 {
1212  CSS_CONN_ENTRY *conn = NULL, *next;
1213  int r;
1214 
1215  if (css_Active_conn_anchor != NULL)
1216  {
1218 
1219  for (conn = css_Active_conn_anchor; conn != NULL; conn = next)
1220  {
1221  next = conn->next;
1222  if (conn->get_tran_index () == tran_index)
1223  {
1224  break;
1225  }
1226  }
1227 
1229  }
1230 
1231  return conn;
1232 }
1233 
1234 /*
1235  * css_find_conn_from_fd() - find a connection having given socket fd.
1236  * return: connection entry if find, or NULL
1237  * fd(in): socket fd
1238  */
1241 {
1242  CSS_CONN_ENTRY *conn = NULL, *next;
1243  int r;
1244 
1245  if (css_Active_conn_anchor != NULL)
1246  {
1248 
1249  for (conn = css_Active_conn_anchor; conn != NULL; conn = next)
1250  {
1251  next = conn->next;
1252  if (conn->fd == fd)
1253  {
1254  break;
1255  }
1256  }
1257 
1259  }
1260  return conn;
1261 }
1262 
1263 /*
1264  * css_get_session_ids_for_active_connections () - get active session ids
1265  * return : error code or NO_ERROR
1266  * session_ids (out) : holder for session ids
1267  * count (out) : number of session ids
1268  */
1269 int
1271 {
1272  CSS_CONN_ENTRY *conn = NULL, *next = NULL;
1273  SESSION_ID *sessions_p = NULL;
1274  int error = NO_ERROR, i = 0, r;
1275 
1276  assert (count != NULL);
1277  if (count == NULL)
1278  {
1279  error = ER_FAILED;
1280  goto error_return;
1281  }
1282 
1283  if (css_Active_conn_anchor == NULL)
1284  {
1285  *session_ids = NULL;
1286  *count = 0;
1287  return NO_ERROR;
1288  }
1289 
1291  *count = css_Num_active_conn;
1292  sessions_p = (SESSION_ID *) malloc (css_Num_active_conn * sizeof (SESSION_ID));
1293 
1294  if (sessions_p == NULL)
1295  {
1297  error = ER_FAILED;
1299  goto error_return;
1300  }
1301 
1302  for (conn = css_Active_conn_anchor; conn != NULL; conn = next)
1303  {
1304  next = conn->next;
1305  sessions_p[i] = conn->session_id;
1306  i++;
1307  }
1308 
1310  *session_ids = sessions_p;
1311  return error;
1312 
1313 error_return:
1314  if (sessions_p != NULL)
1315  {
1316  free_and_init (sessions_p);
1317  }
1318 
1319  *session_ids = NULL;
1320 
1321  if (count != NULL)
1322  {
1323  *count = 0;
1324  }
1325 
1326  return error;
1327 }
1328 
1329 /*
1330  * css_shutdown_conn_by_tran_index() - shutdown connection having given
1331  * transaction id
1332  * return: void
1333  * tran_index(in): transaction id
1334  */
1335 void
1337 {
1338  CSS_CONN_ENTRY *conn = NULL;
1339  int r;
1340 
1341  if (css_Active_conn_anchor != NULL)
1342  {
1344 
1345  for (conn = css_Active_conn_anchor; conn != NULL; conn = conn->next)
1346  {
1347  if (conn->get_tran_index () == tran_index)
1348  {
1349  if (conn->status == CONN_OPEN)
1350  {
1351  conn->status = CONN_CLOSING;
1352  }
1353  break;
1354  }
1355  }
1356 
1358  }
1359 }
1360 
1361 /*
1362  * css_get_request_id() - return the next valid request id
1363  * return: request id
1364  * conn(in): connection entry
1365  */
1366 unsigned short
1368 {
1369  unsigned short old_rid;
1370  unsigned short request_id;
1371  int r;
1372 
1373  r = rmutex_lock (NULL, &conn->rmutex);
1374  assert (r == NO_ERROR);
1375 
1376  old_rid = conn->request_id++;
1377  if (conn->request_id == 0)
1378  {
1379  conn->request_id++;
1380  }
1381 
1382  while (conn->request_id != old_rid)
1383  {
1384  if (css_is_valid_request_id (conn, conn->request_id))
1385  {
1386  request_id = conn->request_id;
1387 
1388  r = rmutex_unlock (NULL, &conn->rmutex);
1389  assert (r == NO_ERROR);
1390 
1391  return (request_id);
1392  }
1393  else
1394  {
1395  conn->request_id++;
1396  if (conn->request_id == 0)
1397  {
1398  conn->request_id++;
1399  }
1400  }
1401  }
1402 
1403  r = rmutex_unlock (NULL, &conn->rmutex);
1404  assert (r == NO_ERROR);
1405 
1406  /* Should never reach this point */
1408  return (0);
1409 }
1410 
1411 /*
1412  * css_abort_request() - helper routine to actually send the abort request.
1413  * return: 0 if success, or error code
1414  * conn(in): connection entry
1415  * rid(in): request id
1416  */
1417 static int
1418 css_abort_request (CSS_CONN_ENTRY * conn, unsigned short rid)
1419 {
1421  unsigned short flags = 0;
1422 
1423  header.type = htonl (ABORT_TYPE);
1424  header.request_id = htonl (rid);
1425  header.transaction_id = htonl (conn->get_tran_index ());
1426 
1427  if (conn->invalidate_snapshot)
1428  {
1430  }
1431  header.flags = htons (flags);
1432  header.db_error = htonl (conn->db_error);
1433 
1434  /* timeout in milli-second in css_net_send() */
1435  return css_net_send (conn, (char *) &header, sizeof (NET_HEADER), -1);
1436 }
1437 
1438 /*
1439  * css_send_abort_request() - abort an outstanding request.
1440  * return: 0 if success, or error code
1441  * conn(in): connection entry
1442  * request_id(in): request id
1443  *
1444  * Note: Once this is issued, any queued data buffers for this command will be
1445  * released.
1446  */
1447 int
1448 css_send_abort_request (CSS_CONN_ENTRY * conn, unsigned short request_id)
1449 {
1450  int rc, r;
1451 
1452  if (!conn || conn->status != CONN_OPEN)
1453  {
1454  return CONNECTION_CLOSED;
1455  }
1456 
1457  r = rmutex_lock (NULL, &conn->rmutex);
1458  assert (r == NO_ERROR);
1459 
1460  css_remove_unexpected_packets (conn, request_id);
1461  rc = css_abort_request (conn, request_id);
1462 
1463  r = rmutex_unlock (NULL, &conn->rmutex);
1464  assert (r == NO_ERROR);
1465 
1466  return rc;
1467 }
1468 
1469 /*
1470  * css_read_header() - helper routine that will read a header from the socket.
1471  * return: 0 if success, or error code
1472  * conn(in): connection entry
1473  * local_header(in):
1474  *
1475  * Note: It is a blocking read.
1476  */
1477 int
1478 css_read_header (CSS_CONN_ENTRY * conn, const NET_HEADER * local_header)
1479 {
1480  int buffer_size;
1481  int rc = 0;
1482  unsigned short flags = 0;
1483 
1484  buffer_size = sizeof (NET_HEADER);
1485 
1486  if (conn->stop_talk == true)
1487  {
1488  return CONNECTION_CLOSED;
1489  }
1490 
1491  rc = css_net_read_header (conn->fd, (char *) local_header, &buffer_size, -1);
1492  if (rc == NO_ERRORS && ntohl (local_header->type) == CLOSE_TYPE)
1493  {
1494  return CONNECTION_CLOSED;
1495  }
1496  if (rc != NO_ERRORS && rc != RECORD_TRUNCATED)
1497  {
1498  return CONNECTION_CLOSED;
1499  }
1500 
1501  conn->set_tran_index (ntohl (local_header->transaction_id));
1502  conn->db_error = (int) ntohl (local_header->db_error);
1503 
1504  flags = ntohs (local_header->flags);
1506 
1507  return rc;
1508 }
1509 
1510 /*
1511  * css_receive_request() - receive request from client
1512  * return: 0 if success, or error code
1513  * conn(in): connection entry
1514  * rid(out): request id
1515  * request(out): request
1516  * buffer_size(out): request data size
1517  */
1518 int
1519 css_receive_request (CSS_CONN_ENTRY * conn, unsigned short *rid, int *request, int *buffer_size)
1520 {
1521  return css_return_queued_request (conn, rid, request, buffer_size);
1522 }
1523 
1524 /*
1525  * css_read_and_queue() - Attempt to read any data packet from the connection.
1526  * return: 0 if success, or error code
1527  * conn(in): connection entry
1528  * type(out): request type
1529  */
1530 int
1532 {
1533  int rc;
1535 
1536  if (!conn || conn->status != CONN_OPEN)
1537  {
1538  return ERROR_ON_READ;
1539  }
1540 
1541  rc = css_read_header (conn, &header);
1542 
1543  if (conn->stop_talk == true)
1544  {
1545  return CONNECTION_CLOSED;
1546  }
1547 
1548  if (rc != NO_ERRORS)
1549  {
1550  return rc;
1551  }
1552 
1553  *type = ntohl (header.type);
1554  rc = css_queue_packet (conn, (int) ntohl (header.type), (unsigned short) ntohl (header.request_id), &header,
1555  sizeof (NET_HEADER));
1556  return rc;
1557 }
1558 
1559 /*
1560  * css_receive_data() - receive a data for an associated request.
1561  * return: 0 if success, or error code
1562  * conn(in): connection entry
1563  * req_id(in): request id
1564  * buffer(out): buffer for data
1565  * buffer_size(out): buffer size
1566  * timeout(in):
1567  *
1568  * Note: this is a blocking read.
1569  */
1570 int
1571 css_receive_data (CSS_CONN_ENTRY * conn, unsigned short req_id, char **buffer, int *buffer_size, int timeout)
1572 {
1573  int *r, rc;
1574 
1575  /* at here, do not use stack variable; must alloc it */
1576  r = (int *) malloc (sizeof (int));
1577  if (r == NULL)
1578  {
1579  return NO_DATA_AVAILABLE;
1580  }
1581 
1582  css_return_queued_data_timeout (conn, req_id, buffer, buffer_size, r, timeout);
1583  rc = *r;
1584 
1585  free_and_init (r);
1586  return rc;
1587 }
1588 
1589 /*
1590  * css_return_eid_from_conn() - get enquiry id from connection entry
1591  * return: enquiry id
1592  * conn(in): connection entry
1593  * rid(in): request id
1594  */
1595 unsigned int
1596 css_return_eid_from_conn (CSS_CONN_ENTRY * conn, unsigned short rid)
1597 {
1598  return css_make_eid ((unsigned short) conn->idx, rid);
1599 }
1600 
1601 /*
1602  * css_make_eid() - make enquiry id
1603  * return: enquiry id
1604  * entry_id(in): connection entry id
1605  * rid(in): request id
1606  */
1607 static unsigned int
1608 css_make_eid (unsigned short entry_id, unsigned short rid)
1609 {
1610  int top;
1611 
1612  top = entry_id;
1613  return ((top << 16) | rid);
1614 }
1615 
1616 /* CSS_CONN_ENTRY's queues related functions */
1617 
1618 /*
1619  * css_claim_queue_entry() - claim a queue entry from free list.
1620  * return: CSS_QUEUE_ENTRY *
1621  * conn(in): connection entry
1622  */
1623 static CSS_QUEUE_ENTRY *
1625 {
1626  CSS_QUEUE_ENTRY *p;
1627 
1628  assert (conn != NULL);
1629 
1630  p = conn->free_queue_list;
1631  if (p == NULL)
1632  {
1633  return NULL;
1634  }
1635 
1636  conn->free_queue_list = p->next;
1637 
1638  conn->free_queue_count--;
1639  assert (0 <= conn->free_queue_count);
1640 
1641  p->next = NULL;
1642 
1643  return p;
1644 }
1645 
1646 /*
1647  * css_retire_queue_entry() - retire a queue entry to free list.
1648  * return: void
1649  * conn(in): connection entry
1650  * entry(in): CSS_QUEUE_ENTRY * to be retired
1651  */
1652 static void
1654 {
1655  assert (conn != NULL && entry != NULL);
1656 
1657  entry->next = conn->free_queue_list;
1658  conn->free_queue_list = entry;
1659 
1660  conn->free_queue_count++;
1661  assert (0 < conn->free_queue_count);
1662 }
1663 
1664 /*
1665  * css_free_queue_entry_list() - free all entries of free queue list
1666  * return: void
1667  * conn(in): connection entry
1668  */
1669 static void
1671 {
1672  CSS_QUEUE_ENTRY *p;
1673 
1674  assert (conn != NULL);
1675 
1676  while (conn->free_queue_list != NULL)
1677  {
1678  p = conn->free_queue_list;
1679  conn->free_queue_list = p->next;
1680 
1681  free (p);
1682  conn->free_queue_count--;
1683  }
1684 
1685  conn->free_queue_list = NULL;
1686  assert (conn->free_queue_count == 0);
1687 }
1688 
1689 /*
1690  * css_claim_wait_queue_entry() - claim a wait queue entry from free list.
1691  * return: CSS_WAIT_QUEUE_ENTRY *
1692  * conn(in): connection entry
1693  */
1694 static CSS_WAIT_QUEUE_ENTRY *
1696 {
1698 
1699  assert (conn != NULL);
1700 
1701  p = conn->free_wait_queue_list;
1702  if (p == NULL)
1703  {
1704  return NULL;
1705  }
1706 
1707  conn->free_wait_queue_list = p->next;
1708 
1709  conn->free_wait_queue_count--;
1710  assert (0 <= conn->free_wait_queue_count);
1711 
1712  p->next = NULL;
1713 
1714  return p;
1715 }
1716 
1717 /*
1718  * css_retire_wait_queue_entry() - retire a wait_queue entry to free list.
1719  * return: void
1720  * conn(in): connection entry
1721  * entry(in): CSS_WAIT_QUEUE_ENTRY * to be retired
1722  */
1723 static void
1725 {
1726  assert (conn != NULL && entry != NULL);
1727 
1728  entry->next = conn->free_wait_queue_list;
1729  conn->free_wait_queue_list = entry;
1730 
1731  conn->free_wait_queue_count++;
1732  assert (0 < conn->free_wait_queue_count);
1733 }
1734 
1735 /*
1736  * css_free_wait_queue_list() - free all entries of free wait queue list
1737  * return: void
1738  * conn(in): connection entry
1739  */
1740 static void
1742 {
1744 
1745  assert (conn != NULL);
1746 
1747  while (conn->free_wait_queue_list != NULL)
1748  {
1749  p = conn->free_wait_queue_list;
1750  conn->free_wait_queue_list = p->next;
1751 
1752  free (p);
1753  conn->free_wait_queue_count--;
1754  }
1755 
1756  conn->free_wait_queue_list = NULL;
1757  assert (conn->free_wait_queue_count == 0);
1758 }
1759 
1760 /*
1761  * css_claim_net_header_entry() - claim a net header entry from free list.
1762  * return: NET_HEADER *
1763  * conn(in): connection entry
1764  *
1765  * TODO - rewrite this to avoid ugly
1766  */
1767 static NET_HEADER *
1769 {
1770  NET_HEADER *p;
1771 
1772  assert (conn != NULL);
1773 
1774  p = (NET_HEADER *) conn->free_net_header_list;
1775  if (p == NULL)
1776  {
1777  return NULL;
1778  }
1779 
1780  conn->free_net_header_list = (char *) (*(UINTPTR *) p);
1781 
1782  conn->free_net_header_count--;
1783  assert (0 <= conn->free_net_header_count);
1784 
1785  return p;
1786 }
1787 
1788 /*
1789  * css_retire_net_header_entry() - retire a net header entry to free list.
1790  * return: void
1791  * conn(in): connection entry
1792  * entry(in): NET_HEADER * to be retired
1793  */
1794 static void
1796 {
1797  assert (conn != NULL && entry != NULL);
1798 
1799  *(UINTPTR *) entry = (UINTPTR) conn->free_net_header_list;
1800  conn->free_net_header_list = (char *) entry;
1801 
1802  conn->free_net_header_count++;
1803  assert (0 < conn->free_net_header_count);
1804 }
1805 
1806 /*
1807  * css_free_net_header_list() - free all entries of free net header list
1808  * return: void
1809  * conn(in): connection entry
1810  */
1811 static void
1813 {
1814  char *p;
1815 
1816  assert (conn != NULL);
1817 
1818  while (conn->free_net_header_list != NULL)
1819  {
1820  p = conn->free_net_header_list;
1821 
1822  conn->free_net_header_list = (char *) (*(UINTPTR *) p);
1823  conn->free_net_header_count--;
1824 
1825  free (p);
1826  }
1827 
1828  conn->free_net_header_list = NULL;
1829  assert (conn->free_net_header_count == 0);
1830 }
1831 
1832 /*
1833  * css_make_queue_entry() - make queue entey
1834  * return: queue entry
1835  * conn(in): connection entry
1836  * key(in):
1837  * buffer(in):
1838  * size(in):
1839  * rc(in):
1840  * transid(in):
1841  * db_error(in):
1842  */
1843 static CSS_QUEUE_ENTRY *
1844 css_make_queue_entry (CSS_CONN_ENTRY * conn, unsigned int key, char *buffer,
1845  int size, int rc, int transid, int invalidate_snapshot, int db_error)
1846 {
1847  CSS_QUEUE_ENTRY *p;
1848 
1849  if (conn->free_queue_list != NULL)
1850  {
1851  p = css_claim_queue_entry (conn);
1852  }
1853  else
1854  {
1855  p = (CSS_QUEUE_ENTRY *) malloc (sizeof (CSS_QUEUE_ENTRY));
1856  }
1857 
1858  if (p == NULL)
1859  {
1860  return NULL;
1861  }
1862 
1863  p->key = key;
1864  p->buffer = buffer;
1865  p->size = size;
1866  p->rc = rc;
1867  p->transaction_id = transid;
1868  p->invalidate_snapshot = invalidate_snapshot;
1869  p->db_error = db_error;
1870 
1871  return p;
1872 }
1873 
1874 /*
1875  * css_free_queue_entry() - free queue entry
1876  * return: void
1877  * conn(in): connection entry
1878  * entry(in): queue entry
1879  */
1880 static void
1882 {
1883  if (entry == NULL)
1884  {
1885  return;
1886  }
1887 
1888  if (entry->buffer != NULL)
1889  {
1890  free_and_init (entry->buffer);
1891  }
1892 
1893  css_retire_queue_entry (conn, entry);
1894 }
1895 
1896 /*
1897  * css_add_queue_entry() - add queue entry
1898  * return: 0 if success, or error code
1899  * conn(in): connection entry
1900  * list(in): queue list
1901  * request_id(in): request id
1902  * buffer(in):
1903  * buffer_size(in):
1904  * rc(in):
1905  * transid(in):
1906  * db_error(in):
1907  */
1908 static css_error_code
1909 css_add_queue_entry (CSS_CONN_ENTRY * conn, CSS_LIST * list, unsigned short request_id, char *buffer, int buffer_size,
1910  int rc, int transid, int invalidate_snapshot, int db_error)
1911 {
1912  CSS_QUEUE_ENTRY *p;
1913  int r;
1914 
1915  p = css_make_queue_entry (conn, request_id, buffer, buffer_size, rc, transid, invalidate_snapshot, db_error);
1916  if (p == NULL)
1917  {
1918  return CANT_ALLOC_BUFFER;
1919  }
1920 
1921  r = css_add_list (list, p);
1922  if (r != NO_ERROR)
1923  {
1924  css_retire_queue_entry (conn, p);
1925  return CANT_ALLOC_BUFFER;
1926  }
1927 
1928  return NO_ERRORS;
1929 }
1930 
1931 /*
1932  * css_find_queue_entry_by_key() - find queue entry using key
1933  * return: status of traverse
1934  * data(in): queue entry
1935  * user(in): search argument
1936  */
1937 static int
1938 css_find_queue_entry_by_key (void *data, void *user)
1939 {
1941  CSS_QUEUE_ENTRY *p = (CSS_QUEUE_ENTRY *) data;
1942 
1943  if (p->key == arg->key)
1944  {
1945  arg->entry_ptr = p;
1946  if (arg->remove_entry)
1947  {
1948  return TRAV_STOP_DELETE;
1949  }
1950  else
1951  {
1952  return TRAV_STOP;
1953  }
1954  }
1955 
1956  return TRAV_CONT;
1957 }
1958 
1959 /*
1960  * css_find_queue_entry() - find queue entry
1961  * return: queue entry
1962  * list(in): queue list
1963  * key(in): key
1964  */
1965 static CSS_QUEUE_ENTRY *
1966 css_find_queue_entry (CSS_LIST * list, unsigned int key)
1967 {
1969 
1970  arg.entry_ptr = NULL;
1971  arg.key = key;
1972  arg.remove_entry = 0;
1973 
1975 
1976  return arg.entry_ptr;
1977 }
1978 
1979 /*
1980  * css_find_and_remove_queue_entry() - find queue entry and remove it
1981  * return: queue entry
1982  * list(in): queue list
1983  * key(in): key
1984  */
1985 static CSS_QUEUE_ENTRY *
1987 {
1989 
1990  arg.entry_ptr = NULL;
1991  arg.key = key;
1992  arg.remove_entry = 1;
1993 
1995 
1996  return arg.entry_ptr;
1997 }
1998 
1999 /*
2000  * css_make_wait_queue_entry() - make wait queue entry
2001  * return: wait queue entry
2002  * conn(in): connection entry
2003  * key(in):
2004  * buffer(out):
2005  * size(out):
2006  * rc(out):
2007  */
2008 static CSS_WAIT_QUEUE_ENTRY *
2009 css_make_wait_queue_entry (CSS_CONN_ENTRY * conn, unsigned int key, char **buffer, int *size, int *rc)
2010 {
2012 
2013  if (conn->free_wait_queue_list != NULL)
2014  {
2015  p = css_claim_wait_queue_entry (conn);
2016  }
2017  else
2018  {
2019  p = (CSS_WAIT_QUEUE_ENTRY *) malloc (sizeof (CSS_WAIT_QUEUE_ENTRY));
2020  }
2021 
2022  if (p == NULL)
2023  {
2024  return NULL;
2025  }
2026 
2027  p->key = key;
2028  p->buffer = buffer;
2029  p->size = size;
2030  p->rc = rc;
2032 
2033  return p;
2034 }
2035 
2036 /*
2037  * css_free_wait_queue_entry() - free wait queue entry
2038  * return: void
2039  * conn(in): connection entry
2040  * entry(in): wait queue entry
2041  */
2042 static void
2044 {
2045  if (entry == NULL)
2046  {
2047  return;
2048  }
2049 
2050  if (entry->thrd_entry != NULL)
2051  {
2052  thread_lock_entry (entry->thrd_entry);
2053 
2054  assert (entry->thrd_entry->resume_status == THREAD_CSS_QUEUE_SUSPENDED);
2056 
2058  }
2059 
2060  css_retire_wait_queue_entry (conn, entry);
2061 }
2062 
2063 /*
2064  * css_add_wait_queue_entry() - add wait queue entry
2065  * return: wait queue entry
2066  * conn(in): connection entry
2067  * list(in): wait queue list
2068  * request_id(in): request id
2069  * buffer(out):
2070  * buffer_size(out):
2071  * rc(out):
2072  */
2073 static CSS_WAIT_QUEUE_ENTRY *
2074 css_add_wait_queue_entry (CSS_CONN_ENTRY * conn, CSS_LIST * list, unsigned short request_id, char **buffer,
2075  int *buffer_size, int *rc)
2076 {
2078 
2079  p = css_make_wait_queue_entry (conn, request_id, buffer, buffer_size, rc);
2080  if (p == NULL)
2081  {
2082  return NULL;
2083  }
2084 
2085  if (css_add_list (list, p) != NO_ERROR)
2086  {
2087  css_retire_wait_queue_entry (conn, p);
2088  return NULL;
2089  }
2090 
2091  return p;
2092 }
2093 
2094 /*
2095  * find_wait_queue_entry_by_key() - find wait queue entry using key
2096  * return: status of traverse
2097  * data(in): wait queue entry
2098  * user(in): search argument
2099  */
2100 static int
2101 find_wait_queue_entry_by_key (void *data, void *user)
2102 {
2105 
2106  if (p->key == arg->key)
2107  {
2108  arg->entry_ptr = p;
2109  if (arg->remove_entry)
2110  {
2111  return TRAV_STOP_DELETE;
2112  }
2113  else
2114  {
2115  return TRAV_STOP;
2116  }
2117  }
2118 
2119  return TRAV_CONT;
2120 }
2121 
2122 /*
2123  * css_find_and_remove_wait_queue_entry() - find wait queue entry and remove it
2124  * return: wait queue entry
2125  * list(in): wait queue list
2126  * key(in):
2127  */
2128 static CSS_WAIT_QUEUE_ENTRY *
2130 {
2132 
2133  arg.entry_ptr = NULL;
2134  arg.key = key;
2135  arg.remove_entry = 1;
2136 
2138 
2139  return arg.entry_ptr;
2140 }
2141 
2142 
2143 /*
2144  * css_queue_packet() - queue packet
2145  * return: void
2146  * conn(in): connection entry
2147  * type(in): packet type
2148  * request_id(in): request id
2149  * header(in): network header
2150  * size(in): packet size
2151  */
2152 static css_error_code
2153 css_queue_packet (CSS_CONN_ENTRY * conn, int type, unsigned short request_id, const NET_HEADER * header, int size)
2154 {
2155  THREAD_ENTRY *wait_thrd = NULL, *p, *next;
2156  unsigned short flags = 0;
2157  int r;
2158  int transaction_id, db_error, invalidate_snapshot;
2160 
2161  transaction_id = ntohl (header->transaction_id);
2162  db_error = (int) ntohl (header->db_error);
2163  flags = ntohs (header->flags);
2164  invalidate_snapshot = flags | NET_HEADER_FLAG_INVALIDATE_SNAPSHOT ? 1 : 0;
2165 
2166  r = rmutex_lock (NULL, &conn->rmutex);
2167  assert (r == NO_ERROR);
2168 
2169  if (conn->stop_talk)
2170  {
2171  r = rmutex_unlock (NULL, &conn->rmutex);
2172  assert (r == NO_ERROR);
2173  return CONNECTION_CLOSED;
2174  }
2175 
2176  conn->set_tran_index (transaction_id);
2177  conn->db_error = db_error;
2178  conn->invalidate_snapshot = invalidate_snapshot;
2179 
2180  switch (type)
2181  {
2182  case CLOSE_TYPE:
2183  css_process_close_packet (conn);
2184  break;
2185 
2186  case ABORT_TYPE:
2187  css_process_abort_packet (conn, request_id);
2188  break;
2189 
2190  case DATA_TYPE:
2191  css_queue_data_packet (conn, request_id, header, &wait_thrd);
2192  break;
2193 
2194  case ERROR_TYPE:
2195  css_queue_error_packet (conn, request_id, header);
2196  break;
2197 
2198  case COMMAND_TYPE:
2199  rc = css_queue_command_packet (conn, request_id, header, size);
2200  if (rc != NO_ERRORS)
2201  {
2202  r = rmutex_unlock (NULL, &conn->rmutex);
2203  assert (r == NO_ERROR);
2204  return rc;
2205  }
2206  break;
2207 
2208  default:
2209  CSS_TRACE2 ("Asked to queue an unknown packet id = %d.\n", type);
2210  assert (false);
2211  return WRONG_PACKET_TYPE;
2212  }
2213 
2214  p = wait_thrd;
2215  while (p != NULL)
2216  {
2217  thread_lock_entry (p);
2218 
2219  assert (p->resume_status == THREAD_CSS_QUEUE_SUSPENDED || p->resume_status == THREAD_CSECT_WRITER_SUSPENDED);
2220  next = p->next_wait_thrd;
2221  p->next_wait_thrd = NULL;
2222 
2223  /* When the resume_status is THREAD_CSS_QUEUE_SUSPENDED, it means the data waiting thread is still waiting on the
2224  * data queue. Otherwise, in case of THREAD_CSECT_WRITER_SUSPENDED, it means that the thread was timed out, is
2225  * trying to clear its queue buffer (see clear_wait_queue_entry_and_free_buffer function), and waiting for its
2226  * conn->csect. We don't need to wakeup the thread for this case. We may send useless signal for it, but it may
2227  * bring other anomalies: the thread may sleep on another resources which we don't know at this moment. */
2228  if (p->resume_status == THREAD_CSS_QUEUE_SUSPENDED)
2229  {
2231  }
2232 
2233  thread_unlock_entry (p);
2234  p = next;
2235  }
2236 
2237  r = rmutex_unlock (NULL, &conn->rmutex);
2238  assert (r == NO_ERROR);
2239 
2240  return NO_ERRORS;
2241 }
2242 
2243 /*
2244  * css_process_close_packet() - prccess close packet
2245  * return: void
2246  * conn(in): conenction entry
2247  */
2248 static void
2250 {
2251  if (!IS_INVALID_SOCKET (conn->fd))
2252  {
2253  css_shutdown_socket (conn->fd);
2254  conn->fd = INVALID_SOCKET;
2255  }
2256 
2257  conn->status = CONN_CLOSED;
2258 }
2259 
2260 /*
2261  * css_process_abort_packet() - process abort packet
2262  * return: void
2263  * conn(in): connection entry
2264  * request_id(in): request id
2265  */
2266 static void
2267 css_process_abort_packet (CSS_CONN_ENTRY * conn, unsigned short request_id)
2268 {
2269  CSS_QUEUE_ENTRY *request, *data;
2270 
2271  request = css_find_and_remove_queue_entry (&conn->request_queue, request_id);
2272  if (request)
2273  {
2274  css_free_queue_entry (conn, request);
2275  }
2276 
2277  data = css_find_and_remove_queue_entry (&conn->data_queue, request_id);
2278  if (data)
2279  {
2280  css_free_queue_entry (conn, data);
2281  }
2282 
2283  if (css_find_queue_entry (&conn->abort_queue, request_id) == NULL)
2284  {
2285  css_add_queue_entry (conn, &conn->abort_queue, request_id, NULL, 0,
2286  NO_ERRORS, conn->get_tran_index (), conn->invalidate_snapshot, conn->db_error);
2287  }
2288 }
2289 
2290 /*
2291  * css_queue_data_packet() - queue data packet
2292  * return: void
2293  * conn(in): connection entry
2294  * request_id(in): request id
2295  * header(in): network header
2296  * wake_thrd(out): thread that wake up
2297  */
2298 static void
2299 css_queue_data_packet (CSS_CONN_ENTRY * conn, unsigned short request_id,
2300  const NET_HEADER * header, THREAD_ENTRY ** wake_thrd)
2301 {
2302  THREAD_ENTRY *thrd = NULL, *last = NULL;
2303  CSS_QUEUE_ENTRY *buffer_entry;
2304  CSS_WAIT_QUEUE_ENTRY *data_wait = NULL;
2305  char *buffer = NULL;
2306  int rc;
2307  int size; /* size to be read */
2308 
2309  /* setup wake_thrd. hmm.. consider recursion */
2310  if (*wake_thrd != NULL)
2311  {
2312  last = *wake_thrd;
2313  while (last->next_wait_thrd != NULL)
2314  {
2315  last = last->next_wait_thrd;
2316  }
2317  }
2318 
2319  size = ntohl (header->buffer_size);
2320  /* check if user have given a buffer */
2321  buffer_entry = css_find_and_remove_queue_entry (&conn->buffer_queue, request_id);
2322  if (buffer_entry != NULL)
2323  {
2324  /* compare data and buffer size. if different? something wrong!!! */
2325  if (size > buffer_entry->size)
2326  {
2327  size = buffer_entry->size;
2328  }
2329  buffer = buffer_entry->buffer;
2330  buffer_entry->buffer = NULL;
2331 
2332  css_free_queue_entry (conn, buffer_entry);
2333  }
2334  else if (size == 0)
2335  {
2336  buffer = NULL;
2337  }
2338  else
2339  {
2340  buffer = (char *) malloc (size);
2341  }
2342 
2343  /*
2344  * check if there exists thread waiting for data.
2345  * Add to wake_thrd list.
2346  */
2347  data_wait = css_find_and_remove_wait_queue_entry (&conn->data_wait_queue, request_id);
2348 
2349  if (data_wait != NULL)
2350  {
2351  thrd = data_wait->thrd_entry;
2352  thrd->next_wait_thrd = NULL;
2353  if (last == NULL)
2354  {
2355  *wake_thrd = thrd;
2356  }
2357  else
2358  {
2359  last->next_wait_thrd = thrd;
2360  }
2361  last = thrd;
2362  }
2363 
2364  /* receive data into buffer and queue data if there's no waiting thread */
2365  if (buffer != NULL)
2366  {
2367  rc = css_net_recv (conn->fd, buffer, &size, -1);
2368  if (rc == NO_ERRORS || rc == RECORD_TRUNCATED)
2369  {
2370  if (!css_is_request_aborted (conn, request_id))
2371  {
2372  if (data_wait == NULL)
2373  {
2374  /* if waiter not exists, add to data queue */
2375  css_add_queue_entry (conn, &conn->data_queue, request_id, buffer, size, rc, conn->get_tran_index (),
2376  conn->invalidate_snapshot, conn->db_error);
2377  return;
2378  }
2379  else
2380  {
2381  *data_wait->buffer = buffer;
2382  *data_wait->size = size;
2383  *data_wait->rc = rc;
2384  data_wait->thrd_entry = NULL;
2385  css_free_wait_queue_entry (conn, data_wait);
2386  return;
2387  }
2388  }
2389  }
2390  /* if error occurred */
2391  free_and_init (buffer);
2392  }
2393  else
2394  {
2395  rc = CANT_ALLOC_BUFFER;
2396  css_read_remaining_bytes (conn->fd, sizeof (int) + size);
2397  if (!css_is_request_aborted (conn, request_id))
2398  {
2399  if (data_wait == NULL)
2400  {
2401  css_add_queue_entry (conn, &conn->data_queue, request_id, NULL,
2402  0, rc, conn->get_tran_index (), conn->invalidate_snapshot, conn->db_error);
2403  return;
2404  }
2405  }
2406  }
2407 
2408  /* if error was occurred, setup error status */
2409  if (data_wait != NULL)
2410  {
2411  *data_wait->buffer = NULL;
2412  *data_wait->size = 0;
2413  *data_wait->rc = rc;
2414  }
2415 }
2416 
2417 /*
2418  * css_queue_error_packet() - queue error packet
2419  * return: void
2420  * conn(in): connection entry
2421  * request_id(in): request id
2422  * header(in): network header
2423  */
2424 static void
2425 css_queue_error_packet (CSS_CONN_ENTRY * conn, unsigned short request_id, const NET_HEADER * header)
2426 {
2427  char *buffer;
2428  int rc;
2429  int size;
2430 
2431  size = ntohl (header->buffer_size);
2432  buffer = (char *) malloc (size);
2433 
2434  if (buffer != NULL)
2435  {
2436  rc = css_net_recv (conn->fd, buffer, &size, -1);
2437  if (rc == NO_ERRORS || rc == RECORD_TRUNCATED)
2438  {
2439  if (!css_is_request_aborted (conn, request_id))
2440  {
2441  css_add_queue_entry (conn, &conn->error_queue, request_id,
2442  buffer, size, rc, conn->get_tran_index (), conn->invalidate_snapshot,
2443  conn->db_error);
2444  return;
2445  }
2446  }
2447  free_and_init (buffer);
2448  }
2449  else
2450  {
2451  rc = CANT_ALLOC_BUFFER;
2452  css_read_remaining_bytes (conn->fd, sizeof (int) + size);
2453  if (!css_is_request_aborted (conn, request_id))
2454  {
2455  css_add_queue_entry (conn, &conn->error_queue, request_id, NULL, 0,
2456  rc, conn->get_tran_index (), conn->invalidate_snapshot, conn->db_error);
2457  }
2458  }
2459 }
2460 
2461 /*
2462  * css_queue_command_packet() - queue command packet
2463  * return: void
2464  * conn(in): connection entry
2465  * request_id(in): request id
2466  * header(in): network header
2467  * size(in): packet size
2468  */
2469 static css_error_code
2470 css_queue_command_packet (CSS_CONN_ENTRY * conn, unsigned short request_id, const NET_HEADER * header, int size)
2471 {
2472  NET_HEADER *p;
2473  NET_HEADER data_header = DEFAULT_HEADER_DATA;
2475 
2476  assert (!conn->stop_talk);
2477 
2478  if (css_is_request_aborted (conn, request_id))
2479  {
2480  // ignore
2481  return NO_ERRORS;
2482  }
2483 
2484  if (conn->free_net_header_list != NULL)
2485  {
2486  p = css_claim_net_header_entry (conn);
2487  }
2488  else
2489  {
2490  p = (NET_HEADER *) malloc (sizeof (NET_HEADER));
2491  }
2492 
2493  if (p == NULL)
2494  {
2495  assert (false);
2496  return CANT_ALLOC_BUFFER;
2497  }
2498 
2499  memcpy ((char *) p, (char *) header, sizeof (NET_HEADER));
2500 
2501  rc = css_add_queue_entry (conn, &conn->request_queue, request_id, (char *) p, size, NO_ERRORS,
2502  conn->get_tran_index (), conn->invalidate_snapshot, conn->db_error);
2503  if (rc != NO_ERRORS)
2504  {
2505  css_retire_net_header_entry (conn, p);
2506  return rc;
2507  }
2508 
2509  if (ntohl (header->buffer_size) <= 0)
2510  {
2511  // a request without a buffer, e.g, NET_SERVER_LOG_CHECKPOINT, NET_SERVER_TM_SERVER_ABORT.
2512  return NO_ERRORS;
2513  }
2514 
2515  rc = (css_error_code) css_read_header (conn, &data_header);
2516  if (rc != NO_ERRORS)
2517  {
2518  // what to do?
2519  return rc;
2520  }
2521 
2522  rc = css_queue_packet (conn, (int) ntohl (data_header.type), (unsigned short) ntohl (data_header.request_id),
2523  &data_header, sizeof (NET_HEADER));
2524  return rc;
2525 }
2526 
2527 /*
2528  * css_request_aborted() - check request is aborted
2529  * return: true if aborted, or false
2530  * conn(in): connection entry
2531  * request_id(in): request id
2532  */
2533 static bool
2534 css_is_request_aborted (CSS_CONN_ENTRY * conn, unsigned short request_id)
2535 {
2536  CSS_QUEUE_ENTRY *p;
2537 
2538  p = css_find_queue_entry (&conn->abort_queue, request_id);
2539  if (p != NULL)
2540  {
2541  return true;
2542  }
2543  else
2544  {
2545  return false;
2546  }
2547 }
2548 
2549 /*
2550  * css_return_queued_request() - get request from queue
2551  * return: 0 if success, or error code
2552  * conn(in): connection entry
2553  * rid(out): request id
2554  * request(out): request
2555  * buffer_size(out): request buffer size
2556  */
2557 int
2558 css_return_queued_request (CSS_CONN_ENTRY * conn, unsigned short *rid, int *request, int *buffer_size)
2559 {
2560  CSS_QUEUE_ENTRY *p;
2561  NET_HEADER *buffer;
2562  int rc, r;
2563 
2564  r = rmutex_lock (NULL, &conn->rmutex);
2565  assert (r == NO_ERROR);
2566 
2567  if (conn->status == CONN_OPEN)
2568  {
2570  if (p != NULL)
2571  {
2572  *rid = p->key;
2573 
2574  buffer = (NET_HEADER *) p->buffer;
2575  p->buffer = NULL;
2576 
2577  *request = ntohs (buffer->function_code);
2578  *buffer_size = ntohl (buffer->buffer_size);
2579 
2580  conn->set_tran_index (p->transaction_id);
2582  conn->db_error = p->db_error;
2583 
2584  css_retire_net_header_entry (conn, buffer);
2585 
2586  css_free_queue_entry (conn, p);
2587  rc = NO_ERRORS;
2588  }
2589  else
2590  {
2591  rc = NO_DATA_AVAILABLE;
2592  }
2593  }
2594  else
2595  {
2596  rc = CONN_CLOSED;
2597  }
2598 
2599  r = rmutex_unlock (NULL, &conn->rmutex);
2600  assert (r == NO_ERROR);
2601  return rc;
2602 }
2603 
2604 /*
2605  * clear_wait_queue_entry_and_free_buffer () - remove data_wait_queue entry when completing or aborting
2606  * to receive buffer from data_wait_queue.
2607  * return: void
2608  * conn(in): connection entry
2609  * rid(in): request id
2610  * bufferp(in): data buffer
2611  */
2612 static void
2613 clear_wait_queue_entry_and_free_buffer (THREAD_ENTRY * thrdp, CSS_CONN_ENTRY * conn, unsigned short rid, char **bufferp)
2614 {
2615  CSS_WAIT_QUEUE_ENTRY *data_wait;
2616  int r;
2617 
2618  r = rmutex_lock (thrdp, &conn->rmutex);
2619  assert (r == NO_ERROR);
2620 
2621  /* check the deadlock related problem */
2622  data_wait = css_find_and_remove_wait_queue_entry (&conn->data_wait_queue, rid);
2623 
2624  /* data_wait might be always not NULL except the actual connection close */
2625  if (data_wait)
2626  {
2627  assert (data_wait->thrd_entry == thrdp); /* it must be me */
2628  data_wait->thrd_entry = NULL;
2629  css_free_wait_queue_entry (conn, data_wait);
2630  }
2631  else
2632  {
2633  /* connection_handler_thread may proceed ahead of me right after timeout has happened. If the case, we must free
2634  * the buffer. */
2635  if (*bufferp != NULL)
2636  {
2637  free_and_init (*bufferp);
2638  }
2639  }
2640 
2641  r = rmutex_unlock (thrdp, &conn->rmutex);
2642  assert (r == NO_ERROR);
2643 }
2644 
2645 /*
2646  * css_return_queued_data_timeout() - get request data from queue until timeout
2647  * return: 0 if success, or error code
2648  * conn(in): connection entry
2649  * rid(out): request id
2650  * buffer(out): data buffer
2651  * bufsize(out): buffer size
2652  * rc(out):
2653  * waitsec: timeout second
2654  */
2655 static int
2657  char **buffer, int *bufsize, int *rc, int waitsec)
2658 {
2659  CSS_QUEUE_ENTRY *data_entry, *buffer_entry;
2660  CSS_WAIT_QUEUE_ENTRY *data_wait;
2661 
2662  int r;
2663 
2664  /* enter the critical section of this connection */
2665  r = rmutex_lock (NULL, &conn->rmutex);
2666  assert (r == NO_ERROR);
2667 
2668  *buffer = NULL;
2669  *bufsize = -1;
2670 
2671  /* if conn is closed or to be closed, return CONECTION_CLOSED */
2672  if (conn->status == CONN_OPEN)
2673  {
2674  /* look up the data queue first to see if the required data is arrived and queued already */
2675  data_entry = css_find_and_remove_queue_entry (&conn->data_queue, rid);
2676 
2677  if (data_entry)
2678  {
2679  /* look up the buffer queue to see if the user provided the receive data buffer */
2680  buffer_entry = css_find_and_remove_queue_entry (&conn->buffer_queue, rid);
2681 
2682  if (buffer_entry)
2683  {
2684  /* copy the received data to the user provided buffer area */
2685  *buffer = buffer_entry->buffer;
2686  *bufsize = MIN (data_entry->size, buffer_entry->size);
2687  if (*buffer != data_entry->buffer || *bufsize != data_entry->size)
2688  {
2689  memcpy (*buffer, data_entry->buffer, *bufsize);
2690  }
2691 
2692  /* destroy the buffer queue entry */
2693  buffer_entry->buffer = NULL;
2694  css_free_queue_entry (conn, buffer_entry);
2695  }
2696  else
2697  {
2698  /* set the buffer to point to the data queue entry */
2699  *buffer = data_entry->buffer;
2700  *bufsize = data_entry->size;
2701  data_entry->buffer = NULL;
2702  }
2703 
2704  /* set return code, transaction id, and error code */
2705  *rc = data_entry->rc;
2706  conn->set_tran_index (data_entry->transaction_id);
2707  conn->invalidate_snapshot = data_entry->invalidate_snapshot;
2708  conn->db_error = data_entry->db_error;
2709 
2710  css_free_queue_entry (conn, data_entry);
2711 
2712  r = rmutex_unlock (NULL, &conn->rmutex);
2713  assert (r == NO_ERROR);
2714 
2715  return NO_ERRORS;
2716  }
2717  else
2718  {
2719  THREAD_ENTRY *thrd;
2720 
2721  /* no data queue entry means that the data is not arrived yet; wait until the data arrives */
2722  *rc = NO_DATA_AVAILABLE;
2723 
2724  /* lock thread entry before enqueue an entry to data wait queue in order to prevent being woken up by
2725  * 'css_queue_packet()' before this thread suspends */
2726  thrd = thread_get_thread_entry_info ();
2727  thread_lock_entry (thrd);
2728  /* make a data wait queue entry */
2729  data_wait = css_add_wait_queue_entry (conn, &conn->data_wait_queue, rid, buffer, bufsize, rc);
2730  if (data_wait)
2731  {
2732  /* exit the critical section before to be suspended */
2733  r = rmutex_unlock (NULL, &conn->rmutex);
2734  assert (r == NO_ERROR);
2735 
2736  /* fall to the thread sleep until the socket listener 'css_server_thread()' receives and enqueues the
2737  * data */
2738  if (waitsec < 0)
2739  {
2741 
2742  if (thrd->resume_status != THREAD_CSS_QUEUE_RESUMED)
2743  {
2744  assert (thrd->resume_status == THREAD_RESUME_DUE_TO_INTERRUPT);
2745 
2746  clear_wait_queue_entry_and_free_buffer (thrd, conn, rid, buffer);
2747  *buffer = NULL;
2748  *bufsize = -1;
2749  return NO_DATA_AVAILABLE;
2750  }
2751  else
2752  {
2753  assert (thrd->resume_status == THREAD_CSS_QUEUE_RESUMED);
2754  }
2755  }
2756  else
2757  {
2758  int r;
2759  struct timespec abstime;
2760 
2761  abstime.tv_sec = (int) time (NULL) + waitsec;
2762  abstime.tv_nsec = 0;
2763 
2765 
2767  {
2768  clear_wait_queue_entry_and_free_buffer (thrd, conn, rid, buffer);
2769  *rc = TIMEDOUT_ON_QUEUE;
2770  *buffer = NULL;
2771  *bufsize = -1;
2772  return TIMEDOUT_ON_QUEUE;
2773  }
2774  else if (thrd->resume_status != THREAD_CSS_QUEUE_RESUMED)
2775  {
2776  assert (thrd->resume_status == THREAD_RESUME_DUE_TO_INTERRUPT);
2777 
2778  clear_wait_queue_entry_and_free_buffer (thrd, conn, rid, buffer);
2779  *buffer = NULL;
2780  *bufsize = -1;
2781  return NO_DATA_AVAILABLE;
2782  }
2783  else
2784  {
2785  assert (thrd->resume_status == THREAD_CSS_QUEUE_RESUMED);
2786  }
2787  }
2788 
2789  if (*buffer == NULL || *bufsize < 0)
2790  {
2791  return CONNECTION_CLOSED;
2792  }
2793 
2794  if (*rc == CONNECTION_CLOSED)
2795  {
2796  clear_wait_queue_entry_and_free_buffer (thrd, conn, rid, buffer);
2797  }
2798 
2799  return NO_ERRORS;
2800  }
2801  else
2802  {
2803  /* oops! error! unlock thread entry */
2804  thread_unlock_entry (thrd);
2805  /* allocation error */
2806  *rc = CANT_ALLOC_BUFFER;
2807  }
2808  }
2809  }
2810  else
2811  {
2812  /* conn->status == CONN_CLOSED || CONN_CLOSING; the connection was closed */
2813  *rc = CONNECTION_CLOSED;
2814  }
2815 
2816  /* exit the critical section */
2817  r = rmutex_unlock (NULL, &conn->rmutex);
2818  assert (r == NO_ERROR);
2819  return *rc;
2820 }
2821 
2822 /*
2823  * css_return_queued_data() - get data from queue
2824  * return: 0 if success, or error code
2825  * conn(in): connection entry
2826  * rid(out): request id
2827  * buffer(out): data buffer
2828  * bufsize(out): buffer size
2829  * rc(out):
2830  */
2831 int
2832 css_return_queued_data (CSS_CONN_ENTRY * conn, unsigned short rid, char **buffer, int *bufsize, int *rc)
2833 {
2834  return css_return_queued_data_timeout (conn, rid, buffer, bufsize, rc, -1);
2835 }
2836 
2837 /*
2838  * css_return_queued_error() - get error from queue
2839  * return: 0 if success, or error code
2840  * conn(in): connection entry
2841  * request_id(out): request id
2842  * buffer(out): data buffer
2843  * buffer_size(out): buffer size
2844  * rc(out):
2845  */
2846 int
2847 css_return_queued_error (CSS_CONN_ENTRY * conn, unsigned short request_id, char **buffer, int *buffer_size, int *rc)
2848 {
2849  CSS_QUEUE_ENTRY *p;
2850  int ret = 0, r;
2851 
2852  r = rmutex_lock (NULL, &conn->rmutex);
2853  assert (r == NO_ERROR);
2854 
2855  p = css_find_and_remove_queue_entry (&conn->error_queue, request_id);
2856  if (p != NULL)
2857  {
2858  *buffer = p->buffer;
2859  *buffer_size = p->size;
2860  *rc = p->db_error;
2861  p->buffer = NULL;
2862  css_free_queue_entry (conn, p);
2863  ret = 1;
2864  }
2865 
2866  r = rmutex_unlock (NULL, &conn->rmutex);
2867  assert (r == NO_ERROR);
2868 
2869  return ret;
2870 }
2871 
2872 /*
2873  * css_is_valid_request_id() - check request id id valid
2874  * return: true if valid, or false
2875  * conn(in): connection entry
2876  * request_id(in): request id
2877  */
2878 static bool
2879 css_is_valid_request_id (CSS_CONN_ENTRY * conn, unsigned short request_id)
2880 {
2881  if (css_find_queue_entry (&conn->data_queue, request_id) != NULL)
2882  {
2883  return false;
2884  }
2885 
2886  if (css_find_queue_entry (&conn->request_queue, request_id) != NULL)
2887  {
2888  return false;
2889  }
2890 
2891  if (css_find_queue_entry (&conn->abort_queue, request_id) != NULL)
2892  {
2893  return false;
2894  }
2895 
2896  if (css_find_queue_entry (&conn->error_queue, request_id) != NULL)
2897  {
2898  return false;
2899  }
2900 
2901  return true;
2902 }
2903 
2904 /*
2905  * css_remove_unexpected_packets() - remove unexpected packet
2906  * return: void
2907  * conn(in): connection entry
2908  * request_id(in): request id
2909  */
2910 void
2911 css_remove_unexpected_packets (CSS_CONN_ENTRY * conn, unsigned short request_id)
2912 {
2916 }
2917 
2918 /*
2919  * css_queue_user_data_buffer() - queue user data
2920  * return: 0 if success, or error code
2921  * conn(in): connection entry
2922  * request_id(in): request id
2923  * size(in): buffer size
2924  * buffer(in): buffer
2925  */
2926 int
2927 css_queue_user_data_buffer (CSS_CONN_ENTRY * conn, unsigned short request_id, int size, char *buffer)
2928 {
2929  int rc = NO_ERRORS, r;
2930 
2931  r = rmutex_lock (NULL, &conn->rmutex);
2932  assert (r == NO_ERROR);
2933 
2934  if (buffer && (!css_is_request_aborted (conn, request_id)))
2935  {
2936  rc = css_add_queue_entry (conn, &conn->buffer_queue, request_id, buffer,
2937  size, NO_ERRORS, conn->get_tran_index (), conn->invalidate_snapshot, conn->db_error);
2938  }
2939 
2940  r = rmutex_unlock (NULL, &conn->rmutex);
2941  assert (r == NO_ERROR);
2942 
2943  return rc;
2944 }
2945 
2946 /*
2947  * css_remove_and_free_queue_entry() - free queue entry
2948  * return: status if traverse
2949  * data(in): connection entry
2950  * arg(in): queue entry
2951  */
2952 static int
2953 css_remove_and_free_queue_entry (void *data, void *arg)
2954 {
2956  return TRAV_CONT_DELETE;
2957 }
2958 
2959 /*
2960  * css_remove_and_free_wait_queue_entry() - free wait queue entry
2961  * return: status if traverse
2962  * data(in): connection entry
2963  * arg(in): wait queue entry
2964  */
2965 static int
2967 {
2969  return TRAV_CONT_DELETE;
2970 }
2971 
2972 /*
2973  * css_remove_all_unexpected_packets() - remove all unexpected packets
2974  * return: void
2975  * conn(in): connection entry
2976  */
2977 void
2979 {
2980  int r;
2981 
2982  r = rmutex_lock (NULL, &conn->rmutex);
2983  assert (r == NO_ERROR);
2984 
2986 
2988 
2989  css_traverse_list (&conn->data_wait_queue, css_remove_and_free_wait_queue_entry, conn);
2990 
2992 
2994 
2995  r = rmutex_unlock (NULL, &conn->rmutex);
2996  assert (r == NO_ERROR);
2997 }
2998 
2999 /*
3000  * css_set_user_access_status() - set user access status information
3001  * return: void
3002  * db_user(in):
3003  * host(in):
3004  * program_name(in):
3005  */
3006 void
3007 css_set_user_access_status (const char *db_user, const char *host, const char *program_name)
3008 {
3009  LAST_ACCESS_STATUS *access = NULL;
3010 
3011  assert (db_user != NULL);
3012  assert (host != NULL);
3013  assert (program_name != NULL);
3014 
3016 
3017  for (access = css_Access_status_anchor; access != NULL; access = access->next)
3018  {
3019  if (strcmp (access->db_user, db_user) == 0)
3020  {
3021  break;
3022  }
3023  }
3024 
3025  if (access == NULL)
3026  {
3027  access = (LAST_ACCESS_STATUS *) malloc (sizeof (LAST_ACCESS_STATUS));
3028  if (access == NULL)
3029  {
3030  /* if memory allocation fail, just ignore and return */
3032  return;
3033  }
3035 
3036  memset (access, 0, sizeof (LAST_ACCESS_STATUS));
3037 
3038  access->next = css_Access_status_anchor;
3039  css_Access_status_anchor = access;
3040 
3041  strncpy (access->db_user, db_user, sizeof (access->db_user) - 1);
3042  }
3043 
3045 
3046  access->time = time (NULL);
3047  strncpy (access->host, host, sizeof (access->host) - 1);
3048  strncpy (access->program_name, program_name, sizeof (access->program_name) - 1);
3049 
3050  return;
3051 }
3052 
3053 /*
3054  * css_get_user_access_status() - get user access status informations
3055  * return: void
3056  * num_user(in):
3057  * access_status_array(out):
3058  */
3059 void
3060 css_get_user_access_status (int num_user, LAST_ACCESS_STATUS ** access_status_array)
3061 {
3062  int i = 0;
3063  LAST_ACCESS_STATUS *access = NULL;
3064 
3066 
3067  for (access = css_Access_status_anchor; (access != NULL && i < num_user); access = access->next, i++)
3068  {
3069  access_status_array[i] = access;
3070  }
3071 
3073 
3074  return;
3075 }
3076 
3077 /*
3078  * css_free_user_access_status() - free all user access status information
3079  * return: void
3080  */
3081 void
3083 {
3084  LAST_ACCESS_STATUS *access = NULL;
3085 
3087 
3088  while (css_Access_status_anchor != NULL)
3089  {
3090  access = css_Access_status_anchor;
3091  css_Access_status_anchor = access->next;
3092 
3093  free_and_init (access);
3094  }
3095 
3096  css_Num_access_user = 0;
3097 
3099 
3100  return;
3101 }
struct css_wait_queue_entry * next
#define rmutex_finalize(a)
void css_shutdown_conn(CSS_CONN_ENTRY *conn)
CSS_QUEUE_ENTRY * entry_ptr
static void css_remove_unexpected_packets(CSS_CONN_ENTRY *conn, unsigned short request_id)
int status
void css_remove_all_unexpected_packets(CSS_CONN_ENTRY *conn)
char ** buffer
Definition: connection_sr.c:98
CSS_CONN_ENTRY * css_find_conn_by_tran_index(int tran_index)
CSS_QUEUE_ENTRY * buffer_queue
css_error_code
cubthread::entry * thread_get_thread_entry_info(void)
#define NO_ERROR
Definition: error_code.h:46
static int css_find_queue_entry_by_key(void *data, void *user)
#define END_SHARED_ACCESS_ACTIVE_CONN_ANCHOR(r)
Definition: connection_sr.h:82
static void css_queue_data_packet(CSS_CONN_ENTRY *conn, unsigned short request_id, const NET_HEADER *header, THREAD_ENTRY **wait_thrd)
static CSS_WAIT_QUEUE_ENTRY * css_find_and_remove_wait_queue_entry(CSS_LIST *list, unsigned int key)
#define ERR_CSS_ERROR_DURING_SERVER_CONNECT
Definition: error_code.h:444
bool css_tcp_listen_server_datagram(SOCKET sockfd, SOCKET *newfd)
Definition: tcp.c:930
static NET_HEADER * css_claim_net_header_entry(CSS_CONN_ENTRY *conn)
#define START_EXCLUSIVE_ACCESS_ACTIVE_CONN_ANCHOR(r)
Definition: connection_sr.h:58
void css_print_free_conn_list(void)
int SOCKET
Definition: porting.h:482
#define ASSERT_ERROR()
int(* CSS_THREAD_FN)(THREAD_ENTRY *thrd, CSS_THREAD_ARG)
static void css_free_net_header_list(CSS_CONN_ENTRY *conn)
void css_shutdown_conn_by_tran_index(int tran_index)
#define ER_CSS_PTHREAD_COND_TIMEDOUT
Definition: error_code.h:1428
const int css_Conn_rules_size
#define rmutex_unlock(a, b)
CSS_CONN_ENTRY * css_make_conn(SOCKET fd)
enum db_client_type BOOT_CLIENT_TYPE
unsigned int htonl(unsigned int from)
static unsigned int css_make_eid(unsigned short entry_id, unsigned short rid)
#define ER_FAILED
Definition: error_code.h:47
int css_return_queued_request(CSS_CONN_ENTRY *conn, unsigned short *rid, int *request, int *buffer_size)
#define csect_enter(a, b, c)
Definition: cnv.c:138
static LAST_ACCESS_STATUS * css_Access_status_anchor
#define pthread_mutex_unlock(a)
Definition: area_alloc.c:51
CSS_CONN_RULE_INFO css_Conn_rules[]
int css_Server_inhibit_connection_socket
static int css_remove_and_free_queue_entry(void *data, void *arg)
int css_Server_use_new_connection_protocol
void css_final_conn_list(void)
int db_error
CSS_THREAD_FN css_Connection_error_handler
int css_return_queued_error(CSS_CONN_ENTRY *conn, unsigned short request_id, char **buffer, int *buffer_size, int *rc)
int css_increment_num_conn(BOOT_CLIENT_TYPE client_type)
unsigned int css_return_eid_from_conn(CSS_CONN_ENTRY *conn, unsigned short rid)
CSS_THREAD_FN css_Request_handler
#define NET_HEADER_FLAG_INVALIDATE_SNAPSHOT
static pthread_mutex_t css_Client_id_lock
void css_print_conn_list(void)
void thread_wakeup_already_had_mutex(cubthread::entry *thread_p, thread_resume_suspend_status resume_reason)
char db_user[DB_MAX_USER_LENGTH]
static css_error_code css_queue_packet(CSS_CONN_ENTRY *conn, int type, unsigned short request_id, const NET_HEADER *header, int size)
int css_queue_user_data_buffer(CSS_CONN_ENTRY *conn, unsigned short request_id, int size, char *buffer)
int size
SOCKET fd
#define ER_CSS_PTHREAD_MUTEX_LOCK
Definition: error_code.h:999
static void css_free_queue_entry(CSS_CONN_ENTRY *conn, CSS_QUEUE_ENTRY *entry)
#define CSS_ACTIVE_CONN_ARGS
#define CSS_RWLOCK_ACTIVE_CONN_ANCHOR_NAME
Definition: connection_sr.h:56
static CSS_QUEUE_ENTRY * css_find_and_remove_queue_entry(CSS_LIST *list, unsigned int key)
void thread_suspend_wakeup_and_unlock_entry(cubthread::entry *thread_p, thread_resume_suspend_status suspended_reason)
static int css_Num_active_conn
#define START_SHARED_ACCESS_FREE_CONN_ANCHOR(r)
unsigned short flags
int css_initialize_list(CSS_LIST *list, int free_count)
void css_free_conn(CSS_CONN_ENTRY *conn)
struct css_wait_queue_entry CSS_WAIT_QUEUE_ENTRY
#define START_EXCLUSIVE_ACCESS_FREE_CONN_ANCHOR(r)
Definition: connection_sr.h:95
bool css_tcp_setup_server_datagram(const char *pathname, SOCKET *sockfd)
Definition: tcp.c:882
#define INVALID_SOCKET
Definition: porting.h:483
static int find_wait_queue_entry_by_key(void *data, void *user)
void css_decrement_num_conn(BOOT_CLIENT_TYPE client_type)
void css_read_remaining_bytes(SOCKET fd, int len)
static int css_return_queued_data_timeout(CSS_CONN_ENTRY *conn, unsigned short rid, char **buffer, int *bufsize, int *rc, int waitsec)
#define CSS_RWLOCK_ACTIVE_CONN_ANCHOR
Definition: connection_sr.h:55
static void css_retire_queue_entry(CSS_CONN_ENTRY *conn, CSS_QUEUE_ENTRY *entry)
unsigned int key
#define END_EXCLUSIVE_ACCESS_FREE_CONN_ANCHOR(r)
char host[CUB_MAXHOSTNAMELEN]
static bool css_is_valid_request_id(CSS_CONN_ENTRY *conn, unsigned short request_id)
static bool css_is_request_aborted(CSS_CONN_ENTRY *conn, unsigned short request_id)
void THREAD_ENTRY
int css_receive_request(CSS_CONN_ENTRY *conn, unsigned short *rid, int *request, int *buffer_size)
static void clear_wait_queue_entry_and_free_buffer(THREAD_ENTRY *thrdp, CSS_CONN_ENTRY *conn, unsigned short rid, char **bufferp)
void css_insert_into_active_conn_list(CSS_CONN_ENTRY *conn)
int css_net_send(CSS_CONN_ENTRY *conn, const char *buff, int len, int timeout)
#define CSS_CONN_IDX(conn_arg)
#define TRACE(string, arg)
Definition: connection_sr.c:92
int css_get_session_ids_for_active_connections(SESSION_ID **session_ids, int *count)
#define ERR_CSS_SERVER_ALREADY_EXISTS
Definition: error_code.h:443
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
LAST_ACCESS_STATUS * next
static void css_free_wait_queue_list(CSS_CONN_ENTRY *conn)
CSS_QUEUE_ENTRY * data_queue
int css_send_request(CSS_CONN_ENTRY *conn, int command, unsigned short *request_id, const char *arg_buffer, int arg_buffer_size)
#define assert(x)
void css_get_user_access_status(int num_user, LAST_ACCESS_STATUS **access_status_array)
int transaction_id
css_error_code(* css_Connect_handler)(CSS_CONN_ENTRY *)
int rc
#define END_SHARED_ACCESS_FREE_CONN_ANCHOR(r)
SOCKET css_tcp_client_open(const char *host, int port)
Definition: tcp.c:182
Definition: connection_sr.c:96
unsigned short css_get_request_id(CSS_CONN_ENTRY *conn)
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
#define START_SHARED_ACCESS_ACTIVE_CONN_ANCHOR(r)
Definition: connection_sr.h:74
int css_init_conn_list(void)
unsigned short request_id
void css_register_handler_routines(css_error_code(*connect_handler)(CSS_CONN_ENTRY *conn), CSS_THREAD_FN request_handler, CSS_THREAD_FN connection_error_handler)
int css_traverse_list(CSS_LIST *list, int(*func)(void *, void *), void *arg)
static void css_free_wait_queue_entry(CSS_CONN_ENTRY *conn, CSS_WAIT_QUEUE_ENTRY *entry)
static CSS_CONN_ENTRY * css_common_connect(CSS_CONN_ENTRY *conn, unsigned short *rid, const char *host_name, int connect_type, const char *server_name, int server_name_length, int port)
#define IS_INVALID_SOCKET(socket)
Definition: porting.h:484
#define DEFAULT_HEADER_DATA
int css_add_list(CSS_LIST *list, void *item)
int css_Num_access_user
int css_return_queued_data(CSS_CONN_ENTRY *conn, unsigned short rid, char **buffer, int *bufsize, int *rc)
static CSS_QUEUE_ENTRY * css_make_queue_entry(CSS_CONN_ENTRY *conn, unsigned int key, char *buffer, int size, int rc, int transid, int invalidate_snapshot, int db_error)
void css_shutdown_socket(SOCKET fd)
Definition: tcp.c:1179
static css_error_code css_add_queue_entry(CSS_CONN_ENTRY *conn, CSS_LIST *list, unsigned short request_id, char *buffer, int buffer_size, int rc, int transid, int invalidate_snapshot, int db_error)
static void css_process_close_packet(CSS_CONN_ENTRY *conn)
#define ER_CSS_CONN_INIT
Definition: error_code.h:1017
static int rv
Definition: area_alloc.c:52
#define NULL
Definition: freelistheap.h:34
static void css_dealloc_conn(CSS_CONN_ENTRY *conn)
static CSS_QUEUE_ENTRY * css_find_queue_entry(CSS_LIST *list, unsigned int key)
#define rmutex_lock(a, b)
static int css_increment_num_conn_internal(CSS_CONN_RULE_INFO *conn_rule_info)
if(extra_options)
Definition: dynamic_load.c:958
bool in_transaction
static CSS_WAIT_QUEUE_ENTRY * css_claim_wait_queue_entry(CSS_CONN_ENTRY *conn)
#define CSS_RWLOCK_FREE_CONN_ANCHOR_NAME
Definition: connection_sr.h:93
unsigned short htons(unsigned short from)
#define err(fd,...)
Definition: porting.h:431
static const int CSS_MAX_CLIENT_ID
struct queue_search_arg CSS_QUEUE_SEARCH_ARG
#define DB_EMPTY_SESSION
Definition: dbtype_def.h:483
void thread_lock_entry(cubthread::entry *thread_p)
CSS_QUEUE_ENTRY * abort_queue
struct wait_queue_search_arg CSS_WAIT_QUEUE_SEARCH_ARG
static css_error_code css_queue_command_packet(CSS_CONN_ENTRY *conn, unsigned short request_id, const NET_HEADER *header, int size)
struct packet_header NET_HEADER
#define csect_exit(a, b)
Definition: cnv.c:139
unsigned int key
static CSS_WAIT_QUEUE_ENTRY * css_make_wait_queue_entry(CSS_CONN_ENTRY *conn, unsigned int key, char **buffer, int *size, int *rc)
CSS_CONN_ENTRY * css_connect_to_master_server(int master_port_id, const char *server_name, int name_length)
static void css_retire_wait_queue_entry(CSS_CONN_ENTRY *conn, CSS_WAIT_QUEUE_ENTRY *entry)
int * size
Definition: connection_sr.c:99
void er_set_with_oserror(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
CSS_CONN_ENTRY * css_Active_conn_anchor
int invalidate_snapshot
static void css_free_queue_entry_list(CSS_CONN_ENTRY *conn)
#define NULL_TRAN_INDEX
void css_init_conn_rules(void)
int css_receive_data(CSS_CONN_ENTRY *conn, unsigned short req_id, char **buffer, int *buffer_size, int timeout)
static void error(const char *msg)
Definition: gencat.c:331
#define ER_CSS_CLIENTS_EXCEEDED
Definition: error_code.h:809
void thread_unlock_entry(cubthread::entry *thread_p)
static void css_process_abort_packet(CSS_CONN_ENTRY *conn, unsigned short request_id)
#define CSS_LOG_STACK(msg_arg,...)
int css_readn(SOCKET fd, char *ptr, int nbytes, int timeout)
int css_get_max_conn(void)
void * css_remove_list_from_head(CSS_LIST *list)
#define ARG_FILE_LINE
Definition: error_manager.h:44
THREAD_ENTRY * thrd_entry
#define rwlock_finalize(a)
bool reset_on_commit
unsigned short ntohs(unsigned short from)
static int css_Num_free_conn
void css_dealloc_conn_rmutex(CSS_CONN_ENTRY *conn)
#define csect_enter_as_reader(a, b, c)
#define free_and_init(ptr)
Definition: memory_alloc.h:147
int css_read_header(CSS_CONN_ENTRY *conn, const NET_HEADER *local_header)
CSS_QUEUE_ENTRY * next
static int css_get_next_client_id(void)
void css_set_user_access_status(const char *db_user, const char *host, const char *program_name)
int css_Service_id
unsigned int SESSION_ID
Definition: dbtype_def.h:480
int css_get_num_free_conn(void)
#define ER_CSS_PTHREAD_MUTEX_UNLOCK
Definition: error_code.h:1001
#define CSS_ACTIVE_CONN_MSG
CSS_QUEUE_ENTRY * error_queue
int thread_suspend_timeout_wakeup_and_unlock_entry(cubthread::entry *thread_p, struct timespec *time_p, thread_resume_suspend_status suspended_reason)
int css_net_recv(SOCKET fd, char *buffer, int *maxlen, int timeout)
int css_finalize_list(CSS_LIST *list)
#define CSS_RWLOCK_FREE_CONN_ANCHOR
Definition: connection_sr.h:92
static void css_retire_net_header_entry(CSS_CONN_ENTRY *conn, NET_HEADER *entry)
int i
Definition: dynamic_load.c:954
static int css_remove_and_free_wait_queue_entry(void *data, void *arg)
CSS_WAIT_QUEUE_ENTRY * entry_ptr
static CSS_CONN_ENTRY * css_Free_conn_anchor
#define NUM_MASTER_CHANNEL
static int css_Num_max_conn
int css_read_and_queue(CSS_CONN_ENTRY *conn, int *type)
int css_send_magic(CSS_CONN_ENTRY *conn)
#define pthread_mutex_lock(a)
Definition: area_alloc.c:50
CSS_CONN_ENTRY * css_find_conn_from_fd(SOCKET fd)
#define CSS_FREE_CONN_MSG
int css_net_read_header(SOCKET fd, char *buffer, int *maxlen, int timeout)
unsigned int ntohl(unsigned int from)
int invalidate_snapshot
int css_send_data(CSS_CONN_ENTRY *conn, unsigned short rid, const char *buffer, int buffer_size)
int * rc
#define CSS_FREE_CONN_ARGS
static void css_decrement_num_conn_internal(CSS_CONN_RULE_INFO *conn_rule_info)
CSS_QUEUE_ENTRY * request_queue
void css_free_user_access_status(void)
CSS_CONN_ENTRY * next
static pthread_mutex_t css_Conn_rule_lock
#define rmutex_initialize(a, b)
#define CSS_CR_NORMAL_ONLY_IDX
int css_send_abort_request(CSS_CONN_ENTRY *conn, unsigned short request_id)
const char * program_name
Definition: cas.c:147
#define CUB_MAXHOSTNAMELEN
Definition: porting.h:379
int db_error
void css_print_conn_entry_info(CSS_CONN_ENTRY *conn)
#define RMUTEX_NAME_CONN_ENTRY
static char * host
int css_open_server_connection_socket(void)
Definition: tcp.c:1228
static CSS_WAIT_QUEUE_ENTRY * css_add_wait_queue_entry(CSS_CONN_ENTRY *conn, CSS_LIST *list, unsigned short request_id, char **buffer, int *buffer_size, int *rc)
static CSS_QUEUE_ENTRY * css_claim_queue_entry(CSS_CONN_ENTRY *conn)
CSS_CONN_ENTRY * css_Conn_array
#define ERR_CSS_REQUEST_ID_FAILURE
Definition: error_code.h:420
static int css_abort_request(CSS_CONN_ENTRY *conn, unsigned short rid)
int css_initialize_conn(CSS_CONN_ENTRY *conn, SOCKET fd)
#define END_EXCLUSIVE_ACCESS_ACTIVE_CONN_ANCHOR(r)
Definition: connection_sr.h:66
#define GETHOSTNAME(p, l)
Definition: porting.h:381
const char ** p
Definition: dynamic_load.c:945
SESSION_ID session_id
SYNC_RWLOCK css_Rwlock_active_conn_anchor
#define rwlock_initialize(a, b)
SYNC_RWLOCK css_Rwlock_free_conn_anchor
int client_id
static void css_queue_error_packet(CSS_CONN_ENTRY *conn, unsigned short request_id, const NET_HEADER *header)
char * buffer
static int css_Client_id