CUBRID Engine  latest
connection_support.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_support.c - general networking function
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/types.h>
32 #include <assert.h>
33 
34 #if defined(WINDOWS)
35 #include <winsock2.h>
36 #else /* WINDOWS */
37 #include <sys/time.h>
38 #include <sys/ioctl.h>
39 #include <sys/uio.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <unistd.h>
43 #include <fcntl.h>
44 #include <poll.h>
45 #endif /* !WINDOWS */
46 
47 #if defined(_AIX)
48 #include <sys/select.h>
49 #endif /* _AIX */
50 
51 #if defined(SOLARIS)
52 #include <sys/filio.h>
53 #include <netdb.h> /* for MAXHOSTNAMELEN */
54 #endif /* SOLARIS */
55 
56 #include "porting.h"
57 #include "error_manager.h"
58 #include "connection_globals.h"
59 #include "memory_alloc.h"
60 #include "environment_variable.h"
61 #include "system_parameter.h"
62 #include "boot_sr.h"
63 #if defined(WINDOWS)
64 #include "wintcp.h"
65 #else /* WINDOWS */
66 #include "tcp.h"
67 #endif /* !WINDOWS */
68 #if defined(SERVER_MODE)
69 #include "connection_sr.h"
70 #else
71 #include "connection_list_cl.h"
72 #include "connection_cl.h"
73 #endif
74 
75 #if defined(CS_MODE)
76 #include "network_interface_cl.h"
77 #endif
78 
79 #include "storage_common.h"
80 #if defined (SERVER_MODE) || defined (SA_MODE)
81 #include "heap_file.h"
82 #endif /* defined (SERVER_MODE) || defined (SA_MODE) */
83 #include "dbtype.h"
84 #include "tz_support.h"
85 #include "db_date.h"
86 #include "show_scan.h"
87 
88 #if !defined (SERVER_MODE)
89 #define pthread_mutex_init(a, b)
90 #define pthread_mutex_destroy(a)
91 #define pthread_mutex_lock(b) 0
92 #define pthread_mutex_unlock(a)
93 static int rv;
94 #endif /* !SERVER_MODE */
95 
96 #define INITIAL_IP_NUM 16
97 
98 #if defined(WINDOWS)
99 typedef char *caddr_t;
100 #endif /* WINDOWS */
101 
102 static const int CSS_TCP_MIN_NUM_RETRIES = 3;
103 #define CSS_TRUNCATE_BUFFER_SIZE 512
104 
105 #if !defined (SERVER_MODE)
106 static void css_default_server_timeout_fn (void);
108 static bool css_default_check_server_alive_fn (const char *db_name, const char *db_host);
110 #endif /* !SERVER_MODE */
111 
112 #if defined(WINDOWS)
113 #define CSS_VECTOR_SIZE (1024 * 64)
114 
115 #if defined(SERVER_MODE)
116 #define CSS_NUM_INTERNAL_VECTOR_BUF 20
117 static char *css_Vector_buffer = NULL;
118 static char *css_Vector_buffer_piece[CSS_NUM_INTERNAL_VECTOR_BUF] = { 0 };
119 static int css_Vector_buffer_occupied_flag[CSS_NUM_INTERNAL_VECTOR_BUF] = { 0 };
120 
121 static pthread_mutex_t css_Vector_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
122 static pthread_cond_t css_Vector_buffer_cond = PTHREAD_COND_INITIALIZER;
123 #else /* SERVER_MODE */
124 static char css_Vector_buffer[CSS_VECTOR_SIZE];
125 #endif /* SERVER_MODE */
126 #endif /* WINDOWS */
127 
128 static int css_sprintf_conn_infoids (SOCKET fd, const char **client_user_name, const char **client_host_name,
129  int *client_pid);
130 static int css_send_io_vector (CSS_CONN_ENTRY * conn, struct iovec *vec_p, ssize_t total_len, int vector_length,
131  int timeout);
132 
133 static int css_net_send2 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2);
134 static int css_net_send3 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2,
135  const char *buff3, int len3);
136 static int css_net_send4 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2,
137  const char *buff3, int len3, const char *buff4, int len4);
138 #if !defined(SERVER_MODE)
139 static int css_net_send5 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2,
140  const char *buff3, int len3, const char *buff4, int len4, const char *buff5, int len5);
141 #endif /* !SERVER_MODE */
142 static int css_net_send6 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2,
143  const char *buff3, int len3, const char *buff4, int len4, const char *buff5, int len5,
144  const char *buff6, int len6);
145 #if !defined(SERVER_MODE)
146 static int css_net_send7 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2,
147  const char *buff3, int len3, const char *buff4, int len4, const char *buff5, int len5,
148  const char *buff6, int len6, const char *buff7, int len7);
149 #endif /* !SERVER_MODE */
150 static int css_net_send8 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2,
151  const char *buff3, int len3, const char *buff4, int len4, const char *buff5, int len5,
152  const char *buff6, int len6, const char *buff7, int len7, const char *buff8, int len8);
153 #if defined(ENABLE_UNUSED_FUNCTION)
154 static int css_net_send_large_data_with_arg (CSS_CONN_ENTRY * conn, const char *header_buffer, int header_len,
155  NET_HEADER * header_array, const char **data_array, int num_array);
156 #endif
157 #if defined(SERVER_MODE)
158 static char *css_trim_str (char *str);
159 #endif
160 
161 #if !defined (CS_MODE)
162 static int css_make_access_status_exist_user (THREAD_ENTRY * thread_p, OID * class_oid,
163  LAST_ACCESS_STATUS ** access_status_array, int num_user,
164  SHOWSTMT_ARRAY_CONTEXT * ctx);
165 
166 static LAST_ACCESS_STATUS *css_get_access_status_with_name (LAST_ACCESS_STATUS ** access_status_array, int num_user,
167  const char *user_name);
168 static LAST_ACCESS_STATUS *css_get_unused_access_status (LAST_ACCESS_STATUS ** access_status_array, int num_user);
169 #endif /* !CS_MODE */
170 
171 #if !defined(SERVER_MODE)
172 static int
173 css_sprintf_conn_infoids (SOCKET fd, const char **client_user_name, const char **client_host_name, int *client_pid)
174 {
175  CSS_CONN_ENTRY *conn;
176  static char user_name[L_cuserid] = { '\0' };
177  static char host_name[CUB_MAXHOSTNAMELEN] = { '\0' };
178  static int pid;
179  int tran_index = -1;
180 
181  conn = css_find_conn_from_fd (fd);
182 
183  if (conn != NULL && conn->get_tran_index () != -1)
184  {
185  if (getuserid (user_name, L_cuserid) == NULL)
186  {
187  strcpy (user_name, "");
188  }
189 
190  if (GETHOSTNAME (host_name, CUB_MAXHOSTNAMELEN) != 0)
191  {
192  strcpy (host_name, "???");
193  }
194 
195  pid = getpid ();
196 
197  *client_user_name = user_name;
198  *client_host_name = host_name;
199  *client_pid = pid;
200  tran_index = conn->get_tran_index ();
201  }
202 
203  return tran_index;
204 }
205 
206 
207 static void
209 {
210  /* do nothing */
211  return;
212 }
213 
214 #elif defined(WINDOWS)
215 /*
216  * css_sprintf_conn_infoids() - find client information of given connection
217  * return: transaction id
218  * fd(in): socket fd
219  * tran_index(in): transaction index associated with socket
220  * client_user_name(in): client user name of socket fd
221  * client_host_name(in): client host name of socket fd
222  * client_pid(in): client process of socket fd
223  */
224 static int
225 css_sprintf_conn_infoids (SOCKET fd, const char **client_user_name, const char **client_host_name, int *client_pid)
226 {
227  const char *client_prog_name;
228  CSS_CONN_ENTRY *conn;
229  int error, tran_index = -1;
230 
231  conn = css_find_conn_from_fd (fd);
232 
233  if (conn != NULL && conn->get_tran_index () != -1)
234  {
235  error = logtb_find_client_name_host_pid (conn->get_tran_index (), &client_prog_name, client_user_name,
236  client_host_name, client_pid);
237  if (error == NO_ERROR)
238  {
239  tran_index = conn->get_tran_index ();
240  }
241  }
242 
243  return tran_index;
244 }
245 #endif /* WINDOWS */
246 
247 #if defined(WINDOWS) || !defined(SERVER_MODE)
248 static void
250 {
251  const char *client_user_name;
252  const char *client_host_name;
253  int client_pid;
254  int client_tranindex;
255 
256  client_tranindex = css_sprintf_conn_infoids (fd, &client_user_name, &client_host_name, &client_pid);
257 
258  if (client_tranindex != -1)
259  {
261  client_user_name, client_host_name, client_pid);
262  }
263 }
264 #endif
265 
266 #if defined (ENABLE_UNUSED_FUNCTION)
267 /*
268  * css_net_send_no_block () - Sends blocks of zero length packets
269  * return:
270  * fd(in): the socket fd
271  * buffer(in): the buffer full of zero data
272  * size(in): amout of data to send
273  *
274  * Note: This allows the server to either detect one of the following cases:
275  * The client has gone down (the send fails)
276  * The client is alive, but not waiting for server input (EWOULDBLOCK)
277  * The client is waiting for a server request to complete, but is
278  * still consuming blocks of zero length data. (This could be the
279  * case when a client is waiting for a lock or query result).
280  */
281 int
282 css_net_send_no_block (SOCKET fd, const char *buffer, int size)
283 {
284 #if defined(WINDOWS)
285  int rc, total = 0;
286  unsigned long noblock = 1, block = 0;
287  int winsock_error;
288 
289  rc = ioctlsocket (fd, FIONBIO, &noblock);
290  if (rc == SOCKET_ERROR)
291  {
292  return ERROR_ON_WRITE;
293  }
294 
295  for (total = 0; total < 2 * size; total += rc)
296  {
297  rc = send (fd, buffer, size, 0);
298  if (rc != size)
299  {
300  winsock_error = WSAGetLastError ();
301  if (rc < 0 && winsock_error != WSAEWOULDBLOCK && winsock_error != WSAEINTR)
302  {
303  return ERROR_ON_WRITE;
304  }
305  else
306  {
307  break;
308  }
309  }
310  }
311 
312  rc = ioctlsocket (fd, FIONBIO, &block);
313  if (rc != 0)
314  {
315  return ERROR_ON_WRITE;
316  }
317 
318  return NO_ERRORS;
319 #else /* WINDOWS */
320  int rc, noblock = 1, block = 0, total = 0;
321 
322  rc = ioctl (fd, FIONBIO, (caddr_t) (&noblock));
323  if (rc < 0)
324  {
325  return ERROR_ON_WRITE;
326  }
327 
328  for (total = 0; total < 2 * size; total += rc)
329  {
330  errno = 0;
331  rc = send (fd, buffer, size, 0);
332  if (rc != size)
333  {
334  if (rc <= 0 && errno != EWOULDBLOCK && errno != EINTR && errno != EAGAIN && errno != EACCES)
335  {
336  return (ERROR_ON_WRITE);
337  }
338  else
339  {
340  break;
341  }
342  }
343  }
344 
345  rc = ioctl (fd, FIONBIO, (caddr_t) (&block));
346  if (rc < 0)
347  {
348  return ERROR_ON_WRITE;
349  }
350 
351  return NO_ERRORS;
352 #endif /* WINDOWS */
353 }
354 #endif /* ENABLE_UNUSED_FUNCTION */
355 /*
356  * css_readn() - read "n" bytes from a descriptor.
357  * return: count of bytes actually read
358  * fd(in): sockert descripter
359  * ptr(out): buffer
360  * nbytes(in): count of bytes will be read
361  * timeout(in): timeout in milli-second
362  */
363 int
364 css_readn (SOCKET fd, char *ptr, int nbytes, int timeout)
365 {
366  int nleft, n;
367 
368 #if defined (WINDOWS)
369  int winsock_error;
370 #else
371  struct pollfd po[1] = { {0, 0, 0} };
372 #endif /* WINDOWS */
373 
374  if (fd < 0)
375  {
376  er_log_debug (ARG_FILE_LINE, "css_readn: fd < 0");
377  errno = EINVAL;
378  return -1;
379  }
380 
381  if (nbytes <= 0)
382  {
383  return 0;
384  }
385 
386  nleft = nbytes;
387  do
388  {
389 #if !defined (WINDOWS)
390  po[0].fd = fd;
391  po[0].events = POLLIN;
392  po[0].revents = 0;
393  n = poll (po, 1, timeout);
394  if (n == 0)
395  {
396  /* 0 means it timed out and no fd is changed. */
397  errno = ETIMEDOUT;
398  return -1;
399  }
400  else if (n < 0)
401  {
402  if (errno == EINTR)
403  {
404 #if !defined (SERVER_MODE)
406  {
408  }
409 #endif /* !SERVER_MODE */
410  continue;
411  }
412  er_log_debug (ARG_FILE_LINE, "css_readn: %s", strerror (errno));
413  return -1;
414  }
415  else
416  {
417  if (po[0].revents & POLLERR || po[0].revents & POLLHUP)
418  {
419  errno = EINVAL;
420  er_log_debug (ARG_FILE_LINE, "css_readn: %s %s", (po[0].revents & POLLERR ? "POLLERR" : "POLLHUP"),
421  strerror (errno));
422  return -1;
423  }
424  }
425 #endif /* !WINDOWS */
426 
427  read_again:
428  n = recv (fd, ptr, nleft, 0);
429 
430  if (n == 0)
431  {
432  break;
433  }
434 
435  if (n < 0)
436  {
437 #if !defined(WINDOWS)
438  if (errno == EAGAIN)
439  {
440  continue;
441  }
442  if (errno == EINTR)
443  {
444  goto read_again;
445  }
446 #else
447  winsock_error = WSAGetLastError ();
448 
449  /* In Windows 2003, pass large length (such as 120MB) to recv() will temporary unavailable by error number
450  * WSAENOBUFS (10055) */
451  if (winsock_error == WSAENOBUFS)
452  {
453  goto read_again;
454  }
455 
456  if (winsock_error == WSAEINTR)
457  {
458  goto read_again;
459  }
460 #endif
461 #if !defined (SERVER_MODE)
463 #endif /* !SERVER_MODE */
464 
465  er_log_debug (ARG_FILE_LINE, "css_readn: returning error n %d, errno %s\n", n, strerror (errno));
466 
467  return n; /* error, return < 0 */
468  }
469  nleft -= n;
470  ptr += n;
471  }
472  while (nleft > 0);
473 
474  return (nbytes - nleft); /* return >= 0 */
475 }
476 
477 /*
478  * css_read_remaining_bytes() - read remaining data
479  * return: void
480  * fd(in): socket descripter
481  * len(in): count of bytes
482  *
483  * Note: This routine will "use up" any remaining data that may be on the
484  * socket, but for which no space has been allocated.
485  * This will happen if the client provides a data buffer for a request
486  * that is too small for the data sent by the server.
487  */
488 void
490 {
491  char temp_buffer[CSS_TRUNCATE_BUFFER_SIZE];
492  int nbytes, buf_size;
493 
494  while (len > 0)
495  {
496  if (len <= SSIZEOF (temp_buffer))
497  {
498  buf_size = len;
499  }
500  else
501  {
502  buf_size = SSIZEOF (temp_buffer);
503  }
504 
505  nbytes = css_readn (fd, temp_buffer, buf_size, -1);
506  /*
507  * nbytes will be less than the size of the buffer if any of the
508  * following hold:
509  * a) the socket has been closed for some reason (e.g., the client
510  * was killed);
511  * b) there was some other kind of read error;
512  * c) we have simply read all of the bytes that were asked for.
513  */
514  if (nbytes < buf_size)
515  {
516  break;
517  }
518  len -= buf_size;
519  }
520  /* TODO: return error or length */
521 }
522 
523 /*
524  * css_net_recv() - reading a "packet" from the socket.
525  * return: 0 if success, or error code
526  * fd(in): socket descripter
527  * buffer(out): buffer for date be read
528  * maxlen(out): count of bytes was read
529  * timeout(in): timeout value in milli-second
530  */
531 int
532 css_net_recv (SOCKET fd, char *buffer, int *maxlen, int timeout)
533 {
534  int nbytes;
535  int templen;
536  int length_to_read;
537  int time_unit;
538  int elapsed;
539 
540  if (timeout < 0)
541  {
542  timeout = INT_MAX;
543  }
544  time_unit = timeout > 5000 ? 5000 : timeout;
545  elapsed = time_unit;
546 
547  /* read data length */
548  while (true)
549  {
550  nbytes = css_readn (fd, (char *) &templen, sizeof (int), time_unit);
551  if (nbytes < 0)
552  {
553  if (errno == ETIMEDOUT && timeout > elapsed)
554  {
555 #if defined (CS_MODE) && !defined (WINDOWS)
556  if (CHECK_SERVER_IS_ALIVE ())
557  {
558  if (css_peer_alive (fd, time_unit) == false)
559  {
561  }
563  {
564  if (css_check_server_alive_fn (NULL, NULL) == false)
565  {
567  }
568  }
569  }
570 #endif /* CS_MODE && !WINDOWS */
571  elapsed += time_unit;
572  continue;
573  }
575  }
576  if (nbytes != sizeof (int))
577  {
578 #ifdef CUBRID_DEBUG
579  er_log_debug (ARG_FILE_LINE, "css_net_recv: returning ERROR_WHEN_READING_SIZE bytes %d \n", nbytes);
580 #endif
582  }
583  else
584  {
585  break;
586  }
587  }
588 
589  templen = ntohl (templen);
590  if (templen > *maxlen)
591  {
592  length_to_read = *maxlen;
593  }
594  else
595  {
596  length_to_read = templen;
597  }
598 
599  /* read data */
600  nbytes = css_readn (fd, buffer, length_to_read, timeout);
601  if (nbytes < length_to_read)
602  {
603 #ifdef CUBRID_DEBUG
604  er_log_debug (ARG_FILE_LINE, "css_net_recv: returning ERROR_ON_READ bytes %d\n", nbytes);
605 #endif
606  return ERROR_ON_READ;
607  }
608 
609  /*
610  * This is possible if the data buffer provided by the client is smaller
611  * than the number of bytes sent by the server
612  */
613 
614  if (nbytes && (templen > nbytes))
615  {
616  css_read_remaining_bytes (fd, templen - nbytes);
617  return RECORD_TRUNCATED;
618  }
619 
620  if (nbytes != templen)
621  {
622 #ifdef CUBRID_DEBUG
623  er_log_debug (ARG_FILE_LINE, "css_net_recv: returning READ_LENGTH_MISMATCH bytes %d\n", nbytes);
624 #endif
625  return READ_LENGTH_MISMATCH;
626  }
627 
628  *maxlen = nbytes;
629  return NO_ERRORS;
630 }
631 
632 #if defined(WINDOWS)
633 /* We implement css_vector_send on Winsock platforms by copying the pieces into
634  a temporary buffer before sending. */
635 
636 /*
637  * css_writen() - write "n" bytes to a descriptor.
638  * return: count of bytes actually written
639  * fd(in): socket descripter
640  * ptr(in): buffer
641  * nbytes(in): count of bytes will be written
642  *
643  * Note: Use in place of write() when fd is a stream socket.
644  * Formerly only present when VECTOR was disabled but we now need this
645  * for the writev() simulation on platforms that don't support the vector
646  * functions.
647  */
648 static int
649 css_writen (SOCKET fd, char *ptr, int nbytes)
650 {
651  int num_retries = 0, sleep_nsecs = 1;
652  int nleft, nwritten;
653 
654  nleft = nbytes;
655  while (nleft > 0)
656  {
657  errno = 0;
658 
659  nwritten = send (fd, ptr, nleft, 0);
660  if (nwritten <= 0)
661  {
662  int winsock_error;
663 
664  winsock_error = WSAGetLastError ();
665  if (winsock_error == WSAEINTR)
666  {
667  continue;
668  }
669 
671  return (nwritten);
672  }
673 
674  nleft -= nwritten;
675  ptr += nwritten;
676  }
677 
678  return (nbytes - nleft);
679 }
680 
681 #if defined(SERVER_MODE)
682 /*
683  * alloc_vector_buffer() - allocate vector buffer
684  * return: index of a free vector_buffer slot
685  *
686  * Note: called whenever threads need a vector buffer.
687  */
688 static int
689 alloc_vector_buffer (void)
690 {
691  int i, r;
692 #ifdef VECTOR_IO_TUNE
693  int wait_count = 0;
694 #endif /* VECTOR_IO_TUNE */
695 
696  r = pthread_mutex_lock (&css_Vector_buffer_mutex);
697 
698  if (css_Vector_buffer == NULL)
699  {
700  r = pthread_cond_init (&css_Vector_buffer_cond, NULL);
701  css_Vector_buffer = (char *) malloc (CSS_NUM_INTERNAL_VECTOR_BUF * CSS_VECTOR_SIZE);
702 
703  if (css_Vector_buffer == NULL)
704  {
705  r = pthread_mutex_unlock (&css_Vector_buffer_mutex);
707  (size_t) (CSS_NUM_INTERNAL_VECTOR_BUF * CSS_VECTOR_SIZE));
708  return -1;
709  }
710 
711  for (i = 0; i < CSS_NUM_INTERNAL_VECTOR_BUF; i++)
712  {
713  css_Vector_buffer_piece[i] = css_Vector_buffer + i * CSS_VECTOR_SIZE;
714  }
715  }
716 
717  while (1)
718  {
719  for (i = 0; i < CSS_NUM_INTERNAL_VECTOR_BUF; i++)
720  {
721  if (css_Vector_buffer_occupied_flag[i] == 0)
722  {
723  css_Vector_buffer_occupied_flag[i] = 1;
724  r = pthread_mutex_unlock (&css_Vector_buffer_mutex);
725 #ifdef VECTOR_IO_TUNE
726  if (wait_count > 0)
727  {
728  fprintf (stderr, "Thread[%d] looped ****** %d ***** to alloc buffer\n", GetCurrentThreadId (),
729  wait_count);
730  }
731  wait_count = 0;
732 #endif /* VECTOR_IO_TUNE */
733  return i; /* I found a free slot. */
734  }
735  }
736 
737 #ifdef VECTOR_IO_TUNE
738  wait_count++;
739 #endif /* VECTOR_IO_TUNE */
740 
741  r = pthread_cond_wait (&css_Vector_buffer_cond, &css_Vector_buffer_mutex);
742  }
743 }
744 #endif
745 
746 #if defined(SERVER_MODE)
747 /*
748  * free_vector_buffer() - free vector buffer
749  * return: void
750  * index(in): index of buffer will be free
751  */
752 static void
753 free_vector_buffer (int index)
754 {
755  int r;
756 
757  r = pthread_mutex_lock (&css_Vector_buffer_mutex);
758 
759  css_Vector_buffer_occupied_flag[index] = 0;
760  r = pthread_cond_signal (&css_Vector_buffer_cond);
761 
762  r = pthread_mutex_unlock (&css_Vector_buffer_mutex);
763 }
764 #endif /* SERVER_MODE */
765 
766 /*
767  * css_vector_send() - Winsock simulation of css_vector_send.
768  * return: size of sent if success, or error code
769  * fd(in): socket descripter
770  * vec(in): vector buffer
771  * len(in): vector length
772  * bytes_written(in):
773  * timeout(in): timeout value in milli-seconds
774  *
775  * Note: Does not support the "byte_written" argument for retries, we'll
776  * internally keep retrying the operation until all the data is written.
777  * That's what all the callers do anyway.
778  */
779 int
780 css_vector_send (SOCKET fd, struct iovec *vec[], int *len, int bytes_written, int timeout)
781 {
782  int i, total_size, available, amount, rc;
783  char *src, *dest;
784  int handle_os_error;
785 #if defined(SERVER_MODE)
786  int vb_index;
787 #endif
788  /* don't support this, we'll write everything supplied with our own internal retry loop */
789  handle_os_error = 1;
790  if (bytes_written)
791  {
792  rc = -1;
793  handle_os_error = 0;
794  goto error;
795  }
796 
797  /* calculate the total size of the stuff we need to send */
798  total_size = 0;
799  for (i = 0; i < *len; i++)
800  {
801  total_size += (*vec)[i].iov_len;
802  }
803 
804 #if defined(SERVER_MODE)
805  vb_index = alloc_vector_buffer ();
806  dest = css_Vector_buffer_piece[vb_index];
807 #else
808  dest = css_Vector_buffer;
809 #endif
810  available = CSS_VECTOR_SIZE;
811 
812  for (i = 0; i < *len; i++)
813  {
814  src = (*vec)[i].iov_base;
815  amount = (*vec)[i].iov_len;
816 
817  /* if we've got more than we have room for, fill and send */
818 
819  while (amount > available)
820  {
821  memcpy (dest, src, available);
822 
823 #if defined(SERVER_MODE)
824  rc = css_writen (fd, css_Vector_buffer_piece[vb_index], CSS_VECTOR_SIZE);
825 #else
826  rc = css_writen (fd, css_Vector_buffer, CSS_VECTOR_SIZE);
827 #endif
828  if (rc != CSS_VECTOR_SIZE)
829  {
830  goto error;
831  }
832 
833  src += available;
834  amount -= available;
835 #if defined(SERVER_MODE)
836  dest = css_Vector_buffer_piece[vb_index];
837 #else
838  dest = css_Vector_buffer;
839 #endif
840  available = CSS_VECTOR_SIZE;
841  }
842 
843  /* if we have some amount that fits within the buffer, store it and move on */
844  if (amount)
845  {
846  memcpy (dest, src, amount);
847  dest += amount;
848  available -= amount;
849  }
850  }
851 
852  /* see if we have any residual bytes left to be sent */
853  if (available < CSS_VECTOR_SIZE)
854  {
855  amount = CSS_VECTOR_SIZE - available;
856 #if defined(SERVER_MODE)
857  rc = css_writen (fd, css_Vector_buffer_piece[vb_index], amount);
858 #else
859  rc = css_writen (fd, css_Vector_buffer, amount);
860 #endif
861  if (rc != amount)
862  {
863  goto error;
864  }
865  }
866 
867 #if defined(SERVER_MODE)
868  free_vector_buffer (vb_index);
869 #endif
870  return total_size;
871 
872 error:
873  /*
874  * We end up with an error. The error has already been set in css_writen
875  */
876 #if defined(SERVER_MODE)
877  free_vector_buffer (vb_index);
878 #endif
879  return rc;
880 }
881 
882 #else /* WINDOWS */
883 /*
884  * css_vector_send() -
885  * return: size of sent if success, or error code
886  * fd(in): socket descripter
887  * vec(in): vector buffer
888  * len(in): vector length
889  * bytes_written(in):
890  * timeout(in): timeout value in milli-seconds
891  */
892 int
893 css_vector_send (SOCKET fd, struct iovec *vec[], int *len, int bytes_written, int timeout)
894 {
895  int i, n;
896  struct pollfd po[1] = { {0, 0, 0} };
897 
898  if (fd < 0)
899  {
900  er_log_debug (ARG_FILE_LINE, "css_vector_send: fd < 0");
901  errno = EINVAL;
902  return -1;
903  }
904 
905  if (bytes_written > 0)
906  {
907  er_log_debug (ARG_FILE_LINE, "css_vector_send: retry called for %d\n", bytes_written);
908 
909  for (i = 0; i < *len; i++)
910  {
911  if ((*vec)[i].iov_len <= (size_t) bytes_written)
912  {
913  bytes_written -= (*vec)[i].iov_len;
914  }
915  else
916  {
917  break;
918  }
919  }
920  (*vec)[i].iov_len -= bytes_written;
921  (*vec)[i].iov_base = ((char *) ((*vec)[i].iov_base)) + bytes_written;
922 
923  (*vec) += i;
924  *len -= i;
925  }
926 
927  while (true)
928  {
929  po[0].fd = fd;
930  po[0].events = POLLOUT;
931  po[0].revents = 0;
932  n = poll (po, 1, timeout);
933  if (n < 0)
934  {
935  if (errno == EINTR)
936  {
937  continue;
938  }
939 
940  er_log_debug (ARG_FILE_LINE, "css_vector_send: EINTR %s\n", strerror (errno));
941  return -1;
942  }
943  else if (n == 0)
944  {
945  /* 0 means it timed out and no fd is changed. */
946  errno = ETIMEDOUT;
947  return -1;
948  }
949  else
950  {
951  if (po[0].revents & POLLERR || po[0].revents & POLLHUP)
952  {
953  errno = EINVAL;
954  er_log_debug (ARG_FILE_LINE, "css_vector_send: %s %s\n",
955  (po[0].revents & POLLERR ? "POLLERR" : "POLLHUP"), strerror (errno));
956  return -1;
957  }
958  }
959 
960  write_again:
961  n = writev (fd, *vec, *len);
962  if (n > 0)
963  {
964  return n;
965  }
966  else if (n == 0)
967  {
968  return 0; /* ??? */
969  }
970  else
971  {
972  if (errno == EINTR)
973  {
974  goto write_again;
975  }
976  if (errno == EAGAIN)
977  {
978  continue;
979  }
980 #if !defined (SERVER_MODE)
982 #endif /* !SERVER_MODE */
983 
984  er_log_debug (ARG_FILE_LINE, "css_vector_send: returning error n %d, errno %s\n", n, strerror (errno));
985  return n; /* error, return < 0 */
986  }
987  }
988 
989  return -1;
990 }
991 #endif /* !WINDOWS */
992 
993 void
994 css_set_io_vector (struct iovec *vec1_p, struct iovec *vec2_p, const char *buff, int len, int *templen)
995 {
996  *templen = htonl (len);
997  vec1_p->iov_base = (caddr_t) templen;
998  vec1_p->iov_len = sizeof (int);
999  vec2_p->iov_base = (caddr_t) buff;
1000  vec2_p->iov_len = len;
1001 }
1002 
1003 /*
1004  * css_send_io_vector -
1005  * return:
1006  * conn(in):
1007  * vec_p(in):
1008  * total_len(in):
1009  * vector_length(in):
1010  * timeout(in): timeout value in milli-seconds
1011  */
1012 static int
1013 css_send_io_vector (CSS_CONN_ENTRY * conn, struct iovec *vec_p, ssize_t total_len, int vector_length, int timeout)
1014 {
1015  int rc = NO_ERRORS;
1016 
1017  rc = css_send_io_vector_with_socket (conn->fd, vec_p, total_len, vector_length, timeout);
1018  if (rc != NO_ERRORS)
1019  {
1020  css_shutdown_conn (conn);
1021  }
1022 
1023  return rc;
1024 }
1025 
1026 int
1027 css_send_io_vector_with_socket (SOCKET & socket, struct iovec *vec_p, ssize_t total_len, int vector_length, int timeout)
1028 {
1029  int rc;
1030 
1031  rc = 0;
1032  while (total_len > 0)
1033  {
1034  rc = css_vector_send (socket, &vec_p, &vector_length, rc, timeout);
1035  if (rc < 0)
1036  {
1037  if (!IS_INVALID_SOCKET (socket))
1038  {
1039  /* if this is the PC, it also shuts down Winsock */
1040  css_shutdown_socket (socket);
1041  socket = INVALID_SOCKET;
1042  }
1043  return ERROR_ON_WRITE;
1044  }
1045  total_len -= rc;
1046  }
1047 
1048  return NO_ERRORS;
1049 }
1050 
1051 /*
1052  * css_net_send() - send a record to the other end.
1053  * return: enum css_error_code (See connection_defs.h)
1054  * fd(in): socket descripter
1055  * buff(in): buffer for data will be sent
1056  * len(in): length for data will be sent
1057  * timeout(in): timeout value in milli-seconds
1058  *
1059  * Note: Used by client and server.
1060  */
1061 int
1062 css_net_send (CSS_CONN_ENTRY * conn, const char *buff, int len, int timeout)
1063 {
1064  return css_net_send_with_socket (conn->fd, buff, len, timeout);
1065 }
1066 
1067 int
1068 css_net_send_with_socket (SOCKET & socket, const char *buff, int len, int timeout)
1069 {
1070  int templen;
1071  struct iovec iov[2];
1072  int total_len;
1073 
1074  css_set_io_vector (&(iov[0]), &(iov[1]), buff, len, &templen);
1075  total_len = len + sizeof (int);
1076 
1077  return css_send_io_vector_with_socket (socket, iov, total_len, 2, timeout);
1078 }
1079 
1080 /*
1081  * css_net_send2() - send a record to the other end.
1082  * return: enum css_error_code (See connection_defs.h)
1083  * conn(in): connection entry
1084  * fd(in): socket descripter
1085  * buff1(in): buffer for data will be sent
1086  * len1(in): length for data will be sent
1087  * buff2(in): buffer for data will be sent
1088  * len2(in): length for data will be sent
1089  *
1090  * Note: Used by client and server.
1091  */
1092 static int
1093 css_net_send2 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2)
1094 {
1095  int templen1, templen2;
1096  struct iovec iov[4];
1097  int total_len;
1098 
1099  css_set_io_vector (&(iov[0]), &(iov[1]), buff1, len1, &templen1);
1100  css_set_io_vector (&(iov[2]), &(iov[3]), buff2, len2, &templen2);
1101 
1102  total_len = len1 + len2 + sizeof (int) * 2;
1103 
1104  /* timeout in milli-second in css_send_io_vector() */
1105  return css_send_io_vector (conn, iov, total_len, 4, -1);
1106 }
1107 
1108 /*
1109  * css_net_send3() - send a record to the other end.
1110  * return: enum css_error_code (See connection_defs.h)
1111  * conn(in): connection entry
1112  * fd(in): socket descripter
1113  * buff1(in): buffer for data will be sent
1114  * len1(in): length for data will be sent
1115  * buff2(in): buffer for data will be sent
1116  * len2(in): length for data will be sent
1117  * buff3(in): buffer for data will be sent
1118  * len3(in): length for data will be sent
1119  *
1120  * Note: Used by client and server.
1121  */
1122 static int
1123 css_net_send3 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3,
1124  int len3)
1125 {
1126  return css_net_send3_with_socket (conn->fd, buff1, len1, buff2, len2, buff3, len3);
1127 }
1128 
1129 int
1130 css_net_send3_with_socket (SOCKET & socket, const char *buff1, int len1, const char *buff2, int len2, const char *buff3,
1131  int len3)
1132 {
1133  int templen1, templen2, templen3;
1134  struct iovec iov[6];
1135  int total_len;
1136 
1137  css_set_io_vector (&(iov[0]), &(iov[1]), buff1, len1, &templen1);
1138  css_set_io_vector (&(iov[2]), &(iov[3]), buff2, len2, &templen2);
1139  css_set_io_vector (&(iov[4]), &(iov[5]), buff3, len3, &templen3);
1140 
1141  total_len = len1 + len2 + len3 + sizeof (int) * 3;
1142 
1143  /* timeout in milli-second in css_send_io_vector() */
1144  return css_send_io_vector_with_socket (socket, iov, total_len, 6, -1);
1145 }
1146 
1147 /*
1148  * css_net_send4() - Send a record to the other end.
1149  * return: enum css_error_code (See connection_defs.h)
1150  * conn(in): connection entry
1151  * fd(in): socket descripter
1152  * buff1(in): buffer for data will be sent
1153  * len1(in): length for data will be sent
1154  * buff2(in): buffer for data will be sent
1155  * len2(in): length for data will be sent
1156  * buff3(in): buffer for data will be sent
1157  * len3(in): length for data will be sent
1158  * buff4(in): buffer for data will be sent
1159  * len4(in): length for data will be sent
1160  *
1161  * Note: Used by client and server.
1162  */
1163 static int
1164 css_net_send4 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3,
1165  int len3, const char *buff4, int len4)
1166 {
1167  int templen1, templen2, templen3, templen4;
1168  struct iovec iov[8];
1169  int total_len;
1170 
1171  css_set_io_vector (&(iov[0]), &(iov[1]), buff1, len1, &templen1);
1172  css_set_io_vector (&(iov[2]), &(iov[3]), buff2, len2, &templen2);
1173  css_set_io_vector (&(iov[4]), &(iov[5]), buff3, len3, &templen3);
1174  css_set_io_vector (&(iov[6]), &(iov[7]), buff4, len4, &templen4);
1175 
1176  total_len = len1 + len2 + len3 + len4 + sizeof (int) * 4;
1177 
1178  /* timeout in milli-second in css_send_io_vector() */
1179  return css_send_io_vector (conn, iov, total_len, 8, -1);
1180 }
1181 
1182 #if defined(CS_MODE) || defined(SA_MODE)
1183 /*
1184  * css_net_send5() - Send a record to the other end.
1185  * return: enum css_error_code (See connection_defs.h)
1186  * param(in):
1187  *
1188  * Note: Used by client and server.
1189  */
1190 static int
1191 css_net_send5 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3,
1192  int len3, const char *buff4, int len4, const char *buff5, int len5)
1193 {
1194  int templen1, templen2, templen3, templen4, templen5;
1195  struct iovec iov[10];
1196  int total_len;
1197 
1198  css_set_io_vector (&(iov[0]), &(iov[1]), buff1, len1, &templen1);
1199  css_set_io_vector (&(iov[2]), &(iov[3]), buff2, len2, &templen2);
1200  css_set_io_vector (&(iov[4]), &(iov[5]), buff3, len3, &templen3);
1201  css_set_io_vector (&(iov[6]), &(iov[7]), buff4, len4, &templen4);
1202  css_set_io_vector (&(iov[8]), &(iov[9]), buff5, len5, &templen5);
1203 
1204  total_len = len1 + len2 + len3 + len4 + len5 + sizeof (int) * 5;
1205 
1206  /* timeout in milli-second in css_send_io_vector() */
1207  return css_send_io_vector (conn, iov, total_len, 10, -1);
1208 }
1209 #endif /* CS_MODE || SA_MODE */
1210 
1211 /*
1212  * css_net_send6() - Send a record to the other end.
1213  * return: enum css_error_code (See connection_defs.h)
1214  * conn(in): connection entry
1215  * fd(in): socket descripter
1216  * buff1(in): buffer for data will be sent
1217  * len1(in): length for data will be sent
1218  * buff2(in): buffer for data will be sent
1219  * len2(in): length for data will be sent
1220  * buff3(in): buffer for data will be sent
1221  * len3(in): length for data will be sent
1222  * buff4(in): buffer for data will be sent
1223  * len4(in): length for data will be sent
1224  * buff5(in): buffer for data will be sent
1225  * len5(in): length for data will be sent
1226  * buff6(in): buffer for data will be sent
1227  * len6(in): length for data will be sent
1228  *
1229  * Note: Used by client and server.
1230  */
1231 static int
1232 css_net_send6 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3,
1233  int len3, const char *buff4, int len4, const char *buff5, int len5, const char *buff6, int len6)
1234 {
1235  int templen1, templen2, templen3, templen4, templen5, templen6;
1236  struct iovec iov[12];
1237  int total_len;
1238 
1239  css_set_io_vector (&(iov[0]), &(iov[1]), buff1, len1, &templen1);
1240  css_set_io_vector (&(iov[2]), &(iov[3]), buff2, len2, &templen2);
1241  css_set_io_vector (&(iov[4]), &(iov[5]), buff3, len3, &templen3);
1242  css_set_io_vector (&(iov[6]), &(iov[7]), buff4, len4, &templen4);
1243  css_set_io_vector (&(iov[8]), &(iov[9]), buff5, len5, &templen5);
1244  css_set_io_vector (&(iov[10]), &(iov[11]), buff6, len6, &templen6);
1245 
1246  total_len = len1 + len2 + len3 + len4 + len5 + len6 + sizeof (int) * 6;
1247 
1248  /* timeout in milli-second in css_send_io_vector() */
1249  return css_send_io_vector (conn, iov, total_len, 12, -1);
1250 }
1251 
1252 #if defined(CS_MODE) || defined(SA_MODE)
1253 /*
1254  * css_net_send7() - Send a record to the other end.
1255  * return: enum css_error_code (See connection_defs.h)
1256  * param(in):
1257  *
1258  * Note: Used by client and server.
1259  */
1260 static int
1261 css_net_send7 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3,
1262  int len3, const char *buff4, int len4, const char *buff5, int len5, const char *buff6, int len6,
1263  const char *buff7, int len7)
1264 {
1265  int templen1, templen2, templen3, templen4, templen5, templen6, templen7;
1266  struct iovec iov[14];
1267  int total_len;
1268 
1269  css_set_io_vector (&(iov[0]), &(iov[1]), buff1, len1, &templen1);
1270  css_set_io_vector (&(iov[2]), &(iov[3]), buff2, len2, &templen2);
1271  css_set_io_vector (&(iov[4]), &(iov[5]), buff3, len3, &templen3);
1272  css_set_io_vector (&(iov[6]), &(iov[7]), buff4, len4, &templen4);
1273  css_set_io_vector (&(iov[8]), &(iov[9]), buff5, len5, &templen5);
1274  css_set_io_vector (&(iov[10]), &(iov[11]), buff6, len6, &templen6);
1275  css_set_io_vector (&(iov[12]), &(iov[13]), buff7, len7, &templen7);
1276 
1277  total_len = len1 + len2 + len3 + len4 + len5 + len6 + len7 + sizeof (int) * 7;
1278 
1279  /* timeout in milli-second in css_send_io_vector() */
1280  return css_send_io_vector (conn, iov, total_len, 14, -1);
1281 }
1282 #endif /* CS_MODE || SA_MODE */
1283 
1284 /*
1285  * css_net_send8() - Send a record to the other end.
1286  * return: enum css_error_code (See connection_defs.h)
1287  * conn(in): connection entry
1288  * fd(in): socket descripter
1289  * buff1(in): buffer for data will be sent
1290  * len1(in): length for data will be sent
1291  * buff2(in): buffer for data will be sent
1292  * len2(in): length for data will be sent
1293  * buff3(in): buffer for data will be sent
1294  * len3(in): length for data will be sent
1295  * buff4(in): buffer for data will be sent
1296  * len4(in): length for data will be sent
1297  * buff5(in): buffer for data will be sent
1298  * len5(in): length for data will be sent
1299  * buff6(in): buffer for data will be sent
1300  * len6(in): length for data will be sent
1301  * buff7(in): buffer for data will be sent
1302  * len7(in): length for data will be sent
1303  * buff8(in): buffer for data will be sent
1304  * len8(in): length for data will be sent
1305  *
1306  * Note: Used by client and server.
1307  */
1308 static int
1309 css_net_send8 (CSS_CONN_ENTRY * conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3,
1310  int len3, const char *buff4, int len4, const char *buff5, int len5, const char *buff6, int len6,
1311  const char *buff7, int len7, const char *buff8, int len8)
1312 {
1313  int templen1, templen2, templen3, templen4, templen5, templen6, templen7, templen8;
1314  struct iovec iov[16];
1315  int total_len;
1316 
1317  css_set_io_vector (&(iov[0]), &(iov[1]), buff1, len1, &templen1);
1318  css_set_io_vector (&(iov[2]), &(iov[3]), buff2, len2, &templen2);
1319  css_set_io_vector (&(iov[4]), &(iov[5]), buff3, len3, &templen3);
1320  css_set_io_vector (&(iov[6]), &(iov[7]), buff4, len4, &templen4);
1321  css_set_io_vector (&(iov[8]), &(iov[9]), buff5, len5, &templen5);
1322  css_set_io_vector (&(iov[10]), &(iov[11]), buff6, len6, &templen6);
1323  css_set_io_vector (&(iov[12]), &(iov[13]), buff7, len7, &templen7);
1324  css_set_io_vector (&(iov[14]), &(iov[15]), buff8, len8, &templen8);
1325 
1326  total_len = len1 + len2 + len3 + len4 + len5 + len6 + len7 + len8 + sizeof (int) * 8;
1327 
1328  /* timeout in milli-second in css_send_io_vector() */
1329  return css_send_io_vector (conn, iov, total_len, 16, -1);
1330 }
1331 
1332 #if defined(ENABLE_UNUSED_FUNCTION)
1333 /*
1334  * css_net_send_large_data() -
1335  * return: enum css_error_code (See connection_defs.h)
1336  * conn(in): connection entry
1337  * header_array(in):
1338  * data_array(in):
1339  * num_array(in):
1340  *
1341  * Note: Used by client and server.
1342  */
1343 static int
1344 css_net_send_large_data (CSS_CONN_ENTRY * conn, NET_HEADER * header_array, const char **data_array, int num_array)
1345 {
1346  int *templen;
1347  struct iovec *iov;
1348  ssize_t total_len;
1349  int rc, i, buffer_size;
1350 
1351  iov = (struct iovec *) malloc (sizeof (struct iovec) * (num_array * 4));
1352  if (iov == NULL)
1353  {
1354  return CANT_ALLOC_BUFFER;
1355  }
1356  templen = (int *) malloc (sizeof (int) * (num_array * 2));
1357  if (templen == NULL)
1358  {
1359  free (iov);
1360  return CANT_ALLOC_BUFFER;
1361  }
1362 
1363  total_len = 0;
1364 
1365  for (i = 0; i < num_array; i++)
1366  {
1367  css_set_io_vector (&(iov[i * 4]), &(iov[i * 4 + 1]), (char *) (&header_array[i]), sizeof (NET_HEADER),
1368  &templen[i * 2]);
1369  total_len += sizeof (NET_HEADER) + sizeof (int);
1370 
1371  buffer_size = ntohl (header_array[i].buffer_size);
1372  css_set_io_vector (&(iov[i * 4 + 2]), &(iov[i * 4 + 3]), data_array[i], buffer_size, &templen[i * 2 + 1]);
1373  total_len += buffer_size + sizeof (int);
1374  }
1375 
1376  rc = css_send_io_vector (conn, iov, total_len, num_array * 4, -1);
1377 
1378  free (iov);
1379  free (templen);
1380 
1381  return rc;
1382 }
1383 
1384 /*
1385  * css_net_send_large_data_with_arg() -
1386  * return: enum css_error_code (See connection_defs.h)
1387  * conn(in): connection entry
1388  * header_buffer(in):
1389  * header_len(in):
1390  * header_array(in):
1391  * data_array(in):
1392  * num_array(in):
1393  *
1394  * Note: Used by client and server.
1395  */
1396 static int
1397 css_net_send_large_data_with_arg (CSS_CONN_ENTRY * conn, const char *header_buffer, int header_len,
1398  NET_HEADER * header_array, const char **data_array, int num_array)
1399 {
1400  int *templen;
1401  struct iovec *iov;
1402  ssize_t total_len;
1403  int rc, i, buffer_size;
1404 
1405  iov = (struct iovec *) malloc (sizeof (struct iovec) * (num_array * 4 + 2));
1406  if (iov == NULL)
1407  {
1408  return CANT_ALLOC_BUFFER;
1409  }
1410  templen = (int *) malloc (sizeof (int) * (num_array * 2 + 1));
1411  if (templen == NULL)
1412  {
1413  free (iov);
1414  return CANT_ALLOC_BUFFER;
1415  }
1416 
1417  total_len = 0;
1418 
1419  css_set_io_vector (&(iov[0]), &(iov[1]), header_buffer, header_len, &templen[0]);
1420  total_len += header_len + sizeof (int);
1421 
1422  for (i = 0; i < num_array; i++)
1423  {
1424  css_set_io_vector (&(iov[i * 4 + 2]), &(iov[i * 4 + 3]), (char *) (&header_array[i]), sizeof (NET_HEADER),
1425  &templen[i * 2 + 1]);
1426 
1427  buffer_size = ntohl (header_array[i].buffer_size);
1428  css_set_io_vector (&(iov[i * 4 + 4]), &(iov[i * 4 + 5]), data_array[i], buffer_size, &templen[i * 2 + 2]);
1429 
1430  total_len += (sizeof (NET_HEADER) + buffer_size + sizeof (int) * 2);
1431  }
1432 
1433  rc = css_send_io_vector (conn, iov, total_len, num_array * 4 + 2, -1);
1434 
1435  free (iov);
1436  free (templen);
1437 
1438  return rc;
1439 }
1440 #endif
1441 
1442 /*
1443  * css_net_send_buffer_only() - send a buffer only to the other end.
1444  * return: enum css_error_code (See connection_defs.h)
1445  * fd(in): socket descripter
1446  * buff(in): buffer for data will be sent
1447  * len(in): length for data will be sent
1448  * timeout(in): timeout value in milli-seconds
1449  *
1450  * Note: Used by client and server.
1451  */
1452 int
1453 css_net_send_buffer_only (CSS_CONN_ENTRY * conn, const char *buff, int len, int timeout)
1454 {
1455  struct iovec iov[1];
1456 
1457  iov[0].iov_base = (caddr_t) buff;
1458  iov[0].iov_len = len;
1459 
1460  return css_send_io_vector (conn, iov, len, 1, timeout);
1461 }
1462 
1463 /*
1464  * css_net_read_header() -
1465  * return: enum css_error_code (See connection_defs.h)
1466  * fd(in): socket descripter
1467  * buffer(out): buffer for date be read
1468  * maxlen(out): count of bytes was read
1469  * timeout(in):
1470  */
1471 int
1472 css_net_read_header (SOCKET fd, char *buffer, int *maxlen, int timeout)
1473 {
1474  return css_net_recv (fd, buffer, maxlen, timeout);
1475 }
1476 
1477 void
1478 css_set_net_header (NET_HEADER * header_p, int type, short function_code, int request_id, int buffer_size,
1479  int transaction_id, int invalidate_snapshot, int db_error)
1480 {
1481  unsigned short flags = 0;
1482  header_p->type = htonl (type);
1483  header_p->function_code = htons (function_code);
1484  header_p->request_id = htonl (request_id);
1485  header_p->buffer_size = htonl (buffer_size);
1486  header_p->transaction_id = htonl (transaction_id);
1487  header_p->db_error = htonl (db_error);
1488 
1489  if (invalidate_snapshot)
1490  {
1492  }
1493  header_p->flags = htons (flags);
1494 }
1495 
1496 /*
1497  * css_send_request_with_data_buffer () - transfer a request to the server.
1498  * return: enum css_error_code (See connection_defs.h)
1499  * conn(in): connection entry
1500  * request(in): request number
1501  * request_id(out): request id
1502  * arg_buffer(in): argument data
1503  * arg_size(in): argument data size
1504  * reply_buffer(out): buffer for reply data
1505  * reply_size(in): reply buffer size
1506  *
1507  * Note: used by css_send_request (with NULL as the data buffer).
1508  */
1509 int
1510 css_send_request_with_data_buffer (CSS_CONN_ENTRY * conn, int request, unsigned short *request_id,
1511  const char *arg_buffer, int arg_size, char *reply_buffer, int reply_size)
1512 {
1513  NET_HEADER local_header = DEFAULT_HEADER_DATA;
1514  NET_HEADER data_header = DEFAULT_HEADER_DATA;
1515 
1516  if (!conn || conn->status != CONN_OPEN)
1517  {
1518  return CONNECTION_CLOSED;
1519  }
1520 
1521  *request_id = css_get_request_id (conn);
1522  css_set_net_header (&local_header, COMMAND_TYPE, request, *request_id, arg_size, conn->get_tran_index (),
1523  conn->invalidate_snapshot, conn->db_error);
1524 
1525  if (reply_buffer && (reply_size > 0))
1526  {
1527  css_queue_user_data_buffer (conn, *request_id, reply_size, reply_buffer);
1528  }
1529 
1530  if (arg_size > 0 && arg_buffer != NULL)
1531  {
1532  css_set_net_header (&data_header, DATA_TYPE, 0, *request_id, arg_size, conn->get_tran_index (),
1533  conn->invalidate_snapshot, conn->db_error);
1534 
1535  return (css_net_send3 (conn, (char *) &local_header, sizeof (NET_HEADER), (char *) &data_header,
1536  sizeof (NET_HEADER), arg_buffer, arg_size));
1537  }
1538  else
1539  {
1540  /* timeout in milli-second in css_net_send() */
1541  if (css_net_send (conn, (char *) &local_header, sizeof (NET_HEADER), -1) == NO_ERRORS)
1542  {
1543  return NO_ERRORS;
1544  }
1545  }
1546 
1547  return ERROR_ON_WRITE;
1548 }
1549 
1550 #if defined(CS_MODE) || defined(SA_MODE)
1551 /*
1552  * css_send_request_no_reply () - transfer a request to the server (no reply)
1553  * return: enum css_error_code (See connection_defs.h)
1554  * conn(in):
1555  * request(in):
1556  * request_id(in):
1557  * arg_buffer(in):
1558  * arg_size(in):
1559  *
1560  */
1561 int
1562 css_send_request_no_reply (CSS_CONN_ENTRY * conn, int request, unsigned short *request_id, char *arg_buffer,
1563  int arg_size)
1564 {
1565  NET_HEADER req_header = DEFAULT_HEADER_DATA;
1566  NET_HEADER data_header = DEFAULT_HEADER_DATA;
1567 
1568  if (!conn || conn->status != CONN_OPEN)
1569  {
1570  return CONNECTION_CLOSED;
1571  }
1572 
1573  *request_id = css_get_request_id (conn);
1574  css_set_net_header (&req_header, COMMAND_TYPE, request, *request_id, arg_size, conn->get_tran_index (),
1575  conn->invalidate_snapshot, conn->db_error);
1576 
1577  css_set_net_header (&data_header, DATA_TYPE, 0, *request_id, arg_size, conn->get_tran_index (),
1578  conn->invalidate_snapshot, conn->db_error);
1579 
1580  return (css_net_send3 (conn, (char *) &req_header, sizeof (NET_HEADER), (char *) &data_header, sizeof (NET_HEADER),
1581  arg_buffer, arg_size));
1582 }
1583 
1584 /*
1585  * css_send_req_with_2_buffers () - transfer a request to the server
1586  * return: enum css_error_code (See connection_defs.h)
1587  * conn(in):
1588  * request(in):
1589  * request_id(out):
1590  * arg_buffer(in):
1591  * arg_size(in):
1592  * data_buffer(in):
1593  * data_size(in):
1594  * reply_buffer(in):
1595  * reply_size(in):
1596  *
1597  * Note: It is used by css_send_request (with NULL as the data buffer).
1598  */
1599 int
1600 css_send_req_with_2_buffers (CSS_CONN_ENTRY * conn, int request, unsigned short *request_id, char *arg_buffer,
1601  int arg_size, char *data_buffer, int data_size, char *reply_buffer, int reply_size)
1602 {
1603  NET_HEADER local_header = DEFAULT_HEADER_DATA;
1604  NET_HEADER arg_header = DEFAULT_HEADER_DATA;
1605  NET_HEADER data_header = DEFAULT_HEADER_DATA;
1606 
1607  if (data_buffer == NULL || data_size <= 0)
1608  {
1609  return (css_send_request_with_data_buffer (conn, request, request_id, arg_buffer, arg_size, reply_buffer,
1610  reply_size));
1611  }
1612  if (!conn || conn->status != CONN_OPEN)
1613  {
1614  return CONNECTION_CLOSED;
1615  }
1616 
1617  *request_id = css_get_request_id (conn);
1618  css_set_net_header (&local_header, COMMAND_TYPE, request, *request_id, arg_size, conn->get_tran_index (),
1619  conn->invalidate_snapshot, conn->db_error);
1620 
1621  if (reply_buffer && reply_size > 0)
1622  {
1623  css_queue_user_data_buffer (conn, *request_id, reply_size, reply_buffer);
1624  }
1625 
1626  css_set_net_header (&arg_header, DATA_TYPE, 0, *request_id, arg_size, conn->get_tran_index (),
1627  conn->invalidate_snapshot, conn->db_error);
1628 
1629  css_set_net_header (&data_header, DATA_TYPE, 0, *request_id, data_size, conn->get_tran_index (),
1630  conn->invalidate_snapshot, conn->db_error);
1631 
1632  return (css_net_send5 (conn, (char *) &local_header, sizeof (NET_HEADER), (char *) &arg_header, sizeof (NET_HEADER),
1633  arg_buffer, arg_size, (char *) &data_header, sizeof (NET_HEADER), data_buffer, data_size));
1634 }
1635 
1636 /*
1637  * css_send_req_with_3_buffers () - transfer a request to the server
1638  * return: enum css_error_code (See connection_defs.h)
1639  * conn(in):
1640  * request(in):
1641  * request_id(in):
1642  * arg_buffer(in):
1643  * arg_size(in):
1644  * data1_buffer(in):
1645  * data1_size(in):
1646  * data2_buffer(in):
1647  * data2_size(in):
1648  * reply_buffer(in):
1649  * reply_size(in):
1650  *
1651  * Note: It is used by css_send_request (with NULL as the data buffer).
1652  */
1653 int
1654 css_send_req_with_3_buffers (CSS_CONN_ENTRY * conn, int request, unsigned short *request_id, char *arg_buffer,
1655  int arg_size, char *data1_buffer, int data1_size, char *data2_buffer, int data2_size,
1656  char *reply_buffer, int reply_size)
1657 {
1658  NET_HEADER local_header = DEFAULT_HEADER_DATA;
1659  NET_HEADER arg_header = DEFAULT_HEADER_DATA;
1660  NET_HEADER data1_header = DEFAULT_HEADER_DATA;
1661  NET_HEADER data2_header = DEFAULT_HEADER_DATA;
1662 
1663  if (data2_buffer == NULL || data2_size <= 0)
1664  {
1665  return (css_send_req_with_2_buffers (conn, request, request_id, arg_buffer, arg_size, data1_buffer, data1_size,
1666  reply_buffer, reply_size));
1667  }
1668 
1669  if (!conn || conn->status != CONN_OPEN)
1670  {
1671  return CONNECTION_CLOSED;
1672  }
1673 
1674  *request_id = css_get_request_id (conn);
1675  css_set_net_header (&local_header, COMMAND_TYPE, request, *request_id, arg_size, conn->get_tran_index (),
1676  conn->invalidate_snapshot, conn->db_error);
1677 
1678  if (reply_buffer && reply_size > 0)
1679  {
1680  css_queue_user_data_buffer (conn, *request_id, reply_size, reply_buffer);
1681  }
1682 
1683  css_set_net_header (&arg_header, DATA_TYPE, 0, *request_id, arg_size, conn->get_tran_index (),
1684  conn->invalidate_snapshot, conn->db_error);
1685 
1686  css_set_net_header (&data1_header, DATA_TYPE, 0, *request_id, data1_size, conn->get_tran_index (),
1687  conn->invalidate_snapshot, conn->db_error);
1688 
1689  css_set_net_header (&data2_header, DATA_TYPE, 0, *request_id, data2_size, conn->get_tran_index (),
1690  conn->invalidate_snapshot, conn->db_error);
1691 
1692  return (css_net_send7 (conn, (char *) &local_header, sizeof (NET_HEADER), (char *) &arg_header, sizeof (NET_HEADER),
1693  arg_buffer, arg_size, (char *) &data1_header, sizeof (NET_HEADER), data1_buffer, data1_size,
1694  (char *) &data2_header, sizeof (NET_HEADER), data2_buffer, data2_size));
1695 }
1696 
1697 #if 0
1698 /*
1699  * css_send_req_with_large_buffer () - transfer a request to the server
1700  * return:
1701  * conn(in):
1702  * request(in):
1703  * request_id(out):
1704  * arg_buffer(in):
1705  * arg_size(in):
1706  * data_buffer(in):
1707  * data_size(in):
1708  * reply_buffer(in):
1709  * reply_size(in):
1710  *
1711  * Note: It is used by css_send_request (with NULL as the data buffer).
1712  */
1713 int
1714 css_send_req_with_large_buffer (CSS_CONN_ENTRY * conn, int request, unsigned short *request_id, char *arg_buffer,
1715  int arg_size, char *data_buffer, INT64 data_size, char *reply_buffer, int reply_size)
1716 {
1717  NET_HEADER local_header = DEFAULT_HEADER_DATA;
1718  NET_HEADER *headers;
1719  char **buffer_array;
1720  int num_array, send_data_size;
1721  int rc, i;
1722 
1723  if (data_buffer == NULL || data_size <= 0)
1724  {
1725  return (css_send_request_with_data_buffer (conn, request, request_id, arg_buffer, arg_size, reply_buffer,
1726  reply_size));
1727  }
1728  if (!conn || conn->status != CONN_OPEN)
1729  {
1730  return CONNECTION_CLOSED;
1731  }
1732 
1733  *request_id = css_get_request_id (conn);
1734  css_set_net_header (&local_header, COMMAND_TYPE, request, *request_id, arg_size, conn->get_tran_index (),
1735  conn->invalidate_snapshot, conn->db_error);
1736 
1737  if (reply_buffer && reply_size > 0)
1738  {
1739  css_queue_user_data_buffer (conn, *request_id, reply_size, reply_buffer);
1740  }
1741 
1742  num_array = (int) (data_size / INT_MAX) + 2;
1743  headers = (NET_HEADER *) malloc (sizeof (NET_HEADER) * num_array);
1744  if (headers == NULL)
1745  {
1746  return CANT_ALLOC_BUFFER;
1747  }
1748  memset (headers, 0, sizeof (NET_HEADER) * num_array);
1749 
1750  buffer_array = (char **) malloc (sizeof (char *) * num_array);
1751  if (buffer_array == NULL)
1752  {
1753  free_and_init (headers);
1754  return CANT_ALLOC_BUFFER;
1755  }
1756 
1757  css_set_net_header (&headers[0], DATA_TYPE, 0, *request_id, arg_size, conn->get_tran_index (),
1758  conn->invalidate_snapshot, conn->db_error);
1759  buffer_array[0] = arg_buffer;
1760 
1761  for (i = 1; i < num_array; i++)
1762  {
1763  if (data_size > INT_MAX)
1764  {
1765  send_data_size = INT_MAX;
1766  }
1767  else
1768  {
1769  send_data_size = (int) data_size;
1770  }
1771 
1772  css_set_net_header (&headers[i], DATA_TYPE, 0, *request_id, send_data_size, conn->get_tran_index (),
1773  conn->invalidate_snapshot, conn->db_error);
1774  buffer_array[i] = data_buffer;
1775 
1776  data_buffer += send_data_size;
1777  data_size -= send_data_size;
1778  }
1779 
1780  rc = css_net_send_large_data_with_arg (conn, (char *) &local_header, sizeof (NET_HEADER), headers,
1781  (const char **) buffer_array, num_array);
1782 
1783  free_and_init (buffer_array);
1784  free_and_init (headers);
1785 
1786  return rc;
1787 }
1788 #endif /* 0 */
1789 
1790 #endif /* CS_MODE || SA_MODE */
1791 
1792 /*
1793  * css_send_request() - to send a request to the server without registering
1794  * a data buffer.
1795  * return: enum css_error_code (See connection_defs.h)
1796  * conn(in):
1797  * command(in): request command
1798  * request_id(out): request id
1799  * arg_buffer: argument data
1800  * arg_buffer_size : argument data size
1801  */
1802 int
1803 css_send_request (CSS_CONN_ENTRY * conn, int command, unsigned short *request_id, const char *arg_buffer,
1804  int arg_buffer_size)
1805 {
1806  return (css_send_request_with_data_buffer (conn, command, request_id, arg_buffer, arg_buffer_size, 0, 0));
1807 }
1808 
1809 int
1810 css_send_request_with_socket (SOCKET & socket, int command, unsigned short *request_id, const char *arg_buffer,
1811  int arg_buffer_size)
1812 {
1813  NET_HEADER local_header = DEFAULT_HEADER_DATA;
1814  NET_HEADER data_header = DEFAULT_HEADER_DATA;
1815 
1816  if (IS_INVALID_SOCKET (socket))
1817  {
1818  return CONNECTION_CLOSED;
1819  }
1820 
1821  *request_id = -1;
1822  css_set_net_header (&local_header, COMMAND_TYPE, command, *request_id, arg_buffer_size, NULL_TRAN_INDEX, 0, 0);
1823 
1824  if (arg_buffer_size > 0 && arg_buffer != NULL)
1825  {
1826  css_set_net_header (&data_header, DATA_TYPE, 0, *request_id, arg_buffer_size, NULL_TRAN_INDEX, 0, 0);
1827 
1828  return (css_net_send3_with_socket (socket, (char *) &local_header, sizeof (NET_HEADER), (char *) &data_header,
1829  sizeof (NET_HEADER), arg_buffer, arg_buffer_size));
1830  }
1831  else
1832  {
1833  /* timeout in milli-second in css_net_send() */
1834  if (css_net_send_with_socket (socket, (char *) &local_header, sizeof (NET_HEADER), -1) == NO_ERRORS)
1835  {
1836  return NO_ERRORS;
1837  }
1838  }
1839 
1840  return ERROR_ON_WRITE;
1841 }
1842 
1843 /*
1844  * css_send_data() - transfer a data packet to the client.
1845  * return: enum css_error_code (See connection_defs.h)
1846  * conn(in): connection entry
1847  * rid(in): request id
1848  * buffer(in): buffer for data will be sent
1849  * buffer_size(in): buffer size
1850  */
1851 int
1852 css_send_data (CSS_CONN_ENTRY * conn, unsigned short rid, const char *buffer, int buffer_size)
1853 {
1855 #if defined(SERVER_MODE)
1856  if (!conn || conn->status == CONN_CLOSED)
1857 #else
1858  if (!conn || conn->status != CONN_OPEN)
1859 #endif
1860  {
1861  return (CONNECTION_CLOSED);
1862  }
1863 
1864  css_set_net_header (&header, DATA_TYPE, 0, rid, buffer_size, conn->get_tran_index (), conn->invalidate_snapshot,
1865  conn->db_error);
1866 
1867  return (css_net_send2 (conn, (char *) &header, sizeof (NET_HEADER), buffer, buffer_size));
1868 }
1869 
1870 #if defined(SERVER_MODE)
1871 /*
1872 * css_send_two_data() - transfer a data packet to the client.
1873 * return: enum css_error_code (See connection_defs.h)
1874 * conn(in): connection entry
1875 * rid(in): request id
1876 * buffer1(in): buffer for data will be sent
1877 * buffer1_size(in): buffer size
1878 * buffer2(in): buffer for data will be sent
1879 * buffer2_size(in): buffer size
1880 */
1881 int
1882 css_send_two_data (CSS_CONN_ENTRY * conn, unsigned short rid, const char *buffer1, int buffer1_size,
1883  const char *buffer2, int buffer2_size)
1884 {
1885  NET_HEADER header1 = DEFAULT_HEADER_DATA;
1886  NET_HEADER header2 = DEFAULT_HEADER_DATA;
1887 
1888  if (!conn || conn->status != CONN_OPEN)
1889  {
1890  return (CONNECTION_CLOSED);
1891  }
1892 
1893  css_set_net_header (&header1, DATA_TYPE, 0, rid, buffer1_size, conn->get_tran_index (), conn->invalidate_snapshot,
1894  conn->db_error);
1895 
1896  css_set_net_header (&header2, DATA_TYPE, 0, rid, buffer2_size, conn->get_tran_index (), conn->invalidate_snapshot,
1897  conn->db_error);
1898 
1899  return (css_net_send4 (conn, (char *) &header1, sizeof (NET_HEADER), buffer1, buffer1_size, (char *) &header2,
1900  sizeof (NET_HEADER), buffer2, buffer2_size));
1901 }
1902 
1903 /*
1904 * css_send_three_data() - transfer a data packet to the client.
1905 * return: enum css_error_code (See connection_defs.h)
1906 * conn(in): connection entry
1907 * rid(in): request id
1908 * buffer1(in): buffer for data will be sent
1909 * buffer1_size(in): buffer size
1910 * buffer2(in): buffer for data will be sent
1911 * buffer2_size(in): buffer size
1912 * buffer3(in): buffer for data will be sent
1913 * buffer3_size(in): buffer size
1914 */
1915 int
1916 css_send_three_data (CSS_CONN_ENTRY * conn, unsigned short rid, const char *buffer1, int buffer1_size,
1917  const char *buffer2, int buffer2_size, const char *buffer3, int buffer3_size)
1918 {
1919  NET_HEADER header1 = DEFAULT_HEADER_DATA;
1920  NET_HEADER header2 = DEFAULT_HEADER_DATA;
1921  NET_HEADER header3 = DEFAULT_HEADER_DATA;
1922 
1923  if (!conn || conn->status != CONN_OPEN)
1924  {
1925  return (CONNECTION_CLOSED);
1926  }
1927 
1928  css_set_net_header (&header1, DATA_TYPE, 0, rid, buffer1_size, conn->get_tran_index (), conn->invalidate_snapshot,
1929  conn->db_error);
1930 
1931  css_set_net_header (&header2, DATA_TYPE, 0, rid, buffer2_size, conn->get_tran_index (), conn->invalidate_snapshot,
1932  conn->db_error);
1933 
1934  css_set_net_header (&header3, DATA_TYPE, 0, rid, buffer3_size, conn->get_tran_index (), conn->invalidate_snapshot,
1935  conn->db_error);
1936 
1937  return (css_net_send6 (conn, (char *) &header1, sizeof (NET_HEADER), buffer1, buffer1_size, (char *) &header2,
1938  sizeof (NET_HEADER), buffer2, buffer2_size, (char *) &header3, sizeof (NET_HEADER), buffer3,
1939  buffer3_size));
1940 }
1941 
1942 /*
1943 * css_send_four_data() - transfer a data packet to the client.
1944 * return: enum css_error_code (See connection_defs.h)
1945 * conn(in): connection entry
1946 * rid(in): request id
1947 * buffer1(in): buffer for data will be sent
1948 * buffer1_size(in): buffer size
1949 * buffer2(in): buffer for data will be sent
1950 * buffer2_size(in): buffer size
1951 * buffer3(in): buffer for data will be sent
1952 * buffer3_size(in): buffer size
1953 * buffer4(in): buffer for data will be sent
1954 * buffer4_size(in): buffer size
1955 *
1956 */
1957 int
1958 css_send_four_data (CSS_CONN_ENTRY * conn, unsigned short rid, const char *buffer1, int buffer1_size,
1959  const char *buffer2, int buffer2_size, const char *buffer3, int buffer3_size, const char *buffer4,
1960  int buffer4_size)
1961 {
1962  NET_HEADER header1 = DEFAULT_HEADER_DATA;
1963  NET_HEADER header2 = DEFAULT_HEADER_DATA;
1964  NET_HEADER header3 = DEFAULT_HEADER_DATA;
1965  NET_HEADER header4 = DEFAULT_HEADER_DATA;
1966 
1967  if (!conn || conn->status != CONN_OPEN)
1968  {
1969  return (CONNECTION_CLOSED);
1970  }
1971 
1972  css_set_net_header (&header1, DATA_TYPE, 0, rid, buffer1_size, conn->get_tran_index (), conn->invalidate_snapshot,
1973  conn->db_error);
1974 
1975  css_set_net_header (&header2, DATA_TYPE, 0, rid, buffer2_size, conn->get_tran_index (), conn->invalidate_snapshot,
1976  conn->db_error);
1977 
1978  css_set_net_header (&header3, DATA_TYPE, 0, rid, buffer3_size, conn->get_tran_index (), conn->invalidate_snapshot,
1979  conn->db_error);
1980 
1981  css_set_net_header (&header4, DATA_TYPE, 0, rid, buffer4_size, conn->get_tran_index (), conn->invalidate_snapshot,
1982  conn->db_error);
1983 
1984  return (css_net_send8 (conn, (char *) &header1, sizeof (NET_HEADER), buffer1, buffer1_size, (char *) &header2,
1985  sizeof (NET_HEADER), buffer2, buffer2_size, (char *) &header3, sizeof (NET_HEADER), buffer3,
1986  buffer3_size, (char *) &header4, sizeof (NET_HEADER), buffer4, buffer4_size));
1987 }
1988 
1989 #if defined(ENABLE_UNUSED_FUNCTION)
1990 /*
1991 * css_send_large_data() - transfer a data packet to the client.
1992 * return: enum css_error_code (See connection_defs.h)
1993 * conn(in): connection entry
1994 * rid(in): request id
1995 * buffers(in):
1996 * buffers_size(in):
1997 * num_buffers(in):
1998 *
1999 */
2000 int
2001 css_send_large_data (CSS_CONN_ENTRY * conn, unsigned short rid, const char **buffers, int *buffers_size,
2002  int num_buffers)
2003 {
2004  NET_HEADER *headers;
2005  int i, rc;
2006 
2007  if (!conn || conn->status != CONN_OPEN)
2008  {
2009  return (CONNECTION_CLOSED);
2010  }
2011 
2012  headers = (NET_HEADER *) malloc (sizeof (NET_HEADER) * num_buffers);
2013  if (headers == NULL)
2014  {
2015  return CANT_ALLOC_BUFFER;
2016  }
2017 
2018  for (i = 0; i < num_buffers; i++)
2019  {
2020  css_set_net_header (&headers[i], DATA_TYPE, 0, rid, buffers_size[i], conn->get_tran_index (),
2021  conn->invalidate_snapshot, conn->db_error);
2022  }
2023 
2024  rc = css_net_send_large_data (conn, headers, buffers, num_buffers);
2025  free_and_init (headers);
2026 
2027  return rc;
2028 }
2029 #endif /* ENABLE_UNUSED_FUNCTION */
2030 #endif /* SERVER_MODE */
2031 
2032 /*
2033 * css_send_error() - transfer an error packet to the client.
2034 * return: enum css_error_code (See connection_defs.h)
2035 * conn(in): connection entry
2036 * rid(in): request id
2037 * buffer(in): buffer for data will be sent
2038 * buffer_size(in): buffer size
2039 */
2040 int
2041 css_send_error (CSS_CONN_ENTRY * conn, unsigned short rid, const char *buffer, int buffer_size)
2042 {
2044 
2045 #if defined (SERVER_MODE)
2046  if (!conn || conn->status == CONN_CLOSED)
2047 #else
2048  if (!conn || conn->status != CONN_OPEN)
2049 #endif
2050  {
2051  return (CONNECTION_CLOSED);
2052  }
2053 
2054  css_set_net_header (&header, ERROR_TYPE, 0, rid, buffer_size, conn->get_tran_index (), conn->invalidate_snapshot,
2055  conn->db_error);
2056 
2057  return (css_net_send2 (conn, (char *) &header, sizeof (NET_HEADER), buffer, buffer_size));
2058 }
2059 
2060 #if defined (ENABLE_UNUSED_FUNCTION)
2061 /*
2062  * css_local_host_name -
2063  * return: enum css_error_code (See connection_defs.h)
2064  *
2065  * conn(in): conn entry
2066  * hostname(out): host name
2067  * namelen(in): size of hostname argument
2068  */
2069 int
2070 css_local_host_name (CSS_CONN_ENTRY * conn, char *hostname, size_t namelen)
2071 {
2072  if (!conn || conn->status != CONN_OPEN || IS_INVALID_SOCKET (conn->fd))
2073  {
2074  return CONNECTION_CLOSED;
2075  }
2076 
2077  if (css_get_sock_name (conn->fd, hostname, namelen) != 0)
2078  {
2079  return OS_ERROR;
2080  }
2081 
2082  return NO_ERRORS;
2083 }
2084 
2085 /*
2086  * css_peer_host_name -
2087  * return: enum css_error_code (See connection_defs.h)
2088  *
2089  * conn(in): conn entry
2090  * hostname(out): host name
2091  * namelen(in): size of hostname argument
2092  */
2093 int
2094 css_peer_host_name (CSS_CONN_ENTRY * conn, char *hostname, size_t namelen)
2095 {
2096  if (!conn || conn->status != CONN_OPEN || IS_INVALID_SOCKET (conn->fd))
2097  {
2098  return CONNECTION_CLOSED;
2099  }
2100 
2101  if (css_get_peer_name (conn->fd, hostname, namelen) != 0)
2102  {
2103  return OS_ERROR;
2104  }
2105 
2106  return NO_ERRORS;
2107 }
2108 #endif /* ENABLE_UNUSED_FUNCTION */
2109 
2110 #if !defined (SERVER_MODE)
2111 /*
2112  * css_default_check_server_alive_fn () - check server alive
2113  *
2114  * return:
2115  * db_host(in):
2116  * db_name(in):
2117  */
2118 static bool
2119 css_default_check_server_alive_fn (const char *db_name, const char *db_host)
2120 {
2121  return true;
2122 }
2123 
2124 /*
2125  * css_register_check_server_alive_fn () - regist the callback function
2126  *
2127  * return: void
2128  * callback_fn(in):
2129  */
2130 void
2132 {
2133  css_check_server_alive_fn = callback_fn;
2134 }
2135 #endif /* !SERVER_MODE */
2136 
2137 /*
2138  * css_ha_server_state_string
2139  */
2140 const char *
2142 {
2143  switch (state)
2144  {
2145  case HA_SERVER_STATE_NA:
2146  return "na";
2147  case HA_SERVER_STATE_IDLE:
2148  return HA_SERVER_STATE_IDLE_STR;
2159  case HA_SERVER_STATE_DEAD:
2160  return HA_SERVER_STATE_DEAD_STR;
2161  }
2162  return "invalid";
2163 }
2164 
2165 /*
2166  * css_ha_applier_state_string
2167  */
2168 const char *
2170 {
2171  switch (state)
2172  {
2174  return "na";
2185  }
2186  return "invalid";
2187 }
2188 
2189 /*
2190  * css_ha_mode_string
2191  */
2192 const char *
2194 {
2195  switch (mode)
2196  {
2197  case HA_MODE_OFF:
2198  return HA_MODE_OFF_STR;
2199  case HA_MODE_FAIL_OVER:
2200  case HA_MODE_FAIL_BACK:
2201  case HA_MODE_LAZY_BACK:
2202  case HA_MODE_ROLE_CHANGE:
2203  return HA_MODE_ON_STR;
2204  case HA_MODE_REPLICA:
2205  return HA_MODE_REPLICA_STR;
2206  }
2207  return "invalid";
2208 }
2209 
2210 #if !defined (SERVER_MODE)
2211 void
2213 {
2214  css_server_timeout_fn = callback_fn;
2215 }
2216 #endif /* !SERVER_MODE */
2217 
2218 #if defined(SERVER_MODE)
2219 int
2220 css_check_ip (IP_INFO * ip_info, unsigned char *address)
2221 {
2222  int i;
2223 
2224  assert (ip_info && address);
2225 
2226  for (i = 0; i < ip_info->num_list; i++)
2227  {
2228  int address_index = i * IP_BYTE_COUNT;
2229 
2230  if (ip_info->address_list[address_index] == 0)
2231  {
2232  return NO_ERROR;
2233  }
2234  else if (memcmp ((void *) &ip_info->address_list[address_index + 1], (void *) address,
2235  ip_info->address_list[address_index]) == 0)
2236  {
2237  return NO_ERROR;
2238  }
2239  }
2240 
2241  return ER_INACCESSIBLE_IP;
2242 }
2243 
2244 int
2245 css_free_ip_info (IP_INFO * ip_info)
2246 {
2247  if (ip_info)
2248  {
2249  free_and_init (ip_info->address_list);
2250  free (ip_info);
2251  }
2252 
2253  return NO_ERROR;
2254 }
2255 
2256 int
2257 css_read_ip_info (IP_INFO ** out_ip_info, char *filename)
2258 {
2259  char buf[32];
2260  FILE *fd_ip_list;
2261  IP_INFO *ip_info;
2262  const char *dbname;
2263  int ip_address_list_buffer_size;
2264  unsigned char i;
2265  bool is_current_db_section;
2266 
2267  if (out_ip_info == NULL)
2268  {
2269  return ER_FAILED;
2270  }
2271 
2272  fd_ip_list = fopen (filename, "r");
2273 
2274  if (fd_ip_list == NULL)
2275  {
2277  return ER_OPEN_ACCESS_LIST_FILE;
2278  }
2279 
2280  is_current_db_section = false;
2281 
2282  ip_info = (IP_INFO *) malloc (sizeof (IP_INFO));
2283  if (ip_info == NULL)
2284  {
2286  fclose (fd_ip_list);
2287  return ER_OUT_OF_VIRTUAL_MEMORY;
2288  }
2289 
2290  ip_info->num_list = 0;
2291  ip_address_list_buffer_size = INITIAL_IP_NUM * IP_BYTE_COUNT;
2292  ip_info->address_list = (unsigned char *) malloc (ip_address_list_buffer_size);
2293 
2294  if (ip_info->address_list == NULL)
2295  {
2296  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) ip_address_list_buffer_size);
2297  goto error;
2298  }
2299 
2300  dbname = boot_db_name ();
2301 
2302  while (fgets (buf, 32, fd_ip_list))
2303  {
2304  char *token, *p, *save = NULL;
2305  int address_index;
2306 
2307  p = strchr (buf, '#');
2308  if (p != NULL)
2309  {
2310  *p = '\0';
2311  }
2312 
2313  css_trim_str (buf);
2314  if (buf[0] == '\0')
2315  {
2316  continue;
2317  }
2318 
2319  if (is_current_db_section == false && strncmp (buf, "[@", 2) == 0 && buf[strlen (buf) - 1] == ']')
2320  {
2321  buf[strlen (buf) - 1] = '\0';
2322  if (strcasecmp (dbname, buf + 2) == 0)
2323  {
2324  is_current_db_section = true;
2325  continue;
2326  }
2327  }
2328 
2329  if (is_current_db_section == false)
2330  {
2331  continue;
2332  }
2333 
2334  if (strncmp (buf, "[@", 2) == 0 && buf[strlen (buf) - 1] == ']')
2335  {
2336  buf[strlen (buf) - 1] = '\0';
2337  if (strcasecmp (dbname, buf + 2) != 0)
2338  {
2339  break;
2340  }
2341  }
2342 
2343  token = strtok_r (buf, ".", &save);
2344 
2345  address_index = ip_info->num_list * IP_BYTE_COUNT;
2346 
2347  if (address_index >= ip_address_list_buffer_size)
2348  {
2349  ip_address_list_buffer_size *= 2;
2350  ip_info->address_list = (unsigned char *) realloc (ip_info->address_list, ip_address_list_buffer_size);
2351  if (ip_info->address_list == NULL)
2352  {
2354  (size_t) ip_address_list_buffer_size);
2355  goto error;
2356  }
2357  }
2358 
2359  for (i = 0; i < 4; i++)
2360  {
2361  if (token == NULL)
2362  {
2364  goto error;
2365  }
2366 
2367  if (strcmp (token, "*") == 0)
2368  {
2369  break;
2370  }
2371  else
2372  {
2373  int adr = 0, result;
2374 
2375  result = parse_int (&adr, token, 10);
2376 
2377  if (result != 0 || adr > 255 || adr < 0)
2378  {
2380  goto error;
2381  }
2382 
2383  ip_info->address_list[address_index + 1 + i] = (unsigned char) adr;
2384  }
2385 
2386  token = strtok_r (NULL, ".", &save);
2387 
2388  if (i == 3 && token != NULL)
2389  {
2391  goto error;
2392  }
2393  }
2394  ip_info->address_list[address_index] = i;
2395  ip_info->num_list++;
2396  }
2397 
2398  fclose (fd_ip_list);
2399 
2400  *out_ip_info = ip_info;
2401 
2402  return 0;
2403 
2404 error:
2405  fclose (fd_ip_list);
2406  css_free_ip_info (ip_info);
2407 
2408  assert (er_errid () != NO_ERROR);
2409  return er_errid ();
2410 }
2411 
2412 static char *
2413 css_trim_str (char *str)
2414 {
2415  char *p, *s;
2416 
2417  if (str == NULL)
2418  {
2419  return (str);
2420  }
2421 
2422  for (s = str; *s != '\0' && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'); s++)
2423  {
2424  ;
2425  }
2426 
2427  if (*s == '\0')
2428  {
2429  *str = '\0';
2430  return (str);
2431  }
2432 
2433  /* *s must be a non-white char */
2434  for (p = s; *p != '\0'; p++)
2435  {
2436  ;
2437  }
2438  for (p--; *p == ' ' || *p == '\t' || *p == '\n' || *p == '\r'; p--)
2439  {
2440  ;
2441  }
2442  *++p = '\0';
2443 
2444  if (s != str)
2445  {
2446  memmove (str, s, strlen (s) + 1);
2447  }
2448 
2449  return (str);
2450 }
2451 #endif
2452 
2453 /*
2454  * css_send_magic () - send magic
2455  *
2456  * return: void
2457  * conn(in/out):
2458  */
2459 int
2461 {
2462  return css_send_magic_with_socket (conn->fd);
2463 }
2464 
2465 int
2467 {
2468  NET_HEADER header;
2469 
2470  memset ((char *) &header, 0, sizeof (NET_HEADER));
2471  memcpy ((char *) &header, css_Net_magic, sizeof (css_Net_magic));
2472 
2473  return css_net_send_with_socket (socket, (const char *) &header, sizeof (NET_HEADER), -1);
2474 }
2475 
2476 /*
2477  * css_check_magic () - check magic
2478  *
2479  * return: void
2480  * conn(in/out):
2481  */
2482 int
2484 {
2485  return css_check_magic_with_socket (conn->fd);
2486 }
2487 
2488 int
2490 {
2491  int size, nbytes;
2492  unsigned int i;
2493  NET_HEADER header;
2494  char *p;
2496 
2497  nbytes = css_readn (fd, (char *) &size, sizeof (int), timeout);
2498  if (nbytes != sizeof (int))
2499  {
2500  return ERROR_WHEN_READING_SIZE;
2501  }
2502  size = ntohl (size);
2503  if (size != sizeof (NET_HEADER))
2504  {
2505  return WRONG_PACKET_TYPE;
2506  }
2507 
2508  p = (char *) &header;
2509  nbytes = css_readn (fd, p, size, timeout);
2510  if (nbytes != size)
2511  {
2512  return ERROR_ON_READ;
2513  }
2514 
2515  for (i = 0; i < sizeof (css_Net_magic); i++)
2516  {
2517  if (*(p++) != css_Net_magic[i])
2518  {
2519  return WRONG_PACKET_TYPE;
2520  }
2521  }
2522 
2523  return NO_ERRORS;
2524 }
2525 
2526 #if !defined (CS_MODE)
2527 /*
2528  * css_user_access_status_start_scan () - start scan function for show access status
2529  * return: NO_ERROR, or ER_CODE
2530  *
2531  * thread_p(in):
2532  * show_type(in):
2533  * arg_values(in):
2534  * arg_cnt(in):
2535  * ptr(in/out):
2536  */
2537 int
2538 css_user_access_status_start_scan (THREAD_ENTRY * thread_p, int type, DB_VALUE ** arg_values, int arg_cnt, void **ptr)
2539 {
2540  int error = NO_ERROR;
2541  int num_user = 0;
2542  const int num_cols = 4; /* user_name, last_access_time, last_access_host, program_name */
2543  const int default_num_tuple = 10;
2544  OID *class_oid;
2546  LAST_ACCESS_STATUS **access_status_array = NULL;
2547 #if defined(SERVER_MODE)
2548  LAST_ACCESS_STATUS *access_status = NULL;
2549  DB_VALUE *vals;
2550  DB_DATETIME access_time;
2551 #endif
2552 
2553  *ptr = NULL;
2554 
2555  ctx = showstmt_alloc_array_context (thread_p, default_num_tuple, num_cols);
2556  if (ctx == NULL)
2557  {
2558  assert (er_errid () != NO_ERROR);
2559  error = er_errid ();
2560  return error;
2561  }
2562 
2563 #if defined(SERVER_MODE)
2564  num_user = css_Num_access_user;
2565 
2566  access_status_array = (LAST_ACCESS_STATUS **) malloc (sizeof (LAST_ACCESS_STATUS *) * num_user);
2567  if (access_status_array == NULL)
2568  {
2569  showstmt_free_array_context (thread_p, ctx);
2571  return ER_FAILED;
2572  }
2573 
2574  css_get_user_access_status (num_user, access_status_array);
2575 #endif
2576 
2577  assert (arg_cnt == 1);
2578  class_oid = db_get_oid (arg_values[0]); /* db_user class oid */
2579 
2580  error = css_make_access_status_exist_user (thread_p, class_oid, access_status_array, num_user, ctx);
2581  if (error != NO_ERROR)
2582  {
2583  goto error;
2584  }
2585 
2586 #if defined(SERVER_MODE)
2587  while (true)
2588  {
2589  access_status = css_get_unused_access_status (access_status_array, num_user);
2590  if (access_status == NULL)
2591  {
2592  break;
2593  }
2594 
2595  vals = showstmt_alloc_tuple_in_context (thread_p, ctx);
2596  if (vals == NULL)
2597  {
2598  assert (er_errid () != NO_ERROR);
2599  error = er_errid ();
2600  goto error;
2601  }
2602 
2603  db_make_string_copy (&vals[0], access_status->db_user);
2604 
2605  db_localdatetime (&access_status->time, &access_time);
2606  db_make_datetime (&vals[1], &access_time);
2607 
2608  db_make_string_copy (&vals[2], access_status->host);
2609  db_make_string_copy (&vals[3], access_status->program_name);
2610  }
2611 #endif /* SERVER_MODE */
2612 
2613  if (access_status_array != NULL)
2614  {
2615  free_and_init (access_status_array);
2616  }
2617 
2618  *ptr = ctx;
2619 
2620  return NO_ERROR;
2621 
2622 error:
2623  if (ctx != NULL)
2624  {
2625  showstmt_free_array_context (thread_p, ctx);
2626  }
2627 
2628  if (access_status_array != NULL)
2629  {
2630  free_and_init (access_status_array);
2631  }
2632 
2633  return error;
2634 }
2635 
2636 /*
2637  * css_make_access_status_exist_user () - set access status information of whom are in db_user class
2638  * return: NO_ERROR, or ER_CODE
2639  *
2640  * thread_p(in):
2641  * class_oid(in): db_user class's class oid
2642  * access_status_array(in):
2643  * num_user(in):
2644  * ctx(in):
2645  */
2646 static int
2647 css_make_access_status_exist_user (THREAD_ENTRY * thread_p, OID * class_oid, LAST_ACCESS_STATUS ** access_status_array,
2648  int num_user, SHOWSTMT_ARRAY_CONTEXT * ctx)
2649 {
2650  int error = NO_ERROR;
2651  int i, attr_idx = -1;
2652  bool attr_info_inited;
2653  bool scan_cache_inited;
2654  char *rec_attr_name_p = NULL, *string = NULL;
2655  const char *user_name = NULL;
2656  HFID hfid;
2657  OID inst_oid;
2658  HEAP_CACHE_ATTRINFO attr_info;
2659  HEAP_SCANCACHE scan_cache;
2660  HEAP_ATTRVALUE *heap_value;
2661  SCAN_CODE scan;
2662  RECDES recdes;
2663  DB_VALUE *vals;
2664  DB_DATETIME access_time;
2665  LAST_ACCESS_STATUS *access_status;
2667 
2668  OID_SET_NULL (&inst_oid);
2669 
2670  error = heap_attrinfo_start (thread_p, class_oid, -1, NULL, &attr_info);
2671  if (error != NO_ERROR)
2672  {
2673  return error;
2674  }
2675  attr_info_inited = true;
2676 
2677  heap_scancache_quick_start_root_hfid (thread_p, &scan_cache);
2678  scan_cache_inited = true;
2679 
2680  if (heap_get_class_record (thread_p, class_oid, &recdes, &scan_cache, PEEK) != S_SUCCESS)
2681  {
2682  assert (er_errid () != NO_ERROR);
2683  error = er_errid ();
2684  goto end;
2685  }
2686 
2687  for (i = 0; i < attr_info.num_values; i++)
2688  {
2689  int alloced_string = 0;
2690  bool set_break = false;
2691  string = NULL;
2692 
2693  error = or_get_attrname (&recdes, i, &string, &alloced_string);
2694  if (error != NO_ERROR)
2695  {
2696  ASSERT_ERROR ();
2697  goto end;
2698  }
2699  rec_attr_name_p = string;
2700 
2701  if (rec_attr_name_p == NULL)
2702  {
2703  continue;
2704  }
2705 
2706  if (strcmp ("name", rec_attr_name_p) == 0)
2707  {
2708  attr_idx = i;
2709  set_break = true;
2710  goto clean_string;
2711  }
2712 
2713  clean_string:
2714  if (string != NULL && alloced_string == 1)
2715  {
2716  db_private_free_and_init (thread_p, string);
2717  }
2718 
2719  if (set_break == true)
2720  {
2721  break;
2722  }
2723  }
2724  heap_scancache_end (thread_p, &scan_cache);
2725  scan_cache_inited = false;
2726 
2727  error = heap_get_class_info (thread_p, class_oid, &hfid, NULL, NULL);
2728  if (error != NO_ERROR)
2729  {
2730  goto end;
2731  }
2732 
2733  if (HFID_IS_NULL (&hfid))
2734  {
2735  error = ER_FAILED;
2736  goto end;
2737  }
2738 
2739  mvcc_snapshot = logtb_get_mvcc_snapshot (thread_p);
2740  if (mvcc_snapshot == NULL)
2741  {
2742  error = ER_FAILED;
2743  goto end;
2744  }
2745 
2746  error = heap_scancache_start (thread_p, &scan_cache, &hfid, NULL, true, false, mvcc_snapshot);
2747  if (error != NO_ERROR)
2748  {
2749  goto end;
2750  }
2751  scan_cache_inited = true;
2752 
2753  while (true)
2754  {
2755  scan = heap_next (thread_p, &hfid, NULL, &inst_oid, &recdes, &scan_cache, PEEK);
2756  if (scan == S_SUCCESS)
2757  {
2758  error = heap_attrinfo_read_dbvalues (thread_p, &inst_oid, &recdes, NULL, &attr_info);
2759  if (error != NO_ERROR)
2760  {
2761  goto end;
2762  }
2763 
2764  for (i = 0, heap_value = attr_info.values; i < attr_info.num_values; i++, heap_value++)
2765  {
2766  if (heap_value->attrid == attr_idx)
2767  {
2768  user_name = db_get_string (&heap_value->dbvalue);
2769  }
2770  }
2771  }
2772  else if (scan == S_END)
2773  {
2774  break;
2775  }
2776  else
2777  {
2778  error = ER_FAILED;
2779  goto end;
2780  }
2781 
2782  vals = showstmt_alloc_tuple_in_context (thread_p, ctx);
2783  if (vals == NULL)
2784  {
2785  assert (er_errid () != NO_ERROR);
2786  error = er_errid ();
2787  goto end;
2788  }
2789 
2790  access_status = css_get_access_status_with_name (access_status_array, num_user, user_name);
2791  db_make_string_copy (&vals[0], user_name);
2792  if (access_status != NULL)
2793  {
2794  db_localdatetime (&access_status->time, &access_time);
2795  db_make_datetime (&vals[1], &access_time);
2796 
2797  db_make_string_copy (&vals[2], access_status->host);
2798  db_make_string_copy (&vals[3], access_status->program_name);
2799  }
2800  else
2801  {
2802  db_make_null (&vals[1]);
2803  db_make_null (&vals[2]);
2804  db_make_null (&vals[3]);
2805  }
2806  }
2807 
2808 end:
2809  if (scan_cache_inited == true)
2810  {
2811  (void) heap_scancache_end (thread_p, &scan_cache);
2812  }
2813 
2814  if (attr_info_inited == true)
2815  {
2816  heap_attrinfo_end (thread_p, &attr_info);
2817  }
2818 
2819  return error;
2820 }
2821 
2822 /*
2823  * css_get_access_status_with_name () - return access status which match with user_name
2824  * return: address of found access status or NULL
2825  *
2826  * access_status_array(in):
2827  * num_user(in):
2828  * user_name(in):
2829  */
2830 static LAST_ACCESS_STATUS *
2831 css_get_access_status_with_name (LAST_ACCESS_STATUS ** access_status_array, int num_user, const char *user_name)
2832 {
2833  int i = 0;
2834  LAST_ACCESS_STATUS *access_status = NULL;
2835 
2836  assert (user_name != NULL);
2837 
2838  if (access_status_array == NULL)
2839  {
2840  return NULL;
2841  }
2842 
2843  for (i = 0; i < num_user; i++)
2844  {
2845  if (access_status_array[i] != NULL && strcmp (access_status_array[i]->db_user, user_name) == 0)
2846  {
2847  access_status = access_status_array[i];
2848 
2849  access_status_array[i] = NULL;
2850  break;
2851  }
2852  }
2853 
2854  return access_status;
2855 }
2856 
2857 /*
2858  * css_get_unused_access_status () - return unused access status from array
2859  * return: address of found access status or NULL
2860  *
2861  * access_status_array(in):
2862  * num_user(in):
2863  */
2864 static LAST_ACCESS_STATUS *
2865 css_get_unused_access_status (LAST_ACCESS_STATUS ** access_status_array, int num_user)
2866 {
2867  int i = 0;
2868  LAST_ACCESS_STATUS *access_status = NULL;
2869 
2870  if (access_status_array == NULL)
2871  {
2872  return NULL;
2873  }
2874 
2875  for (i = 0; i < num_user; i++)
2876  {
2877  if (access_status_array[i] != NULL)
2878  {
2879  access_status = access_status_array[i];
2880 
2881  access_status_array[i] = NULL;
2882  break;
2883  }
2884  }
2885 
2886  return access_status;
2887 }
2888 #endif /* CS_MODE */
2889 
2890 int
2891 css_platform_independent_poll (POLL_FD * fds, int num_of_fds, int timeout)
2892 {
2893  int rc = 0;
2894 
2895 #if defined (WINDOWS)
2896  rc = WSAPoll (fds, num_of_fds, timeout);
2897 #else
2898  rc = poll (fds, num_of_fds, timeout);
2899 #endif
2900 
2901  return rc;
2902 }
2903 
2904 // *INDENT-OFF*
2905 void
2906 css_conn_entry::set_tran_index (int tran_index)
2907 {
2908  // can never be system transaction index
2909  if (tran_index == LOG_SYSTEM_TRAN_INDEX)
2910  {
2911  assert (false);
2912  tran_index = NULL_TRAN_INDEX;
2913  }
2914  transaction_id = tran_index;
2915 }
2916 
2917 int
2918 css_conn_entry::get_tran_index ()
2919 {
2921  return transaction_id;
2922 }
2923 
2924 void
2925 css_conn_entry::add_pending_request ()
2926 {
2927  ++pending_request_count;
2928 }
2929 
2930 void
2931 css_conn_entry::start_request ()
2932 {
2933  --pending_request_count;
2934 }
2935 
2936 bool
2937 css_conn_entry::has_pending_request () const
2938 {
2939  return pending_request_count != 0;
2940 }
2941 
2942 void
2943 css_conn_entry::init_pending_request ()
2944 {
2945  pending_request_count = 0;
2946 }
2947 // *INDENT-ON*
static int css_net_send3(CSS_CONN_ENTRY *conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3, int len3)
int status
unsigned char address_list[ACL_MAX_IP_COUNT *IP_BYTE_COUNT]
Definition: broker_shm.h:202
int db_make_datetime(DB_VALUE *value, const DB_DATETIME *datetime)
#define NO_ERROR
Definition: error_code.h:46
MVCC_SNAPSHOT * logtb_get_mvcc_snapshot(THREAD_ENTRY *thread_p)
static void css_set_networking_error(SOCKET fd)
#define HA_SERVER_STATE_IDLE_STR
Definition: boot.h:127
int SOCKET
Definition: porting.h:482
#define ASSERT_ERROR()
SCAN_CODE
#define INITIAL_IP_NUM
#define L_cuserid
Definition: porting.h:58
void showstmt_free_array_context(THREAD_ENTRY *thread_p, SHOWSTMT_ARRAY_CONTEXT *ctx)
Definition: show_scan.c:373
#define ER_CSS_RECV_OR_SEND
Definition: error_code.h:813
void css_shutdown_conn(CSS_CONN_ENTRY *conn)
#define HA_LOG_APPLIER_STATE_UNREGISTERED_STR
unsigned int htonl(unsigned int from)
int parse_int(int *ret_p, const char *str_p, int base)
Definition: porting.c:2290
#define HA_MODE_OFF_STR
#define ER_FAILED
Definition: error_code.h:47
const int LOG_SYSTEM_TRAN_INDEX
const char * boot_db_name(void)
Definition: boot_sr.c:459
int css_net_send3_with_socket(SOCKET &socket, const char *buff1, int len1, const char *buff2, int len2, const char *buff3, int len3)
#define NET_HEADER_FLAG_INVALIDATE_SNAPSHOT
char db_user[DB_MAX_USER_LENGTH]
void css_set_io_vector(struct iovec *vec1_p, struct iovec *vec2_p, const char *buff, int len, int *templen)
SOCKET fd
int heap_scancache_quick_start_root_hfid(THREAD_ENTRY *thread_p, HEAP_SCANCACHE *scan_cache)
Definition: heap_file.c:19255
struct pollfd POLL_FD
static bool css_default_check_server_alive_fn(const char *db_name, const char *db_host)
#define OID_SET_NULL(oidp)
Definition: oid.h:85
unsigned short flags
int css_net_send_buffer_only(CSS_CONN_ENTRY *conn, const char *buff, int len, int timeout)
int er_errid(void)
void css_register_check_server_alive_fn(CSS_CHECK_SERVER_ALIVE_FN callback_fn)
int css_read_ip_info(IP_INFO **out_ip_info, char *filename)
SHOWSTMT_ARRAY_CONTEXT * showstmt_alloc_array_context(THREAD_ENTRY *thread_p, int num_total, int num_cols)
Definition: show_scan.c:336
static LAST_ACCESS_STATUS * css_get_unused_access_status(LAST_ACCESS_STATUS **access_status_array, int num_user)
#define er_log_debug(...)
static int css_net_send4(CSS_CONN_ENTRY *conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3, int len3, const char *buff4, int len4)
char * getuserid(char *string, int size)
Definition: porting.c:1271
#define INVALID_SOCKET
Definition: porting.h:483
int heap_scancache_end(THREAD_ENTRY *thread_p, HEAP_SCANCACHE *scan_cache)
Definition: heap_file.c:7195
void css_read_remaining_bytes(SOCKET fd, int len)
int css_platform_independent_poll(POLL_FD *fds, int num_of_fds, int timeout)
#define ER_OPEN_ACCESS_LIST_FILE
Definition: error_code.h:1342
#define HA_LOG_APPLIER_STATE_WORKING_STR
char host[CUB_MAXHOSTNAMELEN]
void THREAD_ENTRY
#define HA_MODE_ON_STR
int heap_scancache_start(THREAD_ENTRY *thread_p, HEAP_SCANCACHE *scan_cache, const HFID *hfid, const OID *class_oid, int cache_last_fix_page, int is_indexscan, MVCC_SNAPSHOT *mvcc_snapshot)
Definition: heap_file.c:6833
int css_net_send(CSS_CONN_ENTRY *conn, const char *buff, int len, int timeout)
int transaction_id
unsigned short css_get_request_id(CSS_CONN_ENTRY *conn)
int heap_attrinfo_start(THREAD_ENTRY *thread_p, const OID *class_oid, int requested_num_attrs, const ATTR_ID *attrids, HEAP_CACHE_ATTRINFO *attr_info)
Definition: heap_file.c:9427
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
int css_send_request(CSS_CONN_ENTRY *conn, int command, unsigned short *request_id, const char *arg_buffer, int arg_buffer_size)
CSS_CHECK_SERVER_ALIVE_FN css_check_server_alive_fn
#define assert(x)
void css_get_user_access_status(int num_user, LAST_ACCESS_STATUS **access_status_array)
static int css_make_access_status_exist_user(THREAD_ENTRY *thread_p, OID *class_oid, LAST_ACCESS_STATUS **access_status_array, int num_user, SHOWSTMT_ARRAY_CONTEXT *ctx)
int prm_get_integer_value(PARAM_ID prm_id)
#define HA_MODE_REPLICA_STR
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
#define HA_SERVER_STATE_DEAD_STR
Definition: boot.h:133
char css_Net_magic[CSS_NET_MAGIC_SIZE]
static int rv
const char * css_ha_server_state_string(HA_SERVER_STATE state)
#define HA_SERVER_STATE_MAINTENANCE_STR
Definition: boot.h:132
#define IS_INVALID_SOCKET(socket)
Definition: porting.h:484
#define DEFAULT_HEADER_DATA
static int css_sprintf_conn_infoids(SOCKET fd, const char **client_user_name, const char **client_host_name, int *client_pid)
int css_Num_access_user
void db_localdatetime(time_t *epoch_time, DB_DATETIME *datetime)
Definition: db_date.c:1030
#define HA_SERVER_STATE_TO_BE_STANDBY_STR
Definition: boot.h:131
static enum scanner_mode mode
#define ER_INACCESSIBLE_IP
Definition: error_code.h:1340
enum ha_log_applier_state HA_LOG_APPLIER_STATE
#define HA_LOG_APPLIER_STATE_ERROR_STR
void css_shutdown_socket(SOCKET fd)
Definition: tcp.c:1179
int heap_attrinfo_read_dbvalues(THREAD_ENTRY *thread_p, const OID *inst_oid, RECDES *recdes, HEAP_SCANCACHE *scan_cache, HEAP_CACHE_ATTRINFO *attr_info)
Definition: heap_file.c:10337
#define NULL
Definition: freelistheap.h:34
pid_t pid
Definition: dynamic_load.c:955
static char * dbname
#define CSS_TRUNCATE_BUFFER_SIZE
unsigned short htons(unsigned short from)
bool css_peer_alive(SOCKET sd, int timeout)
Definition: tcp.c:1470
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
#define CHECK_SERVER_IS_ALIVE()
struct packet_header NET_HEADER
DB_VALUE * showstmt_alloc_tuple_in_context(THREAD_ENTRY *thread_p, SHOWSTMT_ARRAY_CONTEXT *ctx)
Definition: show_scan.c:402
char * db_name
static int css_net_send2(CSS_CONN_ENTRY *conn, const char *buff1, int len1, const char *buff2, int len2)
void er_set_with_oserror(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
const char * css_ha_mode_string(HA_MODE mode)
#define NULL_TRAN_INDEX
static void error(const char *msg)
Definition: gencat.c:331
static void css_default_server_timeout_fn(void)
static int rc
Definition: serial.c:50
#define HA_SERVER_STATE_STANDBY_STR
Definition: boot.h:130
int css_readn(SOCKET fd, char *ptr, int nbytes, int timeout)
bool(* CSS_CHECK_SERVER_ALIVE_FN)(const char *, const char *)
#define HFID_IS_NULL(hfid)
#define ARG_FILE_LINE
Definition: error_manager.h:44
int css_send_io_vector_with_socket(SOCKET &socket, struct iovec *vec_p, ssize_t total_len, int vector_length, int timeout)
static int css_send_io_vector(CSS_CONN_ENTRY *conn, struct iovec *vec_p, ssize_t total_len, int vector_length, int timeout)
OID * db_get_oid(const DB_VALUE *value)
static LAST_ACCESS_STATUS * css_get_access_status_with_name(LAST_ACCESS_STATUS **access_status_array, int num_user, const char *user_name)
int css_check_ip(IP_INFO *ip_info, unsigned char *address)
int num_list
Definition: broker_shm.h:204
void(* CSS_SERVER_TIMEOUT_FN)(void)
int css_free_ip_info(IP_INFO *ip_info)
#define free_and_init(ptr)
Definition: memory_alloc.h:147
static CSS_SERVER_TIMEOUT_FN css_server_timeout_fn
#define strlen(s1)
Definition: intl_support.c:43
int or_get_attrname(RECDES *record, int attrid, char **string, int *alloced_string)
int css_send_request_with_socket(SOCKET &socket, int command, unsigned short *request_id, const char *arg_buffer, int arg_buffer_size)
#define HA_SERVER_STATE_TO_BE_ACTIVE_STR
Definition: boot.h:129
static int css_net_send8(CSS_CONN_ENTRY *conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3, int len3, const char *buff4, int len4, const char *buff5, int len5, const char *buff6, int len6, const char *buff7, int len7, const char *buff8, int len8)
int css_queue_user_data_buffer(CSS_CONN_ENTRY *conn, unsigned short request_id, int size, char *buffer)
int db_make_string_copy(DB_VALUE *value, DB_CONST_C_CHAR str)
void css_register_server_timeout_fn(CSS_SERVER_TIMEOUT_FN callback_fn)
int css_check_magic_with_socket(SOCKET fd)
#define pthread_mutex_lock(b)
int logtb_find_client_name_host_pid(int tran_index, const char **client_prog_name, const char **client_user_name, const char **client_host_name, int *client_pid)
static int css_net_send6(CSS_CONN_ENTRY *conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3, int len3, const char *buff4, int len4, const char *buff5, int len5, const char *buff6, int len6)
int css_net_recv(SOCKET fd, char *buffer, int *maxlen, int timeout)
int css_send_request_with_data_buffer(CSS_CONN_ENTRY *conn, int request, unsigned short *request_id, const char *arg_buffer, int arg_size, char *reply_buffer, int reply_size)
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
void css_set_net_header(NET_HEADER *header_p, int type, short function_code, int request_id, int buffer_size, int transaction_id, int invalidate_snapshot, int db_error)
int css_get_peer_name(SOCKET sockfd, char *hostname, size_t len)
Definition: tcp.c:1592
int css_get_sock_name(SOCKET sockfd, char *hostname, size_t len)
Definition: tcp.c:1618
CSS_CONN_ENTRY * css_find_conn_from_fd(SOCKET fd)
enum ha_mode HA_MODE
static const int CSS_TCP_MIN_NUM_RETRIES
int css_send_magic(CSS_CONN_ENTRY *conn)
int css_user_access_status_start_scan(THREAD_ENTRY *thread_p, int type, DB_VALUE **arg_values, int arg_cnt, void **ptr)
int css_vector_send(SOCKET fd, struct iovec *vec[], int *len, int bytes_written, int timeout)
#define pthread_mutex_unlock(a)
int css_net_read_header(SOCKET fd, char *buffer, int *maxlen, int timeout)
unsigned int ntohl(unsigned int from)
void heap_attrinfo_end(THREAD_ENTRY *thread_p, HEAP_CACHE_ATTRINFO *attr_info)
Definition: heap_file.c:9979
int invalidate_snapshot
int css_send_data(CSS_CONN_ENTRY *conn, unsigned short rid, const char *buffer, int buffer_size)
enum ha_server_state HA_SERVER_STATE
Definition: boot.h:126
SCAN_CODE heap_next(THREAD_ENTRY *thread_p, const HFID *hfid, OID *class_oid, OID *next_oid, RECDES *recdes, HEAP_SCANCACHE *scan_cache, int ispeeking)
Definition: heap_file.c:18622
int css_check_magic(CSS_CONN_ENTRY *conn)
int css_send_error(CSS_CONN_ENTRY *conn, unsigned short rid, const char *buffer, int buffer_size)
#define HA_SERVER_STATE_ACTIVE_STR
Definition: boot.h:128
#define CUB_MAXHOSTNAMELEN
Definition: porting.h:379
int heap_get_class_info(THREAD_ENTRY *thread_p, const OID *class_oid, HFID *hfid_out, FILE_TYPE *ftype_out, char **classname_out)
Definition: heap_file.c:16733
int db_error
#define PEEK
Definition: file_io.h:74
#define IP_BYTE_COUNT
Definition: broker_shm.h:129
int css_net_send_with_socket(SOCKET &socket, const char *buff, int len, int timeout)
#define GETHOSTNAME(p, l)
Definition: porting.h:381
const char ** p
Definition: dynamic_load.c:945
static int css_net_send7(CSS_CONN_ENTRY *conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3, int len3, const char *buff4, int len4, const char *buff5, int len5, const char *buff6, int len6, const char *buff7, int len7)
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
#define ER_INVALID_ACCESS_IP_CONTROL_FILE_FORMAT
Definition: error_code.h:1341
#define HA_LOG_APPLIER_STATE_DONE_STR
static int css_net_send5(CSS_CONN_ENTRY *conn, const char *buff1, int len1, const char *buff2, int len2, const char *buff3, int len3, const char *buff4, int len4, const char *buff5, int len5)
const char * css_ha_applier_state_string(HA_LOG_APPLIER_STATE state)
int css_send_magic_with_socket(SOCKET &socket)
#define HA_LOG_APPLIER_STATE_RECOVERING_STR
SCAN_CODE heap_get_class_record(THREAD_ENTRY *thread_p, const OID *class_oid, RECDES *recdes_p, HEAP_SCANCACHE *scan_cache, int ispeeking)
Definition: heap_file.c:24780