CUBRID Engine  latest
broker_util.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 /*
21  * broker_util.c -
22  */
23 
24 #ident "$Id$"
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <time.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <signal.h>
33 #include <assert.h>
34 #include <ctype.h>
35 
36 #if defined(WINDOWS)
37 #include <winsock2.h>
38 #include <windows.h>
39 #include <direct.h>
40 #include <io.h>
41 #include <process.h>
42 #include <sys/timeb.h>
43 #include <mstcpip.h>
44 #else
45 #include <unistd.h>
46 #include <sys/time.h>
47 #include <sys/timeb.h>
48 #include <netinet/tcp.h>
49 #endif
50 
51 #ifdef V3_TEST
52 #include <sys/procfs.h>
53 #endif
54 
55 #include "porting.h"
56 #include "cas_common.h"
57 #include "broker_env_def.h"
58 #include "broker_util.h"
59 #include "broker_filename.h"
60 #include "environment_variable.h"
61 #include "porting.h"
62 #include "util_func.h"
63 
65 
66 #if defined (ENABLE_UNUSED_FUNCTION)
67 int
68 ut_access_log (int as_index, struct timeval *start_time, char error_flag, int error_log_offset)
69 {
70  FILE *fp;
71  char *access_log = getenv (ACCESS_LOG_ENV_STR);
72  char *script = getenv (PATH_INFO_ENV_STR);
73  char *clt_ip = getenv (REMOTE_ADDR_ENV_STR);
74  char *clt_appl = getenv (CLT_APPL_NAME_ENV_STR);
75  struct tm ct1, ct2;
76  time_t t1, t2;
77  char *p;
78  char err_str[4];
79  struct timeval end_time;
80 
81  gettimeofday (&end_time, NULL);
82 
83  t1 = start_time->tv_sec;
84  t2 = end_time.tv_sec;
85  if (localtime_r (&t1, &ct1) == NULL || localtime_r (&t2, &ct2) == NULL)
86  {
87  return -1;
88  }
89  ct1.tm_year += 1900;
90  ct2.tm_year += 1900;
91 
92  if (access_log == NULL)
93  return -1;
94  fp = fopen (access_log, "a");
95  if (fp == NULL)
96  return -1;
97  if (script == NULL)
98  script = (char *) "-";
99  if (clt_ip == NULL)
100  clt_ip = (char *) "-";
101  if (clt_appl == NULL)
102  clt_appl = (char *) "-";
103  for (p = clt_appl; *p; p++)
104  {
105  if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
106  *p = '_';
107  }
108 
109  if (clt_appl[0] == '\0')
110  clt_appl = (char *) "-";
111 
112  if (error_flag == 1)
113  sprintf (err_str, "ERR");
114  else
115  sprintf (err_str, "-");
116 
117 #ifdef V3_TEST
118  fprintf (fp,
119  "%d %s %s %s %d.%03d %d.%03d %02d/%02d/%02d %02d:%02d:%02d ~ " "%02d/%02d/%02d %02d:%02d:%02d %d %s %d %d\n",
120  as_index + 1, clt_ip, clt_appl, script, (int) start_time->tv_sec, (int) (start_time->tv_usec / 1000),
121  (int) end_time.tv_sec, (int) (end_time.tv_usec / 1000), ct1.tm_year, ct1.tm_mon + 1, ct1.tm_mday,
122  ct1.tm_hour, ct1.tm_min, ct1.tm_sec, ct2.tm_year, ct2.tm_mon + 1, ct2.tm_mday, ct2.tm_hour, ct2.tm_min,
123  ct2.tm_sec, (int) getpid (), err_str, error_file_offset, uts_size ());
124 #else
125  fprintf (fp,
126  "%d %s %s %s %d.%03d %d.%03d %02d/%02d/%02d %02d:%02d:%02d ~ " "%02d/%02d/%02d %02d:%02d:%02d %d %s %d\n",
127  as_index + 1, clt_ip, clt_appl, script, (int) start_time->tv_sec, (int) (start_time->tv_usec / 1000),
128  (int) end_time.tv_sec, (int) (end_time.tv_usec / 1000), ct1.tm_year, ct1.tm_mon + 1, ct1.tm_mday,
129  ct1.tm_hour, ct1.tm_min, ct1.tm_sec, ct2.tm_year, ct2.tm_mon + 1, ct2.tm_mday, ct2.tm_hour, ct2.tm_min,
130  ct2.tm_sec, (int) getpid (), err_str, -1);
131 #endif
132 
133  fclose (fp);
134  return (end_time.tv_sec - start_time->tv_sec);
135 }
136 #endif /* ENABLE_UNUSED_FUNCTION */
137 
138 #if defined (ENABLE_UNUSED_FUNCTION)
139 int
140 ut_file_lock (char *lock_file)
141 {
142  int fd;
143 
144  fd = open (lock_file, O_CREAT | O_EXCL, 0666);
145  if (fd < 0)
146  {
147  if (errno == EEXIST)
148  return -1;
149 #ifdef LOCK_FILE_DEBUG
150  {
151  FILE *fp;
152  fp = fopen ("uts_file_lock.log", "a");
153  if (fp != NULL)
154  {
155  fprintf (fp, "[%d] file lock error. err = [%d], [%s]\n", (int) getpid (), errno, strerror (errno));
156  fclose (fp);
157  }
158  }
159 #endif
160  return 0;
161  }
162  close (fd);
163  return 0;
164 }
165 
166 void
167 ut_file_unlock (char *lock_file)
168 {
169  unlink (lock_file);
170 }
171 #endif /* ENABLE_UNUSED_FUNCTION */
172 
173 #if defined(WINDOWS)
174 int
175 ut_kill_process (int pid)
176 {
177  HANDLE phandle;
178 
179  if (pid <= 0)
180  {
181  return 0;
182  }
183 
184  phandle = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
185  if (phandle)
186  {
187  TerminateProcess (phandle, 0);
188  CloseHandle (phandle);
189  return 0;
190  }
191  return -1;
192 }
193 #else
194 int
196 {
197  int i;
198 
199  if (pid > 0)
200  {
201  for (i = 0; i < 10; i++)
202  {
203  if (kill (pid, SIGTERM) < 0)
204  {
205  return 0;
206  }
207  SLEEP_MILISEC (0, 30);
208  if (kill (pid, 0) < 0)
209  {
210  break;
211  }
212  }
213  if (i >= 10)
214  {
215  kill (pid, SIGKILL);
216  }
217  }
218 
219  return 0;
220 }
221 #endif
222 
223 int
225 {
226  ut_kill_process (pid);
227 
228  if (broker_name != NULL)
229  {
230  char tmp[BROKER_PATH_MAX];
231 
232  ut_get_broker_port_name (tmp, broker_name, BROKER_PATH_MAX);
233 
234  unlink (tmp);
235 
236  return 0;
237  }
238  return -1;
239 }
240 
241 int
243 {
244  ut_kill_process (pid);
245 
246  if (broker_name != NULL && proxy_id >= 0)
247  {
248  char tmp[BROKER_PATH_MAX];
249 
250  ut_get_proxy_port_name (tmp, broker_name, proxy_id, BROKER_PATH_MAX);
251 
252  unlink (tmp);
253 
254  return 0;
255  }
256  return -1;
257 }
258 
259 int
260 ut_kill_as_process (int pid, char *broker_name, int as_index, int shard_flag)
261 {
262  ut_kill_process (pid);
263 
264  if (broker_name != NULL)
265  {
266  char tmp[BROKER_PATH_MAX];
267 
268  /*
269  * shard_cas does not have unix-domain socket and pid lock file.
270  * so, we need not delete socket and lock file.
271  */
272  if (shard_flag == OFF)
273  {
274  ut_get_as_port_name (tmp, broker_name, as_index, BROKER_PATH_MAX);
275 
276  unlink (tmp);
277  }
278 
279  ut_get_as_pid_name (tmp, broker_name, as_index, BROKER_PATH_MAX);
280 
281  unlink (tmp);
282 
283  return 0;
284  }
285  return -1;
286 }
287 
288 int
290 {
291  int optval, optlen;
292 
293  optlen = sizeof (optval);
294  optval = 1; /* true for SO_KEEPALIVE */
295  setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (const char *) &optval, optlen);
296 
297  return 0;
298 }
299 
300 #if defined(WINDOWS)
301 int
302 run_child (const char *appl_name)
303 {
304  int new_pid;
305  char cwd[1024];
306  char cmd[1024];
307  STARTUPINFO start_info;
308  PROCESS_INFORMATION proc_info;
309  BOOL res;
310 
311  memset (cwd, 0, sizeof (cwd));
312  getcwd (cwd, sizeof (cwd));
313 
314  GetStartupInfo (&start_info);
315 
316  sprintf (cmd, "%s/%s.exe", cwd, appl_name);
317 
318  res = CreateProcess (cmd, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info);
319 
320  if (res == FALSE)
321  {
322  return 0;
323  }
324 
325  new_pid = proc_info.dwProcessId;
326 
327  CloseHandle (proc_info.hProcess);
328  CloseHandle (proc_info.hThread);
329 
330  return new_pid;
331 }
332 #endif
333 
334 void
336 {
337  char path[BROKER_PATH_MAX];
338 
339  chdir (envvar_bindir_file (path, BROKER_PATH_MAX, ""));
340 }
341 
342 void
344 {
345  chdir (envvar_root ());
346 }
347 
348 #ifdef V3_TEST
349 int
350 uts_size (void)
351 {
352  int procfd;
353  struct prpsinfo info;
354  const char *procdir = "/proc";
355  char pname[128];
356  int pid = getpid ();
357 
358  sprintf (pname, "%s/%05d", procdir, pid);
359 
360 retry:
361  if ((procfd = open (pname, O_RDONLY)) == -1)
362  {
363  return -1;
364  }
365 
366  if (ioctl (procfd, PIOCPSINFO, (char *) &info) == -1)
367  {
368  int saverr = errno;
369 
370  close (procfd);
371  if (saverr == EAGAIN)
372  goto retry;
373  if (saverr != ENOENT)
374  ;
375  return 1;
376  }
377 
378  close (procfd);
379 
380  return (info.pr_bysize);
381 }
382 #endif
383 
384 void
385 as_pid_file_create (char *br_name, int as_index)
386 {
387  FILE *fp;
388  char as_pid_file_name[BROKER_PATH_MAX];
389 
390  ut_get_as_pid_name (as_pid_file_name, br_name, as_index, BROKER_PATH_MAX);
391 
392  fp = fopen (as_pid_file_name, "w");
393  if (fp)
394  {
395  fprintf (fp, "%d\n", (int) getpid ());
396  fclose (fp);
397  }
398 }
399 
400 void
401 as_db_err_log_set (char *br_name, int proxy_index, int shard_id, int shard_cas_id, int as_index, int shard_flag)
402 {
403  char buf[BROKER_PATH_MAX];
404 
405  if (shard_flag == ON)
406  {
407  sprintf (db_err_log_file, "CUBRID_ERROR_LOG=%s%s_%d_%d_%d.err",
408  get_cubrid_file (FID_CUBRID_ERR_DIR, buf, BROKER_PATH_MAX), br_name, proxy_index + 1, shard_id,
409  shard_cas_id + 1);
410  }
411  else
412  {
413  sprintf (db_err_log_file, "CUBRID_ERROR_LOG=%s%s_%d.err",
414  get_cubrid_file (FID_CUBRID_ERR_DIR, buf, BROKER_PATH_MAX), br_name, as_index + 1);
415  }
416 
417  putenv (db_err_log_file);
418 }
419 
420 int
421 ut_time_string (char *buf, struct timeval *time_val)
422 {
423  struct tm tm, *tm_p;
424  time_t sec;
425  int millisec;
426 
427  if (buf == NULL)
428  {
429  return 0;
430  }
431 
432  if (time_val == NULL)
433  {
434  util_get_second_and_ms_since_epoch (&sec, &millisec);
435  }
436  else
437  {
438  sec = time_val->tv_sec;
439  millisec = time_val->tv_usec / 1000;
440  }
441 
442  tm_p = localtime_r (&sec, &tm);
443  tm.tm_mon++;
444 
445  buf[0] = ((tm.tm_year % 100) / 10) + '0';
446  buf[1] = (tm.tm_year % 10) + '0';
447  buf[2] = '-';
448  buf[3] = (tm.tm_mon / 10) + '0';
449  buf[4] = (tm.tm_mon % 10) + '0';
450  buf[5] = '-';
451  buf[6] = (tm.tm_mday / 10) + '0';
452  buf[7] = (tm.tm_mday % 10) + '0';
453  buf[8] = ' ';
454  buf[9] = (tm.tm_hour / 10) + '0';
455  buf[10] = (tm.tm_hour % 10) + '0';
456  buf[11] = ':';
457  buf[12] = (tm.tm_min / 10) + '0';
458  buf[13] = (tm.tm_min % 10) + '0';
459  buf[14] = ':';
460  buf[15] = (tm.tm_sec / 10) + '0';
461  buf[16] = (tm.tm_sec % 10) + '0';
462  buf[17] = '.';
463  buf[20] = (millisec % 10) + '0';
464  millisec /= 10;
465  buf[19] = (millisec % 10) + '0';
466  millisec /= 10;
467  buf[18] = (millisec % 10) + '0';
468  buf[21] = '\0';
469 
470  return 21;
471 }
472 
473 char *
474 ut_get_ipv4_string (char *ip_str, int len, const unsigned char *ip_addr)
475 {
476  assert (ip_addr != NULL);
477  assert (ip_str != NULL);
478  assert (len >= 16); /* xxx.xxx.xxx.xxx\0 */
479 
480  snprintf (ip_str, len, "%d.%d.%d.%d", (unsigned char) ip_addr[0], (unsigned char) ip_addr[1],
481  (unsigned char) ip_addr[2], (unsigned char) ip_addr[3]);
482  return (ip_str);
483 }
484 
485 float
486 ut_get_avg_from_array (int array[], int size)
487 {
488  int i, total = 0;
489  for (i = 0; i < size; i++)
490  {
491  total += array[i];
492  }
493 
494  return (float) total / size;
495 }
496 
497 bool
498 ut_is_appl_server_ready (int pid, char *ready_flag)
499 {
500  unsigned int i;
501 
502  for (i = 0; i < SERVICE_READY_WAIT_COUNT; i++)
503  {
504  if (*ready_flag != 0)
505  {
506  return true;
507  }
508  else
509  {
510 #if defined(WINDOWS)
511  HANDLE h_process;
512 
513  h_process = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, pid);
514  if (h_process != NULL)
515  {
516  CloseHandle (h_process);
517  SLEEP_MILISEC (0, 10);
518  continue;
519  }
520  else
521  {
522  return false;
523  }
524 #else /* WINDOWS */
525  if (kill (pid, 0) == 0)
526  {
527  SLEEP_MILISEC (0, 10);
528  continue;
529  }
530  else
531  {
532  return false;
533  }
534 #endif /* WINDOWS */
535  }
536  }
537 
538  return false;
539 }
540 
541 void
542 ut_get_broker_port_name (char *port_name, char *broker_name, int len)
543 {
544  char dir_name[BROKER_PATH_MAX];
545 
547 
548  if (snprintf (port_name, len, "%s%s.B", dir_name, broker_name) < 0)
549  {
550  assert (false);
551  port_name[0] = '\0';
552  }
553 }
554 
555 void
556 ut_get_proxy_port_name (char *port_name, char *broker_name, int proxy_id, int len)
557 {
558  char dir_name[BROKER_PATH_MAX];
559 
561 
562  if (snprintf (port_name, len, "%s%s.P%d", dir_name, broker_name, proxy_id + 1) < 0)
563  {
564  assert (false);
565  port_name[0] = '\0';
566  }
567 }
568 
569 void
570 ut_get_as_port_name (char *port_name, char *broker_name, int as_id, int len)
571 {
572  char dir_name[BROKER_PATH_MAX];
573 
575 
576  if (snprintf (port_name, len, "%s%s.%d", dir_name, broker_name, as_id + 1) < 0)
577  {
578  assert (false);
579  port_name[0] = '\0';
580  }
581 }
582 
583 double
584 ut_size_string_to_kbyte (const char *size_str, const char *default_unit)
585 {
586  double val;
587  char *end;
588  char *unit;
589 
590  if (size_str == NULL || default_unit == NULL)
591  {
592  assert (false);
593  }
594 
595  val = strtod (size_str, &end);
596  if (end == (char *) size_str)
597  {
598  return -1.0;
599  }
600 
601  if (isalpha (*end))
602  {
603  unit = end;
604  }
605  else
606  {
607  unit = (char *) default_unit;
608  }
609 
610  if (strcasecmp (unit, "b") == 0)
611  {
612  /* byte */
613  val = val / ONE_K;
614  }
615  else if ((strcasecmp (unit, "k") == 0) || (strcasecmp (unit, "kb") == 0))
616  {
617  /* kilo */
618  }
619  else if ((strcasecmp (unit, "m") == 0) || (strcasecmp (unit, "mb") == 0))
620  {
621  /* mega */
622  val = val * ONE_K;
623  }
624  else if ((strcasecmp (unit, "g") == 0) || (strcasecmp (unit, "gb") == 0))
625  {
626  /* giga */
627  val = val * ONE_M;
628  }
629  else
630  {
631  return -1.0;
632  }
633 
634  if (val > INT_MAX) /* spec */
635  {
636  return -1.0;
637  }
638 
639  return val;
640 }
641 
642 double
643 ut_time_string_to_sec (const char *time_str, const char *default_unit)
644 {
645  double val;
646  char *end;
647  char *unit;
648 
649  if (time_str == NULL || default_unit == NULL)
650  {
651  assert (false);
652  }
653 
654  val = strtod (time_str, &end);
655  if (end == (char *) time_str)
656  {
657  return -1.0;
658  }
659 
660  if (isalpha (*end))
661  {
662  unit = end;
663  }
664  else
665  {
666  unit = (char *) default_unit;
667  }
668 
669  if ((strcasecmp (unit, "ms") == 0) || (strcasecmp (unit, "msec") == 0))
670  {
671  /* millisecond */
672  val = val / ONE_SEC;
673  }
674  else if ((strcasecmp (unit, "s") == 0) || (strcasecmp (unit, "sec") == 0))
675  {
676  /* second */
677  }
678  else if (strcasecmp (unit, "min") == 0)
679  {
680  /* minute */
681  val = val * ONE_MIN / ONE_SEC;
682  }
683  else if (strcasecmp (unit, "h") == 0)
684  {
685  /* hours */
686  val = val * ONE_HOUR / ONE_SEC;
687  }
688  else
689  {
690  return -1.0;
691  }
692 
693  if (val > INT_MAX) /* spec */
694  {
695  return -1.0;
696  }
697 
698  return val;
699 }
700 
701 void
702 ut_get_as_pid_name (char *pid_name, char *br_name, int as_index, int len)
703 {
704  char dir_name[BROKER_PATH_MAX];
705 
707 
708  if (snprintf (pid_name, len, "%s%s_%d.pid", dir_name, br_name, as_index + 1) < 0)
709  {
710  assert (false);
711  pid_name[0] = '\0';
712  }
713 }
#define SLEEP_MILISEC(sec, msec)
Definition: util_func.h:40
void ut_cd_work_dir(void)
Definition: broker_util.c:335
const char * envvar_root(void)
int ut_set_keepalive(int sock)
Definition: broker_util.c:289
#define PATH_INFO_ENV_STR
double ut_time_string_to_sec(const char *time_str, const char *default_unit)
Definition: broker_util.c:643
char * ut_get_ipv4_string(char *ip_str, int len, const unsigned char *ip_addr)
Definition: broker_util.c:474
#define BROKER_PATH_MAX
Definition: broker_config.h:91
bool ut_is_appl_server_ready(int pid, char *ready_flag)
Definition: broker_util.c:498
char broker_name[BROKER_NAME_LEN]
Definition: cas.c:148
#define CLT_APPL_NAME_ENV_STR
void ut_get_broker_port_name(char *port_name, char *broker_name, int len)
Definition: broker_util.c:542
void ut_cd_root_dir(void)
Definition: broker_util.c:343
int ut_time_string(char *buf, struct timeval *time_val)
Definition: broker_util.c:421
char * get_cubrid_file(T_CUBRID_FILE_ID fid, char *buf, size_t len)
int ut_kill_as_process(int pid, char *broker_name, int as_index, int shard_flag)
Definition: broker_util.c:260
#define assert(x)
#define ONE_HOUR
Definition: porting.h:70
int proxy_id
Definition: shard_proxy.c:45
char * envvar_bindir_file(char *path, size_t size, const char *filename)
double ut_size_string_to_kbyte(const char *size_str, const char *default_unit)
Definition: broker_util.c:584
#define NULL
Definition: freelistheap.h:34
pid_t pid
Definition: dynamic_load.c:955
#define ONE_M
Definition: porting.h:63
static struct timeval start_time
#define ONE_SEC
Definition: porting.h:68
void as_db_err_log_set(char *br_name, int proxy_index, int shard_id, int shard_cas_id, int as_index, int shard_flag)
Definition: broker_util.c:401
void util_get_second_and_ms_since_epoch(time_t *secs, int *msec)
Definition: util_func.c:829
int ut_kill_process(int pid)
Definition: broker_util.c:195
void as_pid_file_create(char *br_name, int as_index)
Definition: broker_util.c:385
char db_err_log_file[BROKER_PATH_MAX]
Definition: broker_util.c:64
void ut_get_proxy_port_name(char *port_name, char *broker_name, int proxy_id, int len)
Definition: broker_util.c:556
#define FALSE
Definition: broker_admin.c:50
void ut_get_as_port_name(char *port_name, char *broker_name, int as_id, int len)
Definition: broker_util.c:570
#define ONE_K
Definition: porting.h:62
int i
Definition: dynamic_load.c:954
#define REMOTE_ADDR_ENV_STR
void ut_get_as_pid_name(char *pid_name, char *br_name, int as_index, int len)
Definition: broker_util.c:702
int ut_kill_broker_process(int pid, char *broker_name)
Definition: broker_util.c:224
int ut_kill_proxy_process(int pid, char *broker_name, int proxy_id)
Definition: broker_util.c:242
#define ONE_MIN
Definition: porting.h:69
const char ** p
Definition: dynamic_load.c:945
#define SERVICE_READY_WAIT_COUNT
Definition: broker_util.h:47
float ut_get_avg_from_array(int array[], int size)
Definition: broker_util.c:486