CUBRID Engine  latest
event_log.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  * event_log.c - event log module (server)
22  */
23 
24 #ident "$Id$"
25 
26 #if defined (WINDOWS)
27 // TODO: fix lseek
28 #include <io.h>
29 #endif /* WINDOWS */
30 
31 #include "event_log.h"
32 
33 #include "config.h"
34 #include "critical_section.h"
35 #include "dbtype.h"
36 #include "error_manager.h"
37 #include "environment_variable.h"
38 #include "log_impl.h"
39 #include "query_executor.h"
40 #include "object_primitive.h"
41 #include "porting.h"
42 #include "system_parameter.h"
43 #include "xasl_cache.h"
44 
45 #include <assert.h>
46 
47 #if defined (WINDOWS)
48 #include <process.h>
49 #endif /* WINDOWS */
50 #include <stdio.h>
51 #if !defined (WINDOWS)
52 #include <sys/time.h>
53 #endif /* WINDOWS */
54 
55 #define EVENT_LOG_FILE_DIR "server"
56 #define EVENT_LOG_FILE_SUFFIX ".event"
57 
58 static FILE *event_Fp = NULL;
59 static char event_log_file_path[PATH_MAX];
60 
61 static FILE *event_file_open (const char *path);
62 static FILE *event_file_backup (FILE * fp, const char *path);
63 static void event_log_print_client_ids_info (CLIENTIDS * client_info, int indent);
64 
65 /*
66  * event_init - Initialize event log module
67  * return: none
68  */
69 void
70 event_log_init (const char *db_name)
71 {
72  char *s, *base_db_name;
73  char local_db_name[DB_MAX_IDENTIFIER_LENGTH];
74  time_t log_time;
75  struct tm log_tm, *log_tm_p = &log_tm;
76  char event_log_name[PATH_MAX];
77 
78  assert (db_name != NULL);
79 
80  strncpy (local_db_name, db_name, DB_MAX_IDENTIFIER_LENGTH);
81  local_db_name[DB_MAX_IDENTIFIER_LENGTH - 1] = '\0';
82  s = strchr (local_db_name, '@');
83  if (s)
84  {
85  *s = '\0';
86  }
87 
88  base_db_name = basename ((char *) local_db_name);
89  if (base_db_name == NULL)
90  {
91  return;
92  }
93 
94  log_time = time (NULL);
95 #if defined (SERVER_MODE) && !defined (WINDOWS)
96  log_tm_p = localtime_r (&log_time, &log_tm);
97 #else /* SERVER_MODE && !WINDOWS */
98  log_tm_p = localtime (&log_time);
99 #endif /* SERVER_MODE && !WINDOWS */
100 
101  if (log_tm_p == NULL)
102  {
103  return;
104  }
105 
106  snprintf (event_log_name, PATH_MAX - 1, "%s%c%s_%04d%02d%02d_%02d%02d%s", EVENT_LOG_FILE_DIR, PATH_SEPARATOR,
107  base_db_name, log_tm_p->tm_year + 1900, log_tm_p->tm_mon + 1, log_tm_p->tm_mday, log_tm_p->tm_hour,
108  log_tm_p->tm_min, EVENT_LOG_FILE_SUFFIX);
109 
110  envvar_logdir_file (event_log_file_path, PATH_MAX, event_log_name);
112 }
113 
114 /*
115  * event_file_open - Open event log file
116  * return: FILE *
117  * path(in): file path
118  */
119 static FILE *
120 event_file_open (const char *path)
121 {
122  FILE *fp;
123  char dir[PATH_MAX], *tpath;
124 
125  assert (path != NULL);
126 
127  tpath = strdup (path);
128  if (tpath == NULL)
129  {
131  return NULL;
132  }
133 
134  while (1)
135  {
136  if (cub_dirname_r (tpath, dir, PATH_MAX) > 0 && access (dir, F_OK) < 0)
137  {
138  if (mkdir (dir, 0777) < 0 && errno == ENOENT)
139  {
140  free_and_init (tpath);
141 
142  tpath = strdup (dir);
143  if (tpath == NULL)
144  {
146  return NULL;
147  }
148 
149  continue;
150  }
151  }
152 
153  break;
154  }
155 
156  free_and_init (tpath);
157 
158  fp = fopen (path, "r+");
159  if (fp != NULL)
160  {
161  fseek (fp, 0, SEEK_END);
162  if (ftell (fp) > prm_get_integer_value (PRM_ID_ER_LOG_SIZE))
163  {
164  fp = event_file_backup (fp, path);
165  }
166  }
167  else
168  {
169  fp = fopen (path, "w");
170  }
171 
172 #if !defined (WINDOWS) && defined (SERVER_MODE)
173  if (fp != NULL)
174  {
175  er_file_create_link_to_current_log_file (path, EVENT_LOG_FILE_SUFFIX);
176  }
177 #endif /* !WINDOWS && SERVER_MODE */
178 
179  return fp;
180 }
181 
182 /*
183  * event_file_backup - backup event log file
184  * return: FILE *
185  * path(in): file path
186  */
187 static FILE *
188 event_file_backup (FILE * fp, const char *path)
189 {
190  char backup_file[PATH_MAX];
191 
192  assert (fp != NULL);
193  assert (path != NULL);
194 
195  fclose (fp);
196  sprintf (backup_file, "%s.bak", path);
197  (void) unlink (backup_file);
198  (void) rename (path, backup_file);
199 
200  return fopen (path, "w");
201 }
202 
203 /*
204  * event_log_final - Terminate the event log module
205  * return: none
206  */
207 void
209 {
210  if (event_Fp != NULL)
211  {
212  (void) fclose (event_Fp);
213  }
214 }
215 
216 /*
217  * event_log_start -
218  * return: log file pointer
219  * event_name(in):
220  */
221 FILE *
222 event_log_start (THREAD_ENTRY * thread_p, const char *event_name)
223 {
224  time_t er_time;
225  struct tm er_tm;
226  struct tm *er_tm_p = &er_tm;
227  struct timeval tv;
228  char time_array[256];
229  const char *log_file_name = event_log_file_path;
230 
232 
233  /* If file is not exist, it will recreate *log_fh file. */
234  if (event_Fp == NULL || access (log_file_name, F_OK) == -1)
235  {
236  if (event_Fp != NULL)
237  {
238  (void) fclose (event_Fp);
239  }
240 
241  event_Fp = event_file_open (log_file_name);
242  if (event_Fp == NULL)
243  {
245  csect_exit (thread_p, CSECT_EVENT_LOG_FILE);
246  return NULL;
247  }
248  }
250  {
251  (void) fflush (event_Fp);
252 
253  event_Fp = event_file_backup (event_Fp, log_file_name);
254  if (event_Fp == NULL)
255  {
257  csect_exit (thread_p, CSECT_EVENT_LOG_FILE);
258  return NULL;
259  }
260  }
261 
262  er_time = time (NULL);
263 #if defined (SERVER_MODE) && !defined (WINDOWS)
264  er_tm_p = localtime_r (&er_time, &er_tm);
265 #else /* SERVER_MODE && !WINDOWS */
266  er_tm_p = localtime (&er_time);
267 #endif /* SERVER_MODE && !WINDOWS */
268 
269  if (er_tm_p == NULL)
270  {
271  strcpy (time_array, "00/00/00 00:00:00.000");
272  }
273  else
274  {
275  gettimeofday (&tv, NULL);
276  snprintf (time_array + strftime (time_array, 128, "%m/%d/%y %H:%M:%S", er_tm_p), 255, ".%03ld",
277  tv.tv_usec / 1000);
278  }
279 
280  fprintf (event_Fp, "%s - %s\n", time_array, event_name);
281 
282  return event_Fp;
283 }
284 
285 /*
286  * event_log_end -
287  * return:
288  */
289 void
291 {
292  assert (csect_check_own (thread_p, CSECT_EVENT_LOG_FILE) == 1);
293 
294  if (event_Fp == NULL)
295  {
296  return;
297  }
298 
299  fflush (event_Fp);
300  csect_exit (thread_p, CSECT_EVENT_LOG_FILE);
301 }
302 
303 /*
304  * event_log_print_client_ids_info -
305  * return:
306  */
307 static void
308 event_log_print_client_ids_info (CLIENTIDS * client_info, int indent)
309 {
310  if (event_Fp == NULL)
311  {
312  return;
313  }
314 
315  if (client_info->client_type < 0)
316  {
317  return;
318  }
319 
320  if (indent > 0)
321  {
322  fprintf (event_Fp, "%*c", indent, ' ');
323  }
324  fprintf (event_Fp, "client: %s@%s|%s(%d)\n", client_info->get_db_user (), client_info->get_host_name (),
325  client_info->get_program_name (), client_info->process_id);
326 }
327 
328 /*
329  * event_log_print_client_info -
330  * return:
331  * tran_index(in):
332  * indent(in):
333  */
334 void
335 event_log_print_client_info (int tran_index, int indent)
336 {
337  const char *prog, *user, *host;
338  int pid;
339 
340  if (event_Fp == NULL)
341  {
342  return;
343  }
344 
345  logtb_find_client_name_host_pid (tran_index, &prog, &user, &host, &pid);
346 
347  if (indent > 0)
348  {
349  fprintf (event_Fp, "%*c", indent, ' ');
350  }
351  fprintf (event_Fp, "client: %s@%s|%s(%d)\n", user, host, prog, pid);
352 }
353 
354 /*
355  * event_log_sql_string -
356  * return:
357  * thread_p(in):
358  * log_fp(in):
359  * xasl_id(in):
360  */
361 void
362 event_log_sql_string (THREAD_ENTRY * thread_p, FILE * log_fp, XASL_ID * xasl_id, int indent)
363 {
364  XASL_CACHE_ENTRY *ent = NULL;
365 
366  assert (csect_check_own (thread_p, CSECT_EVENT_LOG_FILE) == 1);
367 
368  fprintf (log_fp, "%*csql: ", indent, ' ');
369 
370  if (XASL_ID_IS_NULL (xasl_id))
371  {
372  fprintf (log_fp, "%s\n", EVENT_EMPTY_QUERY);
373  return;
374  }
375 
376  if (xcache_find_sha1 (thread_p, &xasl_id->sha1, XASL_CACHE_SEARCH_GENERIC, &ent, NULL) != NO_ERROR)
377  {
378  ASSERT_ERROR ();
379  return;
380  }
381 
382  if (ent != NULL && ent->sql_info.sql_hash_text != NULL)
383  {
384  fprintf (log_fp, "%s\n", ent->sql_info.sql_hash_text);
385  }
386  else
387  {
388  fprintf (log_fp, "%s\n", EVENT_EMPTY_QUERY);
389  }
390 
391  if (ent != NULL)
392  {
393  xcache_unfix (thread_p, ent);
394  }
395 }
396 
397 /*
398  * event_log_bind_values -
399  * return:
400  * log_fp(in):
401  * tran_index(in):
402  * bind_index(in):
403  */
404 void
405 event_log_bind_values (THREAD_ENTRY * thread_p, FILE * log_fp, int tran_index, int bind_index)
406 {
407  LOG_TDES *tdes;
408  int i, indent = 2;
409  char *val_str;
410 
411  if (bind_index < 0)
412  {
413  return;
414  }
415 
416  tdes = LOG_FIND_TDES (tran_index);
417 
418  if (tdes == NULL || tdes->bind_history[bind_index].vals == NULL)
419  {
420  return;
421  }
422 
423  for (i = 0; i < tdes->bind_history[bind_index].size; i++)
424  {
425  val_str = pr_valstring (&tdes->bind_history[bind_index].vals[i]);
426  fprintf (log_fp, "%*cbind: %s\n", indent, ' ', (val_str == NULL) ? "(null)" : val_str);
427 
428  if (val_str != NULL)
429  {
430  db_private_free (thread_p, val_str);
431  }
432  }
433 }
434 
435 /*
436  * event_log_log_flush_thr_wait -
437  * return:
438  * thread_p(in):
439  * flush_count(in): the num of flushed pages
440  * client_info(in): last log writer client info
441  * flush_time(in): total time spent for flushing
442  * flush_wait_time(in): time waiting for LWT to be finished
443  * writer_time(in): time spent by last LWT (normally same as flush wait time)
444  */
445 void
446 event_log_log_flush_thr_wait (THREAD_ENTRY * thread_p, int flush_count, clientids * client_info, int flush_time,
447  int flush_wait_time, int writer_time)
448 {
449  FILE *log_fp;
450  int indent = 2;
451 
452  log_fp = event_log_start (thread_p, "LOG_FLUSH_THREAD_WAIT");
453  if (log_fp == NULL)
454  {
455  return;
456  }
457 
458  fprintf (log_fp, "%*ctotal flush count: %d page(s)\n", indent, ' ', flush_count);
459  fprintf (log_fp, "%*ctotal flush time: %d ms\n", indent, ' ', flush_time);
460  fprintf (log_fp, "%*ctime waiting for log writer: %d ms\n", indent, ' ', flush_wait_time);
461  fprintf (log_fp, "%*clast log writer info\n", indent, ' ');
462 
463  indent *= 2;
464  event_log_print_client_ids_info (client_info, indent);
465  fprintf (log_fp, "%*ctime spent by last log writer: %d ms\n", indent, ' ', writer_time);
466 
467  event_log_end (thread_p);
468 }
char * envvar_logdir_file(char *path, size_t size, const char *filename)
#define EVENT_LOG_FILE_DIR
Definition: event_log.c:55
#define NO_ERROR
Definition: error_code.h:46
int xcache_find_sha1(THREAD_ENTRY *thread_p, const SHA1Hash *sha1, const XASL_CACHE_SEARCH_MODE search_mode, XASL_CACHE_ENTRY **xcache_entry, xasl_cache_rt_check_result *rt_check)
Definition: xasl_cache.c:791
static FILE * event_Fp
Definition: event_log.c:58
DB_VALUE * vals
Definition: dbtype_def.h:1100
#define ASSERT_ERROR()
SHA1Hash sha1
#define EVENT_EMPTY_QUERY
Definition: event_log.h:37
void event_log_sql_string(THREAD_ENTRY *thread_p, FILE *log_fp, XASL_ID *xasl_id, int indent)
Definition: event_log.c:362
#define csect_enter(a, b, c)
Definition: cnv.c:138
const char * get_host_name() const
static FILE * log_fp
Definition: cas_log.c:91
FILE * event_log_start(THREAD_ENTRY *thread_p, const char *event_name)
Definition: event_log.c:222
LOG_TDES * LOG_FIND_TDES(int tran_index)
Definition: log_impl.h:1095
static void event_log_print_client_ids_info(CLIENTIDS *client_info, int indent)
Definition: event_log.c:308
void THREAD_ENTRY
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
db_client_type client_type
#define csect_check_own(a, b)
const char * get_program_name() const
#define assert(x)
static FILE * event_file_backup(FILE *fp, const char *path)
Definition: event_log.c:188
int prm_get_integer_value(PARAM_ID prm_id)
void event_log_log_flush_thr_wait(THREAD_ENTRY *thread_p, int flush_count, clientids *client_info, int flush_time, int flush_wait_time, int writer_time)
Definition: event_log.c:446
#define ER_GENERIC_ERROR
Definition: error_code.h:49
static char event_log_file_path[PATH_MAX]
Definition: event_log.c:59
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
#define DB_MAX_IDENTIFIER_LENGTH
Definition: dbtype_def.h:495
void xcache_unfix(THREAD_ENTRY *thread_p, XASL_CACHE_ENTRY *xcache_entry)
Definition: xasl_cache.c:1083
void event_log_bind_values(THREAD_ENTRY *thread_p, FILE *log_fp, int tran_index, int bind_index)
Definition: event_log.c:405
int cub_dirname_r(const char *path, char *pathbuf, size_t buflen)
Definition: porting.c:989
#define NULL
Definition: freelistheap.h:34
void event_log_final(void)
Definition: event_log.c:208
void event_log_end(THREAD_ENTRY *thread_p)
Definition: event_log.c:290
pid_t pid
Definition: dynamic_load.c:955
#define csect_exit(a, b)
Definition: cnv.c:139
#define db_private_free(thrd, ptr)
Definition: memory_alloc.h:229
char * db_name
EXECUTION_INFO sql_info
Definition: xasl_cache.h:103
DB_VALUE_ARRAY bind_history[MAX_NUM_EXEC_QUERY_HISTORY]
Definition: log_impl.h:530
#define ARG_FILE_LINE
Definition: error_manager.h:44
void event_log_print_client_info(int tran_index, int indent)
Definition: event_log.c:335
char * sql_hash_text
Definition: xasl_cache.h:76
const char * get_db_user() const
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
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)
char * basename(const char *path)
Definition: porting.c:1132
static FILE * event_file_open(const char *path)
Definition: event_log.c:120
int i
Definition: dynamic_load.c:954
char * pr_valstring(const DB_VALUE *val)
#define XASL_ID_IS_NULL(X)
Definition: xasl.h:560
char * strdup(const char *str)
Definition: porting.c:901
void event_log_init(const char *db_name)
Definition: event_log.c:70
#define EVENT_LOG_FILE_SUFFIX
Definition: event_log.c:56
static char * host
#define PATH_SEPARATOR
Definition: porting.h:347