CUBRID Engine  latest
log_applier.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  * log_applier.c : main routine of Transaction Log Applier
21  *
22  */
23 
24 #ident "$Id$"
25 
26 #if !defined (WINDOWS)
27 #include <unistd.h>
28 #endif
29 #include <errno.h>
30 #include <fcntl.h>
31 #if !defined (WINDOWS)
32 #include <sys/time.h>
33 #endif
34 #include <signal.h>
35 #include <pthread.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/socket.h>
39 #include <sys/un.h>
40 
41 
42 #include "log_applier.h"
43 
44 #include "authenticate.h"
45 #include "porting.h"
46 #include "utility.h"
47 #include "environment_variable.h"
48 #include "message_catalog.h"
49 #include "msgcat_set_log.hpp"
50 #include "log_compress.h"
51 #include "log_lsa.hpp"
52 #include "parser.h"
53 #include "object_primitive.h"
54 #include "object_representation.h"
55 #include "db_value_printer.hpp"
56 #include "db.h"
57 #include "object_accessor.h"
58 #include "locator_cl.h"
59 #include "connection_cl.h"
60 #include "network_interface_cl.h"
61 #include "transform.h"
62 #include "file_io.h"
63 #include "memory_hash.h"
64 #include "schema_manager.h"
65 #include "log_applier_sql_log.h"
66 #include "util_func.h"
67 #include "dbtype.h"
68 #ifdef UNSTABLE_TDE_FOR_REPLICATION_LOG
69 #include "tde.h"
70 #endif /* UNSTABLE_TDE_FOR_REPLICATION_LOG */
71 #if !defined(WINDOWS)
72 #include "heartbeat.h"
73 #endif
74 #include "mem_block.hpp"
75 #include "string_buffer.hpp"
76 
77 #if defined(AIX)
78 #include <procinfo.h>
79 #include <sys/types.h>
80 #endif
81 
82 #define LA_DEFAULT_CACHE_BUFFER_SIZE 100
83 #define LA_MAX_REPL_ITEM_WITHOUT_RELEASE_PB 50
84 #define LA_MAX_UNFLUSHED_REPL_ITEMS 200
85 #define LA_DEFAULT_LOG_PAGE_SIZE 4096
86 #define LA_GET_PAGE_RETRY_COUNT 10
87 #define LA_REPL_LIST_COUNT 50
88 
89 #define LA_PAGE_DOESNOT_EXIST 0
90 #define LA_PAGE_EXST_IN_ACTIVE_LOG 1
91 #define LA_PAGE_EXST_IN_ARCHIVE_LOG 2
92 
93 #define LA_STATUS_BUSY 1
94 #define LA_STATUS_IDLE 0
95 
96 #define LA_LOCK_SUFFIX "_lgla__lock"
97 
98 #define LA_QUERY_BUF_SIZE 2048
99 
100 #define LA_MAX_REPL_ITEMS 1000
101 
102 /* for adaptive commit interval */
103 #define LA_NUM_DELAY_HISTORY 10
104 #define LA_MAX_TOLERABLE_DELAY 2
105 #define LA_REINIT_COMMIT_INTERVAL 10
106 
107 #define LA_WS_CULL_MOPS_PER_APPLY (100000)
108 #define LA_WS_CULL_MOPS_INTERVAL (180)
109 #define LA_WS_CULL_MOPS_PER_APPLY_MIN (100)
110 #define LA_WS_CULL_MOPS_INTERVAL_MIN (2)
111 
112 #define LA_NUM_REPL_FILTER 50
113 
114 #define LA_LOG_IS_IN_ARCHIVE(pageid) \
115  ((pageid) < la_Info.act_log.log_hdr->nxarv_pageid)
116 
117 #define SIZEOF_LA_CACHE_LOG_BUFFER(io_pagesize) \
118  (offsetof(LA_CACHE_BUFFER, logpage) + (io_pagesize))
119 
120 #define LA_LOGAREA_SIZE (la_Info.act_log.db_logpagesize - SSIZEOF(LOG_HDRPAGE))
121 #define LA_LOG_READ_ADVANCE_WHEN_DOESNT_FIT(result, length, offset, pageid, pgptr) \
122  do { \
123  if ((offset)+(length) >= LA_LOGAREA_SIZE) { \
124  if (((pgptr) = la_get_page(++(pageid))) == NULL) { \
125  result = ER_IO_READ; \
126  } \
127  (offset) = 0; \
128  } \
129  } while(0)
130 
131 #define LA_LOG_READ_ALIGN(result, offset, pageid, log_pgptr) \
132  do { \
133  (offset) = DB_ALIGN((offset), MAX_ALIGNMENT); \
134  while ((offset) >= LA_LOGAREA_SIZE) { \
135  if (((log_pgptr) = la_get_page(++(pageid))) == NULL) { \
136  result = ER_IO_READ; \
137  } \
138  (offset) -= LA_LOGAREA_SIZE; \
139  (offset) = DB_ALIGN((offset), MAX_ALIGNMENT); \
140  } \
141  } while(0)
142 
143 #define LA_LOG_READ_ADD_ALIGN(result, add, offset, pageid, log_pgptr) \
144  do { \
145  (offset) += (add); \
146  LA_LOG_READ_ALIGN(result, (offset), (pageid), (log_pgptr)); \
147  } while(0)
148 
149 #define LA_SLEEP(sec, usec) \
150  do { \
151  struct timeval sleep_time_val; \
152  sleep_time_val.tv_sec = (sec); \
153  sleep_time_val.tv_usec = (usec); \
154  select (0, 0, 0, 0, &sleep_time_val); \
155  } while(0)
156 
157 /* move the data inside the record (identical to HEAP_MOVE_INSIDE_RECORD) */
158 #define LA_MOVE_INSIDE_RECORD(rec, dest_offset, src_offset) \
159  do \
160  { \
161  assert ((rec) != NULL && (dest_offset) >= 0 && (src_offset) >= 0); \
162  assert (((rec)->length - (src_offset)) >= 0); \
163  assert (((rec)->area_size <= 0) || ((rec)->area_size >= (rec)->length)); \
164  assert (((rec)->area_size <= 0) \
165  || (((rec)->length + ((dest_offset) - (src_offset))) \
166  <= (rec)->area_size)); \
167  if ((dest_offset) != (src_offset)) \
168  { \
169  memmove ((rec)->data + (dest_offset), (rec)->data + (src_offset), \
170  (rec)->length - (src_offset)); \
171  (rec)->length = (rec)->length + ((dest_offset) - (src_offset)); \
172  } \
173  } \
174  while (0)
175 
178 {
182 
183  LOG_PAGEID pageid; /* Logical page of the log */
185 
186  LOG_PAGE logpage; /* The actual buffered log page */
187 };
188 
191 {
192  LA_CACHE_BUFFER *buffer_area; /* log buffer area */
193  LA_CACHE_BUFFER_AREA *next; /* next area */
194 };
195 
196 typedef struct la_cache_pb LA_CACHE_PB;
198 {
199  MHT_TABLE *hash_table; /* hash table for buffers */
200  LA_CACHE_BUFFER **log_buffer; /* buffer pool */
201  int num_buffers; /* # of buffers */
202  LA_CACHE_BUFFER_AREA *buffer_area; /* contignous area of buffers */
203 };
204 
207 {
208  char **list;
212 };
213 
214 typedef struct la_act_log LA_ACT_LOG;
216 {
217  char path[PATH_MAX];
218  int log_vdes;
223 };
224 
225 typedef struct la_arv_log LA_ARV_LOG;
227 {
228  char path[PATH_MAX];
229  int log_vdes;
232  int arv_num;
233 };
234 
235 typedef struct la_item LA_ITEM;
236 struct la_item
237 {
240 
241  int log_type;
243  char *class_name;
244  char *db_user;
245  char *ha_sys_prm;
247  char *packed_key_value; /* disk image of pkey value */
248  DB_VALUE key; /* it will be unpacked from packed_key_value on demand */
249  LOG_LSA lsa; /* the LSA of the replication log record */
250  LOG_LSA target_lsa; /* the LSA of the target log record */
251 };
252 
253 typedef struct la_apply LA_APPLY;
254 struct la_apply
255 {
256  int tranid;
263 };
264 
265 typedef struct la_commit LA_COMMIT;
266 struct la_commit
267 {
270 
271  int type; /* transaction state - LOG_COMMIT */
272  int tranid; /* transaction id */
273  LOG_LSA log_lsa; /* LSA of LOG_COMMIT */
274  time_t log_record_time; /* commit time at the server site */
275 };
276 
277 /* Log applier info */
278 typedef struct la_info LA_INFO;
279 struct la_info
280 {
281  /* log info */
282  char log_path[PATH_MAX];
283  char loginf_path[PATH_MAX];
287  unsigned long start_vsize;
288  time_t start_time;
289 
290  /* map info */
291  LOG_LSA final_lsa; /* last processed log lsa */
292  LOG_LSA committed_lsa; /* last committed commit log lsa */
293  LOG_LSA committed_rep_lsa; /* last committed replication log lsa */
294  LOG_LSA last_committed_lsa; /* last committed commit log lsa at the beginning of the applylogdb */
295  LOG_LSA last_committed_rep_lsa; /* last committed replication log lsa at the beginning of the applylogdb */
296 
298  int repl_cnt; /* the # of elements of repl_lists */
299  int cur_repl; /* the index of the current repl_lists */
300  int total_rows; /* the # of rows that were replicated */
301  int prev_total_rows; /* the previous # of total_rows */
302  time_t log_record_time; /* time of the last commit log record */
303  LA_COMMIT *commit_head; /* queue list head */
304  LA_COMMIT *commit_tail; /* queue list tail */
306  /* last time that one or more archives were deleted */
308 
309  /* slave info */
310  char *log_data;
311  char *rec_type;
316 
317  /* master info */
324 
325  /* db_ha_apply_info */
326  LOG_LSA append_lsa; /* append lsa of active log header */
327  LOG_LSA eof_lsa; /* eof lsa of active log header */
328  LOG_LSA required_lsa; /* start lsa of the first transaction to be applied */
329  unsigned long insert_counter;
330  unsigned long update_counter;
331  unsigned long delete_counter;
332  unsigned long schema_counter;
333  unsigned long commit_counter;
334  unsigned long fail_counter;
337  int status;
338  bool is_apply_info_updated; /* whether catalog is partially updated or not */
339 
341 
342  /* file lock */
345 
347 
349 #ifdef UNSTABLE_TDE_FOR_REPLICATION_LOG
350  int tde_sock_for_dks; /* unix socket for sharing TDE Data keys with copylogd */
351 #endif /* UNSTABLE_TDE_FOR_REPLICATION_LOG */
352 };
353 
356 {
358  int length;
359  char data[1]; /* Really more than one */
360 };
361 
364 {
366  char data[1]; /* Really more than one */
367 };
368 
369 /* use overflow page list to reduce memory copy overhead. */
372 {
373  char *rec_type; /* record type */
374  char *data; /* overflow page data: header + real data */
375  int length; /* total length of data */
376  LA_OVF_PAGE_LIST *next; /* next page */
377 };
378 
381 {
383  char *area; /* continuous area for recdes data */
384  int next_idx;
388 };
389 
392 {
393  char db_name[256];
395  char copied_log_path[4096];
396  LOG_LSA committed_lsa; /* last committed commit log lsa */
397  LOG_LSA committed_rep_lsa; /* last committed replication log lsa */
398  LOG_LSA append_lsa; /* append lsa of active log header */
399  LOG_LSA eof_lsa; /* eof lsa of active log header */
400  LOG_LSA final_lsa; /* last processed log lsa */
401  LOG_LSA required_lsa; /* start lsa of the first transaction to be applied */
405  int status;
413 };
414 
415 /* Global variable for LA */
417 
419 
420 static bool la_applier_need_shutdown = false;
421 static bool la_applier_shutdown_by_signal = false;
424 
425 static bool la_enable_sql_logging = false;
426 
427 #if defined (WINDOWS)
428 static void la_shutdown_by_signal (void);
429 #else /* !WINDOWS */
430 static void la_shutdown_by_signal (int);
431 #endif /* !WINDOWS */
432 static void la_init_ha_apply_info (LA_HA_APPLY_INFO * ha_apply_info);
433 
434 static LOG_PHY_PAGEID la_log_phypageid (LOG_PAGEID logical_pageid);
435 static int la_log_io_open (const char *vlabel, int flags, int mode);
436 static int la_log_io_read (char *vname, int vdes, void *io_pgptr, LOG_PHY_PAGEID pageid, int pagesize);
437 static int la_log_io_read_with_max_retries (char *vname, int vdes, void *io_pgptr, LOG_PHY_PAGEID pageid, int pagesize,
438  int retries);
439 static int la_find_archive_num (int *arv_log_num, LOG_PAGEID pageid);
440 static int la_get_range_of_archive (int arv_log_num, LOG_PAGEID * fpageid, DKNPAGES * npages);
441 static int la_log_fetch_from_archive (LOG_PAGEID pageid, char *data);
442 static int la_log_fetch (LOG_PAGEID pageid, LA_CACHE_BUFFER * cache_buffer);
443 static int la_expand_cache_log_buffer (LA_CACHE_PB * cache_pb, int slb_cnt, int slb_size);
444 static LA_CACHE_BUFFER *la_cache_buffer_replace (LA_CACHE_PB * cache_pb, LOG_PAGEID pageid, int io_pagesize,
445  int buffer_size);
449 static void la_release_all_page_buffers (LOG_PAGEID except_pageid);
450 static void la_invalidate_page_buffer (LA_CACHE_BUFFER * cache_buffer);
451 static void la_decache_page_buffers (LOG_PAGEID from, LOG_PAGEID to);
452 
453 static int la_find_required_lsa (LOG_LSA * required_lsa);
454 
455 static int la_get_ha_apply_info (const char *log_path, const char *prefix_name, LA_HA_APPLY_INFO * ha_apply_info);
456 static int la_insert_ha_apply_info (DB_DATETIME * creation_time);
457 static int la_update_ha_apply_info_start_time (void);
458 static int la_get_last_ha_applied_info (void);
459 static int la_update_ha_last_applied_info (void);
460 static int la_delete_ha_apply_info (void);
461 
462 static bool la_ignore_on_error (int errid);
463 static bool la_retry_on_error (int errid);
464 
465 static int la_init_recdes_pool (int page_size, int num_recdes);
466 static RECDES *la_assign_recdes_from_pool (void);
467 static int la_realloc_recdes_data (RECDES * recdes, int data_size);
468 static void la_clear_recdes_pool (void);
469 
470 static LA_CACHE_PB *la_init_cache_pb (void);
471 static unsigned int log_pageid_hash (const void *key, unsigned int htsize);
472 static int la_init_cache_log_buffer (LA_CACHE_PB * cache_pb, int slb_cnt, int slb_size);
473 static int la_fetch_log_hdr (LA_ACT_LOG * act_log);
474 static int la_find_log_pagesize (LA_ACT_LOG * act_log, const char *logpath, const char *dbname, bool check_charset);
475 static bool la_apply_pre (void);
477 static int la_init_repl_lists (bool need_realloc);
478 static bool la_is_repl_lists_empty ();
479 static LA_APPLY *la_find_apply_list (int tranid);
480 static void la_log_copy_fromlog (char *rec_type, char *area, int length, LOG_PAGEID log_pageid, PGLENGTH log_offset,
481  LOG_PAGE * log_pgptr);
482 static LA_ITEM *la_new_repl_item (LOG_LSA * lsa, LOG_LSA * target_lsa);
483 static void la_add_repl_item (LA_APPLY * apply, LA_ITEM * item);
484 
485 static DB_VALUE *la_get_item_pk_value (LA_ITEM * item);
486 static LA_ITEM *la_make_repl_item (LOG_PAGE * log_pgptr, int log_type, int tranid, LOG_LSA * lsa);
487 static void la_unlink_repl_item (LA_APPLY * apply, LA_ITEM * item);
488 static void la_free_repl_item (LA_APPLY * apply, LA_ITEM * item);
489 static void la_free_all_repl_items_except_head (LA_APPLY * apply);
490 static void la_free_all_repl_items (LA_APPLY * apply);
491 static void la_free_and_add_next_repl_item (LA_APPLY * apply, LA_ITEM * next_item, LOG_LSA * lsa);
492 static void la_clear_applied_info (LA_APPLY * apply);
493 static void la_clear_all_repl_and_commit_list (void);
494 
495 static int la_set_repl_log (LOG_PAGE * log_pgptr, int log_type, int tranid, LOG_LSA * lsa);
496 static int la_add_node_into_la_commit_list (int tranid, LOG_LSA * lsa, int type, time_t eot_time);
497 static time_t la_retrieve_eot_time (LOG_PAGE * pgptr, LOG_LSA * lsa);
498 static int la_get_current (OR_BUF * buf, SM_CLASS * sm_class, int bound_bit_flag, DB_OTMPL * def, DB_VALUE * key,
499  int offset_size);
501 static int la_disk_to_obj (MOBJ classobj, RECDES * record, DB_OTMPL * def, DB_VALUE * key);
502 static char *la_get_zipped_data (char *undo_data, int undo_length, bool is_diff, bool is_undo_zip, bool is_overflow,
503  char **rec_type, char **data, int *length);
504 static int la_get_undoredo_diff (LOG_PAGE ** pgptr, LOG_PAGEID * pageid, PGLENGTH * offset, bool * is_undo_zip,
505  char **undo_data, int *undo_length);
506 static int la_get_log_data (LOG_RECORD_HEADER * lrec, LOG_LSA * lsa, LOG_PAGE * pgptr, unsigned int match_rcvindex,
507  unsigned int *rcvindex, void **logs, char **rec_type, char **data, int *d_length);
508 static int la_get_overflow_recdes (LOG_RECORD_HEADER * lrec, void *logs, RECDES * recdes, unsigned int rcvindex);
509 static int la_get_next_update_log (LOG_RECORD_HEADER * prev_lrec, LOG_PAGE * pgptr, void **logs, char **rec_type,
510  char **data, int *d_length);
511 static int la_get_relocation_recdes (LOG_RECORD_HEADER * lrec, LOG_PAGE * pgptr, unsigned int match_rcvindex,
512  void **logs, char **rec_type, RECDES * recdes);
513 static int la_get_recdes (LOG_LSA * lsa, LOG_PAGE * pgptr, RECDES * recdes, unsigned int *rcvindex, char *rec_type);
514 
515 static int la_apply_delete_log (LA_ITEM * item);
516 static int la_apply_update_log (LA_ITEM * item);
517 static int la_apply_insert_log (LA_ITEM * item);
518 static int la_update_query_execute (const char *sql, bool au_disable);
519 static int la_update_query_execute_with_values (const char *sql, int arg_count, DB_VALUE * vals, bool au_disable);
520 static int la_apply_statement_log (LA_ITEM * item);
521 static int la_apply_repl_log (int tranid, int rectype, LOG_LSA * commit_lsa, int *total_rows, LOG_PAGEID final_pageid);
522 static int la_apply_commit_list (LOG_LSA * lsa, LOG_PAGEID final_pageid);
523 static void la_free_repl_items_by_tranid (int tranid);
524 static int la_log_record_process (LOG_RECORD_HEADER * lrec, LOG_LSA * final, LOG_PAGE * pg_ptr);
525 static int la_change_state (void);
526 static int la_log_commit (bool update_commit_time);
527 static unsigned long la_get_mem_size (void);
528 static int la_check_mem_size (void);
529 static int la_check_time_commit (struct timeval *time, unsigned int threshold);
530 
531 static void la_init (const char *log_path, const int max_mem_size);
532 
533 static int la_check_duplicated (const char *logpath, const char *dbname, int *lockf_vdes, int *last_deleted_arv_num);
534 static int la_lock_dbname (int *lockf_vdes, char *db_name, char *log_path);
535 static int la_unlock_dbname (int *lockf_vdes, char *db_name, bool clear_owner);
536 
537 static void la_shutdown (void);
538 
539 static int la_remove_archive_logs (const char *db_name, int last_deleted_arv_num, int nxarv_num,
540  int max_arv_count_to_delete);
541 
542 static LA_ITEM *la_get_next_repl_item (LA_ITEM * item, bool is_long_trans, LOG_LSA * last_lsa);
544 static LA_ITEM *la_get_next_repl_item_from_log (LA_ITEM * item, LOG_LSA * last_lsa);
545 
546 static int la_commit_transaction (void);
547 static int la_find_last_deleted_arv_num (void);
548 
549 static bool la_restart_on_bulk_flush_error (int errid);
550 static char *la_get_hostname_from_log_path (char *log_path);
551 
552 static int la_delay_replica (time_t eot_time);
553 
554 static float la_get_avg (int *array, int size);
555 static void la_get_adaptive_time_commit_interval (int *time_commit_interval, int *delay_hist);
556 
557 static int la_flush_repl_items (bool immediate);
558 
559 static bool la_need_filter_out (LA_ITEM * item);
560 static int la_create_repl_filter (void);
561 static void la_destroy_repl_filter (void);
562 static void la_print_repl_filter_info (void);
563 
564 static int check_reinit_copylog (void);
565 
566 #ifdef UNSTABLE_TDE_FOR_REPLICATION_LOG
567 static THREAD_RET_T THREAD_CALLING_CONVENTION la_process_dk_request (void *arg);
568 #endif /* UNSTABLE_TDE_FOR_REPLICATION_LOG */
569 
570 /*
571  * la_shutdown_by_signal() - When the process catches the SIGTERM signal,
572  * it does the shutdown process.
573  * return: none
574  *
575  * Note:
576  * set the "need_shutdown" flag as true, then each threads would
577  * process "shutdown"
578  */
579 static void
580 #if defined (WINDOWS)
582 #else /* !WINDOWS */
584 #endif /* !WINDOWS */
585 {
588 }
589 
590 bool
592 {
593  return (la_applier_need_shutdown || la_applier_shutdown_by_signal) ? true : false;
594 }
595 
596 static void
598 {
599  memset ((void *) ha_apply_info, 0, sizeof (LA_HA_APPLY_INFO));
600 
601  LSA_SET_NULL (&ha_apply_info->committed_lsa);
602  LSA_SET_NULL (&ha_apply_info->committed_rep_lsa);
603  LSA_SET_NULL (&ha_apply_info->append_lsa);
604  LSA_SET_NULL (&ha_apply_info->eof_lsa);
605  LSA_SET_NULL (&ha_apply_info->final_lsa);
606  LSA_SET_NULL (&ha_apply_info->required_lsa);
607 
608  return;
609 }
610 
611 /*
612  * la_log_phypageid() - get the physical page id from the logical pageid
613  * return: physical page id
614  * logical_pageid : logical page id
615  *
616  * Note:
617  * active log 0, 1, 2, .... 4999 (total 5,000 pages)
618  * archive log0
619  */
620 static LOG_PHY_PAGEID
621 la_log_phypageid (LOG_PAGEID logical_pageid)
622 {
624  if (logical_pageid == LOGPB_HEADER_PAGE_ID)
625  {
626  phy_pageid = 0;
627  }
628  else
629  {
630  LOG_PAGEID tmp_pageid;
631 
632  tmp_pageid = logical_pageid - la_Info.act_log.log_hdr->fpageid;
633  if (tmp_pageid >= la_Info.act_log.log_hdr->npages)
634  {
635  tmp_pageid %= la_Info.act_log.log_hdr->npages;
636  }
637  else if (tmp_pageid < 0)
638  {
639  tmp_pageid = la_Info.act_log.log_hdr->npages - ((-tmp_pageid) % la_Info.act_log.log_hdr->npages);
640  }
641  tmp_pageid++;
642  if (tmp_pageid > la_Info.act_log.log_hdr->npages)
643  {
644  tmp_pageid %= la_Info.act_log.log_hdr->npages;
645  }
646 
647  assert (tmp_pageid <= PAGEID_MAX);
648  phy_pageid = (LOG_PHY_PAGEID) tmp_pageid;
649  }
650 
651  return phy_pageid;
652 }
653 
654 
655 /*
656  * la_log_io_read() - read a page from the disk
657  * return: error code
658  * vname(in): the volume name of the target file
659  * vdes(in): the volume descriptor of the target file
660  * io_pgptr(out): start pointer to be read
661  * pageid(in): page id to read
662  * pagesize(in): page size to wrea
663  *
664  * Note:
665  * reads a predefined size of page from the disk
666  */
667 static int
668 la_log_io_read (char *vname, int vdes, void *io_pgptr, LOG_PHY_PAGEID pageid, int pagesize)
669 {
670  return la_log_io_read_with_max_retries (vname, vdes, io_pgptr, pageid, pagesize, -1);
671 }
672 
673 /*
674  * la_log_io_read_with_max_retries() - read a page from the disk with max retries
675  * return: error code
676  * vname(in): the volume name of the target file
677  * vdes(in): the volume descriptor of the target file
678  * io_pgptr(out): start pointer to be read
679  * pageid(in): page id to read
680  * pagesize(in): page size to wrea
681  * retries(in): read retry count
682  *
683  * Note:
684  * reads a predefined size of page from the disk
685  */
686 static int
687 la_log_io_read_with_max_retries (char *vname, int vdes, void *io_pgptr, LOG_PHY_PAGEID pageid, int pagesize,
688  int retries)
689 {
690  int nbytes;
691  int remain_bytes = pagesize;
692  off64_t offset = ((off64_t) pagesize) * ((off64_t) pageid);
693  char *current_ptr = (char *) io_pgptr;
694 
695  if (lseek64 (vdes, offset, SEEK_SET) == -1)
696  {
698  return ER_FAILED;
699  }
700 
701  while (remain_bytes > 0 && retries != 0)
702  {
703  retries = (retries > 0) ? retries - 1 : retries;
704 
705  /* Read the desired page */
706  nbytes = read (vdes, current_ptr, remain_bytes);
707 
708  if (nbytes == 0)
709  {
710  /*
711  * This is an end of file.
712  * We are trying to read beyond the allocated disk space
713  */
715  /* TODO: wait until exist? */
716  usleep (100 * 1000);
717  continue;
718  }
719  else if (nbytes < 0)
720  {
721  if (errno == EINTR)
722  {
723  continue;
724  }
725  else
726  {
728  return ER_FAILED;
729  }
730  }
731 
732  remain_bytes -= nbytes;
733  current_ptr += nbytes;
734  }
735 
736  if (remain_bytes > 0)
737  {
738  if (retries <= 0 && er_errid () == ER_PB_BAD_PAGEID)
739  {
740  return ER_PB_BAD_PAGEID;
741  }
742  else
743  {
745  return ER_FAILED;
746  }
747  }
748 
749  return NO_ERROR;
750 }
751 
752 /*
753  * la_get_range_of_archive() -
754  * return: NO_ERROR or error code
755  * arv_log_num(in): archive log number
756  * fpageid(out): logical pageid at physical location 1 in archive log
757  * npages(out): number of pages in the archive log
758  */
759 static int
760 la_get_range_of_archive (int arv_log_num, LOG_PAGEID * fpageid, DKNPAGES * npages)
761 {
762  int error = NO_ERROR;
763  LOG_ARV_HEADER *log_hdr = NULL;
764  int arv_log_vdes = NULL_VOLDES;
765  char arv_log_path[PATH_MAX];
766 
767  static LOG_PAGE *hdr_page = NULL;
768 
769  if (hdr_page == NULL)
770  {
771  hdr_page = (LOG_PAGE *) malloc (la_Info.act_log.db_logpagesize);
772  if (hdr_page == NULL)
773  {
776  }
777  }
778 
779  /* make archive_name */
780  fileio_make_log_archive_name (arv_log_path, la_Info.log_path, la_Info.act_log.log_hdr->prefix_name, arv_log_num);
781 
782 log_reopen:
783  /* open the archive file */
784  arv_log_vdes = fileio_open (arv_log_path, O_RDONLY, 0);
785  if (arv_log_vdes == NULL_VOLDES)
786  {
788  return ER_LOG_MOUNT_FAIL;
789  }
790 
791  error = la_log_io_read_with_max_retries (arv_log_path, arv_log_vdes, hdr_page, 0, la_Info.act_log.db_logpagesize, 10);
792  if (error != NO_ERROR)
793  {
794  fileio_close (arv_log_vdes);
795 
796  if (error == ER_PB_BAD_PAGEID)
797  {
798  goto log_reopen;
799  }
800  else
801  {
802  er_log_debug (ARG_FILE_LINE, "cannot get header from archive %s.", arv_log_path);
803  return ER_LOG_READ;
804  }
805  }
806 
807  log_hdr = (LOG_ARV_HEADER *) hdr_page->area;
808  *fpageid = log_hdr->fpageid;
809  *npages = log_hdr->npages;
810 
811  fileio_close (arv_log_vdes);
812 
813  return NO_ERROR;
814 }
815 
816 /*
817  * la_find_archive_num() - get archive number with page ID
818  * return: error code
819  * arv_log_num(in/out): archive log number
820  * pageid(in): requested pageid
821  */
822 static int
824 {
825  int error = NO_ERROR;
826  int guess_num = 0;
827  LOG_ARV_HEADER *log_hdr = NULL;
828  LOG_PAGEID fpageid;
829  DKNPAGES npages;
830  char arv_log_path[PATH_MAX];
831  int left;
832  int right;
833 
834  if (*arv_log_num == -1)
835  {
836  /* guess */
837  guess_num = pageid / la_Info.act_log.log_hdr->npages;
838  if (guess_num >= la_Info.act_log.log_hdr->nxarv_num)
839  {
840  fileio_make_log_archive_name (arv_log_path, la_Info.log_path, la_Info.act_log.log_hdr->prefix_name,
841  guess_num);
843  guess_num = la_Info.act_log.log_hdr->nxarv_num - 1;
844  }
845  }
846  else
847  {
848  /* do not guess, just check */
849  guess_num = *arv_log_num;
850  }
851 
852  left = MAX (0, la_Info.last_deleted_archive_num + 1);
853  right = la_Info.act_log.log_hdr->nxarv_num - 1;
854 
855  guess_num = MAX (guess_num, left);
856  do
857  {
858  if (la_Info.arv_log.log_vdes != NULL_VOLDES && la_Info.arv_log.log_hdr != NULL
859  && guess_num == la_Info.arv_log.log_hdr->arv_num)
860  {
861  log_hdr = la_Info.arv_log.log_hdr;
862  fpageid = log_hdr->fpageid;
863  npages = log_hdr->npages;
864  }
865  else
866  {
867  error = la_get_range_of_archive (guess_num, &fpageid, &npages);
868  if (error != NO_ERROR)
869  {
870  return error;
871  }
872  }
873 
874  if (pageid >= fpageid && pageid < fpageid + npages)
875  {
876  *arv_log_num = guess_num;
877  return NO_ERROR;
878  }
879  else if (pageid < fpageid)
880  {
881  right = guess_num - 1;
882  guess_num = CEIL_PTVDIV ((left + right), 2);
883  }
884  else if (pageid >= fpageid + npages)
885  {
886  left = guess_num + 1;
887  guess_num = CEIL_PTVDIV ((left + right), 2);
888  }
889  }
890  while (guess_num >= 0 && guess_num < la_Info.act_log.log_hdr->nxarv_num && left <= right);
891 
893  return ER_LOG_NOTIN_ARCHIVE;
894 }
895 
896 /*
897  * la_log_fetch_from_archive() - read the log page from archive
898  * return: error code
899  * pageid: requested pageid
900  * data: fetched data
901  */
902 static int
904 {
905  int error = NO_ERROR;
906  int arv_log_num;
907  bool need_guess = true;
908  LOG_ARV_HEADER *log_hdr = NULL;
909  LOG_PAGEID fpageid;
910  int npages;
911 
912  if (la_Info.arv_log.log_vdes != NULL_VOLDES && la_Info.arv_log.log_hdr != NULL)
913  {
914  log_hdr = la_Info.arv_log.log_hdr;
915  fpageid = log_hdr->fpageid;
916  npages = log_hdr->npages;
917 
918  if (pageid >= fpageid && pageid < fpageid + npages)
919  {
920  need_guess = false;
921  }
922  }
923 
924  if (need_guess)
925  {
926  arv_log_num = -1;
927  error = la_find_archive_num (&arv_log_num, pageid);
928  if (error < 0)
929  {
930  er_log_debug (ARG_FILE_LINE, "cannot find archive log for %lld page.", (long long int) pageid);
931  return error;
932  }
933  if (la_Info.arv_log.arv_num != arv_log_num)
934  {
935  if (la_Info.arv_log.log_vdes > 0)
936  {
937  fileio_close (la_Info.arv_log.log_vdes);
938  la_Info.arv_log.log_vdes = NULL_VOLDES;
939  }
940  la_Info.arv_log.arv_num = arv_log_num;
941  }
942  }
943 
944 log_reopen:
945  if (la_Info.arv_log.log_vdes == NULL_VOLDES)
946  {
947  /* make archive_name */
949  la_Info.arv_log.arv_num);
950 
951  error = check_reinit_copylog ();
952  if (error != NO_ERROR)
953  {
956 
957  return ER_LOG_MOUNT_FAIL;
958  }
959 
960  /* open the archive file */
961  la_Info.arv_log.log_vdes = fileio_open (la_Info.arv_log.path, O_RDONLY, 0);
962  if (la_Info.arv_log.log_vdes == NULL_VOLDES)
963  {
964  er_log_debug (ARG_FILE_LINE, "cannot open %s archive for %lld page.", la_Info.arv_log.path,
965  (long long int) pageid);
967  return ER_LOG_MOUNT_FAIL;
968  }
969 #if defined (LA_VERBOSE_DEBUG)
970  else
971  {
972  er_log_debug (ARG_FILE_LINE, "archive (%s) has been opened for %lld page", la_Info.arv_log.path,
973  (long long int) pageid);
974  }
975 #endif
976  }
977 
978  /* If this is the frist time to read archive log, read the header info of the target archive */
979  if (la_Info.arv_log.hdr_page == NULL)
980  {
981  la_Info.arv_log.hdr_page = (LOG_PAGE *) malloc (la_Info.act_log.db_logpagesize);
982  if (la_Info.arv_log.hdr_page == NULL)
983  {
986  }
987  }
988 
989  if (la_Info.arv_log.log_hdr == NULL
991  || la_Info.arv_log.log_hdr->arv_num != la_Info.arv_log.arv_num)
992  {
993  error =
995  la_Info.act_log.db_logpagesize, 10);
996  if (error != NO_ERROR)
997  {
998  if (error == ER_PB_BAD_PAGEID)
999  {
1000  fileio_close (la_Info.arv_log.log_vdes);
1001  la_Info.arv_log.log_vdes = NULL_VOLDES;
1002  goto log_reopen;
1003  }
1004  else
1005  {
1006  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_LOG_READ, 3, pageid, 0, la_Info.arv_log.path);
1007  return ER_LOG_READ;
1008 
1009  }
1010  }
1011 
1012  la_Info.arv_log.log_hdr = (LOG_ARV_HEADER *) la_Info.arv_log.hdr_page->area;
1013  }
1014 
1015 
1016  error =
1018  (pageid - la_Info.arv_log.log_hdr->fpageid + 1), la_Info.act_log.db_logpagesize,
1019  10);
1020 
1021  if (error != NO_ERROR)
1022  {
1023  if (error == ER_PB_BAD_PAGEID)
1024  {
1025  fileio_close (la_Info.arv_log.log_vdes);
1026  la_Info.arv_log.log_vdes = NULL_VOLDES;
1027  goto log_reopen;
1028  }
1029  else
1030  {
1032  pageid - la_Info.arv_log.log_hdr->fpageid + 1, la_Info.arv_log.path);
1033 
1034  return ER_LOG_READ;
1035  }
1036  }
1037 
1038 #ifdef UNSTABLE_TDE_FOR_REPLICATION_LOG
1039  if (LOG_IS_PAGE_TDE_ENCRYPTED ((LOG_PAGE *) data))
1040  {
1041  error = tde_decrypt_log_page ((LOG_PAGE *) data, logwr_get_tde_algorithm ((LOG_PAGE *) data), (LOG_PAGE *) data);
1042  if (error != NO_ERROR)
1043  {
1044  ASSERT_ERROR ();
1045  return error;
1046  }
1047  }
1048 #endif /* UNSTABLE_TDE_FOR_REPLICATION_LOG */
1049 
1050  return error;
1051 }
1052 
1053 static int
1055 {
1056  int error = NO_ERROR;
1058  int retry = 5;
1059 
1060  assert (cache_buffer);
1061 
1062  /* get the physical page id */
1063  phy_pageid = la_log_phypageid (pageid);
1064 
1065  if (la_Info.act_log.log_hdr->append_lsa.pageid < pageid)
1066  {
1067  /* check it again */
1068  error = la_fetch_log_hdr (&la_Info.act_log);
1069  if (error != NO_ERROR)
1070  {
1071  return error;
1072  }
1073 
1074  /* check it again */
1075  if (la_Info.act_log.log_hdr->append_lsa.pageid < pageid)
1076  {
1077  return ER_LOG_NOTIN_ARCHIVE;
1078  }
1079  }
1080 
1081  do
1082  {
1083  /* TODO: refactor read the target page */
1084  if (LA_LOG_IS_IN_ARCHIVE (pageid))
1085  {
1086  /* read from the archive log file */
1087  error = la_log_fetch_from_archive (pageid, (char *) &cache_buffer->logpage);
1088  if (error != NO_ERROR)
1089  {
1090  la_applier_need_shutdown = true;
1091  return error;
1092  }
1093  cache_buffer->in_archive = true;
1094  }
1095  else
1096  {
1097  /* read from the active log file */
1098  error =
1099  la_log_io_read (la_Info.act_log.path, la_Info.act_log.log_vdes, &cache_buffer->logpage, phy_pageid,
1100  la_Info.act_log.db_logpagesize);
1101  if (error != NO_ERROR)
1102  {
1103  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_LOG_READ, 3, pageid, phy_pageid, la_Info.act_log.path);
1104  return ER_LOG_READ;
1105  }
1106 #ifdef UNSTABLE_TDE_FOR_REPLICATION_LOG
1107  if (LOG_IS_PAGE_TDE_ENCRYPTED (&cache_buffer->logpage))
1108  {
1109  error =
1110  tde_decrypt_log_page (&cache_buffer->logpage, logwr_get_tde_algorithm (&cache_buffer->logpage),
1111  &cache_buffer->logpage);
1112  if (error != NO_ERROR)
1113  {
1114  return error;
1115  }
1116  }
1117 #endif /* UNSTABLE_TDE_FOR_REPLICATION_LOG */
1118  cache_buffer->in_archive = false;
1119  }
1120 
1121  /* check the fetched page is not the target page ? */
1122  if (cache_buffer->logpage.hdr.logical_pageid == pageid)
1123  {
1124  break;
1125  }
1126 
1127  /* if the master generates the log archive, re-fetch the log header, try again */
1128  usleep (100 * 1000);
1129  error = la_fetch_log_hdr (&la_Info.act_log);
1130  if (error != NO_ERROR)
1131  {
1132  return error;
1133  }
1134  }
1135  while (error == NO_ERROR && --retry > 0);
1136 
1137  if (retry <= 0 || la_Info.act_log.log_hdr->append_lsa.pageid < pageid)
1138  {
1139 #if defined (LA_VERBOSE_DEBUG)
1140  /* it will nagging you */
1141  er_log_debug (ARG_FILE_LINE, "log pageid %d is not exist", pageid);
1142 #endif
1143  return ER_LOG_NOTIN_ARCHIVE;
1144  }
1145 
1146  /* now here, we got log page : */
1147  cache_buffer->pageid = pageid;
1148  cache_buffer->phy_pageid = phy_pageid;
1149 
1150  return error;
1151 
1152 }
1153 
1154 /*
1155  * la_expand_cache_log_buffer() - expand cache log buffer
1156  * return: NO_ERROR or ER_FAILED
1157  * cache_pb : cache page buffer pointer
1158  * slb_cnt : the # of cache log buffers per cache page buffer
1159  * slb_size : size of CACHE_LOG_BUFFER
1160  *
1161  * Note:
1162  * : Expand the cache log buffer pool with the given number of buffers.
1163  * : If a zero or a negative value is given, the function expands
1164  * the cache buffer pool with a default porcentage of the currently
1165  * size.
1166  */
1167 static int
1168 la_expand_cache_log_buffer (LA_CACHE_PB * cache_pb, int slb_cnt, int slb_size)
1169 {
1170  int error = NO_ERROR;
1171  int i, size, bufid, total_buffers;
1173  LA_CACHE_BUFFER **slb_log_buffer;
1174 
1175  assert (slb_cnt > 0);
1176  assert (slb_size > 0);
1177 
1178  size = ((slb_cnt * slb_size) + DB_SIZEOF (LA_CACHE_BUFFER_AREA));
1179  area = (LA_CACHE_BUFFER_AREA *) malloc (size);
1180  if (area == NULL)
1181  {
1183  error = ER_OUT_OF_VIRTUAL_MEMORY;
1184  goto error_rtn;
1185  }
1186  memset (area, 0, size);
1187 
1188  total_buffers = cache_pb->num_buffers + slb_cnt;
1189  slb_log_buffer = (LA_CACHE_BUFFER **) realloc (cache_pb->log_buffer, total_buffers * DB_SIZEOF (LA_CACHE_BUFFER *));
1190  if (slb_log_buffer == NULL)
1191  {
1193  total_buffers * DB_SIZEOF (LA_CACHE_BUFFER *));
1194  error = ER_OUT_OF_VIRTUAL_MEMORY;
1195  goto error_rtn;
1196  }
1197 
1198  area->buffer_area = ((LA_CACHE_BUFFER *) ((char *) area + DB_SIZEOF (LA_CACHE_BUFFER_AREA)));
1199  area->next = cache_pb->buffer_area;
1200  for (i = 0, bufid = cache_pb->num_buffers; i < slb_cnt; i++, bufid++)
1201  {
1202  slb_log_buffer[bufid] = (LA_CACHE_BUFFER *) ((char *) area->buffer_area + slb_size * i);
1203  }
1204 
1205  cache_pb->log_buffer = slb_log_buffer;
1206  cache_pb->buffer_area = area;
1207  cache_pb->num_buffers = total_buffers;
1208 
1209  er_log_debug (ARG_FILE_LINE, "page buffer cache is expanded. (size=%d).", cache_pb->num_buffers);
1210 
1211  return error;
1212 
1213 error_rtn:
1214  if (area)
1215  {
1216  free_and_init (area);
1217  }
1218 
1219  return error;
1220 }
1221 
1222 static LA_CACHE_BUFFER *
1223 la_cache_buffer_replace (LA_CACHE_PB * cache_pb, LOG_PAGEID pageid, int io_pagesize, int buffer_size)
1224 {
1225  int error = NO_ERROR;
1226  LA_CACHE_BUFFER *cache_buffer = NULL;
1227  int i, num_recently_free, found = -1;
1228  static unsigned int last = 0;
1229 
1230  while (found < 0)
1231  {
1232  num_recently_free = 0;
1233 
1234  for (i = 0; i < cache_pb->num_buffers; i++)
1235  {
1236  last = ((last + 1) % cache_pb->num_buffers);
1237  cache_buffer = cache_pb->log_buffer[last];
1238  if (cache_buffer->fix_count == 0)
1239  {
1240  if (cache_buffer->recently_free == true)
1241  {
1242  cache_buffer->recently_free = false;
1243  num_recently_free++;
1244  }
1245  else
1246  {
1247  found = last;
1248  break;
1249  }
1250  }
1251  }
1252 
1253  if (found >= 0)
1254  {
1255  if (cache_buffer->pageid != 0)
1256  {
1257  (void) mht_rem (cache_pb->hash_table, &cache_buffer->pageid, NULL, NULL);
1258  }
1259 
1260  cache_buffer->fix_count = 0;
1261 
1262  error = la_log_fetch (pageid, cache_buffer);
1263  if (error != NO_ERROR)
1264  {
1265  cache_buffer->pageid = 0;
1266  return NULL;
1267  }
1268 
1269  return cache_buffer;
1270  }
1271 
1272  if (num_recently_free > 0)
1273  {
1274  continue;
1275  }
1276 
1277  error = la_expand_cache_log_buffer (cache_pb, buffer_size, SIZEOF_LA_CACHE_LOG_BUFFER (io_pagesize));
1278  if (error != NO_ERROR)
1279  {
1280  return NULL;
1281  }
1282  }
1283 
1284  return NULL;
1285 }
1286 
1287 static LA_CACHE_BUFFER *
1289 {
1290  LA_CACHE_PB *cache_pb = la_Info.cache_pb;
1291  LA_CACHE_BUFFER *cache_buffer = NULL;
1292 
1293  /* find the target page in the cache buffer */
1294  cache_buffer = (LA_CACHE_BUFFER *) mht_get (cache_pb->hash_table, (void *) &pageid);
1295 
1296  if (cache_buffer == NULL)
1297  {
1298  cache_buffer =
1299  la_cache_buffer_replace (cache_pb, pageid, la_Info.act_log.db_logpagesize, la_Info.cache_buffer_size);
1300 
1301  if (cache_buffer == NULL || cache_buffer->logpage.hdr.logical_pageid != pageid)
1302  {
1303  return NULL;
1304  }
1305 
1306  (void) mht_rem (cache_pb->hash_table, &cache_buffer->pageid, NULL, NULL);
1307 
1308  if (mht_put (cache_pb->hash_table, &cache_buffer->pageid, cache_buffer) == NULL)
1309  {
1310  return NULL;
1311  }
1312  }
1313  else
1314  {
1315  if (cache_buffer->logpage.hdr.logical_pageid != pageid)
1316  {
1317  (void) mht_rem (cache_pb->hash_table, &cache_buffer->pageid, NULL, NULL);
1318  return NULL;
1319  }
1320  }
1321 
1322  cache_buffer->fix_count++;
1323  return cache_buffer;
1324 }
1325 
1326 static LOG_PAGE *
1328 {
1329  LA_CACHE_BUFFER *cache_buffer = NULL;
1330 
1331  assert (pageid != NULL_PAGEID);
1332  if (pageid == NULL_PAGEID)
1333  {
1334  return NULL;
1335  }
1336 
1337  do
1338  {
1339  cache_buffer = la_get_page_buffer (pageid);
1340  }
1341  while (cache_buffer == NULL); /* we must get this page */
1342 
1343  return &cache_buffer->logpage;
1344 }
1345 
1346 /*
1347  * la_release_page_buffer() - decrease the fix_count of the target buffer
1348  * return: none
1349  * pageid(in): the target page id
1350  *
1351  * Note:
1352  * if cache buffer's fix_count < 0 then programing error.
1353  */
1354 static void
1356 {
1357  LA_CACHE_PB *cache_pb = la_Info.cache_pb;
1358  LA_CACHE_BUFFER *cache_buffer = NULL;
1359 
1360  cache_buffer = (LA_CACHE_BUFFER *) mht_get (cache_pb->hash_table, (void *) &pageid);
1361  if (cache_buffer != NULL)
1362  {
1363  if ((--cache_buffer->fix_count) <= 0)
1364  {
1365  cache_buffer->fix_count = 0;
1366  }
1367  cache_buffer->recently_free = true;
1368  }
1369 }
1370 
1371 /*
1372  * la_release_all_page_buffers() - release all page buffers
1373  * except_pageid :
1374  * return: none
1375  *
1376  */
1377 static void
1379 {
1380  int i;
1381  LA_CACHE_PB *cache_pb = la_Info.cache_pb;
1382  LA_CACHE_BUFFER *cache_buffer = NULL;
1383 
1384  /* find unfix or unused buffer */
1385  for (i = 0; i < cache_pb->num_buffers; i++)
1386  {
1387  cache_buffer = cache_pb->log_buffer[i];
1388  if (cache_buffer->pageid == except_pageid)
1389  {
1390  continue;
1391  }
1392 
1393  if (cache_buffer->fix_count > 0)
1394  {
1395  cache_buffer->fix_count = 0;
1396  cache_buffer->recently_free = true;
1397  }
1398  }
1399 }
1400 
1401 /*
1402  * la_invalidate_page_buffer() - decrease the fix_count and drop the target buffer from cache
1403  * return: none
1404  * cache_buf(in): cached page buffer
1405  *
1406  * Note:
1407  */
1408 static void
1410 {
1411  LA_CACHE_PB *cache_pb = la_Info.cache_pb;
1412 
1413  if (cache_buffer == NULL)
1414  {
1415  return;
1416  }
1417 
1418  if (cache_buffer->pageid != 0)
1419  {
1420  (void) mht_rem (cache_pb->hash_table, &cache_buffer->pageid, NULL, NULL);
1421  }
1422  cache_buffer->fix_count = 0;
1423  cache_buffer->recently_free = false;
1424  cache_buffer->pageid = 0;
1425 }
1426 
1427 static void
1429 {
1430  int i;
1431  LA_CACHE_PB *cache_pb = la_Info.cache_pb;
1432  LA_CACHE_BUFFER *cache_buffer = NULL;
1433 
1434  for (i = 0; i < cache_pb->num_buffers; i++)
1435  {
1436  cache_buffer = cache_pb->log_buffer[i];
1437 
1438  if ((cache_buffer->pageid == NULL_PAGEID) || (cache_buffer->pageid == 0) || (cache_buffer->pageid < from)
1439  || (cache_buffer->pageid > to))
1440  {
1441  continue;
1442  }
1443 
1444  (void) mht_rem (cache_pb->hash_table, &cache_buffer->pageid, NULL, NULL);
1445 
1446  cache_buffer->fix_count = 0;
1447  cache_buffer->recently_free = false;
1448  cache_buffer->pageid = 0;
1449  }
1450 
1451  return;
1452 }
1453 
1454 /*
1455  * la_find_required_lsa() - Find out the lowest required page ID
1456  * return: NO_ERROR or error code
1457  * required_lsa(in/out) : lowest required LSA
1458  *
1459  * Note:
1460  */
1461 static int
1463 {
1464  int error = NO_ERROR;
1465  int i;
1466  LOG_LSA lowest_lsa;
1467 
1468  LSA_SET_NULL (&lowest_lsa);
1469 
1470  for (i = 0; i < la_Info.cur_repl; i++)
1471  {
1472  if (la_Info.repl_lists[i]->tranid <= 0)
1473  {
1474  continue;
1475  }
1476  if (LSA_ISNULL (&lowest_lsa) || LSA_GT (&lowest_lsa, &la_Info.repl_lists[i]->start_lsa))
1477  {
1478  LSA_COPY (&lowest_lsa, &la_Info.repl_lists[i]->start_lsa);
1479  }
1480  }
1481 
1482  if (LSA_ISNULL (&lowest_lsa))
1483  {
1484  LSA_COPY (required_lsa, &la_Info.final_lsa);
1485  }
1486  else
1487  {
1488  LSA_COPY (required_lsa, &lowest_lsa);
1489  }
1490 
1491  return error;
1492 }
1493 
1494 /*
1495  * la_get_ha_apply_info() -
1496  * returns : error code, if execution failed
1497  * number of affected objects, if a success
1498  *
1499  * log_path(in) :
1500  * prefix_name(in) :
1501  * ha_apply_info(out) :
1502  * Note:
1503  */
1504 static int
1505 la_get_ha_apply_info (const char *log_path, const char *prefix_name, LA_HA_APPLY_INFO * ha_apply_info)
1506 {
1507 #define LA_IN_VALUE_COUNT 2
1508 #define LA_OUT_VALUE_COUNT 23
1509 
1510  int res;
1511  int in_value_idx, out_value_idx;
1512  DB_VALUE in_value[LA_IN_VALUE_COUNT];
1513  DB_VALUE out_value[LA_OUT_VALUE_COUNT];
1514  int i, col_cnt;
1515  char query_buf[LA_QUERY_BUF_SIZE];
1516  DB_DATETIME *db_time;
1517  DB_QUERY_ERROR query_error;
1518  DB_QUERY_RESULT *result = NULL;
1519 
1521  {
1522  assert (er_errid () != NO_ERROR);
1523  return er_errid ();
1524  }
1525 
1526  snprintf (query_buf, sizeof (query_buf), "SELECT " /* SELECT */
1527  " db_creation_time, " /* 2 */
1528  " committed_lsa_pageid, " /* 4 */
1529  " committed_lsa_offset, " /* 5 */
1530  " committed_rep_pageid, " /* 6 */
1531  " committed_rep_offset, " /* 7 */
1532  " append_lsa_pageid, " /* 8 */
1533  " append_lsa_offset, " /* 9 */
1534  " eof_lsa_pageid, " /* 10 */
1535  " eof_lsa_offset, " /* 11 */
1536  " final_lsa_pageid, " /* 12 */
1537  " final_lsa_offset, " /* 13 */
1538  " required_lsa_pageid, " /* 14 */
1539  " required_lsa_offset, " /* 15 */
1540  " log_record_time, " /* 16 */
1541  " log_commit_time, " /* 17 */
1542  " last_access_time, " /* 18 */
1543  " insert_counter, " /* 19 */
1544  " update_counter, " /* 20 */
1545  " delete_counter, " /* 21 */
1546  " schema_counter, " /* 22 */
1547  " commit_counter, " /* 23 */
1548  " fail_counter, " /* 24 */
1549  " start_time " /* 25 */
1550  " FROM %s WHERE db_name = ? and copied_log_path = ? ;", CT_HA_APPLY_INFO_NAME);
1551 
1552  in_value_idx = 0;
1553  db_make_varchar (&in_value[in_value_idx++], 255, (char *) prefix_name, strlen (prefix_name), LANG_SYS_CODESET,
1555  db_make_varchar (&in_value[in_value_idx++], 4096, (char *) log_path, strlen (log_path), LANG_SYS_CODESET,
1557  assert_release (in_value_idx == LA_IN_VALUE_COUNT);
1558 
1559  res = db_execute_with_values (query_buf, &result, &query_error, in_value_idx, &in_value[0]);
1560  if (res > 0)
1561  {
1562  int pos, error;
1563 
1564  pos = db_query_first_tuple (result);
1565  switch (pos)
1566  {
1567  case DB_CURSOR_SUCCESS:
1568  col_cnt = db_query_column_count (result);
1569  assert_release (col_cnt == LA_OUT_VALUE_COUNT);
1570 
1571  error = db_query_get_tuple_valuelist (result, LA_OUT_VALUE_COUNT, out_value);
1572  if (error != NO_ERROR)
1573  {
1574  res = error;
1575  break;
1576  }
1577 
1578  out_value_idx = 0;
1579 
1580  /* 1. db_name */
1581  strncpy (ha_apply_info->db_name, prefix_name, sizeof (ha_apply_info->db_name) - 1);
1582 
1583  /* 3. copied_log_path */
1584  strncpy (ha_apply_info->copied_log_path, log_path, sizeof (ha_apply_info->copied_log_path) - 1);
1585 
1586  /* 2. creation time */
1587  db_time = db_get_datetime (&out_value[out_value_idx++]);
1588  ha_apply_info->creation_time.date = db_time->date;
1589  ha_apply_info->creation_time.time = db_time->time;
1590 
1591  /* 4 ~ 5. committed_lsa */
1592  if (DB_IS_NULL (&out_value[out_value_idx]) || DB_IS_NULL (&out_value[out_value_idx + 1]))
1593  {
1594  LSA_SET_NULL (&ha_apply_info->committed_lsa);
1595  out_value_idx += 2;
1596  }
1597  else
1598  {
1599  ha_apply_info->committed_lsa.pageid = db_get_bigint (&out_value[out_value_idx++]);
1600  ha_apply_info->committed_lsa.offset = db_get_int (&out_value[out_value_idx++]);
1601  }
1602 
1603  /* 6 ~ 7. committed_rep_lsa */
1604  if (DB_IS_NULL (&out_value[out_value_idx]) || DB_IS_NULL (&out_value[out_value_idx + 1]))
1605  {
1606  LSA_SET_NULL (&ha_apply_info->committed_rep_lsa);
1607  out_value_idx += 2;
1608  }
1609  else
1610  {
1611  ha_apply_info->committed_rep_lsa.pageid = db_get_bigint (&out_value[out_value_idx++]);
1612  ha_apply_info->committed_rep_lsa.offset = db_get_int (&out_value[out_value_idx++]);
1613  }
1614 
1615  /* 8 ~ 9. append_lsa */
1616  ha_apply_info->append_lsa.pageid = db_get_bigint (&out_value[out_value_idx++]);
1617  ha_apply_info->append_lsa.offset = db_get_int (&out_value[out_value_idx++]);
1618 
1619  /* 10 ~ 11. eof_lsa */
1620  ha_apply_info->eof_lsa.pageid = db_get_bigint (&out_value[out_value_idx++]);
1621  ha_apply_info->eof_lsa.offset = db_get_int (&out_value[out_value_idx++]);
1622 
1623  /* 12 ~ 13. final_lsa */
1624  if (DB_IS_NULL (&out_value[out_value_idx]) || DB_IS_NULL (&out_value[out_value_idx + 1]))
1625  {
1626  LSA_SET_NULL (&ha_apply_info->final_lsa);
1627  out_value_idx += 2;
1628  }
1629  else
1630  {
1631  ha_apply_info->final_lsa.pageid = db_get_bigint (&out_value[out_value_idx++]);
1632  ha_apply_info->final_lsa.offset = db_get_int (&out_value[out_value_idx++]);
1633  }
1634 
1635  /* 14 ~ 15. required_lsa */
1636  if (DB_IS_NULL (&out_value[out_value_idx]) || DB_IS_NULL (&out_value[out_value_idx + 1]))
1637  {
1638  LSA_SET_NULL (&ha_apply_info->required_lsa);
1639  out_value_idx += 2;
1640  }
1641  else
1642  {
1643  ha_apply_info->required_lsa.pageid = db_get_bigint (&out_value[out_value_idx++]);
1644  ha_apply_info->required_lsa.offset = db_get_int (&out_value[out_value_idx++]);
1645  }
1646 
1647  /* 16. log_record_time */
1648  db_time = db_get_datetime (&out_value[out_value_idx++]);
1649  ha_apply_info->log_record_time.date = db_time->date;
1650  ha_apply_info->log_record_time.time = db_time->time;
1651 
1652  /* 17. log_commit_time */
1653  db_time = db_get_datetime (&out_value[out_value_idx++]);
1654  ha_apply_info->log_commit_time.date = db_time->date;
1655  ha_apply_info->log_commit_time.time = db_time->time;
1656 
1657  /* 18. last_access_time */
1658  db_time = db_get_datetime (&out_value[out_value_idx++]);
1659  ha_apply_info->last_access_time.date = db_time->date;
1660  ha_apply_info->last_access_time.time = db_time->time;
1661 
1662  /* status */
1663  ha_apply_info->status = LA_STATUS_IDLE;
1664 
1665  /* 19 ~ 24. statistics */
1666  ha_apply_info->insert_counter = db_get_bigint (&out_value[out_value_idx++]);
1667  ha_apply_info->update_counter = db_get_bigint (&out_value[out_value_idx++]);
1668  ha_apply_info->delete_counter = db_get_bigint (&out_value[out_value_idx++]);
1669  ha_apply_info->schema_counter = db_get_bigint (&out_value[out_value_idx++]);
1670  ha_apply_info->commit_counter = db_get_bigint (&out_value[out_value_idx++]);
1671  ha_apply_info->fail_counter = db_get_bigint (&out_value[out_value_idx++]);
1672 
1673  /* 25. start_time */
1674  db_time = db_get_datetime (&out_value[out_value_idx++]);
1675  ha_apply_info->start_time.date = db_time->date;
1676  ha_apply_info->start_time.time = db_time->time;
1677 
1678  assert_release (out_value_idx == LA_OUT_VALUE_COUNT);
1679 
1680  for (i = 0; i < LA_OUT_VALUE_COUNT; i++)
1681  {
1682  db_value_clear (&out_value[i]);
1683  }
1684  break;
1685 
1686  case DB_CURSOR_END:
1687  case DB_CURSOR_ERROR:
1688  default:
1689  res = ER_FAILED;
1690  break;
1691  }
1692  }
1693 
1694  db_query_end (result);
1695  for (i = 0; i < in_value_idx; i++)
1696  {
1697  db_value_clear (&in_value[i]);
1698  }
1699 
1700  return res;
1701 
1702 #undef LA_IN_VALUE_COUNT
1703 #undef LA_OUT_VALUE_COUNT
1704 }
1705 
1706 static int
1708 {
1709 #define LA_IN_VALUE_COUNT 15
1710 
1711  int res;
1712  LA_ACT_LOG *act_log;
1713  int i;
1714  int in_value_idx;
1715  DB_VALUE in_value[LA_IN_VALUE_COUNT];
1716  char query_buf[LA_QUERY_BUF_SIZE];
1717  const char *msg;
1718  FILE *fp;
1719 
1720  act_log = &la_Info.act_log;
1721 
1722  snprintf (query_buf, sizeof (query_buf), "INSERT INTO %s " /* INSERT */
1723  "( db_name, " /* 1 */
1724  " db_creation_time, " /* 2 */
1725  " copied_log_path, " /* 3 */
1726  " committed_lsa_pageid, " /* 4 */
1727  " committed_lsa_offset, " /* 5 */
1728  " committed_rep_pageid, " /* 6 */
1729  " committed_rep_offset, " /* 7 */
1730  " append_lsa_pageid, " /* 8 */
1731  " append_lsa_offset, " /* 9 */
1732  " eof_lsa_pageid, " /* 10 */
1733  " eof_lsa_offset, " /* 11 */
1734  " final_lsa_pageid, " /* 12 */
1735  " final_lsa_offset, " /* 13 */
1736  " required_lsa_pageid, " /* 14 */
1737  " required_lsa_offset, " /* 15 */
1738  " log_record_time, " /* 16 */
1739  " log_commit_time, " /* 17 */
1740  " last_access_time, " /* 18 */
1741  " status, " /* 19 */
1742  " insert_counter, " /* 20 */
1743  " update_counter, " /* 21 */
1744  " delete_counter, " /* 22 */
1745  " schema_counter, " /* 23 */
1746  " commit_counter, " /* 24 */
1747  " fail_counter, " /* 25 */
1748  " start_time ) " /* 26 */
1749  " VALUES ( ?, " /* 1. db_name */
1750  " ?, " /* 2. db_creation_time */
1751  " ?, " /* 3. copied_log_path */
1752  " ?, " /* 4. committed_lsa_pageid */
1753  " ?, " /* 5. committed_lsa_offset */
1754  " ?, " /* 6. committed_rep_pageid */
1755  " ?, " /* 7. committed_rep_offset */
1756  " ?, " /* 8. append_lsa_pageid */
1757  " ?, " /* 9. append_lsa_offset */
1758  " ?, " /* 10. eof_lsa_pageid */
1759  " ?, " /* 11. eof_lsa_offset */
1760  " ?, " /* 12. final_lsa_pageid */
1761  " ?, " /* 13. final_lsa_offset */
1762  " ?, " /* 14. required_lsa_pageid */
1763  " ?, " /* 15. required_lsa_offset */
1764  " SYS_DATETIME, " /* 16. log_record_time */
1765  " SYS_DATETIME, " /* 17. log_commit_time */
1766  " SYS_DATETIME, " /* 18. last_access_time */
1767  " 0, " /* 19. status */
1768  " 0, " /* 20. insert_counter */
1769  " 0, " /* 21. update_counter */
1770  " 0, " /* 22. delete_counter */
1771  " 0, " /* 23. schema_counter */
1772  " 0, " /* 24. commit_counter */
1773  " 0, " /* 25. fail_counter */
1774  " SYS_DATETIME " /* 26. start_time */
1775  " ) ;", CT_HA_APPLY_INFO_NAME);
1776 
1777  in_value_idx = 0;
1778 
1779  /* 1. db_name */
1780  db_make_varchar (&in_value[in_value_idx++], 255, act_log->log_hdr->prefix_name,
1782 
1783  /* 2. db_creation time */
1784  db_make_datetime (&in_value[in_value_idx++], creation_time);
1785 
1786  /* 3. copied_log_path */
1787  db_make_varchar (&in_value[in_value_idx++], 4096, la_Info.log_path, strlen (la_Info.log_path), LANG_SYS_CODESET,
1789 
1790  /* 4 ~ 5. committed_lsa */
1791  db_make_bigint (&in_value[in_value_idx++], la_Info.committed_lsa.pageid);
1792  db_make_int (&in_value[in_value_idx++], la_Info.committed_lsa.offset);
1793 
1794  /* 6 ~ 7. committed_rep_lsa */
1795  db_make_bigint (&in_value[in_value_idx++], la_Info.committed_rep_lsa.pageid);
1796  db_make_int (&in_value[in_value_idx++], la_Info.committed_rep_lsa.offset);
1797 
1798  /* 8 ~ 9. append_lsa */
1799  db_make_bigint (&in_value[in_value_idx++], la_Info.append_lsa.pageid);
1800  db_make_int (&in_value[in_value_idx++], la_Info.append_lsa.offset);
1801 
1802  /* 10 ~ 11. eof_lsa */
1803  db_make_bigint (&in_value[in_value_idx++], la_Info.eof_lsa.pageid);
1804  db_make_int (&in_value[in_value_idx++], la_Info.eof_lsa.offset);
1805 
1806  /* 12 ~ 13. final_lsa */
1807  db_make_bigint (&in_value[in_value_idx++], la_Info.final_lsa.pageid);
1808  db_make_int (&in_value[in_value_idx++], la_Info.final_lsa.offset);
1809 
1810  /* 14 ~ 15. required_lsa */
1811  db_make_bigint (&in_value[in_value_idx++], la_Info.required_lsa.pageid);
1812  db_make_int (&in_value[in_value_idx++], la_Info.required_lsa.offset);
1813 
1814  assert_release (in_value_idx == LA_IN_VALUE_COUNT);
1815 
1816  res = la_update_query_execute_with_values (query_buf, in_value_idx, &in_value[0], true);
1817  for (i = 0; i < in_value_idx; i++)
1818  {
1819  db_value_clear (&in_value[i]);
1820  }
1821 
1822  if (res <= 0)
1823  {
1824  return res;
1825  }
1826 
1827  /* create log info */
1829  if (msg == NULL)
1830  {
1831  msg = "COMMENT: %s for database %s\n";
1832  }
1833  fp = fopen (la_Info.loginf_path, "w");
1834  if (fp == NULL)
1835  {
1837  }
1838  else
1839  {
1840  (void) fprintf (fp, msg, CUBRID_MAGIC_LOG_INFO, la_Info.loginf_path);
1841  fflush (fp);
1842  fclose (fp);
1843  }
1844 
1845  return res;
1846 
1847 #undef LA_IN_VALUE_COUNT
1848 }
1849 
1850 static int
1852 {
1853 #define LA_IN_VALUE_COUNT 2
1854  int res;
1855  LA_ACT_LOG *act_log;
1856  int i;
1857  int in_value_idx;
1858  DB_VALUE in_value[LA_IN_VALUE_COUNT];
1859  char query_buf[LA_QUERY_BUF_SIZE];
1860 
1861  act_log = &la_Info.act_log;
1862 
1863  snprintf (query_buf, sizeof (query_buf),
1864  "UPDATE %s SET start_time = SYS_DATETIME, status = 0 WHERE db_name = ? AND copied_log_path = ? ;",
1866 
1867  in_value_idx = 0;
1868  db_make_varchar (&in_value[in_value_idx++], 255, act_log->log_hdr->prefix_name,
1870  db_make_varchar (&in_value[in_value_idx++], 4096, la_Info.log_path, strlen (la_Info.log_path), LANG_SYS_CODESET,
1872  assert (in_value_idx == LA_IN_VALUE_COUNT);
1873 
1874  res = la_update_query_execute_with_values (query_buf, in_value_idx, &in_value[0], true);
1875  la_Info.is_apply_info_updated = true;
1876 
1877  for (i = 0; i < in_value_idx; i++)
1878  {
1879  db_value_clear (&in_value[i]);
1880  }
1881 
1882  return res;
1883 
1884 #undef LA_IN_VALUE_COUNT
1885 }
1886 
1887 static int
1889 {
1890 #define LA_IN_VALUE_COUNT 3
1891  int res;
1892  char query_buf[LA_QUERY_BUF_SIZE];
1893  DB_VALUE in_value[LA_IN_VALUE_COUNT];
1894  DB_DATETIME datetime;
1895  int i, in_value_idx = 0;
1896 
1897  er_clear ();
1898 
1899  snprintf (query_buf, sizeof (query_buf), "UPDATE %s " /* UPDATE */
1900  " SET " /* SET */
1901  " log_record_time = ?, " /* 1 */
1902  " last_access_time = SYS_DATETIME " /* last_access_time */
1903  " WHERE db_name = ? AND copied_log_path = ? ;", /* 2 ~ 3 */
1905 
1906  /* 1. log_record_time */
1907  db_localdatetime (&new_time, &datetime);
1908  db_make_datetime (&in_value[in_value_idx++], &datetime);
1909 
1910  /* 2. db_name */
1911  db_make_varchar (&in_value[in_value_idx++], 255, la_Info.act_log.log_hdr->prefix_name,
1913 
1914  /* 3. copied_log_path */
1915  db_make_varchar (&in_value[in_value_idx++], 4096, la_Info.log_path, strlen (la_Info.log_path), LANG_SYS_CODESET,
1917  assert_release (in_value_idx == LA_IN_VALUE_COUNT);
1918 
1919  res = la_update_query_execute_with_values (query_buf, in_value_idx, &in_value[0], true);
1920  if (res == 0)
1921  {
1922  /* it means db_ha_apply_info was deleted */
1923  DB_DATETIME log_db_creation_time;
1924 
1925  db_localdatetime (&la_Info.act_log.log_hdr->db_creation, &log_db_creation_time);
1926 
1927  res = la_insert_ha_apply_info (&log_db_creation_time);
1928  if (res > 0)
1929  {
1930  res = la_update_query_execute_with_values (query_buf, in_value_idx, &in_value[0], true);
1931  }
1932  }
1933 
1934  if (res > 0)
1935  {
1936  la_Info.log_record_time = new_time;
1937  la_Info.is_apply_info_updated = true;
1938  }
1939 
1940  for (i = 0; i < in_value_idx; i++)
1941  {
1942  db_value_clear (&in_value[i]);
1943  }
1944 
1945  return res;
1946 #undef LA_IN_VALUE_COUNT
1947 }
1948 
1949 /*
1950  * la_get_last_ha_applied_info() - get last applied info
1951  * return: NO_ERROR or error code
1952  *
1953  * Note:
1954  */
1955 static int
1957 {
1958  int res;
1959  LA_ACT_LOG *act_log;
1960  LA_HA_APPLY_INFO apply_info;
1961  time_t log_db_creation;
1962  DB_DATETIME log_db_creation_time;
1963  bool insert_apply_info = false;
1964  char err_msg[LINE_MAX];
1965 
1966  act_log = &la_Info.act_log;
1967 
1968  log_db_creation = act_log->log_hdr->db_creation;
1969  db_localdatetime (&log_db_creation, &log_db_creation_time);
1970 
1971  res = la_get_ha_apply_info (la_Info.log_path, act_log->log_hdr->prefix_name, &apply_info);
1972  if (res > 0)
1973  {
1974  LSA_COPY (&la_Info.committed_lsa, &apply_info.committed_lsa);
1975  LSA_COPY (&la_Info.committed_rep_lsa, &apply_info.committed_rep_lsa);
1976  LSA_COPY (&la_Info.append_lsa, &apply_info.append_lsa);
1977  LSA_COPY (&la_Info.eof_lsa, &apply_info.eof_lsa);
1978  LSA_COPY (&la_Info.final_lsa, &apply_info.final_lsa);
1979  LSA_COPY (&la_Info.required_lsa, &apply_info.required_lsa);
1980 
1981  la_Info.insert_counter = apply_info.insert_counter;
1982  la_Info.update_counter = apply_info.update_counter;
1983  la_Info.delete_counter = apply_info.delete_counter;
1984  la_Info.schema_counter = apply_info.schema_counter;
1985  la_Info.commit_counter = apply_info.commit_counter;
1986  la_Info.fail_counter = apply_info.fail_counter;
1987 
1988  if ((log_db_creation_time.date != apply_info.creation_time.date)
1989  || (log_db_creation_time.time != apply_info.creation_time.time))
1990  {
1991  return ER_FAILED;
1992  }
1993 
1994  if (LSA_ISNULL (&la_Info.required_lsa))
1995  {
1996  snprintf (err_msg, LINE_MAX, "required_lsa in %s cannot be NULL", CT_HA_APPLY_INFO_NAME);
1998  return ER_FAILED;
1999  }
2000  }
2001  else if (res == 0)
2002  {
2003  insert_apply_info = true;
2004  }
2005  else
2006  {
2007  return res;
2008  }
2009 
2010  if (LSA_ISNULL (&la_Info.required_lsa))
2011  {
2012  LSA_COPY (&la_Info.required_lsa, &act_log->log_hdr->eof_lsa);
2013  }
2014 
2015  if (LSA_ISNULL (&la_Info.committed_lsa))
2016  {
2017  LSA_COPY (&la_Info.committed_lsa, &la_Info.required_lsa);
2018  }
2019 
2020  if (LSA_ISNULL (&la_Info.committed_rep_lsa))
2021  {
2022  LSA_COPY (&la_Info.committed_rep_lsa, &la_Info.required_lsa);
2023  }
2024 
2025  if (LSA_ISNULL (&la_Info.final_lsa))
2026  {
2027  LSA_COPY (&la_Info.final_lsa, &la_Info.required_lsa);
2028  }
2029 
2030  if (insert_apply_info == true)
2031  {
2032  res = la_insert_ha_apply_info (&log_db_creation_time);
2033  }
2034  else
2035  {
2037  }
2038 
2039  if (res == 0)
2040  {
2041  return ER_FAILED;
2042  }
2043  else if (res < 0)
2044  {
2045  return res;
2046  }
2047 
2048  (void) db_commit_transaction ();
2049 
2050  LSA_COPY (&la_Info.last_committed_lsa, &la_Info.committed_lsa);
2051  LSA_COPY (&la_Info.last_committed_rep_lsa, &la_Info.committed_rep_lsa);
2052 
2053  return NO_ERROR;
2054 }
2055 
2056 /*
2057  * la_update_ha_last_applied_info() - update db_ha_apply_info table
2058  * returns : error code, if execution failed
2059  * number of affected objects, if a success
2060  *
2061  * Note:
2062  * called by APPLY thread
2063  */
2064 static int
2066 {
2067 #define LA_IN_VALUE_COUNT 22
2068  int res;
2069  char query_buf[LA_QUERY_BUF_SIZE];
2070  DB_VALUE in_value[LA_IN_VALUE_COUNT];
2071  DB_DATETIME datetime;
2072  int i, in_value_idx;
2073 
2074  er_clear ();
2075 
2076  snprintf (query_buf, sizeof (query_buf), "UPDATE %s " /* UPDATE */
2077  " SET " /* SET */
2078  " committed_lsa_pageid = ?, " /* 1 */
2079  " committed_lsa_offset = ?, " /* 2 */
2080  " committed_rep_pageid = ?, " /* 3 */
2081  " committed_rep_offset = ?, " /* 4 */
2082  " append_lsa_pageid = ?, " /* 5 */
2083  " append_lsa_offset = ?, " /* 6 */
2084  " eof_lsa_pageid = ?, " /* 7 */
2085  " eof_lsa_offset = ?, " /* 8 */
2086  " final_lsa_pageid = ?, " /* 9 */
2087  " final_lsa_offset = ?, " /* 10 */
2088  " required_lsa_pageid = ?, " /* 11 */
2089  " required_lsa_offset = ?, " /* 12 */
2090  " log_record_time = IFNULL(?, log_record_time), " /* 13 */
2091  " log_commit_time = IFNULL(?, log_commit_time), " /* 14 */
2092  " last_access_time = SYS_DATETIME, " /* */
2093  " insert_counter = ?, " /* 15 */
2094  " update_counter = ?, " /* 16 */
2095  " delete_counter = ?, " /* 17 */
2096  " schema_counter = ?, " /* 18 */
2097  " commit_counter = ?, " /* 19 */
2098  " fail_counter = ? " /* 20 */
2099  " WHERE db_name = ? AND copied_log_path = ? ;", /* 21 ~ 22 */
2101 
2102  in_value_idx = 0;
2103 
2104  /* 1 ~ 2. committed_lsa */
2105  if (LSA_GE (&la_Info.committed_lsa, &la_Info.last_committed_lsa))
2106  {
2107  db_make_bigint (&in_value[in_value_idx++], la_Info.committed_lsa.pageid);
2108  db_make_int (&in_value[in_value_idx++], la_Info.committed_lsa.offset);
2109  }
2110  else
2111  {
2112  db_make_bigint (&in_value[in_value_idx++], la_Info.last_committed_lsa.pageid);
2113  db_make_int (&in_value[in_value_idx++], la_Info.last_committed_lsa.offset);
2114  }
2115 
2116  /* 3 ~ 4. committed_rep_lsa */
2117  if (LSA_GE (&la_Info.committed_rep_lsa, &la_Info.last_committed_rep_lsa))
2118  {
2119  db_make_bigint (&in_value[in_value_idx++], la_Info.committed_rep_lsa.pageid);
2120  db_make_int (&in_value[in_value_idx++], la_Info.committed_rep_lsa.offset);
2121  }
2122  else
2123  {
2124  db_make_bigint (&in_value[in_value_idx++], la_Info.last_committed_rep_lsa.pageid);
2125  db_make_int (&in_value[in_value_idx++], la_Info.last_committed_rep_lsa.offset);
2126  }
2127 
2128  /* 5 ~ 6. append_lsa */
2129  db_make_bigint (&in_value[in_value_idx++], la_Info.append_lsa.pageid);
2130  db_make_int (&in_value[in_value_idx++], la_Info.append_lsa.offset);
2131 
2132  /* 7 ~ 8. eof_lsa */
2133  db_make_bigint (&in_value[in_value_idx++], la_Info.eof_lsa.pageid);
2134  db_make_int (&in_value[in_value_idx++], la_Info.eof_lsa.offset);
2135 
2136 
2137  /* 9 ~ 10. final_lsa */
2138  db_make_bigint (&in_value[in_value_idx++], la_Info.final_lsa.pageid);
2139  db_make_int (&in_value[in_value_idx++], la_Info.final_lsa.offset);
2140 
2141  /* 11 ~ 12. required_lsa */
2142  db_make_bigint (&in_value[in_value_idx++], la_Info.required_lsa.pageid);
2143  db_make_int (&in_value[in_value_idx++], la_Info.required_lsa.offset);
2144 
2145  /* 13. log_record_time */
2146  if (la_Info.log_record_time)
2147  {
2148  db_localdatetime (&la_Info.log_record_time, &datetime);
2149  db_make_datetime (&in_value[in_value_idx++], &datetime);
2150  }
2151  else
2152  {
2153  db_make_null (&in_value[in_value_idx++]);
2154  }
2155 
2156  /* 14. log_commit_time */
2157  if (la_Info.log_commit_time)
2158  {
2159  db_localdatetime (&la_Info.log_commit_time, &datetime);
2160  db_make_datetime (&in_value[in_value_idx++], &datetime);
2161  }
2162  else
2163  {
2164  db_make_null (&in_value[in_value_idx++]);
2165  }
2166 
2167  /* 15 ~ 20. counter */
2168  db_make_bigint (&in_value[in_value_idx++], la_Info.insert_counter);
2169  db_make_bigint (&in_value[in_value_idx++], la_Info.update_counter);
2170  db_make_bigint (&in_value[in_value_idx++], la_Info.delete_counter);
2171  db_make_bigint (&in_value[in_value_idx++], la_Info.schema_counter);
2172  db_make_bigint (&in_value[in_value_idx++], la_Info.commit_counter);
2173  db_make_bigint (&in_value[in_value_idx++], la_Info.fail_counter);
2174 
2175  /* 21. db_name */
2176  db_make_varchar (&in_value[in_value_idx++], 255, la_Info.act_log.log_hdr->prefix_name,
2178 
2179  /* 22. copied_log_path */
2180  db_make_varchar (&in_value[in_value_idx++], 4096, la_Info.log_path, strlen (la_Info.log_path), LANG_SYS_CODESET,
2182  assert_release (in_value_idx == LA_IN_VALUE_COUNT);
2183 
2184  res = la_update_query_execute_with_values (query_buf, in_value_idx, &in_value[0], true);
2185  if (res == 0)
2186  {
2187  /* it means db_ha_apply_info was deleted */
2188  DB_DATETIME log_db_creation_time;
2189 
2190  db_localdatetime (&la_Info.act_log.log_hdr->db_creation, &log_db_creation_time);
2191 
2192  res = la_insert_ha_apply_info (&log_db_creation_time);
2193  if (res > 0)
2194  {
2195  res = la_update_query_execute_with_values (query_buf, in_value_idx, &in_value[0], true);
2196  }
2197  }
2198 
2199  for (i = 0; i < in_value_idx; i++)
2200  {
2201  db_value_clear (&in_value[i]);
2202  }
2203 
2204  return res;
2205 #undef LA_IN_VALUE_COUNT
2206 }
2207 
2208 static int
2210 {
2211 #define LA_IN_VALUE_COUNT 2
2212  int res;
2213  LA_ACT_LOG *act_log;
2214  int i;
2215  int in_value_idx;
2216  DB_VALUE in_value[LA_IN_VALUE_COUNT];
2217  char query_buf[LA_QUERY_BUF_SIZE];
2218 
2219  act_log = &la_Info.act_log;
2220 
2221  snprintf (query_buf, sizeof (query_buf), "DELETE FROM %s WHERE db_name = ? AND copied_log_path = ?",
2223 
2224  in_value_idx = 0;
2225  db_make_varchar (&in_value[in_value_idx++], 255, act_log->log_hdr->prefix_name,
2227  db_make_varchar (&in_value[in_value_idx++], 4096, la_Info.log_path, strlen (la_Info.log_path), LANG_SYS_CODESET,
2229  assert (in_value_idx == LA_IN_VALUE_COUNT);
2230 
2231  res = la_update_query_execute_with_values (query_buf, in_value_idx, &in_value[0], true);
2232  la_Info.is_apply_info_updated = true;
2233 
2234  for (i = 0; i < in_value_idx; i++)
2235  {
2236  db_value_clear (&in_value[i]);
2237  }
2238 
2239  (void) db_commit_transaction ();
2240 
2241  return res;
2242 
2243 #undef LA_IN_VALUE_COUNT
2244 }
2245 
2246 static bool
2248 {
2249  assert_release (errid != NO_ERROR);
2250 
2251  errid = abs (errid);
2252 
2254  {
2255  return true;
2256  }
2257 
2258  return false;
2259 }
2260 
2261 /*
2262  * la_restart_on_bulk_flush_error() -
2263  * return: whether to restart or not for a given error
2264  *
2265  * Note:
2266  * this function is essentially the same as
2267  * la_retry_on_error but it is used when checking
2268  * error while bulk flushing
2269  */
2270 static bool
2272 {
2273  if (la_ignore_on_error (errid))
2274  {
2275  return false;
2276  }
2277 
2278  return la_retry_on_error (errid);
2279 }
2280 
2281 static bool
2283 {
2284  assert_release (errid != NO_ERROR);
2285 
2286  if (LA_RETRY_ON_ERROR (errid))
2287  {
2288  return true;
2289  }
2290 
2291  errid = abs (errid);
2293  {
2294  return true;
2295  }
2296 
2297  return false;
2298 }
2299 
2300 /*
2301  * la_clear_recdes_pool() - free allocated memory in recdes pool
2302  * and clear recdes pool info
2303  * return: error code
2304  */
2305 static void
2307 {
2308  int i;
2309  RECDES *recdes;
2310 
2311  if (la_recdes_pool.is_initialized == false)
2312  {
2313  return;
2314  }
2315 
2316  if (la_recdes_pool.recdes_arr != NULL)
2317  {
2318  for (i = 0; i < la_recdes_pool.num_recdes; i++)
2319  {
2320  recdes = &la_recdes_pool.recdes_arr[i];
2321  if (recdes->area_size > la_recdes_pool.db_page_size)
2322  {
2323  free_and_init (recdes->data);
2324  }
2325  }
2326  free_and_init (la_recdes_pool.recdes_arr);
2327  }
2328 
2329  if (la_recdes_pool.area != NULL)
2330  {
2331  free_and_init (la_recdes_pool.area);
2332  }
2333 
2334  la_recdes_pool.db_page_size = 0;
2335  la_recdes_pool.next_idx = 0;
2336  la_recdes_pool.num_recdes = 0;
2337  la_recdes_pool.is_initialized = false;
2338 
2339  return;
2340 }
2341 
2342 /*
2343  * la_realloc_recdes_data() - realloc area of given recdes
2344  * return: error code
2345  *
2346  */
2347 static int
2349 {
2350  if (la_recdes_pool.is_initialized == false)
2351  {
2352  return ER_FAILED;
2353  }
2354 
2355  if (recdes->area_size < data_size)
2356  {
2357  if (recdes->area_size > la_recdes_pool.db_page_size)
2358  {
2359  /* recdes->data was realloced by previous operation */
2360  free_and_init (recdes->data);
2361  }
2362 
2363  recdes->data = (char *) malloc (data_size);
2364  if (recdes->data == NULL)
2365  {
2367  return ER_OUT_OF_VIRTUAL_MEMORY;
2368  }
2369 
2370  recdes->area_size = data_size;
2371  }
2372  recdes->length = 0;
2373 
2374  return NO_ERROR;
2375 }
2376 
2377 /*
2378  * la_assign_recdes_from_pool() - get a recdes from pool
2379  * return: a recdes having area with size of db page size
2380  *
2381  * Note: if a recdes that is about to be assigned has an area
2382  * greater than db page size, then it first frees the area.
2383  */
2384 static RECDES *
2386 {
2387  RECDES *recdes;
2388 
2389  if (la_recdes_pool.is_initialized == false)
2390  {
2391  return NULL;
2392  }
2393 
2394  recdes = &la_recdes_pool.recdes_arr[la_recdes_pool.next_idx];
2395  assert (recdes != NULL && recdes->data != NULL);
2396 
2397  if (recdes->area_size > la_recdes_pool.db_page_size)
2398  {
2399  /* recdes->data was realloced by previous operation */
2400  free_and_init (recdes->data);
2401 
2402  recdes->data = la_recdes_pool.area + la_recdes_pool.db_page_size * la_recdes_pool.next_idx;
2403  recdes->area_size = la_recdes_pool.db_page_size;
2404  }
2405 
2406  recdes->length = 0;
2407  la_recdes_pool.next_idx++;
2408  la_recdes_pool.next_idx %= la_recdes_pool.num_recdes;
2409 
2410  return recdes;
2411 }
2412 
2413 /*
2414  * la_init_recdes_pool() - initialize recdes pool
2415  * return:
2416  *
2417  * Note:
2418  */
2419 static int
2420 la_init_recdes_pool (int page_size, int num_recdes)
2421 {
2422  int i;
2423  char *p;
2424  RECDES *recdes;
2425 
2426  assert (page_size >= IO_MIN_PAGE_SIZE && page_size <= IO_MAX_PAGE_SIZE);
2427 
2428  if (la_recdes_pool.is_initialized == false)
2429  {
2430  la_recdes_pool.area = (char *) malloc (page_size * num_recdes);
2431  if (la_recdes_pool.area == NULL)
2432  {
2433  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, page_size * num_recdes);
2434  return ER_OUT_OF_VIRTUAL_MEMORY;
2435  }
2436 
2437  la_recdes_pool.recdes_arr = (RECDES *) malloc (sizeof (RECDES) * num_recdes);
2438  if (la_recdes_pool.recdes_arr == NULL)
2439  {
2441  return ER_OUT_OF_VIRTUAL_MEMORY;
2442  }
2443 
2444  p = la_recdes_pool.area;
2445  for (i = 0; i < num_recdes; i++)
2446  {
2447  recdes = &la_recdes_pool.recdes_arr[i];
2448 
2449  recdes->data = p;
2450  recdes->area_size = page_size;
2451  recdes->length = 0;
2452 
2453  p += page_size;
2454  }
2455 
2456  la_recdes_pool.db_page_size = page_size;
2457  la_recdes_pool.num_recdes = num_recdes;
2458  la_recdes_pool.is_initialized = true;
2459  }
2460  else if (la_recdes_pool.db_page_size != page_size || la_recdes_pool.num_recdes != num_recdes)
2461  {
2463  return la_init_recdes_pool (page_size, num_recdes);
2464  }
2465 
2466  la_recdes_pool.next_idx = 0;
2467 
2468  return NO_ERROR;
2469 }
2470 
2471 /*
2472  * la_init_cache_pb() - initialize the cache page buffer area
2473  * return: the allocated pointer to a cache page buffer
2474  *
2475  * Note:
2476  */
2477 static LA_CACHE_PB *
2479 {
2480  LA_CACHE_PB *cache_pb;
2481 
2482  cache_pb = (LA_CACHE_PB *) malloc (DB_SIZEOF (LA_CACHE_PB));
2483  if (cache_pb == NULL)
2484  {
2486  return NULL;
2487  }
2488 
2489  cache_pb->hash_table = NULL;
2490  cache_pb->log_buffer = NULL;
2491  cache_pb->num_buffers = 0;
2492  cache_pb->buffer_area = NULL;
2493 
2494  return (cache_pb);
2495 }
2496 
2497 /*
2498  * log_pageid_hash - hash a LOG_PAGEID key
2499  * return: hash value
2500  * key(in): void pointer to LOG_PAGEID key to hash
2501  * ht_size(in): size of hash table
2502  */
2503 static unsigned int
2504 log_pageid_hash (const void *key, unsigned int htsize)
2505 {
2506  assert (key != NULL);
2507 
2508  if ((*(const LOG_PAGEID *) key) == LOGPB_HEADER_PAGE_ID)
2509  {
2510  return 0;
2511  }
2512 
2513  assert ((*(const LOG_PAGEID *) key) >= 0);
2514 
2515  return (*(const LOG_PAGEID *) key) % htsize;
2516 }
2517 
2518 /*
2519  * la_init_cache_log_buffer() - Initialize the cache log buffer area of
2520  * a cache page buffer
2521  * return: NO_ERROR or ER_OUT_OF_VIRTUAL_MEMORY
2522  * cache_pb : cache page buffer pointer
2523  * slb_cnt : the # of cache log buffers per cache page buffer
2524  * slb_size : size of CACHE_LOG_BUFFER
2525  *
2526  * Note:
2527  * : allocate the cache page buffer area
2528  * : the size of page buffer area is determined after reading the
2529  * log header, so we split the "initialize" and "allocate" phase.
2530  */
2531 static int
2532 la_init_cache_log_buffer (LA_CACHE_PB * cache_pb, int slb_cnt, int slb_size)
2533 {
2534  int error = NO_ERROR;
2535 
2536  error = la_expand_cache_log_buffer (cache_pb, slb_cnt, slb_size);
2537  if (error != NO_ERROR)
2538  {
2539  return error;
2540  }
2541 
2542  cache_pb->hash_table =
2543  mht_create ("log applier cache log buffer hash table", cache_pb->num_buffers * 8, log_pageid_hash,
2545  if (cache_pb->hash_table == NULL)
2546  {
2548  error = ER_OUT_OF_VIRTUAL_MEMORY;
2549  }
2550 
2551  return error;
2552 }
2553 
2554 static int
2556 {
2557  int error = NO_ERROR;
2558 
2559  error = la_log_io_read (act_log->path, act_log->log_vdes, (void *) act_log->hdr_page, 0, act_log->db_logpagesize);
2560  if (error != NO_ERROR)
2561  {
2563  return ER_LOG_READ;
2564  }
2565 
2566  act_log->log_hdr = (LOG_HEADER *) (act_log->hdr_page->area);
2567 
2568  return error;
2569 }
2570 
2571 static int
2572 la_find_log_pagesize (LA_ACT_LOG * act_log, const char *logpath, const char *dbname, bool check_charset)
2573 {
2574  int error = NO_ERROR;
2575 
2576  /* set active log name */
2577  fileio_make_log_active_name (act_log->path, logpath, dbname);
2578 
2579  /* read active log file to get the io page size */
2580  /* wait until act_log is opened */
2581  do
2582  {
2583  act_log->log_vdes = fileio_open (act_log->path, O_RDONLY, 0);
2584  if (act_log->log_vdes == NULL_VOLDES)
2585  {
2586  er_log_debug (ARG_FILE_LINE, "Active log file(%s) is not exist. waiting...", act_log->path);
2587  /* TODO: is it error? */
2589  error = ER_LOG_MOUNT_FAIL;
2590 
2591  LA_SLEEP (0, 200 * 1000);
2592  }
2593  else
2594  {
2595  error = NO_ERROR;
2596  break;
2597  }
2598  }
2599  while (la_applier_need_shutdown == false);
2600 
2601  if (error != NO_ERROR)
2602  {
2603  return error;
2604  }
2605 
2606  act_log->hdr_page = (LOG_PAGE *) malloc (LA_DEFAULT_LOG_PAGE_SIZE);
2607  if (act_log->hdr_page == NULL)
2608  {
2610  return ER_OUT_OF_VIRTUAL_MEMORY;
2611  }
2612 
2613  do
2614  {
2615  error =
2616  la_log_io_read (act_log->path, act_log->log_vdes, (char *) act_log->hdr_page, 0, LA_DEFAULT_LOG_PAGE_SIZE);
2617  if (error != NO_ERROR)
2618  {
2620  return error;
2621  }
2622 
2623  act_log->log_hdr = (LOG_HEADER *) act_log->hdr_page->area;
2624 
2625  /* check mark will deleted */
2626  if (act_log->log_hdr->mark_will_del == true)
2627  {
2628  LA_SLEEP (3, 0);
2629 
2631  return ER_LOG_MOUNT_FAIL;
2632  }
2633 
2634  /* check if the log header is valid */
2635  if (strncmp (act_log->log_hdr->magic, CUBRID_MAGIC_LOG_ACTIVE, CUBRID_MAGIC_MAX_LENGTH) != 0)
2636  {
2637  /* The active log is formatting by the copylogdb. */
2638  er_log_debug (ARG_FILE_LINE, "Active log file(%s) isn't prepared. waiting...", act_log->path);
2639 
2640  LA_SLEEP (0, 200 * 1000);
2641  continue;
2642  }
2643 
2644  /* The active log header is corrupted. */
2645  if (act_log->log_hdr->prefix_name[0] != '\0'
2646  && strncmp (act_log->log_hdr->prefix_name, dbname, strlen (dbname)) != 0)
2647  {
2648  la_applier_need_shutdown = true;
2649 
2651  return ER_LOG_PAGE_CORRUPTED;
2652  }
2653  else if (check_charset && act_log->log_hdr->db_charset != lang_charset ())
2654  {
2655  char err_msg[ERR_MSG_SIZE];
2656 
2657  la_applier_need_shutdown = true;
2658  snprintf_dots_truncate (err_msg, sizeof (err_msg) - 1,
2659  "Active log file(%s) charset is not valid (%s), expecting %s.",
2662 
2664  return ER_LOC_INIT;
2665  }
2666  else
2667  {
2668  error = NO_ERROR;
2669  break;
2670  }
2671  }
2672  while (la_applier_need_shutdown == false);
2673 
2674  if (error != NO_ERROR)
2675  {
2676  return error;
2677  }
2678 
2679  act_log->db_iopagesize = act_log->log_hdr->db_iopagesize;
2680  act_log->db_logpagesize = act_log->log_hdr->db_logpagesize;
2681  /* check iopage size is valid */
2682  if (act_log->db_logpagesize < IO_MIN_PAGE_SIZE || act_log->db_logpagesize > IO_MAX_PAGE_SIZE)
2683  {
2685  return ER_LOG_PAGE_CORRUPTED;
2686  }
2687  else if (act_log->db_logpagesize > LA_DEFAULT_LOG_PAGE_SIZE)
2688  {
2689  act_log->hdr_page = (LOG_PAGE *) realloc (act_log->hdr_page, act_log->db_logpagesize);
2690  act_log->log_hdr = (LOG_HEADER *) act_log->hdr_page->area;
2691  }
2692 
2693  return error;
2694 }
2695 
2696 static bool
2698 {
2699  LSA_COPY (&la_Info.final_lsa, &la_Info.committed_lsa);
2700 
2701  if (la_Info.rec_type == NULL)
2702  {
2703  la_Info.rec_type = (char *) malloc (DB_SIZEOF (INT16));
2704  if (la_Info.rec_type == NULL)
2705  {
2707  return false;
2708  }
2709  }
2710 
2711  if (la_Info.undo_unzip_ptr == NULL)
2712  {
2713  la_Info.undo_unzip_ptr = log_zip_alloc (la_Info.act_log.db_iopagesize);
2714  if (la_Info.undo_unzip_ptr == NULL)
2715  {
2717  return false;
2718  }
2719  }
2720 
2721  if (la_Info.redo_unzip_ptr == NULL)
2722  {
2723  la_Info.redo_unzip_ptr = log_zip_alloc (la_Info.act_log.db_iopagesize);
2724  if (la_Info.redo_unzip_ptr == NULL)
2725  {
2727  return false;
2728  }
2729  }
2730 
2731  return true;
2732 }
2733 
2734 /*
2735  * la_does_page_exist() - check whether page is exist
2736  * return:
2737  * pageid(in): the target page id
2738  *
2739  * Note
2740  */
2741 static int
2743 {
2745  int log_exist = LA_PAGE_DOESNOT_EXIST;
2746 
2747  log_buffer = la_get_page_buffer (pageid);
2748  if (log_buffer != NULL)
2749  {
2750  if (log_buffer->pageid == pageid && log_buffer->logpage.hdr.logical_pageid == pageid
2751  && log_buffer->logpage.hdr.offset > NULL_OFFSET)
2752  {
2754 
2755  la_release_page_buffer (pageid);
2756  }
2757  else
2758  {
2759  la_invalidate_page_buffer (log_buffer);
2760  }
2761  }
2762 
2763  return log_exist;
2764 }
2765 
2766 /*
2767  * la_init_repl_lists() - Initialize the replication lists
2768  * return: NO_ERROR or error code
2769  * need_realloc : yes when realloc
2770  *
2771  * Note:
2772  * repl_lists is an array of replication items to be applied.
2773  * We maintain repl_lists for a transaction.
2774  * This function initialize the repl_list.
2775  */
2776 static int
2777 la_init_repl_lists (bool need_realloc)
2778 {
2779  int i, j;
2780  int error = NO_ERROR;
2781 
2782  if (need_realloc == false)
2783  {
2784  la_Info.repl_lists = (LA_APPLY **) malloc ((DB_SIZEOF (LA_APPLY *) * LA_REPL_LIST_COUNT));
2785  la_Info.repl_cnt = LA_REPL_LIST_COUNT;
2786  la_Info.cur_repl = 0;
2787  j = 0;
2788  }
2789  else
2790  {
2791  la_Info.repl_lists = (LA_APPLY **)
2792  realloc (la_Info.repl_lists, (DB_SIZEOF (LA_APPLY *) * (LA_REPL_LIST_COUNT + la_Info.repl_cnt)));
2793  j = la_Info.repl_cnt;
2794  la_Info.repl_cnt += LA_REPL_LIST_COUNT;
2795  }
2796 
2797  if (la_Info.repl_lists == NULL)
2798  {
2800  DB_SIZEOF (LA_APPLY *) * (LA_REPL_LIST_COUNT + la_Info.repl_cnt));
2801  return ER_OUT_OF_VIRTUAL_MEMORY;
2802  }
2803 
2804  for (i = j; i < la_Info.repl_cnt; i++)
2805  {
2806  la_Info.repl_lists[i] = (LA_APPLY *) malloc (DB_SIZEOF (LA_APPLY));
2807  if (la_Info.repl_lists[i] == NULL)
2808  {
2810  error = ER_OUT_OF_VIRTUAL_MEMORY;
2811  break;
2812  }
2813  la_Info.repl_lists[i]->tranid = 0;
2814  la_Info.repl_lists[i]->num_items = 0;
2815  la_Info.repl_lists[i]->is_long_trans = false;
2816  LSA_SET_NULL (&la_Info.repl_lists[i]->start_lsa);
2817  LSA_SET_NULL (&la_Info.repl_lists[i]->last_lsa);
2818  la_Info.repl_lists[i]->head = NULL;
2819  la_Info.repl_lists[i]->tail = NULL;
2820  }
2821 
2822  if (error != NO_ERROR)
2823  {
2824  for (j = 0; j < i; j++)
2825  {
2826  free_and_init (la_Info.repl_lists[i]);
2827  }
2828  free_and_init (la_Info.repl_lists);
2829  return error;
2830  }
2831 
2832  return error;
2833 }
2834 
2835 /*
2836  * la_is_repl_lists_empty() -
2837  *
2838  * return: whether repl_lists is empty or not
2839  */
2840 static bool
2842 {
2843  int i;
2844 
2845  for (i = 0; i < la_Info.cur_repl; i++)
2846  {
2847  if (la_Info.repl_lists[i]->num_items > 0)
2848  {
2849  return false;
2850  }
2851  }
2852  return true;
2853 }
2854 
2855 /*
2856  * la_find_apply_list() - return the apply list for the target
2857  * transaction id
2858  * return: pointer to the target apply list
2859  * tranid(in): the target transaction id
2860  *
2861  * Note:
2862  */
2863 static LA_APPLY *
2865 {
2866  int i;
2867  for (i = 0; i < la_Info.cur_repl; i++)
2868  {
2869  if (la_Info.repl_lists[i]->tranid == tranid)
2870  {
2871  return la_Info.repl_lists[i];
2872  }
2873  }
2874  return NULL;
2875 }
2876 
2877 /*
2878  * la_add_apply_list() - return the apply list for the target
2879  * transaction id
2880  * return: pointer to the target apply list
2881  * tranid(in): the target transaction id
2882  *
2883  * Note:
2884  * When we apply the transaction logs to the slave, we have to take them
2885  * in turns of commit order.
2886  * So, each slave maintains the apply list per transaction.
2887  * And an apply list has one or more replication item.
2888  * When the APPLY thread meets the "LOG COMMIT" record, it finds out
2889  * the apply list of the target transaction, and apply the replication
2890  * items to the slave orderly.
2891  */
2892 static LA_APPLY *
2893 la_add_apply_list (int tranid)
2894 {
2895  int i;
2896  int free_index = -1;
2897  LA_APPLY *find_apply = NULL;
2898 
2899  find_apply = la_find_apply_list (tranid);
2900  if (find_apply != NULL)
2901  {
2902  return find_apply;
2903  }
2904 
2905  /* find out the matched index */
2906  for (i = 0; i < la_Info.cur_repl; i++)
2907  {
2908  /* retreive the free index for the laster use */
2909  if (la_Info.repl_lists[i]->tranid == 0)
2910  {
2911  free_index = i;
2912  break;
2913  }
2914  }
2915 
2916  /* not matched, but we have free space */
2917  if (free_index >= 0)
2918  {
2919  la_Info.repl_lists[free_index]->tranid = tranid;
2920  return la_Info.repl_lists[free_index];
2921  }
2922 
2923  /* not matched, no free space */
2924  if (la_Info.cur_repl == la_Info.repl_cnt)
2925  {
2926  /* array is full --> realloc */
2927  if (la_init_repl_lists (true) == NO_ERROR)
2928  {
2929  la_Info.repl_lists[la_Info.cur_repl]->tranid = tranid;
2930  la_Info.cur_repl++;
2931  return la_Info.repl_lists[la_Info.cur_repl - 1];
2932  }
2933  return NULL;
2934  }
2935 
2936  /* mot matched, no free space, array is not full */
2937  la_Info.repl_lists[la_Info.cur_repl]->tranid = tranid;
2938  la_Info.cur_repl++;
2939  return la_Info.repl_lists[la_Info.cur_repl - 1];
2940 }
2941 
2942 /*
2943  * la_log_copy_fromlog() - copy a portion of the log
2944  * return: none
2945  * rec_type(out)
2946  * area: Area where the portion of the log is copied.
2947  * (Set as a side effect)
2948  * length: the length to copy (type change PGLENGTH -> int)
2949  * log_pageid: log page identifier of the log data to copy
2950  * (May be set as a side effect)
2951  * log_offset: log offset within the log page of the log data to copy
2952  * (May be set as a side effect)
2953  * log_pgptr: the buffer containing the log page
2954  * (May be set as a side effect)
2955  *
2956  * Note:
2957  * Copy "length" bytes of the log starting at log_pageid,
2958  * log_offset onto the given area.
2959  *
2960  * area is set as a side effect.
2961  * log_pageid, log_offset, and log_pgptr are set as a side effect.
2962  */
2963 static void
2964 la_log_copy_fromlog (char *rec_type, char *area, int length, LOG_PAGEID log_pageid, PGLENGTH log_offset,
2965  LOG_PAGE * log_pgptr)
2966 {
2967  int rec_length = (int) sizeof (INT16);
2968  int copy_length; /* Length to copy into area */
2969  int t_length; /* target length */
2970  int area_offset = 0; /* The area offset */
2971  int error = NO_ERROR;
2972  LOG_PAGE *pg;
2973 
2974  pg = log_pgptr;
2975 
2976  /* filter the record type */
2977  /* NOTES : in case of overflow page, we don't need to fetch the rectype */
2978  while (rec_type != NULL && rec_length > 0)
2979  {
2980  LA_LOG_READ_ADVANCE_WHEN_DOESNT_FIT (error, 0, log_offset, log_pageid, pg);
2981  if (pg == NULL)
2982  {
2983  /* TODO: huh? what happend */
2984  break;
2985  }
2986 
2987  copy_length = ((log_offset + rec_length <= LA_LOGAREA_SIZE) ? rec_length : LA_LOGAREA_SIZE - log_offset);
2988  memcpy (rec_type + area_offset, (char *) (pg)->area + log_offset, copy_length);
2989  rec_length -= copy_length;
2990  area_offset += copy_length;
2991  log_offset += copy_length;
2992  length = length - DB_SIZEOF (INT16);
2993  }
2994 
2995  area_offset = 0;
2996  t_length = length;
2997 
2998  /* The log data is not contiguous */
2999  while (t_length > 0)
3000  {
3001  LA_LOG_READ_ADVANCE_WHEN_DOESNT_FIT (error, 0, log_offset, log_pageid, pg);
3002  if (pg == NULL)
3003  {
3004  /* TODO: huh? what happend */
3005  break;
3006  }
3007  copy_length = ((log_offset + t_length <= LA_LOGAREA_SIZE) ? t_length : LA_LOGAREA_SIZE - log_offset);
3008  memcpy (area + area_offset, (char *) (pg)->area + log_offset, copy_length);
3009  t_length -= copy_length;
3010  area_offset += copy_length;
3011  log_offset += copy_length;
3012  }
3013 }
3014 
3015 static LA_ITEM *
3016 la_new_repl_item (LOG_LSA * lsa, LOG_LSA * target_lsa)
3017 {
3018  LA_ITEM *item;
3019 
3020  item = (LA_ITEM *) malloc (DB_SIZEOF (LA_ITEM));
3021  if (item == NULL)
3022  {
3024  return NULL;
3025  }
3026 
3027  item->log_type = -1;
3028  item->item_type = -1;
3029  item->class_name = NULL;
3030  item->db_user = NULL;
3031  item->ha_sys_prm = NULL;
3032  LSA_COPY (&item->lsa, lsa);
3033  LSA_COPY (&item->target_lsa, target_lsa);
3034 
3035  db_make_null (&item->key);
3036  item->packed_key_value_length = 0;
3037  item->packed_key_value = NULL;
3038 
3039  item->next = NULL;
3040  item->prev = NULL;
3041 
3042  return item;
3043 }
3044 
3045 /*
3046  * la_add_repl_item() - add the replication item into the apply list
3047  * return: NO_ERROR or error code
3048  * apply(in/out): log apply list
3049  * lsa(in): the target LSA of the log
3050  *
3051  * Note:
3052  */
3053 static void
3055 {
3056  assert (apply);
3057  assert (item);
3058 
3059  item->next = NULL;
3060  item->prev = apply->tail;
3061 
3062  if (apply->tail)
3063  {
3064  apply->tail->next = item;
3065  }
3066  else
3067  {
3068  apply->head = item;
3069  }
3070  apply->tail = item;
3071 
3072  apply->num_items++;
3073  return;
3074 }
3075 
3076 static DB_VALUE *
3078 {
3079  assert (item != NULL);
3080 
3081  if (item->log_type == LOG_REPLICATION_DATA && DB_IS_NULL (&item->key))
3082  {
3083  /* unpack pk image to construct DB_VALUE on demand */
3084  assert (item->packed_key_value != NULL && item->packed_key_value_length > 0);
3085 
3086  or_unpack_mem_value (item->packed_key_value, &item->key);
3087 
3088  assert (DB_VALUE_TYPE (&item->key) != DB_TYPE_NULL);
3089  }
3090 
3091  /* statement replication or key was already unpacked */
3092  return &item->key;
3093 }
3094 
3095 static LA_ITEM *
3096 la_make_repl_item (LOG_PAGE * log_pgptr, int log_type, int tranid, LOG_LSA * lsa)
3097 {
3098  int error = NO_ERROR;
3099  LA_ITEM *item = NULL;
3100  LOG_REC_REPLICATION *repl_log;
3101  LOG_PAGE *repl_log_pgptr;
3102  PGLENGTH offset;
3104  int length; /* type change PGLENGTH -> int */
3105  char *ptr;
3106 
3107  char *str_value;
3108  char *area;
3109 
3110  repl_log_pgptr = log_pgptr;
3111  pageid = lsa->pageid;
3112  offset = DB_SIZEOF (LOG_RECORD_HEADER) + lsa->offset;
3113  length = DB_SIZEOF (LOG_REC_REPLICATION);
3114 
3115  LA_LOG_READ_ALIGN (error, offset, pageid, repl_log_pgptr);
3116  if (error != NO_ERROR)
3117  {
3118  return NULL;
3119  }
3120 
3121  LA_LOG_READ_ADVANCE_WHEN_DOESNT_FIT (error, length, offset, pageid, repl_log_pgptr);
3122  if (error != NO_ERROR)
3123  {
3124  return NULL;
3125  }
3126 
3127  repl_log = (LOG_REC_REPLICATION *) ((char *) repl_log_pgptr->area + offset);
3128  offset += length;
3129  length = repl_log->length;
3130 
3131  LA_LOG_READ_ALIGN (error, offset, pageid, repl_log_pgptr);
3132  if (error != NO_ERROR)
3133  {
3134  return NULL;
3135  }
3136 
3137  area = (char *) malloc (length);
3138  if (area == NULL)
3139  {
3140  return NULL;
3141  }
3142 
3143  (void) la_log_copy_fromlog (NULL, area, length, pageid, offset, repl_log_pgptr);
3144 
3145  item = la_new_repl_item (lsa, &repl_log->lsa);
3146  if (item == NULL)
3147  {
3148  goto error_return;
3149  }
3150 
3151  switch (log_type)
3152  {
3153  case LOG_REPLICATION_DATA:
3154  ptr = or_unpack_int (area, &item->packed_key_value_length);
3155  ptr = or_unpack_string (ptr, &item->class_name);
3156 
3157  item->packed_key_value = (char *) malloc (item->packed_key_value_length);
3158  if (item->packed_key_value == NULL)
3159  {
3160  goto error_return;
3161  }
3162 
3163  ptr = PTR_ALIGN (ptr, MAX_ALIGNMENT); /* 8 bytes alignment. see or_pack_mem_value */
3164  memcpy (item->packed_key_value, ptr, item->packed_key_value_length);
3165 
3166  item->item_type = repl_log->rcvindex;
3167 
3168  break;
3169 
3171  ptr = or_unpack_int (area, &item->item_type);
3172  ptr = or_unpack_string (ptr, &item->class_name);
3173  ptr = or_unpack_string (ptr, &str_value);
3174  db_make_string (&item->key, str_value);
3175  item->key.need_clear = true;
3176  ptr = or_unpack_string (ptr, &item->db_user);
3177  ptr = or_unpack_string (ptr, &item->ha_sys_prm);
3178 
3179  break;
3180 
3181  default:
3182  /* unknown log type */
3184  goto error_return;
3185  }
3186 
3187  item->log_type = log_type;
3188 
3189  if (area)
3190  {
3191  free_and_init (area);
3192  }
3193 
3194  return item;
3195 
3196 error_return:
3197  if (area)
3198  {
3199  free_and_init (area);
3200  }
3201 
3202  if (item)
3203  {
3204  if (item->class_name != NULL)
3205  {
3207  pr_clear_value (&item->key);
3208  }
3209 
3210  if (item->db_user != NULL)
3211  {
3213  }
3214 
3215  if (item->ha_sys_prm != NULL)
3216  {
3218  }
3219 
3220  if (item->packed_key_value != NULL)
3221  {
3223  }
3224 
3225  free_and_init (item);
3226  }
3227 
3228  return NULL;
3229 }
3230 
3231 static void
3233 {
3234  assert (apply);
3235  assert (item);
3236 
3237  /* Long transaction case, replication item does not make link */
3238  if ((item->prev == NULL && apply->head != item) || (item->next == NULL && apply->tail != item))
3239  {
3240  return;
3241  }
3242 
3243  if (item->next)
3244  {
3245  item->next->prev = item->prev;
3246  }
3247  else
3248  {
3249  apply->tail = item->prev;
3250  }
3251 
3252  if (item->prev)
3253  {
3254  item->prev->next = item->next;
3255  }
3256  else
3257  {
3258  apply->head = item->next;
3259  }
3260 
3261  if ((--apply->num_items) < 0)
3262  {
3263  apply->num_items = 0;
3264  }
3265 
3266  return;
3267 }
3268 
3269 static void
3271 {
3272  assert (apply);
3273  assert (item);
3274 
3275  la_unlink_repl_item (apply, item);
3276 
3277  if (item->class_name != NULL)
3278  {
3280  pr_clear_value (&item->key);
3281  }
3282 
3283  if (item->db_user != NULL)
3284  {
3286  }
3287 
3288  if (item->ha_sys_prm != NULL)
3289  {
3291  }
3292 
3293  if (item->packed_key_value != NULL)
3294  {
3296  }
3297 
3298  free_and_init (item);
3299 
3300  return;
3301 }
3302 
3303 static void
3305 {
3306  LA_ITEM *item, *next_item;
3307 
3308  assert (apply);
3309 
3310  if (apply->head)
3311  {
3312  item = apply->head->next;
3313  }
3314  else
3315  {
3316  return;
3317  }
3318 
3319  for (; item; item = next_item)
3320  {
3321  next_item = item->next;
3322 
3323  la_free_repl_item (apply, item);
3324  item = NULL;
3325  }
3326 
3327  return;
3328 }
3329 
3330 static void
3331 la_free_and_add_next_repl_item (LA_APPLY * apply, LA_ITEM * last_item, LOG_LSA * commit_lsa)
3332 {
3333  LA_ITEM *item, *next_item;
3334 
3335  assert (apply);
3336  assert (!LSA_ISNULL (commit_lsa));
3337 
3338  if (apply->is_long_trans)
3339  {
3340  if (apply->head == NULL && last_item != NULL)
3341  {
3342  la_add_repl_item (apply, last_item);
3343  }
3344  }
3345  else
3346  {
3347  for (item = apply->head; (item != NULL) && (LSA_LT (&item->lsa, commit_lsa)); item = next_item)
3348  {
3349  next_item = item->next;
3350 
3351  la_free_repl_item (apply, item);
3352  item = NULL;
3353  }
3354 
3355  apply->head = item;
3356  }
3357 
3358  return;
3359 }
3360 
3361 static void
3363 {
3364  assert (apply);
3365 
3367 
3368  if (apply->head)
3369  {
3370  la_free_repl_item (apply, apply->head);
3371  }
3372 
3373  apply->num_items = 0;
3374  apply->is_long_trans = false;
3375  apply->head = NULL;
3376  apply->tail = NULL;
3377 
3378  return;
3379 }
3380 
3381 static void
3383 {
3384  assert (apply);
3385 
3386  la_free_all_repl_items (apply);
3387 
3388  LSA_SET_NULL (&apply->start_lsa);
3389  LSA_SET_NULL (&apply->last_lsa);
3390  apply->tranid = 0;
3391 
3392  return;
3393 }
3394 
3395 static void
3397 {
3398  int i;
3399 
3400  for (i = 0; i < la_Info.cur_repl; i++)
3401  {
3403  }
3404 
3405  return;
3406 }
3407 
3408 /*
3409  * la_set_repl_log() - insert the replication item into the apply list
3410  * return: NO_ERROR or error code
3411  * log_pgptr : pointer to the log page
3412  * tranid: the target transaction id
3413  * lsa : the target LSA of the log
3414  *
3415  * Note:
3416  * APPLY thread traverses the transaction log pages, and finds out the
3417  * REPLICATION LOG record. If it meets the REPLICATION LOG record,
3418  * it adds that record to the apply list for later use.
3419  * When the APPLY thread meets the LOG COMMIT record, it applies the
3420  * inserted REPLICAION LOG records to the slave.
3421  */
3422 static int
3423 la_set_repl_log (LOG_PAGE * log_pgptr, int log_type, int tranid, LOG_LSA * lsa)
3424 {
3425  LA_APPLY *apply;
3426  LA_ITEM *item = NULL;
3427 
3428  apply = la_find_apply_list (tranid);
3429  if (apply == NULL)
3430  {
3431  er_log_debug (ARG_FILE_LINE, "fail to find out %d transaction in apply list", tranid);
3432  return NO_ERROR;
3433  }
3434 
3435  if (apply->is_long_trans)
3436  {
3437  LSA_COPY (&apply->last_lsa, lsa);
3438  return NO_ERROR;
3439  }
3440 
3441  if (apply->num_items >= LA_MAX_REPL_ITEMS)
3442  {
3444  apply->is_long_trans = true;
3445  LSA_COPY (&apply->last_lsa, lsa);
3446  return NO_ERROR;
3447  }
3448 
3449  item = la_make_repl_item (log_pgptr, log_type, tranid, lsa);
3450  if (item == NULL)
3451  {
3452  return ER_OUT_OF_VIRTUAL_MEMORY;
3453  }
3454 
3455  la_add_repl_item (apply, item);
3456 
3457  return NO_ERROR;
3458 }
3459 
3460 /*
3461  * la_add_node_into_la_commit_list() - add a LA_COMMIT node into the commit list
3462  * return: NO_ERROR or error code
3463  * tranid: the target transaction id
3464  * lsa : the target LSA of the log
3465  * type : the type of the log
3466  * eot_time : timestamp of EOT
3467  *
3468  * Note:
3469  * APPLY thread traverses the transaction log pages, and finds out the
3470  * REPLICATION LOG record. If it meets the REPLICATION LOG record,
3471  * it adds that record to the apply list for later use.
3472  * When the APPLY thread meets the LOG_COMMIT record, it applies the
3473  * inserted REPLICAION LOG records into the slave.
3474  * The APPLY thread applies transaction with the order of LOG_COMMIT record.
3475  */
3476 static int
3477 la_add_node_into_la_commit_list (int tranid, LOG_LSA * lsa, int type, time_t eot_time)
3478 {
3479  LA_COMMIT *commit;
3480  int error = NO_ERROR;
3481 
3482  commit = (LA_COMMIT *) malloc (DB_SIZEOF (LA_COMMIT));
3483  if (commit == NULL)
3484  {
3486  return ER_OUT_OF_VIRTUAL_MEMORY;
3487  }
3488 
3489  commit->prev = NULL;
3490  commit->next = NULL;
3491  commit->type = type;
3492  commit->log_record_time = eot_time;
3493  LSA_COPY (&commit->log_lsa, lsa);
3494  commit->tranid = tranid;
3495 
3496  if (la_Info.commit_head == NULL && la_Info.commit_tail == NULL)
3497  {
3498  la_Info.commit_head = commit;
3499  la_Info.commit_tail = commit;
3500  }
3501  else
3502  {
3503  commit->prev = la_Info.commit_tail;
3504  la_Info.commit_tail->next = commit;
3505  la_Info.commit_tail = commit;
3506  }
3507 
3508  return error;
3509 }
3510 
3511 /*
3512  * la_retrieve_eot_time() - Retrieve the timestamp of End of Transaction
3513  * return: NO_ERROR or error code
3514  * log_pgptr : pointer to the log page
3515  *
3516  * Note:
3517  */
3518 static time_t
3520 {
3521  int error = NO_ERROR;
3522  LOG_REC_DONETIME *donetime;
3524  PGLENGTH offset;
3525  LOG_PAGE *pg;
3526 
3527  pageid = lsa->pageid;
3528  offset = DB_SIZEOF (LOG_RECORD_HEADER) + lsa->offset;
3529 
3530  pg = pgptr;
3531 
3532  LA_LOG_READ_ALIGN (error, offset, pageid, pg);
3533  if (error != NO_ERROR)
3534  {
3535  /* cannot get eot time */
3536  return 0;
3537  }
3538 
3539  LA_LOG_READ_ADVANCE_WHEN_DOESNT_FIT (error, SSIZEOF (*donetime), offset, pageid, pg);
3540  if (error != NO_ERROR)
3541  {
3542  /* cannot get eot time */
3543  return 0;
3544  }
3545  donetime = (LOG_REC_DONETIME *) ((char *) pg->area + offset);
3546 
3547  return donetime->at_time;
3548 }
3549 
3550 /*
3551  * la_get_current()
3552  * return: NO_ERROR or error code
3553  *
3554  * Note:
3555  * Analyze the record description, get the value for each attribute,
3556  * call dbt_put_internal() for update...
3557  */
3558 static int
3559 la_get_current (OR_BUF * buf, SM_CLASS * sm_class, int bound_bit_flag, DB_OTMPL * def, DB_VALUE * key, int offset_size)
3560 {
3561  SM_ATTRIBUTE *att;
3562  int *vars = NULL;
3563  int i, j, offset, offset2, pad;
3564  char *bits, *start, *v_start;
3565  int rc = NO_ERROR;
3566  DB_VALUE value;
3567  int error = NO_ERROR;
3568 
3569  if (sm_class->variable_count)
3570  {
3571  vars = (int *) malloc (DB_SIZEOF (int) * sm_class->variable_count);
3572  if (vars == NULL)
3573  {
3575  DB_SIZEOF (int) * sm_class->variable_count);
3576  return ER_OUT_OF_VIRTUAL_MEMORY;
3577  }
3578  offset = or_get_offset_internal (buf, &rc, offset_size);
3579  for (i = 0; i < sm_class->variable_count; i++)
3580  {
3581  offset2 = or_get_offset_internal (buf, &rc, offset_size);
3582  vars[i] = offset2 - offset;
3583  offset = offset2;
3584  }
3585  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
3586  }
3587 
3588  bits = NULL;
3589  if (bound_bit_flag)
3590  {
3591  /* assume that the buffer is in contiguous memory and that we can seek ahead to the bound bits. */
3592  bits = (char *) buf->ptr + sm_class->fixed_size;
3593  }
3594 
3595  att = sm_class->attributes;
3596  start = buf->ptr;
3597 
3598  /* process the fixed length column */
3599  for (i = 0; i < sm_class->fixed_count; i++, att = (SM_ATTRIBUTE *) att->header.next)
3600  {
3601  if (bits != NULL && !OR_GET_BOUND_BIT (bits, i))
3602  {
3603  /* its a NULL value, skip it */
3604  db_make_null (&value);
3605  or_advance (buf, tp_domain_disk_size (att->domain));
3606  }
3607  else
3608  {
3609  /* read the disk value into the db_value */
3610  att->type->data_readval (buf, &value, att->domain, -1, true, NULL, 0);
3611  }
3612 
3613  /* update the column */
3614  error = dbt_put_internal (def, att->header.name, &value);
3615  pr_clear_value (&value);
3616  if (error != NO_ERROR)
3617  {
3618  if (vars != NULL)
3619  {
3620  free_and_init (vars);
3621  }
3622  return error;
3623  }
3624  }
3625 
3626  /* round up to a to the end of the fixed block */
3627  pad = (int) (buf->ptr - start);
3628  if (pad < sm_class->fixed_size)
3629  {
3630  or_advance (buf, sm_class->fixed_size - pad);
3631  }
3632 
3633  /* skip over the bound bits */
3634  if (bound_bit_flag)
3635  {
3636  or_advance (buf, OR_BOUND_BIT_BYTES (sm_class->fixed_count));
3637  }
3638 
3639  /* process variable length column */
3640  v_start = buf->ptr;
3641  for (i = sm_class->fixed_count, j = 0; i < sm_class->att_count && j < sm_class->variable_count;
3642  i++, j++, att = (SM_ATTRIBUTE *) att->header.next)
3643  {
3644  att->type->data_readval (buf, &value, att->domain, vars[j], true, NULL, 0);
3645  v_start += vars[j];
3646  buf->ptr = v_start;
3647 
3648  /* update the column */
3649  error = dbt_put_internal (def, att->header.name, &value);
3650  pr_clear_value (&value);
3651  if (error != NO_ERROR)
3652  {
3653  free_and_init (vars);
3654  return error;
3655  }
3656  }
3657 
3658  if (vars != NULL)
3659  {
3660  free_and_init (vars);
3661  }
3662 
3663  return error;
3664 }
3665 
3666 /*
3667  * la_make_room_for_mvcc_insid() - preserve space for mvcc insert id
3668  * see heap_mvcc_log_insert
3669  * return:
3670  *
3671  */
3672 static void
3674 {
3675  int repid_and_flag_bits = 0;
3676  char mvcc_flag;
3677 
3678  assert (recdes->type != REC_BIGONE);
3679 
3680  repid_and_flag_bits = OR_GET_MVCC_REPID_AND_FLAG (recdes->data);
3681  mvcc_flag = (char) ((repid_and_flag_bits >> OR_MVCC_FLAG_SHIFT_BITS) & OR_MVCC_FLAG_MASK);
3682 
3683  assert (mvcc_flag != 0);
3684  assert (!(mvcc_flag & OR_MVCC_FLAG_VALID_DELID));
3685 
3686  assert (recdes->area_size >= recdes->length + OR_MVCCID_SIZE);
3687 
3689 
3690  return;
3691 }
3692 
3693 /*
3694  * la_disk_to_obj() - same function with tf_disk_to_obj, but always use
3695  * the current representation.
3696  * return: NO_ERROR or error code
3697  *
3698  * Note:
3699  * Analyze the record description, get the value for each attribute,
3700  * call dbt_put_internal() for update...
3701  */
3702 static int
3703 la_disk_to_obj (MOBJ classobj, RECDES * record, DB_OTMPL * def, DB_VALUE * key)
3704 {
3705  OR_BUF orep, *buf;
3706  int status;
3707  SM_CLASS *sm_class;
3708  unsigned int repid_bits;
3709  int bound_bit_flag;
3710  int rc = NO_ERROR;
3711  int error = NO_ERROR;
3712  int offset_size;
3713  char mvcc_flags;
3714 
3715  /* Kludge, make sure we don't upgrade objects to OID'd during the reading */
3716  buf = &orep;
3717  or_init (buf, record->data, record->length);
3718  buf->error_abort = 1;
3719 
3720  status = setjmp (buf->env);
3721  if (status == 0)
3722  {
3723  sm_class = (SM_CLASS *) classobj;
3724 
3725  /* offset size */
3726  offset_size = OR_GET_OFFSET_SIZE (buf->ptr);
3727 
3728  /* in case of MVCC, repid_bits contains MVCC flags */
3729  repid_bits = or_mvcc_get_repid_and_flags (buf, &rc);
3730 
3731  mvcc_flags = (char) ((repid_bits >> OR_MVCC_FLAG_SHIFT_BITS) & OR_MVCC_FLAG_MASK);
3732  if (mvcc_flags == 0)
3733  {
3734  /* non mvcc header */
3735  /* skip chn */
3736  (void) or_advance (buf, OR_INT_SIZE);
3737  }
3738  else
3739  {
3740  if (mvcc_flags & OR_MVCC_FLAG_VALID_INSID)
3741  {
3742  /* skip insert id */
3743  (void) or_advance (buf, OR_MVCCID_SIZE);
3744  }
3745 
3746  if (mvcc_flags & OR_MVCC_FLAG_VALID_DELID)
3747  {
3748  /* skip delete id */
3749  (void) or_advance (buf, OR_MVCCID_SIZE);
3750  }
3751 
3752  /* skip chn */
3753  (void) or_advance (buf, OR_INT_SIZE);
3754 
3755  if (mvcc_flags & OR_MVCC_FLAG_VALID_PREV_VERSION)
3756  {
3757  /* skip prev version lsa */
3758  (void) or_advance (buf, sizeof (LOG_LSA));
3759  }
3760  }
3761 
3762  bound_bit_flag = repid_bits & OR_BOUND_BIT_FLAG;
3763 
3764  error = la_get_current (buf, sm_class, bound_bit_flag, def, key, offset_size);
3765  }
3766  else
3767  {
3769  error = ER_GENERIC_ERROR;
3770  }
3771 
3772  return error;
3773 }
3774 
3775 /*
3776  * la_get_zipped_data () - get zipped data
3777  * return: error code
3778  */
3779 char *
3780 la_get_zipped_data (char *undo_data, int undo_length, bool is_diff, bool is_undo_zip, bool is_overflow, char **rec_type,
3781  char **data, int *length)
3782 {
3783  int redo_length = 0;
3784  int rec_len = 0;
3785 
3786  LOG_ZIP *undo_unzip_data = NULL;
3787  LOG_ZIP *redo_unzip_data = NULL;
3788 
3789  undo_unzip_data = la_Info.undo_unzip_ptr;
3790  redo_unzip_data = la_Info.redo_unzip_ptr;
3791 
3792  if (is_diff)
3793  {
3794  if (is_undo_zip)
3795  {
3796  undo_length = undo_unzip_data->data_length;
3797  redo_length = redo_unzip_data->data_length;
3798 
3799  (void) log_diff (undo_length, undo_unzip_data->log_data, redo_length, redo_unzip_data->log_data);
3800  }
3801  else
3802  {
3803 
3804  redo_length = redo_unzip_data->data_length;
3805  (void) log_diff (undo_length, undo_data, redo_length, redo_unzip_data->log_data);
3806  }
3807  }
3808  else
3809  {
3810  redo_length = redo_unzip_data->data_length;
3811  }
3812 
3813  if (rec_type)
3814  {
3815  rec_len = DB_SIZEOF (INT16);
3816  *length = redo_length - rec_len;
3817  }
3818  else
3819  {
3820  *length = redo_length;
3821  }
3822 
3823  if (is_overflow)
3824  {
3825  if (*data)
3826  {
3827  free_and_init (*data);
3828  }
3829  *data = (char *) malloc (*length);
3830  if (*data == NULL)
3831  {
3833  *length = 0;
3834  return NULL;
3835  }
3836  }
3837 
3838  if (rec_type)
3839  {
3840  memcpy (*rec_type, (la_Info.redo_unzip_ptr)->log_data, rec_len);
3841  memcpy (*data, (la_Info.redo_unzip_ptr)->log_data + rec_len, *length);
3842  }
3843  else
3844  {
3845  memcpy (*data, (la_Info.redo_unzip_ptr)->log_data, redo_length);
3846  }
3847 
3848  return *data;
3849 }
3850 
3851 
3852 /*
3853  * la_get_undoredo_diff() - get undo/redo diff data
3854  * return: next log page pointer
3855  */
3856 int
3857 la_get_undoredo_diff (LOG_PAGE ** pgptr, LOG_PAGEID * pageid, PGLENGTH * offset, bool * is_undo_zip, char **undo_data,
3858  int *undo_length)
3859 {
3860  int error = NO_ERROR;
3861 
3862  LOG_ZIP *undo_unzip_data = NULL;
3863 
3864  LOG_PAGE *temp_pg;
3865  LOG_PAGEID temp_pageid;
3866  PGLENGTH temp_offset;
3867 
3868  undo_unzip_data = la_Info.undo_unzip_ptr;
3869 
3870  temp_pg = *pgptr;
3871  temp_pageid = *pageid;
3872  temp_offset = *offset;
3873 
3874  if (ZIP_CHECK (*undo_length))
3875  { /* Undo data is Zip Check */
3876  *is_undo_zip = true;
3877  *undo_length = GET_ZIP_LEN (*undo_length);
3878  }
3879 
3880  *undo_data = (char *) malloc (*undo_length);
3881  if (*undo_data == NULL)
3882  {
3884  return ER_OUT_OF_VIRTUAL_MEMORY;
3885  }
3886 
3887  /* get undo data for XOR process */
3888  la_log_copy_fromlog (NULL, *undo_data, *undo_length, *pageid, *offset, *pgptr);
3889 
3890  if (*is_undo_zip && *undo_length > 0)
3891  {
3892  if (!log_unzip (undo_unzip_data, *undo_length, *undo_data))
3893  {
3894  free_and_init (*undo_data);
3895 
3898  }
3899  }
3900 
3901  LA_LOG_READ_ADD_ALIGN (error, *undo_length, temp_offset, temp_pageid, temp_pg);
3902 
3903  *pgptr = temp_pg;
3904  *pageid = temp_pageid;
3905  *offset = temp_offset;
3906  return error;
3907 }
3908 
3909 /*
3910  * la_get_log_data() - get the data area of log record
3911  * return: error code
3912  * lrec (in) : target log record
3913  * lsa (in) : the LSA of the target log record
3914  * pgptr (in) : the start log page pointer
3915  * match_rcvindex (in) : index
3916  * rcvindex : recovery index to be returned
3917  * logs : the specialized log info
3918  * rec_type : the type of RECDES
3919  * data : the log data
3920  * d_length : the length of data
3921  *
3922  * Note: get the data area, and rcvindex, length of data for the
3923  * given log record
3924  */
3925 static int
3926 la_get_log_data (LOG_RECORD_HEADER * lrec, LOG_LSA * lsa, LOG_PAGE * pgptr, unsigned int match_rcvindex,
3927  unsigned int *rcvindex, void **logs, char **rec_type, char **data, int *d_length)
3928 {
3929  LOG_PAGE *pg;
3930  PGLENGTH offset;
3931  int length; /* type change PGLENGTH -> int */
3932  int log_size;
3934  int error = NO_ERROR;
3935 
3936  LOG_REC_UNDOREDO *undoredo;
3937  LOG_REC_UNDO *undo;
3938  LOG_REC_REDO *redo;
3939 
3940  LOG_REC_MVCC_UNDOREDO *mvcc_undoredo = NULL;
3941  LOG_REC_MVCC_UNDO *mvcc_undo = NULL;
3942  LOG_REC_MVCC_REDO *mvcc_redo = NULL;
3943 
3944  bool is_undo_zip = false;
3945  int zip_len = 0;
3946  int undo_length = 0;
3947  int temp_length = 0;
3948  char *undo_data = NULL;
3949 
3950  bool is_overflow = false;
3951  bool is_diff = false;
3952  bool is_mvcc_log = false;
3953 
3954  pg = pgptr;
3955 
3956  offset = DB_SIZEOF (LOG_RECORD_HEADER) + lsa->offset;
3957  pageid = lsa->pageid;
3958 
3959  LA_LOG_READ_ALIGN (error, offset, pageid, pg);
3960  if (error != NO_ERROR)
3961  {
3962  return error;
3963  }
3964 
3965  if (LOG_IS_MVCC_OP_RECORD_TYPE (lrec->type) == true)
3966  {
3967  is_mvcc_log = true;
3968  }
3969 
3970  switch (lrec->type)
3971  {
3972  case LOG_UNDOREDO_DATA:
3976  if (LOG_IS_DIFF_UNDOREDO_TYPE (lrec->type) == true)
3977  {
3978  is_diff = true;
3979  }
3980 
3981  if (is_mvcc_log == true)
3982  {
3983  log_size = DB_SIZEOF (LOG_REC_MVCC_UNDOREDO);
3984  }
3985  else
3986  {
3987  log_size = DB_SIZEOF (LOG_REC_UNDOREDO);
3988  }
3989 
3990  LA_LOG_READ_ADVANCE_WHEN_DOESNT_FIT (error, log_size, offset, pageid, pg);
3991 
3992  if (error == NO_ERROR)
3993  {
3994  if (is_mvcc_log == true)
3995  {
3996  mvcc_undoredo = (LOG_REC_MVCC_UNDOREDO *) ((char *) pg->area + offset);
3997  undoredo = &mvcc_undoredo->undoredo;
3998  }
3999  else
4000  {
4001  undoredo = (LOG_REC_UNDOREDO *) ((char *) pg->area + offset);
4002  }
4003 
4004  undo_length = undoredo->ulength; /* undo log length */
4005  temp_length = undoredo->rlength; /* for the replication, we just need the redo data */
4006  length = GET_ZIP_LEN (undoredo->rlength);
4007 
4008  if (match_rcvindex == 0 || undoredo->data.rcvindex == match_rcvindex)
4009  {
4010  if (rcvindex)
4011  {
4012  *rcvindex = undoredo->data.rcvindex;
4013  }
4014  if (logs)
4015  {
4016  *logs = (void *) undoredo;
4017  }
4018  }
4019  else if (logs)
4020  {
4021  *logs = (void *) NULL;
4022  }
4023 
4024  LA_LOG_READ_ADD_ALIGN (error, log_size, offset, pageid, pg);
4025  if (error == NO_ERROR)
4026  {
4027  if (is_diff)
4028  { /* XOR Redo Data */
4029  error = la_get_undoredo_diff (&pg, &pageid, &offset, &is_undo_zip, &undo_data, &undo_length);
4030  if (error != NO_ERROR)
4031  {
4032  if (undo_data != NULL)
4033  {
4034  free_and_init (undo_data);
4035  }
4036  return error;
4037  }
4038  }
4039  else
4040  {
4041  LA_LOG_READ_ADD_ALIGN (error, GET_ZIP_LEN (undo_length), offset, pageid, pg);
4042  }
4043  }
4044  }
4045 
4046  break;
4047 
4048  case LOG_UNDO_DATA:
4049  case LOG_MVCC_UNDO_DATA:
4050  if (is_mvcc_log == true)
4051  {
4052  log_size = DB_SIZEOF (LOG_REC_MVCC_UNDO);
4053  }
4054  else
4055  {
4056  log_size = DB_SIZEOF (LOG_REC_UNDO);
4057  }
4058 
4059  LA_LOG_READ_ADVANCE_WHEN_DOESNT_FIT (error, log_size, offset, pageid, pg);
4060  if (error == NO_ERROR)
4061  {
4062  if (is_mvcc_log == true)
4063  {
4064  mvcc_undo = (LOG_REC_MVCC_UNDO *) ((char *) pg->area + offset);
4065  undo = &mvcc_undo->undo;
4066  }
4067  else
4068  {
4069  undo = (LOG_REC_UNDO *) ((char *) pg->area + offset);
4070  }
4071 
4072  temp_length = undo->length;
4073  length = (int) GET_ZIP_LEN (undo->length);
4074 
4075  if (match_rcvindex == 0 || undo->data.rcvindex == match_rcvindex)
4076  {
4077  if (logs)
4078  {
4079  *logs = (void *) undo;
4080  }
4081  if (rcvindex)
4082  {
4083  *rcvindex = undo->data.rcvindex;
4084  }
4085  }
4086  else if (logs)
4087  {
4088  *logs = (void *) NULL;
4089  }
4090  LA_LOG_READ_ADD_ALIGN (error, log_size, offset, pageid, pg);
4091  }
4092  break;
4093 
4094  case LOG_REDO_DATA:
4095  case LOG_MVCC_REDO_DATA:
4096  if (is_mvcc_log == true)
4097  {
4098  log_size = DB_SIZEOF (LOG_REC_MVCC_REDO);
4099  }
4100  else
4101  {
4102  log_size = DB_SIZEOF (LOG_REC_REDO);
4103  }
4104 
4105  LA_LOG_READ_ADVANCE_WHEN_DOESNT_FIT (error, log_size, offset, pageid, pg);
4106  if (error == NO_ERROR)
4107  {
4108  if (is_mvcc_log == true)
4109  {
4110  mvcc_redo = (LOG_REC_MVCC_REDO *) ((char *) pg->area + offset);
4111  redo = &mvcc_redo->redo;
4112  }
4113  else
4114  {
4115  redo = (LOG_REC_REDO *) ((char *) pg->area + offset);
4116  }
4117 
4118  temp_length = redo->length;
4119  length = GET_ZIP_LEN (redo->length);
4120 
4121  if (match_rcvindex == 0 || redo->data.rcvindex == match_rcvindex)
4122  {
4123  if (logs)
4124  {
4125  *logs = (void *) redo;
4126  }
4127  if (rcvindex)
4128  {
4129  *rcvindex = redo->data.rcvindex;
4130  }
4131  }
4132  else if (logs)
4133  {
4134  *logs = (void *) NULL;
4135  }
4136  LA_LOG_READ_ADD_ALIGN (error, log_size, offset, pageid, pg);
4137  }
4138  break;
4139 
4140  default:
4141  if (logs)
4142  {
4143  *logs = NULL;
4144  }
4145 
4146  return error;
4147  }
4148 
4149  if (error != NO_ERROR)
4150  {
4151  if (undo_data != NULL)
4152  {
4153  free_and_init (undo_data);
4154  }
4155 
4156  return error;
4157  }
4158 
4159  if (*data == NULL)
4160  {
4161  /* general cases, use the pre-allocated buffer */
4162  *data = (char *) malloc (length);
4163  is_overflow = true;
4164 
4165  if (*data == NULL)
4166  {
4167  *d_length = 0;
4168  if (undo_data != NULL)
4169  {
4170  free_and_init (undo_data);
4171  }
4172 
4174  return ER_OUT_OF_VIRTUAL_MEMORY;
4175  }
4176  }
4177 
4178  if (ZIP_CHECK (temp_length))
4179  {
4180  zip_len = GET_ZIP_LEN (temp_length);
4181  /* Get Zip Data */
4182  la_log_copy_fromlog (NULL, *data, zip_len, pageid, offset, pg);
4183 
4184  if (zip_len != 0)
4185  {
4186  if (!log_unzip (la_Info.redo_unzip_ptr, zip_len, *data))
4187  {
4188  if (undo_data != NULL)
4189  {
4190  free_and_init (undo_data);
4191  }
4194  }
4195  }
4196 
4197  *data = la_get_zipped_data (undo_data, undo_length, is_diff, is_undo_zip, is_overflow, rec_type, data, &length);
4198  if (*data == NULL)
4199  {
4200  assert (er_errid () != NO_ERROR);
4201  error = er_errid ();
4202  }
4203  }
4204  else
4205  {
4206  /* Get Redo Data */
4207  la_log_copy_fromlog (rec_type ? *rec_type : NULL, *data, length, pageid, offset, pg);
4208  }
4209 
4210  *d_length = length;
4211 
4212  if (undo_data != NULL)
4213  {
4214  free_and_init (undo_data);
4215  }
4216 
4217  return error;
4218 }
4219 
4220 /*
4221  * la_get_overflow_update_recdes() - prepare the overflow page update
4222  * return: NO_ERROR or error code
4223  *
4224  */
4225 static int
4226 la_get_overflow_recdes (LOG_RECORD_HEADER * log_record, void *logs, RECDES * recdes, unsigned int rcvindex)
4227 {
4228  LOG_LSA current_lsa;
4229  LOG_PAGE *current_log_page;
4230  LOG_RECORD_HEADER *current_log_record;
4231  LA_OVF_PAGE_LIST *ovf_list_head = NULL;
4232  LA_OVF_PAGE_LIST *ovf_list_tail = NULL;
4233  LA_OVF_PAGE_LIST *ovf_list_data = NULL;
4234  void *log_info;
4235  VPID prev_vpid;
4236  bool first = true;
4237  int copyed_len;
4238  int area_len;
4239  int area_offset;
4240  int error = NO_ERROR;
4241  int length = 0;
4242 
4243  LSA_COPY (&current_lsa, &log_record->prev_tranlsa);
4244  prev_vpid.pageid = ((LOG_REC_UNDOREDO *) logs)->data.pageid;
4245  prev_vpid.volid = ((LOG_REC_UNDOREDO *) logs)->data.volid;
4246 
4247  while (!LSA_ISNULL (&current_lsa))
4248  {
4249  current_log_page = la_get_page (current_lsa.pageid);
4250  current_log_record = LOG_GET_LOG_RECORD_HEADER (current_log_page, &current_lsa);
4251 
4252  if (current_log_record->trid != log_record->trid || current_log_record->type == LOG_DUMMY_OVF_RECORD)
4253  {
4254  la_release_page_buffer (current_lsa.pageid);
4255  break;
4256  }
4257  else if (LOG_IS_REDO_RECORD_TYPE (current_log_record->type) == true)
4258  {
4259  /* process only LOG_REDO_DATA */
4260 
4261  ovf_list_data = (LA_OVF_PAGE_LIST *) malloc (DB_SIZEOF (LA_OVF_PAGE_LIST));
4262  if (ovf_list_data == NULL)
4263  {
4264  /* malloc failed */
4265  while (ovf_list_head)
4266  {
4267  ovf_list_data = ovf_list_head;
4268  ovf_list_head = ovf_list_head->next;
4269  free_and_init (ovf_list_data->data);
4270  free_and_init (ovf_list_data);
4271  }
4272 
4273  la_release_page_buffer (current_lsa.pageid);
4274 
4276  return ER_OUT_OF_VIRTUAL_MEMORY;
4277  }
4278 
4279  memset (ovf_list_data, 0, DB_SIZEOF (LA_OVF_PAGE_LIST));
4280  error =
4281  la_get_log_data (current_log_record, &current_lsa, current_log_page, rcvindex, NULL, &log_info, NULL,
4282  &ovf_list_data->data, &ovf_list_data->length);
4283 
4284  if (error == NO_ERROR && log_info && ovf_list_data->data)
4285  {
4286  /* add to linked-list */
4287  if (ovf_list_head == NULL)
4288  {
4289  ovf_list_head = ovf_list_tail = ovf_list_data;
4290  }
4291  else
4292  {
4293  ovf_list_data->next = ovf_list_head;
4294  ovf_list_head = ovf_list_data;
4295  }
4296 
4297  length += ovf_list_data->length;
4298  }
4299  else
4300  {
4301  if (ovf_list_data->data != NULL)
4302  {
4303  free_and_init (ovf_list_data->data);
4304  }
4305  free_and_init (ovf_list_data);
4306  }
4307  }
4308  la_release_page_buffer (current_lsa.pageid);
4309  LSA_COPY (&current_lsa, &current_log_record->prev_tranlsa);
4310  }
4311 
4312  assert (recdes != NULL);
4313 
4314  error = la_realloc_recdes_data (recdes, length);
4315  if (error != NO_ERROR)
4316  {
4317  /* malloc failed: clear linked-list */
4318  while (ovf_list_head)
4319  {
4320  ovf_list_data = ovf_list_head;
4321  ovf_list_head = ovf_list_head->next;
4322  free_and_init (ovf_list_data->data);
4323  free_and_init (ovf_list_data);
4324  }
4325 
4326  return error;
4327  }
4328 
4329  /* make record description */
4330  copyed_len = 0;
4331  while (ovf_list_head)
4332  {
4333  ovf_list_data = ovf_list_head;
4334  ovf_list_head = ovf_list_head->next;
4335 
4336  if (first)
4337  {
4338  area_offset = offsetof (LA_OVF_FIRST_PART, data);
4339  first = false;
4340  }
4341  else
4342  {
4343  area_offset = offsetof (LA_OVF_REST_PARTS, data);
4344  }
4345  area_len = ovf_list_data->length - area_offset;
4346  memcpy (recdes->data + copyed_len, ovf_list_data->data + area_offset, area_len);
4347  copyed_len += area_len;
4348 
4349  free_and_init (ovf_list_data->data);
4350  free_and_init (ovf_list_data);
4351  }
4352 
4353  recdes->length = length;
4354 
4355  return error;
4356 }
4357 
4358 /*
4359  * la_get_next_update_log() - get the right update log
4360  * return: NO_ERROR or error code
4361  * prev_lrec(in): prev log record
4362  * pgptr(in): the start log page pointer
4363  * logs(out) : the specialized log info
4364  * rec_type(out) : the type of RECDES
4365  * data(out) : the log data
4366  * d_length(out): the length of data
4367  *
4368  * Note:
4369  * When the applier meets the REC_ASSIGN_ADDRESS or REC_RELOCATION
4370  * record, it should fetch the real UPDATE log record to be processed.
4371  */
4372 static int
4373 la_get_next_update_log (LOG_RECORD_HEADER * prev_lrec, LOG_PAGE * pgptr, void **logs, char **rec_type, char **data,
4374  int *d_length)
4375 {
4376  LOG_PAGE *pg;
4377  LOG_LSA lsa;
4378  PGLENGTH offset;
4379  int length; /* type change PGLENGTH -> int */
4380  int log_size;
4382  int error = NO_ERROR;
4383  LOG_RECORD_HEADER *lrec;
4384  LOG_REC_UNDOREDO *undoredo;
4385  LOG_REC_UNDOREDO *prev_log;
4386  LOG_REC_MVCC_UNDOREDO *mvcc_undoredo = NULL;
4387  int zip_len = 0;
4388  int temp_length = 0;
4389  int undo_length = 0;
4390 
4391  bool is_undo_zip = false;
4392  bool is_mvcc_log = false;
4393 
4394  char *undo_data = NULL;
4395  LOG_ZIP *redo_unzip_data = NULL;
4396 
4397  bool is_diff = false;
4398 
4399  pg = pgptr;
4400  LSA_COPY (&lsa, &prev_lrec->forw_lsa);
4401  prev_log = *(LOG_REC_UNDOREDO **) logs;
4402 
4403  redo_unzip_data = la_Info.redo_unzip_ptr;
4404 
4405  while (true)
4406  {
4407  while (pg && pg->hdr.logical_pageid == lsa.pageid)
4408  {
4409  lrec = LOG_GET_LOG_RECORD_HEADER (pg, &lsa);
4410  if (lrec->trid == prev_lrec->trid && LOG_IS_UNDOREDO_RECORD_TYPE (lrec->type))
4411  {
4412  if (LOG_IS_DIFF_UNDOREDO_TYPE (lrec->type) == true)
4413  {
4414  is_diff = true;
4415  }
4416  else
4417  {
4418  is_diff = false;
4419  }
4420 
4421  if (LOG_IS_MVCC_OP_RECORD_TYPE (lrec->type) == true)
4422  {
4423  is_mvcc_log = true;
4424  log_size = DB_SIZEOF (LOG_REC_MVCC_UNDOREDO);
4425  }
4426  else
4427  {
4428  is_mvcc_log = false;
4429  log_size = DB_SIZEOF (LOG_REC_UNDOREDO);
4430  }
4431 
4432  offset = DB_SIZEOF (LOG_RECORD_HEADER) + lsa.offset;
4433  pageid = lsa.pageid;
4434  LA_LOG_READ_ALIGN (error, offset, pageid, pg);
4435  LA_LOG_READ_ADVANCE_WHEN_DOESNT_FIT (error, log_size, offset, pageid, pg);
4436  if (error == NO_ERROR)
4437  {
4438  if (is_mvcc_log == true)
4439  {
4440  mvcc_undoredo = (LOG_REC_MVCC_UNDOREDO *) ((char *) pg->area + offset);
4441  undoredo = &mvcc_undoredo->undoredo;
4442  }
4443  else
4444  {
4445  undoredo = (LOG_REC_UNDOREDO *) ((char *) pg->area + offset);
4446  }
4447 
4448  undo_length = undoredo->ulength;
4449  temp_length = undoredo->rlength;
4450  length = GET_ZIP_LEN (undoredo->rlength);
4451 
4452  if ((undoredo->data.rcvindex == RVHF_UPDATE || undoredo->data.rcvindex == RVHF_UPDATE_NOTIFY_VACUUM)
4453  && undoredo->data.pageid == prev_log->data.pageid
4454  && undoredo->data.offset == prev_log->data.offset && undoredo->data.volid == prev_log->data.volid)
4455  {
4456  LA_LOG_READ_ADD_ALIGN (error, log_size, offset, pageid, pg);
4457  if (is_diff)
4458  {
4459  error = la_get_undoredo_diff (&pg, &pageid, &offset, &is_undo_zip, &undo_data, &undo_length);
4460  if (error != NO_ERROR)
4461  {
4462 
4463  if (undo_data != NULL)
4464  {
4465  free_and_init (undo_data);
4466  }
4467  return error;
4468  }
4469  }
4470  else
4471  {
4472  LA_LOG_READ_ADD_ALIGN (error, GET_ZIP_LEN (undo_length), offset, pageid, pg);
4473  }
4474 
4475  if (ZIP_CHECK (temp_length))
4476  {
4477  zip_len = GET_ZIP_LEN (temp_length);
4478  la_log_copy_fromlog (NULL, *data, zip_len, pageid, offset, pg);
4479 
4480  if (zip_len != 0)
4481  {
4482  if (!log_unzip (redo_unzip_data, zip_len, *data))
4483  {
4484  if (undo_data != NULL)
4485  {
4486  free_and_init (undo_data);
4487  }
4490  }
4491  }
4492 
4493  *data =
4494  la_get_zipped_data (undo_data, undo_length, is_diff, is_undo_zip, false, rec_type, data,
4495  &length);
4496  if (*data == NULL)
4497  {
4498  assert (er_errid () != NO_ERROR);
4499  error = er_errid ();
4500  }
4501  }
4502  else
4503  {
4504  la_log_copy_fromlog (rec_type ? *rec_type : NULL, *data, length, pageid, offset, pg);
4505  }
4506 
4507  *d_length = length;
4508 
4509  if (undo_data != NULL)
4510  {
4511  free_and_init (undo_data);
4512  }
4513 
4514  return error;
4515  }
4516  }
4517  }
4518  else if (lrec->trid == prev_lrec->trid && (lrec->type == LOG_COMMIT || lrec->type == LOG_ABORT))
4519  {
4520  return ER_GENERIC_ERROR;
4521  }
4522  LSA_COPY (&lsa, &lrec->forw_lsa);
4523  }
4524 
4525  pg = la_get_page (lsa.pageid);
4526  }
4527 
4528  return error;
4529 }
4530 
4531 static int
4532 la_get_relocation_recdes (LOG_RECORD_HEADER * lrec, LOG_PAGE * pgptr, unsigned int match_rcvindex, void **logs,
4533  char **rec_type, RECDES * recdes)
4534 {
4535  LOG_RECORD_HEADER *tmp_lrec;
4536  unsigned int rcvindex;
4537  LOG_PAGE *pg = pgptr;
4538  LOG_LSA lsa;
4539  int error = NO_ERROR;
4540 
4541  LSA_COPY (&lsa, &lrec->prev_tranlsa);
4542  if (!LSA_ISNULL (&lsa))
4543  {
4544  pg = la_get_page (lsa.pageid);
4545  tmp_lrec = LOG_GET_LOG_RECORD_HEADER (pg, &lsa);
4546  if (tmp_lrec->trid != lrec->trid)
4547  {
4549  error = ER_LOG_PAGE_CORRUPTED;
4550  }
4551  else
4552  {
4553  error =
4554  la_get_log_data (tmp_lrec, &lsa, pg, RVHF_INSERT_NEWHOME, &rcvindex, logs, rec_type, &recdes->data,
4555  &recdes->length);
4556  }
4558  }
4559  else
4560  {
4562  error = ER_LOG_PAGE_CORRUPTED;
4563  }
4564 
4565  return error;
4566 }
4567 
4568 /*
4569  * la_get_recdes() - get the record description from the log file
4570  * return: NO_ERROR or error code
4571  * pgptr: point to the target log page
4572  * recdes(out): record description (output)
4573  * rcvindex(out): recovery index (output)
4574  * log_data: log data area
4575  * ovf_yn(out) : true if the log data is in overflow page
4576  *
4577  * Note:
4578  * To replicate the data, we have to filter the record descripion
4579  * from the log record. This function retrieves the record description
4580  * for the given lsa.
4581  */
4582 static int
4583 la_get_recdes (LOG_LSA * lsa, LOG_PAGE * pgptr, RECDES * recdes, unsigned int *rcvindex, char *rec_type)
4584 {
4585  LOG_RECORD_HEADER *lrec;
4586  LOG_PAGE *pg;
4587  int error = NO_ERROR;
4588  void *logs = NULL;
4589 
4590  pg = pgptr;
4591  lrec = LOG_GET_LOG_RECORD_HEADER (pg, lsa);
4592 
4593  error = la_get_log_data (lrec, lsa, pg, 0, rcvindex, &logs, &rec_type, &recdes->data, &recdes->length);
4594 
4595  if (error == NO_ERROR && logs != NULL)
4596  {
4597  recdes->type = *(INT16 *) (rec_type);
4598  }
4599  else
4600  {
4601  er_log_debug (ARG_FILE_LINE, "cannot get log record from LSA(%d|%d)", lsa->pageid, lsa->offset);
4602  if (error != NO_ERROR)
4603  {
4604  return error;
4605  }
4606  else
4607  {
4608  return ER_FAILED;
4609  }
4610  }
4611 
4612  /* Now.. we have to process overflow pages */
4613  if (*rcvindex == RVOVF_CHANGE_LINK)
4614  {
4615  /* if overflow page update */
4616  error = la_get_overflow_recdes (lrec, logs, recdes, RVOVF_PAGE_UPDATE);
4617  recdes->type = REC_BIGONE;
4618  }
4619  else if (recdes->type == REC_BIGONE)
4620  {
4621  /* if overflow page insert */
4622  error = la_get_overflow_recdes (lrec, logs, recdes, RVOVF_NEWPAGE_INSERT);
4623  }
4624  else if (*rcvindex == RVHF_INSERT && recdes->type == REC_ASSIGN_ADDRESS)
4625  {
4626  error = la_get_next_update_log (lrec, pg, &logs, &rec_type, &recdes->data, &recdes->length);
4627  if (error == NO_ERROR)
4628  {
4629  recdes->type = *(INT16 *) (rec_type);
4630  if (recdes->type == REC_BIGONE)
4631  {
4632  error = la_get_overflow_recdes (lrec, logs, recdes, RVOVF_NEWPAGE_INSERT);
4633  }
4634  }
4635  }
4636  else if ((*rcvindex == RVHF_UPDATE || *rcvindex == RVHF_UPDATE_NOTIFY_VACUUM) && recdes->type == REC_RELOCATION)
4637  {
4638  error = la_get_relocation_recdes (lrec, pg, 0, &logs, &rec_type, recdes);
4639  if (error == NO_ERROR)
4640  {
4641  recdes->type = *(INT16 *) (rec_type);
4642  }
4643  }
4644 
4645  if (*rcvindex == RVHF_MVCC_INSERT && recdes->type != REC_BIGONE)
4646  {
4647  la_make_room_for_mvcc_insid (recdes);
4648  }
4649 
4650  return error;
4651 }
4652 
4653 static LOG_REC_HA_SERVER_STATE *
4655 {
4656  LOG_REC_HA_SERVER_STATE *state = NULL;
4657  int error = NO_ERROR;
4659  PGLENGTH offset;
4660  int length;
4661  LOG_PAGE *pg;
4662 
4663  pageid = lsa->pageid;
4664  offset = DB_SIZEOF (LOG_RECORD_HEADER) + lsa->offset;
4665  pg = pgptr;
4666 
4668  LA_LOG_READ_ADVANCE_WHEN_DOESNT_FIT (error, length, offset, pageid, pg);
4669  if (error == NO_ERROR)
4670  {
4671  state = (LOG_REC_HA_SERVER_STATE *) ((char *) pg->area + offset);
4672  }
4673 
4674  return state;
4675 }
4676 
4677 /*
4678  * la_flush_repl_items() - flush stored repl items to server
4679  * return: NO_ERROR or error code
4680  * immediate(in): whether to immediately flush or not
4681  *
4682  * Note:
4683  */
4684 static int
4685 la_flush_repl_items (bool immediate)
4686 {
4687  int error = NO_ERROR;
4688  int la_err_code = ER_FAILED;
4689  WS_REPL_FLUSH_ERR *flush_err;
4690  MOP class_mop = NULL;
4691  const char *class_name = "UNKNOWN CLASS";
4692  const char *server_err_msg = "UNKOWN";
4693  char pkey_str[256];
4694  char buf[LINE_MAX];
4695 
4696  string_buffer sb;
4697 
4698  if (la_Info.num_unflushed == 0)
4699  {
4700  return NO_ERROR;
4701  }
4702 
4703  if (la_Info.num_unflushed >= LA_MAX_UNFLUSHED_REPL_ITEMS || immediate == true)
4704  {
4705  error = locator_repl_flush_all ();
4706  if (error == ER_LC_PARTIALLY_FAILED_TO_FLUSH)
4707  {
4708  while (true)
4709  {
4710  flush_err = ws_get_repl_error_from_error_link ();
4711  if (flush_err == NULL)
4712  {
4713  break;
4714  }
4715 
4716  class_mop = ws_mop (&flush_err->class_oid, sm_Root_class_mop);
4717  if (class_mop != NULL && class_mop->object != NULL)
4718  {
4719  class_name = sm_ch_name ((MOBJ) (class_mop->object));
4720  assert (class_name != NULL);
4721  }
4722 
4723  if (flush_err->error_msg != NULL)
4724  {
4725  server_err_msg = flush_err->error_msg;
4726  }
4727 
4728  sb.clear ();
4729  db_sprint_value (&flush_err->pkey_value, sb);
4730  snprintf (pkey_str, sizeof (pkey_str) - 1, sb.get_buffer ());
4731 
4732  if (LC_IS_FLUSH_INSERT (flush_err->operation) == true)
4733  {
4734  la_err_code = ER_HA_LA_FAILED_TO_APPLY_INSERT;
4735  if (la_Info.insert_counter > 0)
4736  {
4737  la_Info.insert_counter--;
4738  }
4739  }
4740  else if (LC_IS_FLUSH_UPDATE (flush_err->operation) == true)
4741  {
4742  la_err_code = ER_HA_LA_FAILED_TO_APPLY_UPDATE;
4743  if (la_Info.update_counter > 0)
4744  {
4745  la_Info.update_counter--;
4746  }
4747  }
4748  else if (flush_err->operation == LC_FLUSH_DELETE)
4749  {
4750  la_err_code = ER_HA_LA_FAILED_TO_APPLY_DELETE;
4751  if (la_Info.delete_counter > 0)
4752  {
4753  la_Info.delete_counter--;
4754  }
4755  }
4756  else
4757  {
4758  assert (false);
4759  }
4760 
4761  er_stack_push ();
4762  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, la_err_code, 4, class_name, pkey_str, flush_err->error_code,
4763  server_err_msg);
4764  er_stack_pop ();
4765 
4766  la_Info.fail_counter++;
4767 
4768  if (la_restart_on_bulk_flush_error (flush_err->error_code) == true)
4769  {
4770  snprintf (buf, sizeof (buf),
4771  "applylogdb will reconnect to server due to a failure in flushing changes. "
4772  "class: %s, key: %s, server error: %d, %s", class_name, pkey_str, flush_err->error_code,
4773  server_err_msg);
4774  er_stack_push ();
4776  er_stack_pop ();
4777 
4779 
4780  ws_free_repl_flush_error (flush_err);
4782 
4783  return error;
4784  }
4785 
4786  ws_free_repl_flush_error (flush_err);
4787  }
4788 
4790  error = NO_ERROR;
4791  }
4792  else if (error != NO_ERROR)
4793  {
4794  la_Info.fail_counter++;
4796 
4797  er_stack_push ();
4799  er_stack_pop ();
4800 
4802  }
4803 
4804  la_Info.num_unflushed = 0;
4806  }
4807 
4808  return error;
4809 }
4810 
4811 /*
4812  * la_repl_add_object : create a replication object and add it to link for bulk flushing
4813  * return:
4814  * classop(in):
4815  * item (in): item
4816  * recdes(in): record to be inserted
4817  */
4818 static int
4820 {
4821  int error = NO_ERROR;
4822  SM_CLASS *class_;
4823  int pruning_type = DB_NOT_PARTITIONED_CLASS;
4824  int operation = 0;
4825  OID *class_oid;
4826  bool has_index = false;
4827 
4828  assert (classop != NULL && item != NULL);
4829 
4830  class_oid = ws_oid (classop);
4831 
4832  error = au_fetch_class (classop, &class_, AU_FETCH_READ, AU_SELECT);
4833  if (error != NO_ERROR)
4834  {
4835  return error;
4836  }
4837 
4838  error = sm_flush_objects (classop);
4839  if (error != NO_ERROR)
4840  {
4841  return error;
4842  }
4843 
4844  if (item->item_type != RVREPL_DATA_DELETE)
4845  {
4846  error = sm_partitioned_class_type (classop, &pruning_type, NULL, NULL);
4847  if (error != NO_ERROR)
4848  {
4849  return error;
4850  }
4851  }
4852 
4853  switch (item->item_type)
4854  {
4857  case RVREPL_DATA_UPDATE:
4858  operation = LC_UPDATE_OPERATION_TYPE (pruning_type);
4859  break;
4860  case RVREPL_DATA_INSERT:
4861  operation = LC_INSERT_OPERATION_TYPE (pruning_type);
4862  break;
4863  case RVREPL_DATA_DELETE:
4864  operation = LC_FLUSH_DELETE;
4865  break;
4866  default:
4867  assert (false);
4868  }
4869 
4870  has_index = classobj_class_has_indexes (class_);
4871 
4872  error = ws_add_to_repl_obj_list (class_oid, item->packed_key_value, item->packed_key_value_length, recdes,
4873  operation, has_index);
4874  return error;
4875 }
4876 
4877 /*
4878  * la_apply_delete_log() - apply the delete log to the target slave
4879  * return: NO_ERROR or error code
4880  * item(in): replication item
4881  *
4882  * Note:
4883  */
4884 static int
4886 {
4887  DB_OBJECT *class_obj;
4888  MOBJ mclass;
4889  char buf[256];
4890  char sql_log_err[LINE_MAX];
4891 
4892  string_buffer sb;
4893 
4894  int error = la_flush_repl_items (false);
4895  if (error != NO_ERROR)
4896  {
4897  return error;
4898  }
4899 
4900  /* find out class object by class name */
4901  class_obj = db_find_class (item->class_name);
4902  if (class_obj == NULL)
4903  {
4904  assert (er_errid () != NO_ERROR);
4905  error = er_errid ();
4906  }
4907  else
4908  {
4909  /* get class info */
4910  mclass = locator_fetch_class (class_obj, DB_FETCH_CLREAD_INSTREAD);
4911 
4913  {
4914  if (sl_write_delete_sql (item->class_name, mclass, la_get_item_pk_value (item)) != NO_ERROR)
4915  {
4916  sb.clear ();
4917  db_sprint_value (&item->key, sb);
4918  snprintf (sql_log_err, sizeof (sql_log_err), "failed to write SQL log. class: %s, key: %s",
4919  item->class_name, sb.get_buffer ());
4920 
4921  er_stack_push ();
4923  er_stack_pop ();
4924  }
4925  }
4926 
4927  error = la_repl_add_object (class_obj, item, NULL);
4928  if (error == NO_ERROR)
4929  {
4930  la_Info.delete_counter++;
4931  la_Info.num_unflushed++;
4932  }
4933  }
4934 
4935  if (error != NO_ERROR)
4936  {
4937  sb.clear ();
4939 #if defined (LA_VERBOSE_DEBUG)
4940  er_log_debug (ARG_FILE_LINE, "apply_delete : error %d %s\n\tclass %s key %s\n", error, er_msg (),
4941  item->class_name, sb.get_buffer ());
4942 #endif
4943  er_stack_push ();
4945  error, "internal client error.");
4946  er_stack_pop ();
4947 
4948  la_Info.fail_counter++;
4949  }
4950 
4951  return error;
4952 }
4953 
4954 /*
4955  * la_apply_update_log() - apply the update log to the target slave using server side update
4956  * return: NO_ERROR or error code
4957  * item : replication item
4958  *
4959  * Note:
4960  * Apply the update log to the target slave.
4961  * . get the target log page
4962  * . get the record description
4963  * . fetch the class info
4964  * . create a replication object to be flushed and add it to a link
4965  */
4966 static int
4968 {
4969  int error = NO_ERROR, au_save;
4970  unsigned int rcvindex;
4971  RECDES *recdes;
4972  LOG_PAGE *pgptr = NULL;
4973  LOG_PAGEID old_pageid = NULL_PAGEID;
4974  DB_OBJECT *class_obj;
4975  MOBJ mclass;
4976  DB_OTMPL *inst_tp = NULL;
4977  char sql_log_err[LINE_MAX];
4978 
4979  string_buffer sb;
4980 
4981  error = la_flush_repl_items (false);
4982  if (error != NO_ERROR)
4983  {
4984  return error;
4985  }
4986 
4987  /* get the target log page */
4988  old_pageid = item->target_lsa.pageid;
4989  pgptr = la_get_page (old_pageid);
4990  if (pgptr == NULL)
4991  {
4992  assert (er_errid () != NO_ERROR);
4993  return er_errid ();
4994  }
4995 
4996  recdes = la_assign_recdes_from_pool ();
4997 
4998  /* retrieve the target record description */
4999  error = la_get_recdes (&item->target_lsa, pgptr, recdes, &rcvindex, la_Info.rec_type);
5000  if (error != NO_ERROR)
5001  {
5002  goto end;
5003  }
5004 
5005  if (recdes->type == REC_ASSIGN_ADDRESS || recdes->type == REC_RELOCATION)
5006  {
5007  er_log_debug (ARG_FILE_LINE, "apply_update : rectype.type = %d\n", recdes->type);
5008  error = ER_FAILED;
5009 
5010  goto end;
5011  }
5012  if (rcvindex != RVHF_UPDATE && rcvindex != RVOVF_CHANGE_LINK && rcvindex != RVHF_MVCC_INSERT
5013  && rcvindex != RVHF_UPDATE_NOTIFY_VACUUM && rcvindex != RVHF_INSERT_NEWHOME)
5014  {
5015  er_log_debug (ARG_FILE_LINE, "apply_update : rcvindex = %d\n", rcvindex);
5016  error = ER_FAILED;
5017 
5018  goto end;
5019  }
5020 
5021  class_obj = db_find_class (item->class_name);
5022  if (class_obj == NULL)
5023  {
5024  assert (er_errid () != NO_ERROR);
5025  error = er_errid ();
5026  if (error == NO_ERROR)
5027  {
5028  error = ER_FAILED;
5029  }
5030  goto end;
5031  }
5032 
5033  error = la_repl_add_object (class_obj, item, recdes);
5034 
5035  /*
5036  * regardless of the success or failure of obj_repl_update_object,
5037  * we should write sql log.
5038  */
5040  {
5041  bool sql_logging_failed = false;
5042  int rc;
5043 
5044  er_stack_push ();
5045  do
5046  {
5047  mclass = locator_fetch_class (class_obj, DB_FETCH_CLREAD_INSTREAD);
5048  if (mclass == NULL)
5049  {
5050  sql_logging_failed = true;
5051  break;
5052  }
5053 
5054  AU_SAVE_AND_DISABLE (au_save);
5055 
5056  inst_tp = dbt_create_object_internal (class_obj);
5057  if (inst_tp == NULL)
5058  {
5059  sql_logging_failed = true;
5060  AU_RESTORE (au_save);
5061  break;
5062  }
5063 
5064  rc = la_disk_to_obj (mclass, recdes, inst_tp, la_get_item_pk_value (item));
5065  if (rc != NO_ERROR)
5066  {
5067  sql_logging_failed = true;
5068  AU_RESTORE (au_save);
5069  break;
5070  }
5071 
5072  if (sl_write_update_sql (inst_tp, &item->key) != NO_ERROR)
5073  {
5074  AU_RESTORE (au_save);
5075  sql_logging_failed = true;
5076  break;
5077  }
5078 
5079  AU_RESTORE (au_save);
5080  }
5081  while (0);
5082  er_stack_pop ();
5083 
5084  if (sql_logging_failed == true)
5085  {
5086  sb.clear ();
5088  snprintf (sql_log_err, sizeof (sql_log_err), "failed to write SQL log. class: %s, key: %s", item->class_name,
5089  sb.get_buffer ());
5090 
5091  er_stack_push ();
5093  er_stack_pop ();
5094  }
5095  }
5096 
5097 end:
5098  if (error != NO_ERROR)
5099  {
5100  sb.clear ();
5102 #if defined (LA_VERBOSE_DEBUG)
5103  er_log_debug (ARG_FILE_LINE, "apply_update : error %d %s\n\tclass %s key %s\n", error, er_msg (),
5104  item->class_name, sb.get_buffer ());
5105 #endif
5106  er_stack_push ();
5108  error, "internal client error.");
5109  er_stack_pop ();
5110 
5111  la_Info.fail_counter++;
5112 
5113  if (error == ER_NET_CANT_CONNECT_SERVER || error == ER_OBJ_NO_CONNECT)
5114  {
5116  }
5117  }
5118  else
5119  {
5120  la_Info.update_counter++;
5121  la_Info.num_unflushed++;
5122  }
5123 
5124  if (inst_tp)
5125  {
5126  if (inst_tp->object)
5127  {
5128  ws_release_user_instance (inst_tp->object);
5129  ws_decache (inst_tp->object);
5130  }
5131  dbt_abort_object (inst_tp);
5132  }
5133 
5134  la_release_page_buffer (old_pageid);
5135 
5136  return error;
5137 }
5138 
5139 /*
5140  * la_apply_insert_log() - apply the insert log to the target slave
5141  * return: NO_ERROR or error code
5142  * item : replication item
5143  *
5144  * Note:
5145  * Apply the insert log to the target slave.
5146  * . get the target log page
5147  * . get the record description
5148  * . fetch the class info
5149  * . create a replication object to be flushed and add it to a link
5150  */
5151 static int
5153 {
5154  int error = NO_ERROR, au_save;
5155  DB_OBJECT *class_obj;
5156  MOBJ mclass;
5157  LOG_PAGE *pgptr;
5158  unsigned int rcvindex;
5159  RECDES *recdes;
5160  DB_OTMPL *inst_tp = NULL;
5161  LOG_PAGEID old_pageid = NULL_PAGEID;
5162 
5163  string_buffer sb;
5164 
5165  error = la_flush_repl_items (false);
5166  if (error != NO_ERROR)
5167  {
5168  return error;
5169  }
5170 
5171  /* get the target log page */
5172  old_pageid = item->target_lsa.pageid;
5173  pgptr = la_get_page (old_pageid);
5174  if (pgptr == NULL)
5175  {
5176  assert (er_errid () != NO_ERROR);
5177  return er_errid ();
5178  }
5179 
5180  recdes = la_assign_recdes_from_pool ();
5181 
5182  /* retrieve the target record description */
5183  error = la_get_recdes (&item->target_lsa, pgptr, recdes, &rcvindex, la_Info.rec_type);
5184  if (error != NO_ERROR)
5185  {
5186  goto end;
5187  }
5188 
5189  if (recdes->type == REC_ASSIGN_ADDRESS || recdes->type == REC_RELOCATION)
5190  {
5191  er_log_debug (ARG_FILE_LINE, "apply_insert : rectype.type = %d\n", recdes->type);
5192  error = ER_FAILED;
5193 
5194  goto end;
5195  }
5196 
5197  if (rcvindex != RVHF_INSERT && rcvindex != RVHF_MVCC_INSERT)
5198  {
5199  er_log_debug (ARG_FILE_LINE, "apply_insert : rcvindex = %d\n", rcvindex);
5200  error = ER_FAILED;
5201 
5202  goto end;
5203  }
5204 
5205  class_obj = db_find_class (item->class_name);
5206  if (class_obj == NULL)
5207  {
5208  assert (er_errid () != NO_ERROR);
5209  error = er_errid ();
5210  if (error == NO_ERROR)
5211  {
5212  error = ER_FAILED;
5213  }
5214  goto end;
5215  }
5216 
5217  error = la_repl_add_object (class_obj, item, recdes);
5218 
5219  if (la_enable_sql_logging == true)
5220  {
5221  bool sql_logging_failed = false;
5222  int rc;
5223  char sql_log_err[LINE_MAX];
5224 
5225  er_stack_push ();
5226 
5227  do
5228  {
5229  mclass = locator_fetch_class (class_obj, DB_FETCH_CLREAD_INSTREAD);
5230  if (mclass == NULL)
5231  {
5232  sql_logging_failed = true;
5233  break;
5234  }
5235 
5236  AU_SAVE_AND_DISABLE (au_save);
5237 
5238  inst_tp = dbt_create_object_internal (class_obj);
5239  if (inst_tp == NULL)
5240  {
5241  sql_logging_failed = true;
5242  AU_RESTORE (au_save);
5243  break;
5244  }
5245 
5246  /* make object using the record description */
5247  rc = la_disk_to_obj (mclass, recdes, inst_tp, la_get_item_pk_value (item));
5248  if (rc != NO_ERROR)
5249  {
5250  sql_logging_failed = true;
5251  AU_RESTORE (au_save);
5252  break;
5253  }
5254 
5255  if (sl_write_insert_sql (inst_tp, la_get_item_pk_value (item)) != NO_ERROR)
5256  {
5257  sql_logging_failed = true;
5258  AU_RESTORE (au_save);
5259  break;
5260  }
5261 
5262  AU_RESTORE (au_save);
5263  }
5264  while (0);
5265  er_stack_pop ();
5266 
5267  if (sql_logging_failed == true)
5268  {
5269  sb.clear ();
5271  snprintf (sql_log_err, sizeof (sql_log_err), "failed to write SQL log. class: %s, key: %s", item->class_name,
5272  sb.get_buffer ());
5273 
5274  er_stack_push ();
5276  er_stack_pop ();
5277  }
5278  }
5279 
5280 end:
5281  if (error != NO_ERROR)
5282  {
5283  sb.clear ();
5285 #if defined (LA_VERBOSE_DEBUG)
5286  er_log_debug (ARG_FILE_LINE, "apply_insert : error %d %s\n\tclass %s key %s\n", error, er_msg (),
5287  item->class_name, sb.get_buffer ());
5288 #endif
5289  er_stack_push ();
5291  error, "internal client error.");
5292  er_stack_pop ();
5293 
5294  la_Info.fail_counter++;
5295 
5296  if (error == ER_NET_CANT_CONNECT_SERVER || error == ER_OBJ_NO_CONNECT)
5297  {
5299  }
5300  }
5301  else
5302  {
5303  la_Info.insert_counter++;
5304  la_Info.num_unflushed++;
5305  }
5306 
5307  if (inst_tp)
5308  {
5309  if (inst_tp->object)
5310  {
5311  ws_release_user_instance (inst_tp->object);
5312  ws_decache (inst_tp->object);
5313  }
5314  dbt_abort_object (inst_tp);
5315  }
5316 
5317  la_release_page_buffer (old_pageid);
5318 
5319  return error;
5320 }
5321 
5322 /*
5323  * la_update_query_execute()
5324  * returns : error code, if execution failed
5325  * number of affected objects, if a success
5326  * sql(in)
5327  */
5328 static int
5329 la_update_query_execute (const char *sql, bool au_disable)
5330 {
5331  int res, au_save;
5332  DB_QUERY_RESULT *result;
5333  DB_QUERY_ERROR query_error;
5334 
5335  er_log_debug (ARG_FILE_LINE, "update_query_execute : %s\n", sql);
5336 
5337  if (au_disable)
5338  {
5339  /* in order to update 'db_ha_info', disable authorization temporarily */
5340  AU_DISABLE (au_save);
5341  }
5342 
5343  res = db_execute (sql, &result, &query_error);
5344  if (res >= 0)
5345  {
5346  int error;
5347 
5348  error = db_query_end (result);
5349  if (error != NO_ERROR)
5350  {
5351  res = error;
5352  }
5353  }
5354 
5355  if (au_disable)
5356  {
5357  AU_ENABLE (au_save);
5358  }
5359 
5360  return res;
5361 }
5362 
5363 /*
5364  * la_update_query_execute_with_values()
5365  * returns : error code, if execution failed
5366  * number of affected objects, if a success
5367  * sql(in)
5368  * arg_count(in)
5369  * vals(in)
5370  * au_disable(in)
5371  */
5372 static int
5373 la_update_query_execute_with_values (const char *sql, int arg_count, DB_VALUE * vals, bool au_disable)
5374 {
5375  int res, au_save;
5376  DB_QUERY_RESULT *result;
5377  DB_QUERY_ERROR query_error;
5378 
5379  if (au_disable)
5380  {
5381  /* in order to update 'db_ha_info', disable authorization temporarily */
5382  AU_DISABLE (au_save);
5383  }
5384 
5385  res = db_execute_with_values (sql, &result, &query_error, arg_count, vals);
5386  if (res >= 0)
5387  {
5388  int error;
5389 
5390  error = db_query_end (result);
5391  if (error != NO_ERROR)
5392  {
5393  res = error;
5394  }
5395  }
5396 
5397  if (au_disable)
5398  {
5399  AU_ENABLE (au_save);
5400  }
5401 
5402  return res;
5403 }
5404 
5405 /*
5406  * la_apply_schema_log() - apply the schema log to the target slave
5407  * return: NO_ERROR or error code
5408  * item(in): replication item
5409  *
5410  * Note:
5411  */
5412 static int
5414 {
5415  const char *stmt_text = NULL;
5416  int error = NO_ERROR, error2 = NO_ERROR;
5417  const char *error_msg = "";
5418  DB_OBJECT *user = NULL, *save_user = NULL;
5419  char sql_log_err[LINE_MAX];
5420  bool is_ddl = false;
5421  int res;
5422 
5423  error = la_flush_repl_items (true);
5424  if (error != NO_ERROR)
5425  {
5426  return error;
5427  }
5428 
5429  switch (item->item_type)
5430  {
5435 
5439 
5443 
5445 
5449 
5450  case CUBRID_STMT_TRUNCATE:
5451 
5452  /* TODO: check it */
5455  case CUBRID_STMT_DROP_USER:
5456  case CUBRID_STMT_GRANT:
5457  case CUBRID_STMT_REVOKE:
5458 
5459  /* TODO: check it */
5465 
5467  is_ddl = true;
5468  /* FALLTHRU */
5469 
5470  case CUBRID_STMT_INSERT:
5471  case CUBRID_STMT_DELETE:
5472  case CUBRID_STMT_UPDATE:
5473 
5474  if (item->item_type == CUBRID_STMT_TRUNCATE && la_need_filter_out (item) == true)
5475  {
5476  return NO_ERROR;
5477  }
5478 
5479  /*
5480  * When we create the schema objects, the object's owner must be changed
5481  * to the appropriate owner.
5482  * Special alter statement, non partitioned -> partitioned is the same.
5483  * Also, the result of statement-based DML replication may be affected by user
5484  */
5488  || item->item_type == CUBRID_STMT_DELETE || item->item_type == CUBRID_STMT_UPDATE)
5489  && (item->db_user != NULL && item->db_user[0] != '\0'))
5490  {
5491  user = au_find_user (item->db_user);
5492  if (user == NULL)
5493  {
5495  {
5497  }
5498  else
5499  {
5500  assert (er_errid () != NO_ERROR);
5501  error = er_errid ();
5502  }
5503 
5504  error_msg = er_msg ();
5505  break;
5506  }
5507 
5508  /* change owner */
5509  save_user = Au_user;
5510  er_stack_push ();
5511  error = AU_SET_USER (user);
5512  er_stack_pop ();
5513  if (error != NO_ERROR)
5514  {
5515  save_user = NULL;
5516  /* go on with original user */
5517  }
5518  }
5519 
5520  stmt_text = db_get_string (&item->key);
5521  assert (stmt_text != NULL);
5522 
5523  /* write sql log */
5525  {
5526  if (sl_write_statement_sql (item->class_name, item->db_user, item->item_type, stmt_text, item->ha_sys_prm) !=
5527  NO_ERROR)
5528  {
5529  snprintf (sql_log_err, sizeof (sql_log_err), "failed to write SQL log. class: %s, stmt: %s",
5530  item->class_name, stmt_text);
5531 
5532  er_stack_push ();
5534  er_stack_pop ();
5535  }
5536  }
5537 
5538  if (item->ha_sys_prm != NULL)
5539  {
5540  er_log_debug (ARG_FILE_LINE, "la_apply_statement_log : %s\n", item->ha_sys_prm);
5541  er_stack_push ();
5543  if (error2 != NO_ERROR)
5544  {
5545  snprintf (sql_log_err, sizeof (sql_log_err), "failed to change sys prm: %s", item->ha_sys_prm);
5546 
5548  }
5549  er_stack_pop ();
5550  }
5551 
5552  res = la_update_query_execute (stmt_text, false);
5553  if (res < 0)
5554  {
5555  assert (er_errid () != NO_ERROR);
5556  error = er_errid ();
5557  error_msg = er_msg ();
5558  if (error == ER_NET_CANT_CONNECT_SERVER || error == ER_OBJ_NO_CONNECT)
5559  {
5561  }
5562  }
5563  else if (is_ddl == true)
5564  {
5565  la_Info.schema_counter++;
5566  }
5567  else if (item->item_type == CUBRID_STMT_INSERT)
5568  {
5569  la_Info.insert_counter += res;
5570  }
5571  else if (item->item_type == CUBRID_STMT_DELETE)
5572  {
5573  la_Info.delete_counter += res;
5574  }
5575  else if (item->item_type == CUBRID_STMT_UPDATE)
5576  {
5577  la_Info.update_counter += res;
5578  }
5579 
5580  if (item->ha_sys_prm != NULL)
5581  {
5582  er_log_debug (ARG_FILE_LINE, "la_apply_statement_log : reset sysprm\n");
5583  er_stack_push ();
5585  if (error2 != NO_ERROR)
5586  {
5587  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HA_GENERIC_ERROR, 1, "failed to reset sys prm");
5588  }
5589  er_stack_pop ();
5590  }
5591 
5592  if (save_user != NULL)
5593  {
5594  er_stack_push ();
5595  if (AU_SET_USER (save_user))
5596  {
5597  er_stack_pop ();
5598  /* it can be happened */
5599  abort ();
5600  }
5601  er_stack_pop ();
5602  }
5603  break;
5604 
5606  default:
5607  return NO_ERROR;
5608  }
5609 
5610  if (error != NO_ERROR)
5611  {
5612 #if defined (LA_VERBOSE_DEBUG)
5613  er_log_debug (ARG_FILE_LINE, "apply_statement : error %d class %s stmt %s\n", error, item->class_name, stmt_text);
5614 #endif
5615  er_stack_push ();
5617  error, error_msg);
5618  er_stack_pop ();
5619 
5620  la_Info.fail_counter++;
5621  }
5622  return error;
5623 }
5624 
5625 /*
5626  * la_apply_repl_log() - apply the log to the target slave
5627  * return: NO_ERROR or error code
5628  * tranid: the target transaction id
5629  * rectype: the target log record type
5630  * final_pageid : the final pageid
5631  *
5632  * Note:
5633  * This function is called when the APPLY thread meets the LOG_COMMIT
5634  * record.
5635  */
5636 static int
5637 la_apply_repl_log (int tranid, int rectype, LOG_LSA * commit_lsa, int *total_rows, LOG_PAGEID final_pageid)
5638 {
5639  LA_ITEM *item = NULL;
5640  LA_ITEM *next_item = NULL;
5641  int error = NO_ERROR;
5642  int errid;
5643  LA_APPLY *apply;
5644  int apply_repl_log_cnt = 0;
5645  char error_string[1024];
5646  char buf[256];
5647  static unsigned int total_repl_items = 0;
5648  bool release_pb = false;
5649  bool has_more_commit_items = false;
5650 
5651  apply = la_find_apply_list (tranid);
5652  if (apply == NULL)
5653  {
5654  return NO_ERROR;
5655  }
5656 
5657  if (rectype == LOG_ABORT)
5658  {
5659  la_clear_applied_info (apply);
5660  return NO_ERROR;
5661  }
5662 
5663  if (apply->head == NULL || LSA_LE (commit_lsa, &la_Info.last_committed_lsa))
5664  {
5665  if (rectype == LOG_SYSOP_END)
5666  {
5667  la_free_all_repl_items (apply);
5668  }
5669  else
5670  {
5671  la_clear_applied_info (apply);
5672  }
5673 
5674  return NO_ERROR;
5675  }
5676 
5677  error = la_lock_dbname (&la_Info.db_lockf_vdes, la_slave_db_name, la_Info.log_path);
5678  assert_release (error == NO_ERROR);
5679 
5680  string_buffer sb;
5681 
5682  item = apply->head;
5683  while (item)
5684  {
5685  error = NO_ERROR;
5686 
5687  total_repl_items++;
5688  release_pb = ((total_repl_items % LA_MAX_REPL_ITEM_WITHOUT_RELEASE_PB) == 0) ? true : false;
5689 
5690  if (final_pageid != NULL_PAGEID && release_pb == true)
5691  {
5692  la_release_all_page_buffers (final_pageid);
5693  }
5694 
5695  if (LSA_GT (&item->lsa, &la_Info.last_committed_rep_lsa) && la_need_filter_out (item) == false)
5696  {
5697  if (item->log_type == LOG_REPLICATION_DATA)
5698  {
5699  switch (item->item_type)
5700  {
5703  case RVREPL_DATA_UPDATE:
5704  error = la_apply_update_log (item);
5705  break;
5706 
5707  case RVREPL_DATA_INSERT:
5708  error = la_apply_insert_log (item);
5709  break;
5710 
5711  case RVREPL_DATA_DELETE:
5712  error = la_apply_delete_log (item);
5713  break;
5714 
5715  default:
5716  er_log_debug (ARG_FILE_LINE, "apply_repl_log : log_type %d item_type %d\n", item->log_type,
5717  item->item_type);
5718 
5719  assert_release (false);
5720  }
5721  }
5722  else if (item->log_type == LOG_REPLICATION_STATEMENT)
5723  {
5724  error = la_apply_statement_log (item);
5725  }
5726  else
5727  {
5728  er_log_debug (ARG_FILE_LINE, "apply_repl_log : log_type %d item_type\n", item->log_type, item->item_type);
5729 
5730  assert_release (false);
5731  }
5732 
5733  apply_repl_log_cnt++;
5734 
5735  if (error == NO_ERROR)
5736  {
5737  LSA_COPY (&la_Info.committed_rep_lsa, &item->lsa);
5738  }
5739  else
5740  {
5741  /* reconnect to server due to error while flushing repl items */
5743  {
5744  goto end;
5745  }
5746 
5747  assert (er_errid () != NO_ERROR);
5748  errid = er_errid ();
5749 
5750  sb.clear ();
5752  sprintf (error_string, "[%s,%s] %s", item->class_name, sb.get_buffer (), db_error_string (1));
5753  er_log_debug (ARG_FILE_LINE, "Internal system failure: %s", error_string);
5754 
5755  if (errid == ER_NET_CANT_CONNECT_SERVER || errid == ER_OBJ_NO_CONNECT)
5756  {
5758  goto end;
5759  }
5760  else if (la_ignore_on_error (errid) == false && la_retry_on_error (errid) == true)
5761  {
5762  snprintf (buf, sizeof (buf), "attempts to try applying failed replication log again. (error:%d)",
5763  errid);
5765 
5766  /* try it again */
5767  LA_SLEEP (10, 0);
5768  continue;
5769  }
5770  }
5771  }
5772 
5773  next_item = la_get_next_repl_item (item, apply->is_long_trans, &apply->last_lsa);
5774  la_free_repl_item (apply, item);
5775  item = next_item;
5776 
5777  if ((item != NULL) && LSA_GT (&item->lsa, commit_lsa))
5778  {
5779  assert (rectype == LOG_SYSOP_END);
5780  has_more_commit_items = true;
5781  break;
5782  }
5783  }
5784 
5785 end:
5786  *total_rows += apply_repl_log_cnt;
5787 
5788  if (rectype == LOG_SYSOP_END)
5789  {
5790  if (has_more_commit_items)
5791  {
5792  la_free_and_add_next_repl_item (apply, item, commit_lsa);
5793  }
5794  else
5795  {
5796  la_free_all_repl_items (apply);
5797  }
5798  }
5799  else
5800  {
5801  la_clear_applied_info (apply);
5802  }
5803 
5804  return error;
5805 }
5806 
5807 /*
5808  * la_apply_commit_list() - apply the log to the target slave
5809  * return: NO_ERROR or error code
5810  * lsa : the target LSA of the log
5811  * final_pageid : the final pageid
5812  *
5813  * Note:
5814  * This function is called when the APPLY thread meets the LOG_COMMIT
5815  * record.
5816  */
5817 static int
5819 {
5820  LA_COMMIT *commit;
5821  int error = NO_ERROR;
5822 
5823  LSA_SET_NULL (lsa);
5824 
5825  commit = la_Info.commit_head;
5826  if (commit && (commit->type == LOG_COMMIT || commit->type == LOG_SYSOP_END || commit->type == LOG_ABORT))
5827  {
5828  error = la_apply_repl_log (commit->tranid, commit->type, &commit->log_lsa, &la_Info.total_rows, final_pageid);
5829  if (error != NO_ERROR)
5830  {
5831  er_log_debug (ARG_FILE_LINE, "apply_commit_list : error %d while apply_repl_log\n", error);
5832  }
5833 
5834  LSA_COPY (lsa, &commit->log_lsa);
5835 
5836  if (commit->type == LOG_COMMIT)
5837  {
5838  la_Info.log_record_time = commit->log_record_time;
5839  }
5840 
5841  if (commit->next != NULL)
5842  {
5843  commit->next->prev = NULL;
5844  }
5845  la_Info.commit_head = commit->next;
5846  if (la_Info.commit_head == NULL)
5847  {
5848  la_Info.commit_tail = NULL;
5849  }
5850 
5851  free_and_init (commit);
5852  }
5853 
5854  return error;
5855 }
5856 
5857 /*
5858  * la_free_repl_items_by_tranid() - clear replication item using tranid
5859  * return: none
5860  * tranid: transaction id
5861  *
5862  * Note:
5863  * clear the applied list area after processing ..
5864  * When we meet the LOG_ABORT_TOPOPE or LOG_ABORT record,
5865  * we have to clear the replication items of the target transaction.
5866  * In case of LOG_ABORT_TOPOPE, the apply list should be preserved
5867  * for the later use (so call la_clear_applied_info() using
5868  * false as the second argument).
5869  */
5870 static void
5872 {
5873  LA_APPLY *apply;
5874  LA_COMMIT *commit, *commit_next;
5875 
5876  apply = la_find_apply_list (tranid);
5877  if (apply)
5878  {
5879  la_clear_applied_info (apply);
5880  }
5881 
5882  for (commit = la_Info.commit_head; commit; commit = commit_next)
5883  {
5884  commit_next = commit->next;
5885 
5886  if (commit->tranid == tranid)
5887  {
5888  if (commit->next)
5889  {
5890  commit->next->prev = commit->prev;
5891  }
5892  else
5893  {
5894  la_Info.commit_tail = commit->prev;
5895  }
5896 
5897  if (commit->prev)
5898  {
5899  commit->prev->next = commit->next;
5900  }
5901  else
5902  {
5903  la_Info.commit_head = commit->next;
5904  }
5905 
5906  commit->next = NULL;
5907  commit->prev = NULL;
5908 
5909  free_and_init (commit);
5910  }
5911  }
5912 
5913  if (la_Info.commit_head == NULL)
5914  {
5915  la_Info.commit_tail = NULL;
5916  }
5917 
5918  return;
5919 }
5920 
5921 static LA_ITEM *
5922 la_get_next_repl_item (LA_ITEM * item, bool is_long_trans, LOG_LSA * last_lsa)
5923 {
5924  if (is_long_trans)
5925  {
5926  return la_get_next_repl_item_from_log (item, last_lsa);
5927  }
5928  else
5929  {
5930  return la_get_next_repl_item_from_list (item);
5931  }
5932 }
5933 
5934 static LA_ITEM *
5936 {
5937  return (item->next);
5938 }
5939 
5940 static LA_ITEM *
5942 {
5943  LOG_LSA prev_repl_lsa;
5944  LOG_LSA curr_lsa;
5945  LOG_PAGE *curr_log_page;
5946  LOG_RECORD_HEADER *prev_repl_log_record = NULL;
5947  LOG_RECORD_HEADER *curr_log_record;
5948  LA_ITEM *next_item = NULL;
5949 
5950  LSA_COPY (&prev_repl_lsa, &item->lsa);
5951  LSA_COPY (&curr_lsa, &item->lsa);
5952 
5953  while (!LSA_ISNULL (&curr_lsa))
5954  {
5955  curr_log_page = la_get_page (curr_lsa.pageid);
5956  curr_log_record = LOG_GET_LOG_RECORD_HEADER (curr_log_page, &curr_lsa);
5957 
5958  if (prev_repl_log_record == NULL)
5959  {
5960  prev_repl_log_record = (LOG_RECORD_HEADER *) malloc (sizeof (LOG_RECORD_HEADER));
5961  if (prev_repl_log_record == NULL)
5962  {
5963  return NULL;
5964  }
5965 
5966  memcpy (prev_repl_log_record, curr_log_record, sizeof (LOG_RECORD_HEADER));
5967  }
5968  if (!LSA_EQ (&curr_lsa, &prev_repl_lsa) && prev_repl_log_record->trid == curr_log_record->trid)
5969  {
5970  if (LSA_GT (&curr_lsa, last_lsa) || curr_log_record->type == LOG_COMMIT || curr_log_record->type == LOG_ABORT
5971  || LSA_GE (&curr_lsa, &la_Info.act_log.log_hdr->eof_lsa))
5972  {
5973  break;
5974  }
5975 
5976  if (curr_log_record->type == LOG_REPLICATION_DATA || curr_log_record->type == LOG_REPLICATION_STATEMENT)
5977  {
5978  next_item = la_make_repl_item (curr_log_page, curr_log_record->type, curr_log_record->trid, &curr_lsa);
5979  assert (next_item);
5980 
5981  break;
5982  }
5983 
5984  }
5985  la_release_page_buffer (curr_lsa.pageid);
5986  LSA_COPY (&curr_lsa, &curr_log_record->forw_lsa);
5987  }
5988 
5989  if (prev_repl_log_record)
5990  {
5991  free_and_init (prev_repl_log_record);
5992  }
5993 
5994  return next_item;
5995 }
5996 
5997 
5998 static int
6000 {
6001  LA_APPLY *apply = NULL;
6002  int error = NO_ERROR;
6003  LOG_LSA lsa_apply;
6004  LOG_PAGEID final_pageid;
6006  char buffer[256];
6007  time_t eot_time;
6008 
6009  if (lrec->trid == NULL_TRANID || LSA_GT (&lrec->prev_tranlsa, final) || LSA_GT (&lrec->back_lsa, final))
6010  {
6011  if (lrec->type != LOG_END_OF_LOG)
6012  {
6013  la_applier_need_shutdown = true;
6014 
6015  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HA_LA_INVALID_REPL_LOG_RECORD, 10, final->pageid, final->offset,
6016  lrec->forw_lsa.pageid, lrec->forw_lsa.offset, lrec->back_lsa.pageid, lrec->back_lsa.offset,
6017  lrec->trid, lrec->prev_tranlsa.pageid, lrec->prev_tranlsa.offset, lrec->type);
6018  return ER_LOG_PAGE_CORRUPTED;
6019  }
6020  }
6021 
6022  if ((lrec->type != LOG_END_OF_LOG && lrec->type != LOG_DUMMY_HA_SERVER_STATE) && lrec->trid != LOG_SYSTEM_TRANID
6023  && LSA_ISNULL (&lrec->prev_tranlsa))
6024  {
6025  apply = la_add_apply_list (lrec->trid);
6026  if (apply == NULL)
6027  {
6028  la_applier_need_shutdown = true;
6029 
6030  assert (er_errid () != NO_ERROR);
6031  error = er_errid ();
6032  if (error != NO_ERROR)
6033  {
6034  return error;
6035  }
6036  else
6037  {
6038  return ER_FAILED;
6039  }
6040  }
6041  if (LSA_ISNULL (&apply->start_lsa))
6042  {
6043  LSA_COPY (&apply->start_lsa, final);
6044  }
6045  }
6046 
6047  la_Info.is_end_of_record = false;
6048  switch (lrec->type)
6049  {
6050  case LOG_END_OF_LOG:
6051  if (la_does_page_exist (final->pageid + 1) && la_does_page_exist (final->pageid) == LA_PAGE_EXST_IN_ARCHIVE_LOG)
6052  {
6053  /* when we meet the END_OF_LOG of archive file, skip log page */
6055  final->offset);
6056  final->pageid++;
6057  final->offset = 0;
6058  }
6059  else
6060  {
6061  /* we meet the END_OF_LOG */
6062 #if defined (LA_VERBOSE_DEBUG)
6063  er_log_debug (ARG_FILE_LINE, "reached END_OF_LOG in active log. LSA(%d|%d)", final->pageid, final->offset);
6064 #endif
6065  la_Info.is_end_of_record = true;
6066  }
6067  return ER_INTERRUPTED;
6068 
6069  case LOG_REPLICATION_DATA:
6071  /* add the replication log to the target transaction */
6072  error = la_set_repl_log (pg_ptr, lrec->type, lrec->trid, final);
6073  if (error != NO_ERROR)
6074  {
6075  la_applier_need_shutdown = true;
6076  return error;
6077  }
6078  break;
6079 
6080  case LOG_SYSOP_END:
6081  case LOG_COMMIT:
6082  /* apply the replication log to the slave */
6083  if (LSA_GT (final, &la_Info.committed_lsa))
6084  {
6085  /* add the repl_list to the commit_list */
6086  if (lrec->type == LOG_SYSOP_END)
6087  {
6088  eot_time = 0;
6089  }
6090  else
6091  {
6092  eot_time = la_retrieve_eot_time (pg_ptr, final);
6093  }
6094 
6095  error = la_add_node_into_la_commit_list (lrec->trid, final, lrec->type, eot_time);
6096  if (error != NO_ERROR)
6097  {
6098  la_applier_need_shutdown = true;
6099  return error;
6100  }
6101 
6102  /* in case of delayed/time-bound replication */
6103  if (eot_time != 0)
6104  {
6105  error = la_delay_replica (eot_time);
6106  if (error != NO_ERROR)
6107  {
6108  return error;
6109  }
6110  }
6111 
6112  /* make db_ha_apply_info.status busy */
6113  if (la_Info.status == LA_STATUS_IDLE)
6114  {
6115  la_Info.status = LA_STATUS_BUSY;
6116  }
6117 
6118  final_pageid = (pg_ptr) ? pg_ptr->hdr.logical_pageid : NULL_PAGEID;
6119  do
6120  {
6121  error = la_apply_commit_list (&lsa_apply, final_pageid);
6122  if (error == ER_NET_CANT_CONNECT_SERVER)
6123  {
6124  switch (er_errid ())
6125  {
6127  break;
6129  break;
6130  default:
6132  "cannot connect with server");
6133  return error;
6134  }
6135  }
6136  else if (error == ER_HA_LA_EXCEED_MAX_MEM_SIZE)
6137  {
6138  la_applier_need_shutdown = true;
6139  return error;
6140  }
6142  {
6143  return error;
6144  }
6145  else if (error == ER_TDE_CIPHER_IS_NOT_LOADED)
6146  {
6147  la_applier_need_shutdown = true;
6148  return error;
6149  }
6150 
6151  if (!LSA_ISNULL (&lsa_apply))
6152  {
6153  LSA_COPY (&(la_Info.committed_lsa), &lsa_apply);
6154 
6155  if (lrec->type == LOG_COMMIT)
6156  {
6157  la_Info.commit_counter++;
6158  }
6159  }
6160  }
6161  while (!LSA_ISNULL (&lsa_apply)); /* if lsa_apply is not null then there is the replication log applying
6162  * to the slave */
6163  }
6164  else
6165  {
6167  }
6168  break;
6169 
6170  case LOG_ABORT:
6171  error = la_add_node_into_la_commit_list (lrec->trid, final, LOG_ABORT, 0);
6172  if (error != NO_ERROR)
6173  {
6174  la_applier_need_shutdown = true;
6175  return error;
6176  }
6177  break;
6178 
6180  snprintf (buffer, sizeof (buffer), "process log record (type:%d). skip this log record. LSA: %lld|%d",
6181  lrec->type, (long long int) final->pageid, (int) final->offset);
6183 
6184  LSA_COPY (final, &lrec->forw_lsa);
6185  return ER_INTERRUPTED;
6186 
6187  case LOG_END_CHKPT:
6188  break;
6189 
6191  ha_server_state = la_get_ha_server_state (pg_ptr, final);
6192  if (ha_server_state == NULL)
6193  {
6194  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HA_GENERIC_ERROR, 1, "failed to read LOG_DUMMY_HA_SERVER_STATE");
6195  break;
6196  }
6197 
6198  if (ha_server_state->state != HA_SERVER_STATE_ACTIVE && ha_server_state->state != HA_SERVER_STATE_TO_BE_STANDBY)
6199  {
6200  if (la_Info.db_lockf_vdes != NULL_VOLDES)
6201  {
6202  snprintf_dots_truncate (buffer, sizeof (buffer) - 1, "the state of HA server (%s@%s) is changed to %s",
6204  css_ha_server_state_string ((HA_SERVER_STATE) ha_server_state->state));
6206 
6207  la_Info.is_role_changed = true;
6208 
6209  return ER_INTERRUPTED;
6210  }
6211  }
6212  else if (la_is_repl_lists_empty ())
6213  {
6214  (void) la_update_ha_apply_info_log_record_time (ha_server_state->at_time);
6215  error = la_log_commit (true);
6216  if (error != NO_ERROR)
6217  {
6218  return error;
6219  }
6220  }
6221  break;
6222 
6223  default:
6224  break;
6225  } /* switch(lrec->type) */
6226 
6227  /* if this is the last record of the archive log.. we have to fetch the next page. So, increase the pageid, but we
6228  * don't know the exact offset of the next record. the offset would be adjusted after getting the next log page */
6229  if (lrec->forw_lsa.pageid == -1 || lrec->type <= LOG_SMALLER_LOGREC_TYPE || lrec->type >= LOG_LARGER_LOGREC_TYPE)
6230  {
6231  if (la_does_page_exist (final->pageid) == LA_PAGE_EXST_IN_ARCHIVE_LOG)
6232  {
6233  snprintf (buffer, sizeof (buffer), "process last log record in archive. LSA: %lld|%d",
6234  (long long int) final->pageid, (int) final->offset);
6236 
6237  final->pageid++;
6238  final->offset = 0;
6239  }
6240 
6241  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HA_LA_INVALID_REPL_LOG_RECORD, 10, final->pageid, final->offset,
6242  lrec->forw_lsa.pageid, lrec->forw_lsa.offset, lrec->back_lsa.pageid, lrec->back_lsa.offset, lrec->trid,
6243  lrec->prev_tranlsa.pageid, lrec->prev_tranlsa.offset, lrec->type);
6244 
6245  return ER_LOG_PAGE_CORRUPTED;
6246  }
6247 
6248  return NO_ERROR;
6249 }
6250 
6251 static char *
6253 {
6254  char *hostname = NULL, *p;
6255 
6256  if (log_path == NULL)
6257  {
6258  return NULL;
6259  }
6260 
6261  p = log_path;
6262  p += (strlen (log_path) - 1);
6263 
6264  /* log_path: "path/dbname_hostname/" */
6265  if (*p == '/')
6266  {
6267  p--;
6268  }
6269 
6270  while (*p != '/')
6271  {
6272  p--;
6273  if (p == log_path)
6274  {
6275  return NULL;
6276  }
6277  }
6278 
6279  hostname = strstr (p, la_slave_db_name);
6280  if (hostname == NULL)
6281  {
6282  return NULL;
6283  }
6284 
6285  hostname += strlen (la_slave_db_name);
6286  if (*hostname != '_')
6287  {
6288  return NULL;
6289  }
6290 
6291  return hostname + 1;
6292 }
6293 
6294 static int
6296 {
6297  int error = NO_ERROR;
6298  int new_state = HA_LOG_APPLIER_STATE_NA;
6299  char buffer[1024];
6300 
6301  if (la_Info.last_server_state == la_Info.act_log.log_hdr->ha_server_state
6302  && la_Info.last_file_state == la_Info.act_log.log_hdr->ha_file_status
6303  && la_Info.last_is_end_of_record == la_Info.is_end_of_record)
6304  {
6305  /* there are no need to change */
6306  return NO_ERROR;
6307  }
6308 
6309  if (la_Info.last_server_state != la_Info.act_log.log_hdr->ha_server_state)
6310  {
6311  sprintf (buffer, "change the state of HA server (%s@%s) from '%s' to '%s'", la_slave_db_name, la_peer_host,
6315  }
6316 
6317  la_Info.last_server_state = la_Info.act_log.log_hdr->ha_server_state;
6318  la_Info.last_file_state = la_Info.act_log.log_hdr->ha_file_status;
6319  la_Info.last_is_end_of_record = la_Info.is_end_of_record;
6320 
6321  /* check log file status */
6322  if (la_Info.is_end_of_record == true && (la_Info.act_log.log_hdr->ha_file_status == LOG_HA_FILESTAT_SYNCHRONIZED))
6323  {
6324  /* check server's state with log header */
6325  switch (la_Info.act_log.log_hdr->ha_server_state)
6326  {
6331  {
6332  /* notify to slave db */
6333  new_state = HA_LOG_APPLIER_STATE_WORKING;
6334  }
6335  break;
6336 
6337  case HA_SERVER_STATE_DEAD:
6340  if (la_Info.apply_state != HA_LOG_APPLIER_STATE_DONE)
6341  {
6342  /* notify to slave db */
6343  new_state = HA_LOG_APPLIER_STATE_DONE;
6344 
6345  /* clear all repl_lists */
6347  {
6349  }
6350  }
6351  break;
6352  default:
6353  er_log_debug (ARG_FILE_LINE, "BUG. Unknown LOG_HA_SRVSTAT (%x)", la_Info.act_log.log_hdr->ha_server_state);
6354  return ER_FAILED;
6355  break;
6356  }
6357 
6358  }
6359  else
6360  {
6361  switch (la_Info.act_log.log_hdr->ha_server_state)
6362  {
6367  {
6368  new_state = HA_LOG_APPLIER_STATE_RECOVERING;
6369  }
6370  break;
6373  case HA_SERVER_STATE_DEAD:
6375  if (la_Info.apply_state != HA_LOG_APPLIER_STATE_DONE
6377  {
6378  new_state = HA_LOG_APPLIER_STATE_RECOVERING;
6379  }
6380  break;
6381  default:
6382  er_log_debug (ARG_FILE_LINE, "BUG. Unknown LOG_HA_SRVSTAT (%x)", la_Info.act_log.log_hdr->ha_server_state);
6383  return ER_FAILED;
6384  break;
6385  }
6386  }
6387 
6388  if (new_state != HA_LOG_APPLIER_STATE_NA)
6389  {
6390  if (la_Info.apply_state == new_state)
6391  {
6392  return NO_ERROR;
6393  }
6394 
6395  /* force commit when state is changing */
6396  error = la_log_commit (true);
6397  if (error != NO_ERROR)
6398  {
6399  return error;
6400  }
6401 
6403  if (error == NO_ERROR)
6404  {
6405  snprintf (buffer, sizeof (buffer), "change log apply state from '%s' to '%s'. last committed LSA: %lld|%d",
6408  (long long int) la_Info.committed_lsa.pageid, (int) la_Info.committed_lsa.offset);
6410 
6411  la_Info.apply_state = new_state;
6412  }
6413  else
6414  {
6418  }
6419  }
6420 
6421  return error;
6422 }
6423 
6424 /*
6425  * la_log_commit() -
6426  * return: NO_ERROR or error code
6427  */
6428 static int
6429 la_log_commit (bool update_commit_time)
6430 {
6431  int res;
6432  int error = NO_ERROR;
6433 
6434  (void) la_find_required_lsa (&la_Info.required_lsa);
6435 
6436  LSA_COPY (&la_Info.append_lsa, &la_Info.act_log.log_hdr->append_lsa);
6437  LSA_COPY (&la_Info.eof_lsa, &la_Info.act_log.log_hdr->eof_lsa);
6438 
6439  if (update_commit_time)
6440  {
6441  la_Info.log_commit_time = time (0);
6442  }
6443 
6444  error = la_flush_repl_items (true);
6445  if (error != NO_ERROR)
6446  {
6447  return error;
6448  }
6449 
6451  if (res > 0)
6452  {
6453  error = la_commit_transaction ();
6454  }
6455  else
6456  {
6457  la_Info.fail_counter++;
6458 
6459  er_log_debug (ARG_FILE_LINE, "log applied but cannot update last committed LSA (%d|%d)",
6460  la_Info.committed_lsa.pageid, la_Info.committed_lsa.offset);
6461  if (res == ER_NET_CANT_CONNECT_SERVER || res == ER_OBJ_NO_CONNECT)
6462  {
6464  }
6465  else
6466  {
6467  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HA_GENERIC_ERROR, 1, "failed to update db_ha_apply_info");
6468  error = NO_ERROR;
6469  }
6470  }
6471 
6472  return error;
6473 }
6474 
6475 /*
6476  * la_get_mem_size () - get mem size with own pid
6477  */
6478 static unsigned long
6480 {
6481  unsigned long vsize = 0;
6482 #if defined(LINUX)
6483  FILE *fp;
6484 
6485  fp = fopen ("/proc/self/statm", "r");
6486  if (fp != NULL)
6487  {
6488  fscanf (fp, "%lu", &vsize);
6489  /* page to Kbyte */
6490  vsize *= (sysconf (_SC_PAGESIZE) / ONE_K);
6491  fclose (fp);
6492  }
6493 #elif defined(AIX)
6494  struct procentry64 entry;
6495  pid_t pid = getpid ();
6496 
6497  if (getprocs64 (&entry, sizeof (entry), NULL, 0, &pid, 1))
6498  {
6499  vsize = (unsigned long) entry.pi_dvm * (sysconf (_SC_PAGESIZE) / ONE_K);
6500  }
6501 #else
6502 #error
6503 #endif
6504  return vsize;
6505 }
6506 
6507 static int
6509 {
6510  int error = NO_ERROR;
6511  unsigned long vsize;
6512  unsigned long max_vsize;
6513  int diff_sec;
6514  time_t now;
6515 
6516  now = time (NULL);
6517  diff_sec = now - la_Info.start_time;
6518  if (diff_sec >= 0 && diff_sec <= HB_START_WAITING_TIME_IN_SECS)
6519  {
6520  return NO_ERROR;
6521  }
6522 
6523  vsize = la_get_mem_size ();
6524 #if defined(AIX)
6525  max_vsize = MAX ((unsigned long) (la_Info.max_mem_size * ONE_K), (la_Info.start_vsize * 60));
6526 #else
6527  max_vsize = MAX ((unsigned long) (la_Info.max_mem_size * ONE_K), (la_Info.start_vsize * 2));
6528 #endif
6529  if (vsize > max_vsize)
6530  {
6531  /*
6532  * vmem size is more than max_mem_size
6533  * or grow more than 2 times
6534  */
6536  (la_Info.start_vsize / ONE_K), la_Info.required_lsa.pageid, la_Info.required_lsa.offset,
6537  la_Info.committed_lsa.pageid, la_Info.committed_lsa.offset);
6539  }
6540 
6541  return error;
6542 }
6543 
6544 int
6546 {
6547  int error = NO_ERROR;
6548  static int last_time = 0;
6549  static unsigned long long last_applied_item = 0;
6550  int curr_time;
6551  int diff_time;
6552  unsigned long long curr_applied_item;
6553  unsigned long long diff_applied_item;
6554  unsigned long ws_cull_mops_interval;
6555  unsigned long ws_cull_mops_per_apply;
6556  int start_time;
6557 
6558  if (last_time == 0)
6559  {
6560  last_time = time (NULL);
6561  }
6562 
6563  if (last_applied_item == 0)
6564  {
6565  last_applied_item =
6566  la_Info.insert_counter + la_Info.update_counter + la_Info.delete_counter + la_Info.fail_counter;
6567  }
6568 
6569  error = db_commit_transaction ();
6570  if (error != NO_ERROR)
6571  {
6572  return error;
6573  }
6574 
6575  curr_time = time (NULL);
6576  diff_time = curr_time - last_time;
6577 
6578  curr_applied_item = la_Info.insert_counter + la_Info.update_counter + la_Info.delete_counter + la_Info.fail_counter;
6579  diff_applied_item = curr_applied_item - last_applied_item;
6580 
6581  start_time = curr_time - la_Info.start_time;
6582  if (start_time >= 0 && start_time <= HB_START_WAITING_TIME_IN_SECS)
6583  {
6584  ws_cull_mops_interval = LA_WS_CULL_MOPS_INTERVAL_MIN;
6585  ws_cull_mops_per_apply = LA_WS_CULL_MOPS_PER_APPLY_MIN;
6586  }
6587  else
6588  {
6589  ws_cull_mops_interval = LA_WS_CULL_MOPS_INTERVAL;
6590  ws_cull_mops_per_apply = LA_WS_CULL_MOPS_PER_APPLY;
6591  }
6592 
6593  if ((long unsigned) diff_time >= ws_cull_mops_interval || diff_applied_item >= ws_cull_mops_per_apply)
6594  {
6595  ws_filter_dirty ();
6596  ws_cull_mops ();
6597 
6598  last_time = curr_time;
6599  last_applied_item = curr_applied_item;
6600  }
6601 
6602  return error;
6603 }
6604 
6605 static int
6606 la_check_time_commit (struct timeval *time_commit, unsigned int threshold)
6607 {
6608  int error = NO_ERROR;
6609  struct timeval curtime;
6610  int diff_msec;
6611  bool need_commit = false;
6612 
6613  assert (time_commit);
6614 
6615  /* check interval time for commit */
6616  gettimeofday (&curtime, NULL);
6617  diff_msec = (curtime.tv_sec - time_commit->tv_sec) * 1000 + (curtime.tv_usec / 1000 - time_commit->tv_usec / 1000);
6618  if (diff_msec < 0)
6619  {
6620  diff_msec = 0;
6621  }
6622 
6623  if (threshold < (unsigned int) diff_msec)
6624  {
6625  gettimeofday (time_commit, NULL);
6626 
6627  /* check server is connected now */
6628  error = db_ping_server (0, NULL);
6629  if (error != NO_ERROR)
6630  {
6632  }
6633 
6634  /* check for # of rows to commit */
6635  if (la_Info.prev_total_rows != la_Info.total_rows)
6636  {
6637  need_commit = true;
6638  }
6639 
6640  if (need_commit == true || la_Info.is_apply_info_updated == true)
6641  {
6642  error = la_log_commit (need_commit);
6643  if (error == NO_ERROR)
6644  {
6645  /* sync with new one */
6646  la_Info.prev_total_rows = la_Info.total_rows;
6647  la_Info.is_apply_info_updated = false;
6648  }
6649  }
6650  else
6651  {
6652  if (la_Info.status == LA_STATUS_BUSY)
6653  {
6654  /* make db_ha_apply_info.status idle */
6655  la_Info.status = LA_STATUS_IDLE;
6656  }
6657  }
6658  }
6659 
6660  return error;
6661 }
6662 
6663 static int
6664 la_check_duplicated (const char *logpath, const char *dbname, int *lockf_vdes, int *last_deleted_arv_num)
6665 {
6666  char lock_path[PATH_MAX];
6667  FILEIO_LOCKF_TYPE lockf_type = FILEIO_NOT_LOCKF;
6668 
6669  sprintf (lock_path, "%s%s%s%s", logpath, FILEIO_PATH_SEPARATOR (logpath), dbname, LA_LOCK_SUFFIX);
6670 
6671  *lockf_vdes = fileio_open (lock_path, O_RDWR | O_CREAT, 0644);
6672  if (*lockf_vdes == NULL_VOLDES)
6673  {
6674  er_log_debug (ARG_FILE_LINE, "unable to open lock_file (%s)", lock_path);
6676  return ER_IO_MOUNT_FAIL;
6677  }
6678 
6679  lockf_type = fileio_lock_la_log_path (dbname, lock_path, *lockf_vdes, last_deleted_arv_num);
6680  if (lockf_type == FILEIO_NOT_LOCKF)
6681  {
6682  er_log_debug (ARG_FILE_LINE, "unable to wlock lock_file (%s)", lock_path);
6683  fileio_close (*lockf_vdes);
6684  *lockf_vdes = NULL_VOLDES;
6685  return ER_FAILED;
6686  }
6687 
6688 #if defined (LA_VERBOSE_DEBUG)
6689  er_log_debug (ARG_FILE_LINE, "last_deleted_arv_num is %d.", *last_deleted_arv_num);
6690 #endif
6691 
6692  return NO_ERROR;
6693 }
6694 
6695 static int
6696 la_update_last_deleted_arv_num (int lockf_vdes, int last_deleted_arv_num)
6697 {
6698  char arv_num_str[11];
6699  int len;
6700 
6701  assert (last_deleted_arv_num >= -1);
6702  if (lockf_vdes == NULL_VOLDES || last_deleted_arv_num < -1)
6703  {
6704  return ER_FAILED;
6705  }
6706 
6707  snprintf (arv_num_str, sizeof (arv_num_str), "%-10d", last_deleted_arv_num);
6708 
6709  if ((lseek (lockf_vdes, 0, SEEK_SET) != 0))
6710  {
6711  return ER_FAILED;
6712  }
6713 
6714  len = write (lockf_vdes, arv_num_str, sizeof (arv_num_str) - 1);
6715  if (len != (sizeof (arv_num_str) - 1))
6716  {
6717  return ER_FAILED;
6718  }
6719 
6720  return NO_ERROR;
6721 }
6722 
6723 static int
6724 la_lock_dbname (int *lockf_vdes, char *db_name, char *log_path)
6725 {
6726  int error = NO_ERROR;
6727  FILEIO_LOCKF_TYPE result;
6728 
6729  if (*lockf_vdes != NULL_VOLDES)
6730  {
6731  return NO_ERROR;
6732  }
6733 
6734  while (1)
6735  {
6736  result = fileio_lock_la_dbname (lockf_vdes, db_name, log_path);
6737  if (result == FILEIO_LOCKF)
6738  {
6739  break;
6740  }
6741 
6742  LA_SLEEP (3, 0);
6743  }
6744 
6745  assert_release ((*lockf_vdes) != NULL_VOLDES);
6746 
6747  la_Info.is_role_changed = false;
6748 
6749  return error;
6750 }
6751 
6752 
6753 static int
6754 la_unlock_dbname (int *lockf_vdes, char *db_name, bool clear_owner)
6755 {
6756  int error = NO_ERROR;
6757  int result;
6758 
6759  if ((*lockf_vdes) == NULL_VOLDES)
6760  {
6761  return NO_ERROR;
6762  }
6763 
6764  result = fileio_unlock_la_dbname (lockf_vdes, db_name, clear_owner);
6765  if (result == FILEIO_LOCKF)
6766  {
6767  return ER_FAILED;
6768  }
6769 
6770  la_Info.is_role_changed = false;
6771 
6772  if (clear_owner)
6773  {
6774  LA_SLEEP (60, 0);
6775  }
6776 
6777  return error;
6778 }
6779 
6780 static void
6781 la_init (const char *log_path, const int max_mem_size)
6782 {
6783  static unsigned long start_vsize = 0;
6784 
6785  memset (&la_Info, 0, sizeof (la_Info));
6786 
6787  strncpy (la_Info.log_path, log_path, PATH_MAX - 1);
6788 
6792 
6793  la_Info.act_log.log_vdes = NULL_VOLDES;
6794  la_Info.arv_log.log_vdes = NULL_VOLDES;
6795 
6796  LSA_SET_NULL (&la_Info.committed_lsa);
6797  LSA_SET_NULL (&la_Info.committed_rep_lsa);
6798  LSA_SET_NULL (&la_Info.append_lsa);
6799  LSA_SET_NULL (&la_Info.eof_lsa);
6800  LSA_SET_NULL (&la_Info.required_lsa);
6801  LSA_SET_NULL (&la_Info.final_lsa);
6802  LSA_SET_NULL (&la_Info.last_committed_lsa);
6804 
6805  la_Info.last_deleted_archive_num = -1;
6806  la_Info.is_role_changed = false;
6807  la_Info.is_apply_info_updated = false;
6808 
6809  la_Info.max_mem_size = max_mem_size;
6810  /* check vsize when it started */
6811  if (!start_vsize)
6812  {
6813  start_vsize = la_get_mem_size ();
6814  }
6815  la_Info.start_vsize = start_vsize;
6816  la_Info.start_time = time (NULL);
6817 
6818  la_Info.last_time_archive_deleted = la_Info.start_time;
6819 
6820  la_Info.db_lockf_vdes = NULL_VOLDES;
6821 
6822  la_Info.num_unflushed = 0;
6823 
6824  la_recdes_pool.is_initialized = false;
6825 
6827  {
6828  ws_init_repl_objs ();
6829  }
6830 
6831  la_Info.repl_filter.type = REPL_FILTER_NONE;
6832  la_Info.repl_filter.list_size = 0;
6833  la_Info.repl_filter.num_filters = 0;
6834 
6835  la_Info.reinit_copylog = false;
6836 
6837 #ifdef UNSTABLE_TDE_FOR_REPLICATION_LOG
6838  la_Info.tde_sock_for_dks = -1;
6839 #endif /* UNSTABLE_TDE_FOR_REPLICATION_LOG */
6840 
6841  return;
6842 }
6843 
6844 static void
6846 {
6847  int i;
6848 
6849  /* clean up */
6850  if (la_Info.arv_log.log_vdes != NULL_VOLDES)
6851  {
6852  fileio_close (la_Info.arv_log.log_vdes);
6853  la_Info.arv_log.log_vdes = NULL_VOLDES;
6854  }
6855  if (la_Info.act_log.log_vdes != NULL_VOLDES)
6856  {
6857  fileio_close (la_Info.act_log.log_vdes);
6858  la_Info.act_log.log_vdes = NULL_VOLDES;
6859  }
6860  if (la_Info.log_path_lockf_vdes != NULL_VOLDES)
6861  {
6863  la_Info.log_path_lockf_vdes = NULL_VOLDES;
6864  }
6865 
6866  if (la_Info.db_lockf_vdes != NULL_VOLDES)
6867  {
6868  int error;
6869  bool clear_owner = false;
6870 
6871  error = la_unlock_dbname (&la_Info.db_lockf_vdes, la_slave_db_name, clear_owner);
6872  if (error == NO_ERROR)
6873  {
6874  la_Info.db_lockf_vdes = NULL_VOLDES;
6875  }
6876  else
6877  {
6878  assert_release (false);
6879  }
6880  }
6881 
6882  if (la_Info.rec_type != NULL)
6883  {
6884  free_and_init (la_Info.rec_type);
6885  }
6886 
6887  if (la_Info.undo_unzip_ptr != NULL)
6888  {
6889  log_zip_free (la_Info.undo_unzip_ptr);
6890  la_Info.undo_unzip_ptr = NULL;
6891  }
6892  if (la_Info.redo_unzip_ptr != NULL)
6893  {
6894  log_zip_free (la_Info.redo_unzip_ptr);
6895  la_Info.redo_unzip_ptr = NULL;
6896  }
6897 
6898  if (la_Info.cache_pb != NULL)
6899  {
6900  if (la_Info.cache_pb->buffer_area != NULL)
6901  {
6902  free_and_init (la_Info.cache_pb->buffer_area);
6903  }
6904 
6905  if (la_Info.cache_pb->log_buffer != NULL)
6906  {
6907  free_and_init (la_Info.cache_pb->log_buffer);
6908  }
6909 
6910  if (la_Info.cache_pb->hash_table != NULL)
6911  {
6912  mht_destroy (la_Info.cache_pb->hash_table);
6913  la_Info.cache_pb->hash_table = NULL;
6914  }
6915 
6916  free_and_init (la_Info.cache_pb);
6917  }
6918 
6919  if (la_Info.repl_lists)
6920  {
6921  for (i = 0; i < la_Info.repl_cnt; i++)
6922  {
6923  if (la_Info.repl_lists[i] != NULL)
6924  {
6925  free_and_init (la_Info.repl_lists[i]);
6926  }
6927  }
6928 
6929  free_and_init (la_Info.repl_lists);
6930  }
6931 
6932  if (la_Info.act_log.hdr_page)
6933  {
6934  free_and_init (la_Info.act_log.hdr_page);
6935  }
6936 
6938  {
6940  }
6941 
6942  if (la_recdes_pool.is_initialized == true)
6943  {
6945  }
6946 
6947  la_Info.num_unflushed = 0;
6948 
6950 
6951  la_Info.reinit_copylog = false;
6952 
6953  return;
6954 }
6955 
6956 /*
6957  * la_print_log_header () -
6958  */
6959 void
6960 la_print_log_header (const char *database_name, LOG_HEADER * hdr, bool verbose)
6961 {
6962  time_t tloc;
6963  DB_DATETIME datetime;
6964  char timebuf[1024];
6965 
6966  tloc = hdr->db_creation;
6967  db_localdatetime (&tloc, &datetime);
6968  db_datetime_to_string ((char *) timebuf, 1024, &datetime);
6969 
6970  if (verbose)
6971  {
6972  printf ("%-30s : %s\n", "Magic", hdr->magic);
6973  }
6974  printf ("%-30s : %s\n", "DB name", database_name);
6975  printf ("%-30s : %s (%ld)\n", "DB creation time", timebuf, tloc);
6976  printf ("%-30s : %lld | %d\n", "EOF LSA", (long long int) hdr->eof_lsa.pageid, (int) hdr->eof_lsa.offset);
6977  printf ("%-30s : %lld | %d\n", "Append LSA", (long long int) hdr->append_lsa.pageid, (int) hdr->append_lsa.offset);
6978  printf ("%-30s : %s\n", "HA server state", css_ha_server_state_string ((HA_SERVER_STATE) hdr->ha_server_state));
6979  if (verbose)
6980  {
6981  printf ("%-30s : %s\n", "CUBRID release", hdr->db_release);
6982  printf ("%-30s : %d\n", "DB iopagesize", hdr->db_iopagesize);
6983  printf ("%-30s : %d\n", "DB logpagesize", hdr->db_logpagesize);
6984  printf ("%-30s : %d\n", "Is log shutdown", hdr->is_shutdown);
6985  printf ("%-30s : %d\n", "Next transaction identifier", hdr->next_trid);
6986  printf ("%-30s : %d\n", "Number of pages", hdr->npages);
6987  printf ("%-30s : %d (%s)\n", "Charset", hdr->db_charset,
6989  printf ("%-30s : %lld\n", "Logical pageid", (long long int) hdr->fpageid);
6990  printf ("%-30s : %lld | %d\n", "CHKPT LSA", (long long int) hdr->chkpt_lsa.pageid, (int) hdr->chkpt_lsa.offset);
6991  printf ("%-30s : %lld\n", "Next archive pageid", (long long int) hdr->nxarv_pageid);
6992  printf ("%-30s : %lld\n", "Next archive physical pageid", (long long int) hdr->nxarv_phy_pageid);
6993  printf ("%-30s : %d\n", "Next archive number", hdr->nxarv_num);
6994  printf ("%-30s : %s\n", "HA file status",
6996  }
6997 
6998 
6999  tloc = hdr->ha_promotion_time;
7000  db_localdatetime (&tloc, &datetime);
7001  db_datetime_to_string ((char *) timebuf, 1024, &datetime);
7002  printf ("%-30s : %s (%ld)\n", "HA promotion time", timebuf, tloc);
7003 
7004  tloc = hdr->db_restore_time;
7005  db_localdatetime (&tloc, &datetime);
7006  db_datetime_to_string ((char *) timebuf, 1024, &datetime);
7007  printf ("%-30s : %s (%ld)\n", "DB restore time", timebuf, tloc);
7008 
7009  printf ("%-30s : %s \n", "Mark will be deleted", (hdr->mark_will_del == true) ? "true" : "false");
7010 
7011  return;
7012 }
7013 
7014 /*
7015  * la_print_log_arv_header () -
7016  */
7017 void
7018 la_print_log_arv_header (const char *database_name, LOG_ARV_HEADER * hdr, bool verbose)
7019 {
7020  time_t tloc;
7021  DB_DATETIME datetime;
7022  char timebuf[1024];
7023 
7024  tloc = hdr->db_creation;
7025  db_localdatetime (&tloc, &datetime);
7026  db_datetime_to_string ((char *) timebuf, 1024, &datetime);
7027 
7028  printf ("%-30s : %s\n", "DB name ", database_name);
7029  printf ("%-30s : %s (%ld)\n", "DB creation time ", timebuf, tloc);
7030  if (verbose)
7031  {
7032  printf ("%-30s : %d\n", "Next transaction identifier", hdr->next_trid);
7033  printf ("%-30s : %d\n", "Number of pages", hdr->npages);
7034  printf ("%-30s : %lld\n", "Logical pageid", (long long int) hdr->fpageid);
7035  }
7036  printf ("%-30s : %d\n", "Archive number", hdr->arv_num);
7037 }
7038 
7039 /*
7040  * la_log_page_check() - test the transaction log
7041  * return: void
7042  * log_path: log path
7043  * page_num: test page number
7044  */
7045 int
7046 la_log_page_check (const char *database_name, const char *log_path, INT64 page_num, bool check_applied_info,
7047  bool check_copied_info, bool check_replica_info, bool verbose, LOG_LSA * copied_eof_lsa,
7048  LOG_LSA * copied_append_lsa, LOG_LSA * applied_final_lsa)
7049 {
7050  int error = NO_ERROR;
7051  int res;
7052  char *atchar;
7053  char active_log_path[PATH_MAX];
7054  char *replica_time_bound_str;
7055 
7056  assert (database_name != NULL);
7057  assert (log_path != NULL);
7058 
7059  atchar = (char *) strchr (database_name, '@');
7060  if (atchar)
7061  {
7062  *atchar = '\0';
7063  }
7064 
7065  /* init la_Info */
7066  la_init (log_path, 0);
7067 
7068  if (check_applied_info)
7069  {
7070  LA_HA_APPLY_INFO ha_apply_info;
7071  char timebuf[1024];
7072 
7073  la_init_ha_apply_info (&ha_apply_info);
7074 
7075  res = la_get_ha_apply_info (log_path, database_name, &ha_apply_info);
7076  if ((res <= 0) || (ha_apply_info.creation_time.date == 0 && ha_apply_info.creation_time.time == 0))
7077  {
7078  error = res;
7079 
7080  goto check_applied_info_end;
7081  }
7082 
7083  *applied_final_lsa = ha_apply_info.final_lsa;
7084 
7085  printf ("\n *** Applied Info. *** \n");
7086 
7087  if (verbose)
7088  {
7089  db_datetime_to_string ((char *) timebuf, 1024, &ha_apply_info.creation_time);
7090  printf ("%-30s : %s\n", "DB creation time", timebuf);
7091 
7092  printf ("%-30s : %lld | %d\n", "Last committed LSA", LSA_AS_ARGS (&ha_apply_info.committed_lsa));
7093  printf ("%-30s : %lld | %d\n", "Last committed replog LSA", LSA_AS_ARGS (&ha_apply_info.committed_rep_lsa));
7094  printf ("%-30s : %lld | %d\n", "Last append LSA", LSA_AS_ARGS (&ha_apply_info.append_lsa));
7095  printf ("%-30s : %lld | %d\n", "Last EOF LSA", LSA_AS_ARGS (&ha_apply_info.eof_lsa));
7096  printf ("%-30s : %lld | %d\n", "Final LSA", LSA_AS_ARGS (&ha_apply_info.final_lsa));
7097  printf ("%-30s : %lld | %d\n", "Required LSA", LSA_AS_ARGS (&ha_apply_info.required_lsa));
7098 
7099  db_datetime_to_string ((char *) timebuf, 1024, &ha_apply_info.log_record_time);
7100  printf ("%-30s : %s\n", "Log record time", timebuf);
7101 
7102  db_datetime_to_string ((char *) timebuf, 1024, &ha_apply_info.log_commit_time);
7103  printf ("%-30s : %s\n", "Log committed time", timebuf);
7104 
7105  db_datetime_to_string ((char *) timebuf, 1024, &ha_apply_info.last_access_time);
7106  printf ("%-30s : %s\n", "Last access time", timebuf);
7107  }
7108 
7109  printf ("%-30s : %ld\n", "Insert count", ha_apply_info.insert_counter);
7110  printf ("%-30s : %ld\n", "Update count", ha_apply_info.update_counter);
7111  printf ("%-30s : %ld\n", "Delete count", ha_apply_info.delete_counter);
7112  printf ("%-30s : %ld\n", "Schema count", ha_apply_info.schema_counter);
7113  printf ("%-30s : %ld\n", "Commit count", ha_apply_info.commit_counter);
7114  printf ("%-30s : %ld\n", "Fail count", ha_apply_info.fail_counter);
7115 
7116  if (verbose)
7117  {
7118  db_datetime_to_string ((char *) timebuf, 1024, &ha_apply_info.start_time);
7119  printf ("%-30s : %s\n", "Start time", timebuf);
7120  }
7121 
7122  if (check_replica_info)
7123  {
7124  replica_time_bound_str = prm_get_string_value (PRM_ID_HA_REPLICA_TIME_BOUND);
7125  db_datetime_to_string2 ((char *) timebuf, 1024, &ha_apply_info.log_record_time);
7126 
7127  printf ("\n *** Replica-specific Info. *** \n");
7128  if (replica_time_bound_str == NULL)
7129  {
7130  printf ("%-30s : %d second(s)\n", "Deliberate lag",
7132  }
7133 
7134  printf ("%-30s : %s\n", "Last applied log record time", timebuf);
7135  if (replica_time_bound_str != NULL)
7136  {
7137  printf ("%-30s : %s\n", "Will apply log records up to", replica_time_bound_str);
7138  }
7139  }
7140  }
7141 check_applied_info_end:
7142  if (error != NO_ERROR)
7143  {
7144  printf ("%s\n", db_error_string (3));
7145  }
7146  error = NO_ERROR;
7147 
7148  if (check_copied_info)
7149  {
7150  /* check active log file */
7151  memset (active_log_path, 0, PATH_MAX);
7152  fileio_make_log_active_name ((char *) active_log_path, la_Info.log_path, database_name);
7153  if (!fileio_is_volume_exist ((const char *) active_log_path))
7154  {
7156  error = ER_LOG_MOUNT_FAIL;
7157  goto check_copied_info_end;
7158  }
7159 
7160  /* read copied active page */
7161  error = la_find_log_pagesize (&la_Info.act_log, la_Info.log_path, database_name, false);
7162  if (error != NO_ERROR)
7163  {
7164  goto check_copied_info_end;
7165  }
7166 
7167  *copied_eof_lsa = la_Info.act_log.log_hdr->eof_lsa;
7168  *copied_append_lsa = la_Info.act_log.log_hdr->append_lsa;
7169 
7170  printf ("\n *** Copied Active Info. *** \n");
7171  la_print_log_header (database_name, la_Info.act_log.log_hdr, verbose);
7172  }
7173 
7174  if (check_copied_info && (page_num > 1))
7175  {
7176  LOG_PAGE *logpage;
7177 
7178  /* get last deleted archive number */
7179  if (la_Info.last_deleted_archive_num == (-1))
7180  {
7182  }
7183 
7184  la_Info.log_data = (char *) malloc (la_Info.act_log.db_iopagesize);
7185  if (la_Info.log_data == NULL)
7186  {
7188  error = ER_OUT_OF_VIRTUAL_MEMORY;
7189  goto check_copied_info_end;
7190  }
7191 
7192  logpage = (LOG_PAGE *) la_Info.log_data;
7193 
7194  if (LA_LOG_IS_IN_ARCHIVE (page_num))
7195  {
7196  /* read from the archive log file */
7197  printf ("\n *** Copied Archive Info. *** \n");
7198  error = la_log_fetch_from_archive (page_num, (char *) logpage);
7199  }
7200  else
7201  {
7202  /* read from the active log file */
7203  error =
7204  la_log_io_read (la_Info.act_log.path, la_Info.act_log.log_vdes, logpage, la_log_phypageid (page_num),
7205  la_Info.act_log.db_logpagesize);
7206 
7207 #ifdef UNSTABLE_TDE_FOR_REPLICATION_LOG
7208  if (error != NO_ERROR && LOG_IS_PAGE_TDE_ENCRYPTED (logpage))
7209  {
7210  error = tde_decrypt_log_page (logpage, logwr_get_tde_algorithm (logpage), logpage);
7211  if (error != NO_ERROR)
7212  {
7213  goto check_copied_info_end;
7214  }
7215  }
7216 #endif /* UNSTABLE_TDE_FOR_REPLICATION_LOG */
7217  }
7218 
7219  if (error != NO_ERROR)
7220  {
7221  goto check_copied_info_end;
7222  }
7223  else
7224  {
7225  LOG_RECORD_HEADER *lrec;
7226  LOG_LSA lsa;
7227 
7228  if (LA_LOG_IS_IN_ARCHIVE (page_num))
7229  {
7230  la_print_log_arv_header (database_name, la_Info.arv_log.log_hdr, verbose);
7231  }
7232  printf ("Log page %lld (phy: %lld pageid: %lld, offset %d)\n", (long long int) page_num,
7233  (long long int) la_log_phypageid (page_num), (long long int) logpage->hdr.logical_pageid,
7234  logpage->hdr.offset);
7235 
7236  if (logpage->hdr.offset < 0)
7237  {
7238  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HA_GENERIC_ERROR, 1, "Invalid pageid");
7239  error = ER_HA_GENERIC_ERROR;
7240  goto check_copied_info_end;
7241  }
7242 
7243  lsa.pageid = logpage->hdr.logical_pageid;
7244  lsa.offset = logpage->hdr.offset;
7245 
7246  while (lsa.pageid == page_num)
7247  {
7248  lrec = LOG_GET_LOG_RECORD_HEADER (logpage, &lsa);
7249 
7250  printf ("offset:%04ld (tid:%d bck p:%lld,o:%ld frw p:%lld,o:%ld type:%d)\n", lsa.offset, lrec->trid,
7251  (long long int) lrec->back_lsa.pageid, lrec->back_lsa.offset,
7252  (long long int) lrec->forw_lsa.pageid, lrec->forw_lsa.offset, lrec->type);
7253  LSA_COPY (&lsa, &lrec->forw_lsa);
7254  }
7255  }
7256  free_and_init (la_Info.log_data);
7257  } /* check_copied_info */
7258 
7259 check_copied_info_end:
7260  if (error != NO_ERROR)
7261  {
7262  printf ("%s\n", db_error_string (3));
7263  }
7264 
7265  return NO_ERROR;
7266 }
7267 
7268 void
7269 la_print_delay_info (LOG_LSA working_lsa, LOG_LSA target_lsa, float process_rate)
7270 {
7271  INT64 delayed_page_count = 0;
7272  INT64 estimated_delay = 0;
7273 
7274  delayed_page_count = target_lsa.pageid - working_lsa.pageid;
7275 
7276  if (process_rate != 0.0f)
7277  {
7278  estimated_delay = (INT64) (delayed_page_count / process_rate);
7279  }
7280 
7281  printf ("%-30s : %lld\n", "Delayed log page count", (long long int) delayed_page_count);
7282 
7283  if (process_rate == 0.0f)
7284  {
7285  printf ("%-30s : - second(s)\n", "Estimated Delay");
7286  }
7287  else
7288  {
7289  printf ("%-30s : %ld second(s)\n", "Estimated Delay", estimated_delay);
7290  }
7291 }
7292 
7293 /*
7294  * la_remove_archive_logs() -
7295  * return: int
7296  *
7297  * db_name(in):
7298  * last_deleted_arv_num(in):
7299  * nxarv_num(in):
7300  * max_count_arv_to_delete(in): max number of archive files to remove
7301  */
7302 int
7303 la_remove_archive_logs (const char *db_name, int last_deleted_arv_num, int nxarv_num, int max_arv_count_to_delete)
7304 {
7305  int error = NO_ERROR;
7306  int log_max_archives = prm_get_integer_value (PRM_ID_HA_COPY_LOG_MAX_ARCHIVES);
7307  const char *info_reason, *catmsg;
7308  char archive_name[PATH_MAX] = { '\0', }, archive_name_first[PATH_MAX];
7309  int first_arv_num_to_delete = -1;
7310  int last_arv_num_to_delete = -1;
7311  int required_arv_num = -1;
7312  int max_arv_count;
7313  int current_arv_count;
7314  int i;
7315 
7317  {
7318  error = la_find_archive_num (&required_arv_num, la_Info.required_lsa.pageid);
7319  if (error != NO_ERROR)
7320  {
7321  return last_deleted_arv_num;
7322  }
7323  max_arv_count = MAX (log_max_archives, nxarv_num - required_arv_num);
7324  }
7325  else
7326  {
7327  max_arv_count = log_max_archives;
7328  }
7329 
7330  current_arv_count = nxarv_num - last_deleted_arv_num - 1;
7331  if (current_arv_count > max_arv_count)
7332  {
7333  first_arv_num_to_delete = last_deleted_arv_num + 1;
7334  last_arv_num_to_delete = nxarv_num - max_arv_count - 1;
7335  if ((last_arv_num_to_delete < 0) || (last_arv_num_to_delete < first_arv_num_to_delete))
7336  {
7337  return last_deleted_arv_num;
7338  }
7339 
7340  if (max_arv_count_to_delete < last_arv_num_to_delete - first_arv_num_to_delete + 1)
7341  {
7342  last_arv_num_to_delete = first_arv_num_to_delete + max_arv_count_to_delete - 1;
7343  }
7344 
7345  for (i = first_arv_num_to_delete; i <= last_arv_num_to_delete; i++)
7346  {
7347  fileio_make_log_archive_name (archive_name, la_Info.log_path, db_name, i);
7348  fileio_unformat (NULL, archive_name);
7349  }
7350 
7352  if (info_reason == NULL)
7353  {
7354  info_reason = "Number of active log archives has been exceeded the max desired number.";
7355  }
7357  if (catmsg == NULL)
7358  {
7359  catmsg = "REMOVE: %d %s to \n%d %s.\nREASON: %s\n";
7360  }
7361  if (first_arv_num_to_delete == last_arv_num_to_delete)
7362  {
7363  log_dump_log_info (la_Info.loginf_path, false, catmsg, first_arv_num_to_delete, archive_name,
7364  last_arv_num_to_delete, archive_name, info_reason);
7365  }
7366  else
7367  {
7368  fileio_make_log_archive_name (archive_name_first, la_Info.log_path, db_name, first_arv_num_to_delete);
7369  log_dump_log_info (la_Info.loginf_path, false, catmsg, first_arv_num_to_delete, archive_name_first,
7370  last_arv_num_to_delete, archive_name, info_reason);
7371  }
7372  return last_arv_num_to_delete;
7373  }
7374 
7375  return last_deleted_arv_num;
7376 }
7377 
7378 static int
7380 {
7381  int arv_log_num;
7382  char arv_log_path[PATH_MAX];
7383  int arv_log_vdes = NULL_VOLDES;
7384 
7385  arv_log_num = la_Info.act_log.log_hdr->nxarv_num - 1;
7386  while (arv_log_num >= 0)
7387  {
7388  /* make archive_name */
7389  fileio_make_log_archive_name (arv_log_path, la_Info.log_path, la_Info.act_log.log_hdr->prefix_name, arv_log_num);
7390 
7391  /* open the archive file */
7392  arv_log_vdes = fileio_open (arv_log_path, O_RDONLY, 0);
7393  if (arv_log_vdes == NULL_VOLDES)
7394  {
7395  break;
7396  }
7397 
7398  fileio_close (arv_log_vdes);
7399  arv_log_num--;
7400  }
7401 
7402  return arv_log_num;
7403 }
7404 
7405 static float
7406 la_get_avg (int *array, int size)
7407 {
7408  int i, total = 0;
7409 
7410  assert (size > 0);
7411 
7412  for (i = 0; i < size; i++)
7413  {
7414  total += array[i];
7415  }
7416 
7417  return (float) total / size;
7418 }
7419 
7420 /*
7421  * la_get_adaptive_time_commit_interval () - adjust commit interval
7422  * based on the replication delay
7423  * time_commit_interval(in/out): commit interval
7424  * delay_hist(in): delay history
7425  * return: none
7426  */
7427 static void
7428 la_get_adaptive_time_commit_interval (int *time_commit_interval, int *delay_hist)
7429 {
7430  int delay;
7431  int max_commit_interval;
7432  float avg_delay;
7433  static int delay_hist_idx = 0;
7434 
7435  if (la_Info.log_record_time != 0)
7436  {
7437  delay = time (NULL) - la_Info.log_record_time;
7438  }
7439  else
7440  {
7441  return;
7442  }
7443 
7445 
7446  if (delay > LA_MAX_TOLERABLE_DELAY)
7447  {
7448  *time_commit_interval = max_commit_interval;
7449  }
7450  else if (delay == 0)
7451  {
7452  *time_commit_interval /= 2;
7453  }
7454  /* check if delay history is filled up */
7455  else if (delay_hist[delay_hist_idx] >= 0)
7456  {
7457  avg_delay = la_get_avg (delay_hist, LA_NUM_DELAY_HISTORY);
7458 
7459  if (delay < avg_delay)
7460  {
7461  *time_commit_interval /= 2;
7462  }
7463  else if (delay > avg_delay)
7464  {
7465  *time_commit_interval *= 2;
7466 
7467  if (*time_commit_interval == 0)
7468  {
7469  *time_commit_interval = LA_REINIT_COMMIT_INTERVAL;
7470  }
7471  else if (*time_commit_interval > max_commit_interval)
7472  {
7473  *time_commit_interval = max_commit_interval;
7474  }
7475  }
7476  }
7477 
7478  delay_hist[delay_hist_idx++] = delay;
7479  delay_hist_idx %= LA_NUM_DELAY_HISTORY;
7480 
7481  return;
7482 }
7483 
7484 /*
7485  * la_print_repl_filter_info() - print replication filter info
7486  * return: none
7487  *
7488  */
7489 static void
7491 {
7492  char buffer[LINE_MAX];
7493  char *p, *last;
7494  int i;
7495  LA_REPL_FILTER *filter;
7496 
7497  p = buffer;
7498  last = buffer + sizeof (buffer);
7499 
7500  filter = &la_Info.repl_filter;
7501 
7502  if (filter->type == REPL_FILTER_NONE || filter->num_filters <= 0)
7503  {
7504  return;
7505  }
7506 
7507  if (filter->type == REPL_FILTER_INCLUDE_TBL)
7508  {
7509  p += snprintf (p, MAX ((last - p), 0), "updates only on the following tables will be applied: ");
7510  }
7511  else if (filter->type == REPL_FILTER_EXCLUDE_TBL)
7512  {
7513  p += snprintf (p, MAX ((last - p), 0), "updates on the following tables will be ignored: ");
7514  }
7515 
7516  p += snprintf (p, MAX ((last - p), 0), "[%s]", filter->list[0]);
7517  for (i = 1; i < filter->num_filters; i++)
7518  {
7519  p += snprintf (p, MAX (last - p, 0), ", [%s]", filter->list[i]);
7520  }
7521 
7522  er_stack_push ();
7524  er_stack_pop ();
7525 
7526  return;
7527 }
7528 
7529 /*
7530  * la_need_filter_out() - check if an item needs to be applied or not.
7531  * item (in): replication item
7532  * return: true when to exclude the given item for replication
7533  *
7534  */
7535 static bool
7537 {
7538  LA_REPL_FILTER *filter;
7539  bool filter_found = false;
7540  int i;
7541 
7542  filter = &la_Info.repl_filter;
7543 
7544  if (filter->type == REPL_FILTER_NONE
7546  || strcasecmp (item->class_name, CT_SERIAL_NAME) == 0)
7547  {
7548  return false;
7549  }
7550 
7551  assert (item != NULL && item->class_name != NULL);
7552 
7553  for (i = 0; i < filter->num_filters; i++)
7554  {
7555  if (strcasecmp (filter->list[i], item->class_name) == 0)
7556  {
7557  filter_found = true;
7558  break;
7559  }
7560  }
7561 
7562  if ((filter->type == REPL_FILTER_INCLUDE_TBL && filter_found == false)
7563  || (filter->type == REPL_FILTER_EXCLUDE_TBL && filter_found == true))
7564  {
7565  return true;
7566  }
7567 
7568  return false;
7569 }
7570 
7571 /*
7572  * la_add_repl_filter() - add a table to filter list
7573  * return: error
7574  *
7575  */
7576 static int
7577 la_add_repl_filter (const char *classname)
7578 {
7579  LA_REPL_FILTER *filter;
7580 
7581  filter = &la_Info.repl_filter;
7582 
7583  assert (filter != NULL);
7584  assert (filter->list != NULL && filter->list_size > 0);
7585 
7586  if (classname == NULL || classname[0] == '\0')
7587  {
7588  return NO_ERROR;
7589  }
7590 
7591  if (filter->num_filters >= filter->list_size)
7592  {
7593  filter->list = (char **) realloc (filter->list, (filter->list_size + LA_NUM_REPL_FILTER) * sizeof (char *));
7594  if (filter->list == NULL)
7595  {
7597  return ER_OUT_OF_VIRTUAL_MEMORY;
7598  }
7599 
7600  filter->list_size += LA_NUM_REPL_FILTER;
7601  }
7602 
7603  filter->list[filter->num_filters] = strdup (classname);
7604 
7605  if (filter->list[filter->num_filters] == NULL)
7606  {
7608  return ER_OUT_OF_VIRTUAL_MEMORY;
7609  }
7610  else
7611  {
7612  filter->num_filters++;
7613  }
7614 
7615  return NO_ERROR;
7616 }
7617 
7618 /*
7619  * la_create_repl_filter() - read replication filter file and setup filters
7620  * return: error
7621  *
7622  */
7623 static int
7625 {
7626  int error = NO_ERROR;
7627  char *filter_file;
7628  char filter_file_real_path[PATH_MAX];
7629  char buffer[LINE_MAX];
7630  char error_msg[LINE_MAX];
7631  char classname[SM_MAX_IDENTIFIER_LENGTH];
7632  int classname_len = 0;
7633  LA_REPL_FILTER *filter;
7634  FILE *fp;
7635  DB_OBJECT *class_ = NULL;
7636 
7637  filter = &la_Info.repl_filter;
7638 
7640  if (filter->type == REPL_FILTER_NONE)
7641  {
7642  return NO_ERROR;
7643  }
7644 
7646  if (filter_file == NULL || filter_file[0] == '\0')
7647  {
7648  snprintf (error_msg, LINE_MAX, "no replication filter file is specified");
7650 
7652  }
7653 
7654  if (filter_file[0] != PATH_SEPARATOR)
7655  {
7656  filter_file = envvar_confdir_file (filter_file_real_path, PATH_MAX, filter_file);
7657  }
7658 
7659  fp = fopen (filter_file, "r");
7660  if (fp == NULL)
7661  {
7662  snprintf (error_msg, LINE_MAX, "failed to open %s", filter_file);
7664 
7666  }
7667 
7668  filter->list = (char **) malloc (LA_NUM_REPL_FILTER * sizeof (char *));
7669  if (filter->list == NULL)
7670  {
7671  fclose (fp);
7673 
7674  return ER_OUT_OF_VIRTUAL_MEMORY;
7675  }
7676 
7677  filter->list_size = LA_NUM_REPL_FILTER;
7678 
7679  /* get filter table list */
7680  while (fgets ((char *) buffer, LINE_MAX, fp) != NULL)
7681  {
7682  trim (buffer);
7683  classname_len = strlen (buffer);
7684  if (classname_len > 0 && buffer[classname_len - 1] == '\n')
7685  {
7686  buffer[classname_len - 1] = '\0';
7687  classname_len--;
7688  }
7689 
7690  if (classname_len <= 0)
7691  {
7692  continue;
7693  }
7694 
7695  if (classname_len >= SM_MAX_IDENTIFIER_LENGTH)
7696  {
7697  snprintf_dots_truncate (error_msg, LINE_MAX - 1, "invalid table name %s", buffer);
7700 
7701  goto error_return;
7702  }
7703 
7704  sm_downcase_name (buffer, classname, SM_MAX_IDENTIFIER_LENGTH);
7705 
7706  class_ = locator_find_class (classname);
7707  if (class_ == NULL)
7708  {
7709  snprintf_dots_truncate (error_msg, LINE_MAX - 1, "cannot find table [%s] listed in %s", buffer, filter_file);
7710  er_stack_push ();
7712  er_stack_pop ();
7713  }
7714  else
7715  {
7716  ws_release_user_instance (class_);
7717  ws_decache (class_);
7718  }
7719 
7720  error = la_add_repl_filter (classname);
7721  if (error != NO_ERROR)
7722  {
7723  goto error_return;
7724  }
7725  }
7726 
7727  ws_cull_mops ();
7728 
7729  fclose (fp);
7730  return NO_ERROR;
7731 
7732 error_return:
7733  fclose (fp);
7735 
7736  return error;
7737 }
7738 
7739 /*
7740  * la_destroy_repl_filter() - free memory used for replication filter
7741  * return: none
7742  *
7743  */
7744 static void
7746 {
7747  int i;
7748  LA_REPL_FILTER *filter;
7749 
7750  filter = &la_Info.repl_filter;
7751 
7752  if (filter->list_size > 0 && filter->list != NULL)
7753  {
7754  for (i = 0; i < filter->num_filters; i++)
7755  {
7756  if (filter->list[i] != NULL)
7757  {
7758  free_and_init (filter->list[i]);
7759  }
7760  }
7761  free_and_init (filter->list);
7762  }
7763 
7764  filter->list_size = 0;
7765  filter->num_filters = 0;
7766 
7767  return;
7768 }
7769 
7770 static int
7772 {
7773  int error = NO_ERROR;
7774 
7775  /* fetch header */
7776  error = la_fetch_log_hdr (&la_Info.act_log);
7777  if (error != NO_ERROR)
7778  {
7779  error = ER_FAILED;
7780  return error;
7781  }
7782 
7783  if (la_Info.act_log.log_hdr->mark_will_del == true)
7784  {
7785  la_Info.reinit_copylog = true;
7786  error = ER_FAILED;
7787  return error;
7788  }
7789 
7790  return error;
7791 }
7792 
7793 /*
7794  * la_apply_log_file() - apply the transaction log to the slave
7795  * return: int
7796  * database_name: apply database
7797  * log_path: log volume path for apply
7798  * max_mem_size: maximum memory size
7799  *
7800  * Note:
7801  * The main routine.
7802  * 1. Initialize
7803  * . signal process
7804  * . get the log file name & IO page size
7805  * 2. body (loop) - process the request
7806  * . catch the request
7807  * . if shutdown request --> process
7808  */
7809 int
7810 la_apply_log_file (const char *database_name, const char *log_path, const int max_mem_size)
7811 {
7812  int error = NO_ERROR;
7813  LOG_HEADER final_log_hdr;
7814  LA_CACHE_BUFFER *log_buf = NULL;
7815  LOG_PAGE *pg_ptr;
7816  LOG_RECORD_HEADER *lrec = NULL;
7817  LOG_LSA old_lsa = {
7818  -1, -1
7819  };
7820  LOG_LSA prev_final;
7821  struct timeval time_commit;
7822  char *s;
7823  int last_nxarv_num = 0;
7824  bool clear_owner;
7825  int now = 0, last_eof_time = 0;
7826  LOG_LSA last_eof_lsa;
7827  int time_commit_interval;
7828  int delay_hist[LA_NUM_DELAY_HISTORY];
7829  int i;
7830  int remove_arv_interval_in_secs;
7831  int max_arv_count_to_delete = 0;
7832 
7833  assert (database_name != NULL);
7834  assert (log_path != NULL);
7835 
7836  la_applier_need_shutdown = false;
7837 
7838  /* signal processing */
7839 #if defined(WINDOWS)
7840  (void) os_set_signal_handler (SIGABRT, la_shutdown_by_signal);
7842  (void) os_set_signal_handler (SIGTERM, la_shutdown_by_signal);
7843 #else /* ! WINDOWS */
7844  (void) os_set_signal_handler (SIGSTOP, la_shutdown_by_signal);
7845  (void) os_set_signal_handler (SIGTERM, la_shutdown_by_signal);
7846  (void) os_set_signal_handler (SIGPIPE, SIG_IGN);
7847 #endif /* ! WINDOWS */
7848 
7849  strncpy (la_slave_db_name, database_name, DB_MAX_IDENTIFIER_LENGTH);
7850  s = strchr (la_slave_db_name, '@');
7851  if (s)
7852  {
7853  *s = '\0';
7854  }
7855 
7856  s = la_get_hostname_from_log_path ((char *) log_path);
7857  if (s)
7858  {
7859  strncpy (la_peer_host, s, CUB_MAXHOSTNAMELEN);
7860  }
7861  else
7862  {
7863  strncpy (la_peer_host, "unknown", CUB_MAXHOSTNAMELEN);
7864  }
7865 
7866  /* init la_Info */
7867  la_init (log_path, max_mem_size);
7868 
7870  {
7871  if (sl_init (la_slave_db_name, log_path) != NO_ERROR)
7872  {
7873  er_stack_push ();
7874  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HA_GENERIC_ERROR, 1, "Failed to initialize SQL logger");
7875  er_stack_pop ();
7876  }
7877  else
7878  {
7879  la_enable_sql_logging = true;
7880  }
7881  }
7882 
7883  error =
7885  &la_Info.last_deleted_archive_num);
7886  if (error != NO_ERROR)
7887  {
7888  return error;
7889  }
7890 
7891  /* init cache buffer */
7892  la_Info.cache_pb = la_init_cache_pb ();
7893  if (la_Info.cache_pb == NULL)
7894  {
7895  er_log_debug (ARG_FILE_LINE, "Cannot initialize cache page buffer");
7896  return ER_OUT_OF_VIRTUAL_MEMORY;
7897  }
7898 
7899  /* get log header info. page size. start_page id, etc */
7900  error = la_find_log_pagesize (&la_Info.act_log, la_Info.log_path, la_slave_db_name, true);
7901  if (error != NO_ERROR)
7902  {
7903  er_log_debug (ARG_FILE_LINE, "Cannot find log page size");
7904  return error;
7905  }
7906 
7907  error =
7910  if (error != NO_ERROR)
7911  {
7912  er_log_debug (ARG_FILE_LINE, "Cannot initialize cache log buffer");
7913  return error;
7914  }
7915 
7917  if (error != NO_ERROR)
7918  {
7919  er_log_debug (ARG_FILE_LINE, "Cannot initialize recdes pool");
7920  return error;
7921  }
7922 
7923  /* get log info path */
7925 
7926  /* get last deleted archive number */
7927  if (la_Info.last_deleted_archive_num == (-1))
7928  {
7930  }
7931 
7932  remove_arv_interval_in_secs = prm_get_integer_value (PRM_ID_REMOVE_LOG_ARCHIVES_INTERVAL);
7933 
7934  /* find out the last log applied LSA */
7935  error = la_get_last_ha_applied_info ();
7936  if (error != NO_ERROR)
7937  {
7938  er_stack_push ();
7939  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HA_GENERIC_ERROR, 1, "Failed to initialize db_ha_apply_info");
7940  er_stack_pop ();
7941  return error;
7942  }
7943 
7944  for (i = 0; i < LA_NUM_DELAY_HISTORY; i++)
7945  {
7946  delay_hist[i] = -1;
7947  }
7949 
7951  {
7952  error = la_create_repl_filter ();
7953  if (error != NO_ERROR)
7954  {
7956  "failed to initialize replication filters");
7957  return error;
7958  }
7959 
7961  }
7962 
7964  la_Info.required_lsa.offset, la_Info.committed_lsa.pageid, la_Info.committed_lsa.offset,
7966 
7967  /* initialize final_lsa */
7968  LSA_COPY (&la_Info.committed_lsa, &la_Info.required_lsa);
7969 
7970  gettimeofday (&time_commit, NULL);
7971  last_eof_time = time (NULL);
7972  LSA_SET_NULL (&last_eof_lsa);
7973 #ifdef UNSTABLE_TDE_FOR_REPLICATION_LOG
7974  error = tde_get_data_keys ();
7975  if (error == NO_ERROR)
7976  {
7977  tde_Cipher.is_loaded = true;
7978  error = la_start_dk_sharing ();
7979  if (error != NO_ERROR)
7980  {
7981  return error;
7982  }
7983  }
7984 #endif /* UNSTABLE_TDE_FOR_REPLICATION_LOG */
7985 
7986  /* start the main loop */
7987  do
7988  {
7989  int retry_count = 0;
7990 
7991  /* get next LSA to be processed */
7992  if (la_apply_pre () == false)
7993  {
7994  assert (er_errid () != NO_ERROR);
7995  error = er_errid ();
7996  la_applier_need_shutdown = true;
7997  break;
7998  }
7999 
8000  /* start loop for apply */
8001  while (!LSA_ISNULL (&la_Info.final_lsa) && la_applier_need_shutdown == false)
8002  {
8003  /* release all page buffers */
8005 
8006  /* we should fetch final log page from disk not cache buffer */
8008 
8009  error = check_reinit_copylog ();
8010  if (error != NO_ERROR)
8011  {
8012  la_applier_need_shutdown = true;
8013  break;
8014  }
8015 
8016  if (last_nxarv_num == 0)
8017  {
8018  last_nxarv_num = la_Info.act_log.log_hdr->nxarv_num;
8019  }
8020 
8021  if (remove_arv_interval_in_secs == 0)
8022  {
8023  if (last_nxarv_num != la_Info.act_log.log_hdr->nxarv_num)
8024  {
8025  max_arv_count_to_delete = INT_MAX;
8026  }
8027  }
8028  else if (time (NULL) - la_Info.last_time_archive_deleted > remove_arv_interval_in_secs)
8029  {
8030  max_arv_count_to_delete = 1;
8031  }
8032 
8033  if (max_arv_count_to_delete > 0)
8034  {
8035  la_Info.last_deleted_archive_num =
8037  la_Info.act_log.log_hdr->nxarv_num, max_arv_count_to_delete);
8038  if (la_Info.last_deleted_archive_num >= 0)
8039  {
8041  }
8042  last_nxarv_num = la_Info.act_log.log_hdr->nxarv_num;
8043 
8044  la_Info.last_time_archive_deleted = time (NULL);
8045  max_arv_count_to_delete = 0;
8046  }
8047 
8048  memcpy (&final_log_hdr, la_Info.act_log.log_hdr, sizeof (LOG_HEADER));
8049 
8051  {
8052  if (final_log_hdr.ha_server_state == HA_SERVER_STATE_DEAD
8053  && LSA_EQ (&last_eof_lsa, &final_log_hdr.eof_lsa))
8054  {
8055  now = time (NULL);
8056  assert_release (now >= last_eof_time);
8057 
8059  {
8060  clear_owner = true;
8061  error = la_unlock_dbname (&la_Info.db_lockf_vdes, la_slave_db_name, clear_owner);
8062  assert_release (error == NO_ERROR);
8063  }
8064  }
8065  else
8066  {
8067  last_eof_time = time (NULL);
8068  }
8069 
8070  LSA_COPY (&last_eof_lsa, &final_log_hdr.eof_lsa);
8071  }
8072 
8073  /* check log hdr's master state */
8074  if (la_Info.apply_state == HA_LOG_APPLIER_STATE_DONE
8075  && (final_log_hdr.ha_server_state != HA_SERVER_STATE_ACTIVE)
8076  && (final_log_hdr.ha_server_state != HA_SERVER_STATE_TO_BE_STANDBY))
8077  {
8078  /* if there's no replication log to be applied, we should release dbname lock */
8079  clear_owner = true;
8080  error = la_unlock_dbname (&la_Info.db_lockf_vdes, la_slave_db_name, clear_owner);
8081  assert_release (error == NO_ERROR);
8082 
8083  if (final_log_hdr.ha_server_state != HA_SERVER_STATE_DEAD)
8084  {
8085  LSA_COPY (&la_Info.committed_lsa, &la_Info.final_lsa);
8086  }
8087 
8088  if (LSA_GE (&la_Info.final_lsa, &la_Info.committed_lsa))
8089  {
8090  er_log_debug (ARG_FILE_LINE, "lowest required page id is %lld",
8091  (long long int) la_Info.committed_lsa.pageid);
8092 
8093  error = la_log_commit (false);
8094  if (error == ER_NET_CANT_CONNECT_SERVER || error == ER_OBJ_NO_CONNECT
8096  {
8097  la_shutdown ();
8098  return error;
8099  }
8100  }
8101 
8103 
8104  LA_SLEEP (1, 0);
8105  continue;
8106  }
8107 
8108  if (final_log_hdr.eof_lsa.pageid < la_Info.final_lsa.pageid)
8109  {
8110  usleep (100 * 1000);
8111  continue;
8112  }
8113 
8114  /* get the target page from log */
8115  log_buf = la_get_page_buffer (la_Info.final_lsa.pageid);
8116  LSA_COPY (&old_lsa, &la_Info.final_lsa);
8117 
8118  if (log_buf == NULL)
8119  {
8120  if (la_applier_need_shutdown == true)
8121  {
8123  error = ER_LOG_PAGE_CORRUPTED;
8124  break;
8125  }
8126 
8127  /* it can be happend when log file is not synced yet */
8128  if (final_log_hdr.ha_file_status != LOG_HA_FILESTAT_SYNCHRONIZED)
8129  {
8130  er_log_debug (ARG_FILE_LINE, "requested pageid (%lld) is not yet exist",
8131  (long long int) la_Info.final_lsa.pageid);
8132  usleep (300 * 1000);
8133  continue;
8134  }
8135  /* request page is greater then append_lsa.(in log_header) */
8136  else if (final_log_hdr.append_lsa.pageid < la_Info.final_lsa.pageid)
8137  {
8139  "requested pageid (%lld) is greater than append_las.pageid (%lld) in log header",
8140  (long long int) la_Info.final_lsa.pageid,
8141  (long long int) final_log_hdr.append_lsa.pageid);
8142  usleep (100 * 1000);
8143  continue;
8144  }
8145 
8146  er_log_debug (ARG_FILE_LINE, "requested pageid (%lld) may be corrupted ",
8147  (long long int) la_Info.final_lsa.pageid);
8148 
8149  if (retry_count++ < LA_GET_PAGE_RETRY_COUNT)
8150  {
8151  er_log_debug (ARG_FILE_LINE, "but retry again...", la_Info.final_lsa.pageid);
8152  usleep (300 * 1000 + (retry_count * 100));
8153  continue;
8154  }
8155 
8157  error = ER_LOG_PAGE_CORRUPTED;
8158  la_applier_need_shutdown = true;
8159  break;
8160  }
8161  else
8162  {
8163  retry_count = 0;
8164  }
8165 
8166  /* check it and verify it */
8167  if (log_buf->logpage.hdr.logical_pageid == la_Info.final_lsa.pageid)
8168  {
8169  if (log_buf->logpage.hdr.offset < 0)
8170  {
8171  la_invalidate_page_buffer (log_buf);
8172  if ((final_log_hdr.ha_file_status == LOG_HA_FILESTAT_SYNCHRONIZED)
8173  && ((la_Info.final_lsa.pageid + 1) <= final_log_hdr.eof_lsa.pageid)
8175  {
8177  log_buf->logpage.hdr.logical_pageid, log_buf->logpage.hdr.offset,
8178  la_Info.final_lsa.pageid, la_Info.final_lsa.offset, final_log_hdr.append_lsa.pageid,
8179  final_log_hdr.append_lsa.offset, final_log_hdr.eof_lsa.pageid,
8180  final_log_hdr.eof_lsa.offset, final_log_hdr.ha_file_status, la_Info.is_end_of_record);
8181 
8182  /* make sure to target page does not exist */
8184  && la_Info.final_lsa.pageid < final_log_hdr.eof_lsa.pageid)
8185  {
8186  er_log_debug (ARG_FILE_LINE, "skip this page (pageid=%lld/%lld/%lld)",
8187  (long long int) la_Info.final_lsa.pageid,
8188  (long long int) final_log_hdr.eof_lsa.pageid,
8189  (long long int) final_log_hdr.append_lsa.pageid);
8190  /* skip it */
8191  la_Info.final_lsa.pageid++;
8192  la_Info.final_lsa.offset = 0;
8193  continue;
8194  }
8195  }
8196 
8197 #if defined (LA_VERBOSE_DEBUG)
8198  er_log_debug (ARG_FILE_LINE, "refetch this page... (pageid=%lld/%lld/%lld)",
8199  (long long int) la_Info.final_lsa.pageid, (long long int) final_log_hdr.eof_lsa.pageid,
8200  (long long int) final_log_hdr.append_lsa.pageid);
8201 #endif
8202  /* wait a moment and retry it */
8203  usleep (100 * 1000);
8204  continue;
8205  }
8206  else
8207  {
8208  /* we get valid page */
8209  }
8210  }
8211  else
8212  {
8214  log_buf->logpage.hdr.logical_pageid, log_buf->logpage.hdr.offset, la_Info.final_lsa.pageid,
8215  la_Info.final_lsa.offset, final_log_hdr.append_lsa.pageid, final_log_hdr.append_lsa.offset,
8216  final_log_hdr.eof_lsa.pageid, final_log_hdr.eof_lsa.offset, final_log_hdr.ha_file_status,
8217  la_Info.is_end_of_record);
8218 
8219  la_invalidate_page_buffer (log_buf);
8220  /* TODO: continue? error ? just sleep and continue? */
8221  usleep (100 * 1000);
8222 
8223  continue;
8224  }
8225 
8226  /* apply it */
8227  LSA_SET_NULL (&prev_final);
8228  pg_ptr = &(log_buf->logpage);
8229 
8230  while (la_Info.final_lsa.pageid == log_buf->pageid && la_applier_need_shutdown == false)
8231  {
8232  /* adjust the offset when the offset is 0. If we read final log record from the archive, we don't know
8233  * the exact offset of the next record, In this case, we set the offset as 0, increase the pageid. So,
8234  * before getting the log record, check the offset and adjust it */
8235  if ((la_Info.final_lsa.offset == 0) || (la_Info.final_lsa.offset == NULL_OFFSET))
8236  {
8237  la_Info.final_lsa.offset = log_buf->logpage.hdr.offset;
8238  }
8239 
8240  /* check for end of log */
8241  if (LSA_GT (&la_Info.final_lsa, &final_log_hdr.eof_lsa))
8242  {
8243 #if defined (LA_VERBOSE_DEBUG)
8245  "this page is grater than eof_lsa. (%lld|%d) > eof (%lld|%d). appended (%lld|%d)",
8246  (long long int) la_Info.final_lsa.pageid, la_Info.final_lsa.offset,
8247  (long long int) final_log_hdr.eof_lsa.pageid, final_log_hdr.eof_lsa.offset,
8248  (long long int) final_log_hdr.append_lsa.pageid, final_log_hdr.append_lsa.offset);
8249 #endif
8250  la_Info.is_end_of_record = true;
8251  /* it should be refetched and release later */
8252  la_invalidate_page_buffer (log_buf);
8253  break;
8254  }
8255  else if (LSA_GT (&la_Info.final_lsa, &final_log_hdr.append_lsa))
8256  {
8257  la_invalidate_page_buffer (log_buf);
8258  break;
8259  }
8260 
8261  lrec = LOG_GET_LOG_RECORD_HEADER (pg_ptr, &la_Info.final_lsa);
8262 
8263  if (!LSA_ISNULL (&prev_final) && !LSA_EQ (&prev_final, &lrec->back_lsa))
8264  {
8266  error = ER_LOG_PAGE_CORRUPTED;
8267  la_shutdown ();
8268  return error;
8269  }
8270 
8271  if (LSA_EQ (&la_Info.final_lsa, &final_log_hdr.eof_lsa) && lrec->type != LOG_END_OF_LOG)
8272  {
8273  la_Info.is_end_of_record = true;
8274  la_invalidate_page_buffer (log_buf);
8275  break;
8276  }
8277 
8278  /* process the log record */
8279  error = la_log_record_process (lrec, &la_Info.final_lsa, pg_ptr);
8280  if (error != NO_ERROR)
8281  {
8282  /* check connection error */
8283  if (error == ER_NET_CANT_CONNECT_SERVER || error == ER_OBJ_NO_CONNECT)
8284  {
8285  la_shutdown ();
8287  }
8288  else if (error == ER_HA_LA_EXCEED_MAX_MEM_SIZE)
8289  {
8290  la_applier_need_shutdown = true;
8291  break;
8292  }
8294  {
8295  la_shutdown ();
8296  return error;
8297  }
8298 
8299  if (error == ER_LOG_PAGE_CORRUPTED)
8300  {
8301  if (la_applier_need_shutdown == true)
8302  {
8304  error = ER_LOG_PAGE_CORRUPTED;
8305  break;
8306  }
8307  else
8308  {
8309  /* it should be refetched and release later */
8310  la_invalidate_page_buffer (log_buf);
8311  }
8312  }
8313 
8314  break;
8315  }
8316 
8317  if (!LSA_ISNULL (&lrec->forw_lsa) && LSA_GT (&la_Info.final_lsa, &lrec->forw_lsa))
8318  {
8320  error = ER_LOG_PAGE_CORRUPTED;
8321  la_shutdown ();
8322  return error;
8323  }
8324 
8325  /* set the prev/next record */
8326  LSA_COPY (&prev_final, &la_Info.final_lsa);
8327  LSA_COPY (&la_Info.final_lsa, &lrec->forw_lsa);
8328  }
8329 
8330  /* commit */
8331  la_get_adaptive_time_commit_interval (&time_commit_interval, delay_hist);
8332 
8333  error = la_check_time_commit (&time_commit, time_commit_interval);
8334  if (error != NO_ERROR)
8335  {
8336  /* check connection error */
8337  if (error == ER_NET_CANT_CONNECT_SERVER || error == ER_OBJ_NO_CONNECT
8339  {
8340  la_shutdown ();
8341  return error;
8342 
8343  }
8344  }
8345 
8346  error = la_check_mem_size ();
8347  if (error == ER_HA_LA_EXCEED_MAX_MEM_SIZE)
8348  {
8349  la_applier_need_shutdown = true;
8350  break;
8351  }
8352 
8353  /* check and change state */
8354  error = la_change_state ();
8355  if (error == ER_NET_CANT_CONNECT_SERVER || error == ER_OBJ_NO_CONNECT
8357  {
8358  la_shutdown ();
8359  return error;
8360  }
8361  else if (error != NO_ERROR)
8362  {
8363  la_applier_need_shutdown = true;
8364  break;
8365  }
8366 
8367  if (la_Info.final_lsa.pageid >= final_log_hdr.eof_lsa.pageid
8368  || la_Info.final_lsa.pageid >= final_log_hdr.append_lsa.pageid || la_Info.is_end_of_record == true)
8369  {
8370  /* it should be refetched and release */
8371  la_invalidate_page_buffer (log_buf);
8372  }
8373 
8374  if (la_Info.is_role_changed == true)
8375  {
8376  clear_owner = true;
8377  error = la_unlock_dbname (&la_Info.db_lockf_vdes, la_slave_db_name, clear_owner);
8378  assert_release (error == NO_ERROR);
8379  }
8380 
8381  /* there is no something new */
8382  if (LSA_EQ (&old_lsa, &la_Info.final_lsa))
8383  {
8384  usleep (100 * 1000);
8385  continue;
8386  }
8387  } /* while (!LSA_ISNULL (&la_Info.final_lsa) && la_applier_need_shutdown == false) */
8388  }
8389  while (la_applier_need_shutdown == false);
8390 
8391  if (la_Info.reinit_copylog == true)
8392  {
8393  char error_str[LINE_MAX];
8394 
8397 
8398  la_Info.reinit_copylog = false;
8399 
8400  sprintf (error_str,
8401  "Replication logs and catalog have been reinitialized due to rebuilt database on the peer node");
8402 
8404  error = ER_HA_GENERIC_ERROR;
8405 
8406  LA_SLEEP (10, 0);
8407  }
8408 
8409  la_shutdown ();
8410 
8411 #if !defined(WINDOWS)
8412  if (hb_Proc_shutdown == true)
8413  {
8415  "Disconnected with the cub_master and will shut itself down", "");
8416  }
8417 #endif /* ! WINDOWS */
8418 
8419  if (la_applier_shutdown_by_signal == true)
8420  {
8423  }
8424 
8425  return error;
8426 }
8427 
8428 /*
8429  * la_delay_replica () -
8430  */
8431 static int
8432 la_delay_replica (time_t eot_time)
8433 {
8434  int error = NO_ERROR;
8435  static int ha_mode = -1;
8436  static int replica_delay = -1;
8437  static time_t replica_time_bound = -1;
8438  static char *replica_time_bound_str = (char *) -1;
8439  char buffer[LINE_MAX];
8440 
8441  if (ha_mode < HA_MODE_OFF)
8442  {
8444  }
8445 
8446  if (replica_delay < 0)
8447  {
8449  }
8450 
8451  if (replica_time_bound_str == (void *) -1)
8452  {
8453  replica_time_bound_str = prm_get_string_value (PRM_ID_HA_REPLICA_TIME_BOUND);
8454  }
8455 
8456  if (ha_mode == HA_MODE_REPLICA)
8457  {
8458  if (replica_time_bound_str != NULL)
8459  {
8460  if (replica_time_bound == -1)
8461  {
8462  replica_time_bound = util_str_to_time_since_epoch (replica_time_bound_str);
8463  assert (replica_time_bound != 0);
8464  }
8465 
8466  if (eot_time >= replica_time_bound)
8467  {
8468  error = la_log_commit (true);
8469  if (error != NO_ERROR)
8470  {
8471  return error;
8472  }
8473 
8474  snprintf (buffer, sizeof (buffer),
8475  "applylogdb paused since it reached a log record committed on master at %s or later.\n"
8476  "Adjust or remove %s and restart applylogdb to resume", replica_time_bound_str,
8479 
8480  /* applylogdb waits indefinitely */
8481  select (0, NULL, NULL, NULL, NULL);
8482  }
8483  }
8484  else if (replica_delay > 0)
8485  {
8486  while ((time (NULL) - eot_time) < replica_delay)
8487  {
8488  LA_SLEEP (0, 100 * 1000);
8489  }
8490  }
8491  }
8492 
8493  return NO_ERROR;
8494 }
8495 
8496 #ifdef UNSTABLE_TDE_FOR_REPLICATION_LOG
8497 int
8498 la_start_dk_sharing (void)
8499 {
8500  int server_sockfd;
8501  char sock_path[PATH_MAX] = { 0, };
8502  pid_t pid;
8503  size_t ts_size;
8504  pthread_t processing_th;
8505 
8506  struct sockaddr_un serveraddr;
8507 
8508  fileio_make_ha_sock_name (sock_path, la_Info.log_path, TDE_HA_SOCK_NAME);
8509 
8510  if (access (sock_path, F_OK) == 0)
8511  {
8512  if (unlink (sock_path) < 0)
8513  {
8514  er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_TDE_DK_SHARING_SOCK_UNLINK, 1, sock_path);
8515  return ER_TDE_DK_SHARING_SOCK_UNLINK;
8516  }
8517  }
8518 
8519  if ((server_sockfd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
8520  {
8521  er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_TDE_DK_SHARING_SOCK_OPEN, 1, sock_path);
8522  return ER_TDE_DK_SHARING_SOCK_OPEN;
8523  }
8524 
8525  bzero (&serveraddr, sizeof (serveraddr));
8526  serveraddr.sun_family = AF_UNIX;
8527  strcpy (serveraddr.sun_path, sock_path);
8528 
8529  if (bind (server_sockfd, (struct sockaddr *) &serveraddr, sizeof (serveraddr)) < 0)
8530  {
8531  er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_TDE_DK_SHARING_SOCK_BIND, 1, sock_path);
8532  return ER_TDE_DK_SHARING_SOCK_BIND;
8533  }
8534 
8535  if (listen (server_sockfd, 1) < 0)
8536  {
8537  er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_TDE_DK_SHARING_SOCK_LISTEN, 1, sock_path);
8538  return ER_TDE_DK_SHARING_SOCK_LISTEN;
8539  }
8540 
8541  la_Info.tde_sock_for_dks = server_sockfd;
8542  if (pthread_create (&processing_th, NULL, la_process_dk_request, NULL) < 0)
8543  {
8544  er_set_with_oserror (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_TDE_DK_SHARING_PTHREAD_CREATE, 0);
8545  return ER_TDE_DK_SHARING_PTHREAD_CREATE;
8546  }
8547  return NO_ERROR;
8548 }
8549 
8551 la_process_dk_request (void *arg)
8552 {
8553  int client_sockfd, server_sockfd;
8554  unsigned int client_len;
8555  struct sockaddr_un clientaddr;
8556  char buf[PATH_MAX];
8557  char *bufptr;
8558  int nbytes, len;
8559  int error = NO_ERROR;
8560 
8561  server_sockfd = la_Info.tde_sock_for_dks;
8562 
8563  client_len = sizeof (clientaddr);
8564 
8565  while (1)
8566  {
8567  client_sockfd = accept (server_sockfd, (struct sockaddr *) &clientaddr, &client_len);
8568  if (client_sockfd < 0)
8569  {
8570  continue;
8571  }
8572  bufptr = buf;
8573  len = PATH_MAX;
8574  while (len > 0)
8575  {
8576  nbytes = read (client_sockfd, bufptr, len);
8577  if (nbytes < 0)
8578  {
8579  switch (errno) // errno is thread-local on linux
8580  {
8581  case EINTR:
8582  case EAGAIN:
8583  continue;
8584  default:
8585  {
8586  error = ER_TDE_DK_SHARING_SOCK_READ;
8587  break;
8588  }
8589  }
8590  }
8591  bufptr += nbytes;
8592  len -= nbytes;
8593  }
8594 
8595  if (error == NO_ERROR)
8596  {
8597  if (!tde_Cipher.is_loaded)
8598  {
8600  }
8601  else
8602  {
8603  /* validate the msg from copylogdb */
8604  if (memcmp (buf, la_Info.log_path, PATH_MAX) != 0)
8605  {
8606  /* wrong request */
8607  error = ER_TDE_WRONG_DK_REQUEST;
8608  }
8609  }
8610  }
8611 
8612  /* send error message */
8613  bufptr = (char *) &error;
8614  len = sizeof (error);
8615  while (len > 0)
8616  {
8617  nbytes = write (client_sockfd, bufptr, len);
8618  if (nbytes < 0)
8619  {
8620  switch (errno)
8621  {
8622  case EINTR:
8623  case EAGAIN:
8624  continue;
8625  default:
8626  {
8627  error = ER_TDE_DK_SHARING_SOCK_WRITE;
8628  break;
8629  }
8630  }
8631  }
8632  bufptr += nbytes;
8633  len -= nbytes;
8634  }
8635 
8636  /* send data keys */
8637  if (error == NO_ERROR)
8638  {
8639  bufptr = (char *) &tde_Cipher.data_keys;
8640  len = sizeof (TDE_DATA_KEY_SET);
8641  while (len > 0)
8642  {
8643  nbytes = write (client_sockfd, bufptr, len);
8644  if (nbytes < 0)
8645  {
8646  switch (errno)
8647  {
8648  case EINTR:
8649  case EAGAIN:
8650  continue;
8651  default:
8652  {
8653  error = ER_TDE_DK_SHARING_SOCK_WRITE;
8654  break;
8655  }
8656  }
8657  }
8658  bufptr += nbytes;
8659  len -= nbytes;
8660  }
8661  }
8662  close (client_sockfd);
8663  }
8664 
8665  assert (false);
8666  return (THREAD_RET_T) - 1;
8667 }
8668 #endif /* UNSTABLE_TDE_FOR_REPLICATION_LOG */
#define ER_HA_LA_FAILED_TO_APPLY_UPDATE
Definition: error_code.h:1290
bool la_force_shutdown(void)
Definition: log_applier.c:591
DB_OBJECT * db_find_class(const char *name)
Definition: db_info.c:133
LOG_REC_UNDO undo
Definition: log_record.hpp:209
static bool la_enable_sql_logging
Definition: log_applier.c:425
#define ER_LK_UNILATERALLY_ABORTED
Definition: error_code.h:130
#define ER_IO_LZ4_DECOMPRESS_FAIL
Definition: error_code.h:1119
LOG_ZIP * redo_unzip_ptr
Definition: log_applier.c:313
static time_t la_retrieve_eot_time(LOG_PAGE *pgptr, LOG_LSA *lsa)
Definition: log_applier.c:3519
static int la_init_repl_lists(bool need_realloc)
Definition: log_applier.c:2777
static int la_fetch_log_hdr(LA_ACT_LOG *act_log)
Definition: log_applier.c:2555
int tp_domain_disk_size(TP_DOMAIN *domain)
LOG_LSA committed_lsa
Definition: log_applier.c:292
LA_COMMIT * commit_tail
Definition: log_applier.c:304
int db_set_system_parameters_for_ha_repl(const char *data)
Definition: db_admin.c:2727
#define LA_IN_VALUE_COUNT
static int la_create_repl_filter(void)
Definition: log_applier.c:7624
char * packed_key_value
Definition: log_applier.c:247
char prefix_name[MAXLOGNAME]
int db_make_datetime(DB_VALUE *value, const DB_DATETIME *datetime)
int page_size
Definition: unloaddb.c:52
char * trim(char *str)
Definition: porting.c:2260
#define NO_ERROR
Definition: error_code.h:46
static int la_add_repl_filter(const char *classname)
Definition: log_applier.c:7577
DKNPAGES npages
int area_size
#define AU_DISABLE(save)
Definition: authenticate.h:106
void er_stack_push(void)
#define LANG_SYS_COLLATION
static LOG_PHY_PAGEID la_log_phypageid(LOG_PAGEID logical_pageid)
Definition: log_applier.c:621
static int la_find_last_deleted_arv_num(void)
Definition: log_applier.c:7379
static void la_release_all_page_buffers(LOG_PAGEID except_pageid)
Definition: log_applier.c:1378
int fixed_count
Definition: class_object.h:737
int num_items
Definition: log_applier.c:257
LOG_LSA start_lsa
Definition: log_applier.c:259
static void la_shutdown_by_signal(int)
Definition: log_applier.c:583
#define ER_LC_FAILED_TO_FLUSH_REPL_ITEMS
Definition: error_code.h:1501
static void la_clear_recdes_pool(void)
Definition: log_applier.c:2306
static int check_reinit_copylog(void)
Definition: log_applier.c:7771
char * or_unpack_string(char *ptr, char **string)
#define ASSERT_ERROR()
#define LOG_IS_UNDOREDO_RECORD_TYPE(type)
Definition: log_record.hpp:420
LOG_DATA data
Definition: log_record.hpp:182
#define LA_REINIT_COMMIT_INTERVAL
Definition: log_applier.c:105
int sl_init(const char *db_name, const char *repl_log_path)
MOP ws_mop(const OID *oid, MOP class_mop)
Definition: work_space.c:614
bool LSA_EQ(const log_lsa *plsa1, const log_lsa *plsa2)
Definition: log_lsa.hpp:160
int db_datetime_to_string2(char *buf, int bufsize, DB_DATETIME *datetime)
Definition: db_date.c:4375
static void la_destroy_repl_filter(void)
Definition: log_applier.c:7745
void ws_clear_all_repl_objs(void)
Definition: work_space.c:5377
char * MOBJ
Definition: work_space.h:174
static int la_apply_delete_log(LA_ITEM *item)
Definition: log_applier.c:4885
LOG_LSA last_committed_rep_lsa
Definition: log_applier.c:295
void LSA_COPY(log_lsa *plsa1, const log_lsa *plsa2)
Definition: log_lsa.hpp:139
char * db_user
Definition: log_applier.c:244
#define LOG_IS_PAGE_TDE_ENCRYPTED(log_page_p)
Definition: log_storage.hpp:47
void ws_release_user_instance(MOP mop)
Definition: work_space.c:1579
static void la_invalidate_page_buffer(LA_CACHE_BUFFER *cache_buffer)
Definition: log_applier.c:1409
PAGEID DKNPAGES
static void la_free_repl_item(LA_APPLY *apply, LA_ITEM *item)
Definition: log_applier.c:3270
int boot_notify_ha_log_applier_state(HA_LOG_APPLIER_STATE state)
#define ER_LOG_PAGE_CORRUPTED
Definition: error_code.h:140
int db_make_bigint(DB_VALUE *value, const DB_BIGINT num)
int db_get_int(const DB_VALUE *value)
#define LA_LOGAREA_SIZE
Definition: log_applier.c:120
#define ER_HA_LA_FAILED_TO_APPLY_INSERT
Definition: error_code.h:1289
static int la_repl_add_object(MOP classop, LA_ITEM *item, RECDES *recdes)
Definition: log_applier.c:4819
static int la_log_fetch(LOG_PAGEID pageid, LA_CACHE_BUFFER *cache_buffer)
Definition: log_applier.c:1054
static int la_get_range_of_archive(int arv_log_num, LOG_PAGEID *fpageid, DKNPAGES *npages)
Definition: log_applier.c:760
#define ER_HA_LA_FAILED_TO_CHANGE_STATE
Definition: error_code.h:1284
#define GET_ZIP_LEN(length)
Definition: log_compress.h:36
#define LA_PAGE_DOESNOT_EXIST
Definition: log_applier.c:89
#define CUBRID_MAGIC_LOG_ACTIVE
#define ER_FAILED
Definition: error_code.h:47
#define LOG_IS_MVCC_OP_RECORD_TYPE(type)
Definition: log_record.hpp:428
LOG_PHY_PAGEID phy_pageid
Definition: log_applier.c:184
int db_make_varchar(DB_VALUE *value, const int max_char_length, DB_CONST_C_CHAR str, const int char_str_byte_size, const int codeset, const int collation_id)
LOG_REC_REDO redo
Definition: log_record.hpp:218
LOG_PAGE * hdr_page
Definition: log_applier.c:230
LOG_PAGE * hdr_page
Definition: log_applier.c:219
static int la_update_last_deleted_arv_num(int lockf_vdes, int last_deleted_arv_num)
Definition: log_applier.c:6696
#define CUBRID_MAGIC_LOG_ARCHIVE
#define NULL_TRANID
int ws_add_to_repl_obj_list(OID *class_oid, char *packed_pkey_value, int packed_pkey_value_length, RECDES *recdes, int operation, bool has_index)
Definition: work_space.c:5408
LOG_LSA committed_rep_lsa
Definition: log_applier.c:397
int mht_rem(MHT_TABLE *ht, const void *key, int(*rem_func)(const void *key, void *data, void *args), void *func_args)
Definition: memory_hash.c:1952
#define LA_LOG_READ_ADVANCE_WHEN_DOESNT_FIT(result, length, offset, pageid, pgptr)
Definition: log_applier.c:121
LOG_HDRPAGE hdr
Definition: log_storage.hpp:84
static int la_lock_dbname(int *lockf_vdes, char *db_name, char *log_path)
Definition: log_applier.c:6724
FILEIO_LOCKF_TYPE fileio_lock_la_log_path(const char *db_full_name_p, const char *lock_path_p, int vol_fd, int *last_deleted_arv_num)
Definition: file_io.c:1392
static int la_delete_ha_apply_info(void)
Definition: log_applier.c:2209
void fileio_unformat(THREAD_ENTRY *thread_p, const char *vol_label_p)
Definition: file_io.c:2721
unsigned long insert_counter
Definition: log_applier.c:329
#define LOG_GET_LOG_RECORD_HEADER(log_page_p, lsa)
Definition: log_record.hpp:406
static LA_ITEM * la_make_repl_item(LOG_PAGE *log_pgptr, int log_type, int tranid, LOG_LSA *lsa)
Definition: log_applier.c:3096
LOG_LSA forw_lsa
Definition: log_record.hpp:146
int repl_cnt
Definition: log_applier.c:298
static bool la_ignore_on_error(int errid)
Definition: log_applier.c:2247
#define LA_GET_PAGE_RETRY_COUNT
Definition: log_applier.c:86
static int la_apply_commit_list(LOG_LSA *lsa, LOG_PAGEID final_pageid)
Definition: log_applier.c:5818
#define CUBRID_MAGIC_LOG_INFO
#define PAGEID_MAX
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
const void * mht_put(MHT_TABLE *ht, const void *key, void *data)
Definition: memory_hash.c:1778
LOG_LSA prev_tranlsa
Definition: log_record.hpp:144
const LOG_PAGEID LOGPB_HEADER_PAGE_ID
Definition: log_storage.hpp:51
int db_query_end(DB_QUERY_RESULT *result)
Definition: db_query.c:3362
PAGEID LOG_PHY_PAGEID
int log_path_lockf_vdes
Definition: log_applier.c:343
#define OR_MVCC_FLAG_VALID_INSID
#define assert_release(e)
Definition: error_manager.h:96
static LA_CACHE_BUFFER * la_get_page_buffer(LOG_PAGEID pageid)
Definition: log_applier.c:1288
#define ER_NET_CANT_CONNECT_SERVER
Definition: error_code.h:261
static bool la_applier_shutdown_by_signal
Definition: log_applier.c:421
#define SM_MAX_IDENTIFIER_LENGTH
LOG_PAGE logpage
Definition: log_applier.c:186
char copied_log_path[4096]
Definition: log_applier.c:395
#define ER_HA_LA_INVALID_REPL_LOG_PAGEID_OFFSET
Definition: error_code.h:1286
static int la_update_query_execute_with_values(const char *sql, int arg_count, DB_VALUE *vals, bool au_disable)
Definition: log_applier.c:5373
void ws_clear_all_repl_errors_of_error_link(void)
Definition: work_space.c:5096
static void la_clear_all_repl_and_commit_list(void)
Definition: log_applier.c:3396
MHT_TABLE * hash_table
Definition: log_applier.c:199
LOG_ARV_HEADER * log_hdr
Definition: log_applier.c:231
static void la_add_repl_item(LA_APPLY *apply, LA_ITEM *item)
Definition: log_applier.c:3054
int sl_write_update_sql(DB_OTMPL *inst_tp, DB_VALUE *key)
static int la_log_io_read_with_max_retries(char *vname, int vdes, void *io_pgptr, LOG_PHY_PAGEID pageid, int pagesize, int retries)
Definition: log_applier.c:687
LOG_LSA required_lsa
Definition: log_applier.c:401
static LOG_PAGE * la_get_page(LOG_PAGEID pageid)
Definition: log_applier.c:1327
#define OR_MVCC_FLAG_VALID_DELID
static bool la_need_filter_out(LA_ITEM *item)
Definition: log_applier.c:7536
#define OR_MVCCID_SIZE
LOG_LSA target_lsa
Definition: log_applier.c:250
VOLID volid
Definition: log_record.hpp:158
OID * ws_oid(MOP mop)
Definition: work_space.c:2884
LA_OVF_PAGE_LIST * next
Definition: log_applier.c:376
#define SIZEOF_LA_CACHE_LOG_BUFFER(io_pagesize)
Definition: log_applier.c:117
ha_mode
int fixed_size
Definition: class_object.h:739
static int la_apply_update_log(LA_ITEM *item)
Definition: log_applier.c:4967
struct sm_component * next
Definition: class_object.h:384
void sm_downcase_name(const char *name, char *buf, int maxlen)
#define ER_HA_LA_REPL_FILTER_GENERIC
Definition: error_code.h:1280
#define OR_MVCC_FLAG_SHIFT_BITS
#define ER_LOG_MOUNT_FAIL
Definition: error_code.h:141
char * data
static void la_free_and_add_next_repl_item(LA_APPLY *apply, LA_ITEM *next_item, LOG_LSA *lsa)
Definition: log_applier.c:3331
MOP locator_find_class(const char *classname)
Definition: locator_cl.c:3142
#define DB_CURSOR_ERROR
Definition: dbtype_def.h:168
bool fileio_is_volume_exist(const char *vol_label_p)
Definition: file_io.c:5094
LOG_PAGEID fpageid
#define AU_RESTORE(save)
Definition: authenticate.h:133
#define ER_HA_LA_FAILED_TO_APPLY_STATEMENT
Definition: error_code.h:1288
unsigned long fail_counter
Definition: log_applier.c:334
time_t log_record_time
Definition: log_applier.c:302
bool classobj_class_has_indexes(SM_CLASS *class_)
int32_t pageid
Definition: dbtype_def.h:879
#define LSA_AS_ARGS(lsa_ptr)
Definition: log_lsa.hpp:78
static void la_log_copy_fromlog(char *rec_type, char *area, int length, LOG_PAGEID log_pageid, PGLENGTH log_offset, LOG_PAGE *log_pgptr)
Definition: log_applier.c:2964
#define LA_SLEEP(sec, usec)
Definition: log_applier.c:149
int au_disable(void)
int er_errid(void)
LOG_ZIP_SIZE_T data_length
Definition: log_compress.h:55
#define OR_BOUND_BIT_BYTES(count)
void dbt_abort_object(DB_OTMPL *def)
Definition: db_obj.c:616
#define PTR_ALIGN(addr, boundary)
Definition: memory_alloc.h:77
static int la_commit_transaction(void)
Definition: log_applier.c:6545
#define AU_SET_USER
Definition: authenticate.h:141
int mht_compare_logpageids_are_equal(const void *key1, const void *key2)
Definition: memory_hash.c:743
LOG_PAGEID pageid
Definition: log_applier.c:183
bool LSA_LT(const log_lsa *plsa1, const log_lsa *plsa2)
Definition: log_lsa.hpp:174
#define er_log_debug(...)
int log_type
Definition: log_applier.c:241
static void la_release_page_buffer(LOG_PAGEID pageid)
Definition: log_applier.c:1355
LA_ACT_LOG act_log
Definition: log_applier.c:284
char * ha_sys_prm
Definition: log_applier.c:245
LOG_ZIP * log_zip_alloc(LOG_ZIP_SIZE_T size)
Definition: log_compress.c:230
LOG_LSA append_lsa
bool hb_Proc_shutdown
Definition: heartbeat.c:93
DB_DATETIME last_access_time
Definition: log_applier.c:404
int la_log_page_check(const char *database_name, const char *log_path, INT64 page_num, bool check_applied_info, bool check_copied_info, bool check_replica_info, bool verbose, LOG_LSA *copied_eof_lsa, LOG_LSA *copied_append_lsa, LOG_LSA *applied_final_lsa)
Definition: log_applier.c:7046
#define NULL_VOLDES
Definition: file_io.h:44
#define ER_HA_LA_STARTED
Definition: error_code.h:1295
#define MAX_ALIGNMENT
Definition: memory_alloc.h:70
int sl_write_statement_sql(char *class_name, char *db_user, int item_type, const char *stmt_text, char *ha_sys_prm)
#define ER_OBJ_NO_CONNECT
Definition: error_code.h:295
#define LC_UPDATE_OPERATION_TYPE(p)
Definition: locator_cl.h:58
LA_CACHE_BUFFER_AREA * next
Definition: log_applier.c:193
DB_DOMAIN_INFO domain
Definition: dbtype_def.h:1082
#define ER_HA_LA_FAILED_TO_APPLY_DELETE
Definition: error_code.h:1291
bool is_apply_info_updated
Definition: log_applier.c:338
static RECDES * la_assign_recdes_from_pool(void)
Definition: log_applier.c:2385
LOG_LSA back_lsa
Definition: log_record.hpp:145
static int la_delay_replica(time_t eot_time)
Definition: log_applier.c:8432
RECDES * recdes_arr
Definition: log_applier.c:382
LOG_LSA last_lsa
Definition: log_applier.c:260
#define NULL_PAGEID
char * log_data
Definition: log_compress.h:57
PGLENGTH offset
Definition: log_record.hpp:157
int dbt_put_internal(DB_OTMPL *def, const char *name, DB_VALUE *value)
Definition: db_obj.c:670
#define CT_SERIAL_NAME
Definition: transform.h:135
time_t log_record_time
Definition: log_applier.c:274
int db_logpagesize
Definition: log_applier.c:222
#define MSGCAT_SET_LOG
unsigned long update_counter
Definition: log_applier.c:330
#define ER_LOG_READ
Definition: error_code.h:137
LOG_LSA log_lsa
Definition: log_applier.c:273
LOG_LSA eof_lsa
Definition: log_applier.c:327
INT64 db_creation
#define LA_WS_CULL_MOPS_INTERVAL
Definition: log_applier.c:108
#define ER_IO_READ
Definition: error_code.h:62
MOBJ locator_fetch_class(MOP class_mop, DB_FETCH_MODE purpose)
Definition: locator_cl.c:2293
int db_make_string(DB_VALUE *value, DB_CONST_C_CHAR str)
unsigned long delete_counter
Definition: log_applier.c:331
int last_server_state
Definition: log_applier.c:322
#define LA_DEFAULT_LOG_PAGE_SIZE
Definition: log_applier.c:85
LOG_RECTYPE type
Definition: log_record.hpp:148
int db_lockf_vdes
Definition: log_applier.c:344
void mht_destroy(MHT_TABLE *ht)
Definition: memory_hash.c:1140
INTL_CODESET lang_charset(void)
#define LA_REPL_LIST_COUNT
Definition: log_applier.c:87
#define CT_HA_APPLY_INFO_NAME
Definition: transform.h:136
unsigned long schema_counter
Definition: log_applier.c:332
static char * la_get_zipped_data(char *undo_data, int undo_length, bool is_diff, bool is_undo_zip, bool is_overflow, char **rec_type, char **data, int *length)
Definition: log_applier.c:3780
static void la_make_room_for_mvcc_insid(RECDES *recdes)
Definition: log_applier.c:3673
#define THREAD_RET_T
Definition: porting.h:713
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
time_t start_time
Definition: log_applier.c:288
INT64 db_restore_time
LA_REPL_FILTER repl_filter
Definition: log_applier.c:346
const char * sm_ch_name(const MOBJ clobj)
LA_CACHE_BUFFER_AREA * buffer_area
Definition: log_applier.c:202
#define LA_WS_CULL_MOPS_INTERVAL_MIN
Definition: log_applier.c:110
#define OR_MVCC_FLAG_VALID_PREV_VERSION
static int la_check_mem_size(void)
Definition: log_applier.c:6508
#define assert(x)
#define ER_LC_PARTIALLY_FAILED_TO_FLUSH
Definition: error_code.h:1394
char path[PATH_MAX]
Definition: log_applier.c:228
int sl_write_insert_sql(DB_OTMPL *inst_tp, DB_VALUE *key)
static void la_free_repl_items_by_tranid(int tranid)
Definition: log_applier.c:5871
#define LA_MAX_TOLERABLE_DELAY
Definition: log_applier.c:104
static bool la_apply_pre(void)
Definition: log_applier.c:2697
LOG_PAGEID fpageid
#define OR_MVCC_FLAG_MASK
int prm_get_integer_value(PARAM_ID prm_id)
#define ER_GENERIC_ERROR
Definition: error_code.h:49
int au_fetch_class(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
LA_APPLY ** repl_lists
Definition: log_applier.c:297
static int la_find_log_pagesize(LA_ACT_LOG *act_log, const char *logpath, const char *dbname, bool check_charset)
Definition: log_applier.c:2572
static char la_peer_host[CUB_MAXHOSTNAMELEN+1]
Definition: log_applier.c:423
int or_mvcc_get_repid_and_flags(OR_BUF *buf, int *error)
LA_ITEM * prev
Definition: log_applier.c:239
void fileio_close(int vol_fd)
Definition: file_io.c:2078
PGLENGTH db_logpagesize
int db_query_first_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2309
#define CUBRID_MAGIC_MAX_LENGTH
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
#define LA_WS_CULL_MOPS_PER_APPLY
Definition: log_applier.c:107
#define MSGCAT_LOG_LOGINFO_COMMENT
TDE_CIPHER tde_Cipher
Definition: tde.c:69
int ha_server_state
REPL_FILTER_TYPE type
Definition: log_applier.c:211
char area[1]
Definition: log_storage.hpp:85
static int la_log_commit(bool update_commit_time)
Definition: log_applier.c:6429
int tranid
Definition: log_applier.c:256
bool LSA_LE(const log_lsa *plsa1, const log_lsa *plsa2)
Definition: log_lsa.hpp:167
static void la_print_repl_filter_info(void)
Definition: log_applier.c:7490
static void la_free_all_repl_items(LA_APPLY *apply)
Definition: log_applier.c:3362
unsigned long start_vsize
Definition: log_applier.c:287
char * log_data
Definition: log_applier.c:310
int la_apply_log_file(const char *database_name, const char *log_path, const int max_mem_size)
Definition: log_applier.c:7810
char loginf_path[PATH_MAX]
Definition: log_applier.c:283
int db_iopagesize
Definition: log_applier.c:221
const char * css_ha_server_state_string(HA_SERVER_STATE state)
int prev_total_rows
Definition: log_applier.c:301
#define ER_HA_GENERIC_ERROR
Definition: error_code.h:1297
#define ER_HB_PROCESS_EVENT
Definition: error_code.h:1239
#define DB_MAX_IDENTIFIER_LENGTH
Definition: dbtype_def.h:495
static LA_CACHE_BUFFER * la_cache_buffer_replace(LA_CACHE_PB *cache_pb, LOG_PAGEID pageid, int io_pagesize, int buffer_size)
Definition: log_applier.c:1223
LOG_PAGEID logical_pageid
Definition: log_storage.hpp:65
void db_localdatetime(time_t *epoch_time, DB_DATETIME *datetime)
Definition: db_date.c:1030
#define LA_NUM_REPL_FILTER
Definition: log_applier.c:112
LOG_HA_FILESTAT
const char * db_error_string(int level)
Definition: db_admin.c:2116
static enum scanner_mode mode
int ha_file_status
INT64 ha_promotion_time
static int la_add_node_into_la_commit_list(int tranid, LOG_LSA *lsa, int type, time_t eot_time)
Definition: log_applier.c:3477
char * rec_type
Definition: log_applier.c:311
#define LA_MAX_REPL_ITEM_WITHOUT_RELEASE_PB
Definition: log_applier.c:83
LOG_LSA last_committed_lsa
Definition: log_applier.c:294
LOG_LSA required_lsa
Definition: log_applier.c:328
#define IO_MIN_PAGE_SIZE
DB_DATETIME start_time
Definition: log_applier.c:412
short volid
Definition: dbtype_def.h:880
int last_file_state
Definition: log_applier.c:286
enum ha_log_applier_state HA_LOG_APPLIER_STATE
ha_server_state
Definition: boot.h:115
int db_reset_system_parameters_from_assignments(const char *data)
Definition: db_admin.c:2742
static int la_apply_repl_log(int tranid, int rectype, LOG_LSA *commit_lsa, int *total_rows, LOG_PAGEID final_pageid)
Definition: log_applier.c:5637
static int la_apply_statement_log(LA_ITEM *item)
Definition: log_applier.c:5413
static int la_get_log_data(LOG_RECORD_HEADER *lrec, LOG_LSA *lsa, LOG_PAGE *pgptr, unsigned int match_rcvindex, unsigned int *rcvindex, void **logs, char **rec_type, char **data, int *d_length)
Definition: log_applier.c:3926
std::int64_t pageid
Definition: log_lsa.hpp:36
LOG_LSA committed_rep_lsa
Definition: log_applier.c:293
#define DB_SIZEOF(val)
Definition: memory_alloc.h:54
LOG_PAGEID nxarv_pageid
static LA_ITEM * la_get_next_repl_item(LA_ITEM *item, bool is_long_trans, LOG_LSA *last_lsa)
Definition: log_applier.c:5922
static int la_log_fetch_from_archive(LOG_PAGEID pageid, char *data)
Definition: log_applier.c:903
LA_INFO la_Info
Definition: log_applier.c:416
DB_DATETIME log_record_time
Definition: log_applier.c:402
INT64 LOG_PAGEID
void * mht_get(MHT_TABLE *ht, const void *key)
Definition: memory_hash.c:1419
bool reinit_copylog
Definition: log_applier.c:348
FILEIO_LOCKF_TYPE
Definition: file_io.h:151
LOG_DATA data
Definition: log_record.hpp:174
static int la_get_undoredo_diff(LOG_PAGE **pgptr, LOG_PAGEID *pageid, PGLENGTH *offset, bool *is_undo_zip, char **undo_data, int *undo_length)
Definition: log_applier.c:3857
#define NULL
Definition: freelistheap.h:34
#define ER_HA_LA_EXCEED_MAX_MEM_SIZE
Definition: error_code.h:1292
bool is_end_of_record
Definition: log_applier.c:321
const char * er_msg(void)
int sl_write_delete_sql(char *class_name, MOBJ mclass, DB_VALUE *key)
int db_execute(const char *CSQL_query, DB_QUERY_RESULT **result, DB_QUERY_ERROR *query_error)
Definition: db_query.c:1836
MOP au_find_user(const char *user_name)
static int la_get_relocation_recdes(LOG_RECORD_HEADER *lrec, LOG_PAGE *pgptr, unsigned int match_rcvindex, void **logs, char **rec_type, RECDES *recdes)
Definition: log_applier.c:4532
static int la_get_next_update_log(LOG_RECORD_HEADER *prev_lrec, LOG_PAGE *pgptr, void **logs, char **rec_type, char **data, int *d_length)
Definition: log_applier.c:4373
pid_t pid
Definition: dynamic_load.c:955
static int la_get_current(OR_BUF *buf, SM_CLASS *sm_class, int bound_bit_flag, DB_OTMPL *def, DB_VALUE *key, int offset_size)
Definition: log_applier.c:3559
char path[PATH_MAX]
Definition: log_applier.c:217
static char * dbname
if(extra_options)
Definition: dynamic_load.c:958
LOG_LSA append_lsa
Definition: log_applier.c:326
DB_DATETIME log_commit_time
Definition: log_applier.c:403
static int la_realloc_recdes_data(RECDES *recdes, int data_size)
Definition: log_applier.c:2348
#define ER_LOC_INIT
Definition: error_code.h:1370
static int la_change_state(void)
Definition: log_applier.c:6295
static int la_unlock_dbname(int *lockf_vdes, char *db_name, bool clear_owner)
Definition: log_applier.c:6754
#define ER_IO_MOUNT_FAIL
Definition: error_code.h:59
#define LA_STATUS_BUSY
Definition: log_applier.c:93
bool LSA_ISNULL(const log_lsa *lsa_ptr)
Definition: log_lsa.hpp:153
LOG_ZIP * undo_unzip_ptr
Definition: log_applier.c:312
#define LA_MAX_UNFLUSHED_REPL_ITEMS
Definition: log_applier.c:84
#define ER_PB_BAD_PAGEID
Definition: error_code.h:67
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
static int la_init_recdes_pool(int page_size, int num_recdes)
Definition: log_applier.c:2420
static LA_APPLY * la_find_apply_list(int tranid)
Definition: log_applier.c:2864
MHT_TABLE * mht_create(const char *name, int est_size, unsigned int(*hash_func)(const void *key, unsigned int ht_size), int(*cmp_func)(const void *key1, const void *key2))
Definition: memory_hash.c:894
const char * get_buffer() const
PGLENGTH offset
Definition: log_storage.hpp:66
int total_rows
Definition: log_applier.c:300
static int la_get_last_ha_applied_info(void)
Definition: log_applier.c:1956
char * or_unpack_int(char *ptr, int *number)
void ws_cull_mops(void)
Definition: work_space.c:1406
void or_init(OR_BUF *buf, char *data, int length)
int num_unflushed
Definition: log_applier.c:340
LA_ITEM * head
Definition: log_applier.c:261
LA_CACHE_BUFFER ** log_buffer
Definition: log_applier.c:200
static struct timeval start_time
static bool la_retry_on_error(int errid)
Definition: log_applier.c:2282
char log_path[PATH_MAX]
Definition: log_applier.c:282
#define NULL_OFFSET
need_clear_type need_clear
Definition: dbtype_def.h:1084
#define CEIL_PTVDIV(dividend, divisor)
Definition: memory_alloc.h:50
char * db_name
#define ER_LOG_NOTIN_ARCHIVE
Definition: error_code.h:156
int sm_flush_objects(MOP obj)
#define HB_START_WAITING_TIME_IN_SECS
Definition: heartbeat.h:56
void er_set_with_oserror(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
int pr_clear_value(DB_VALUE *value)
int db_query_get_tuple_valuelist(DB_QUERY_RESULT *result, int size, DB_VALUE *value_list)
Definition: db_query.c:3025
#define MSGCAT_CATALOG_CUBRID
REPL_FILTER_TYPE
Definition: log_applier.h:48
DB_BIGINT db_get_bigint(const DB_VALUE *value)
static int la_update_ha_apply_info_start_time(void)
Definition: log_applier.c:1851
bool is_long_trans
Definition: log_applier.c:258
void fileio_make_log_active_name(char *log_active_name_p, const char *log_path_p, const char *db_name_p)
Definition: file_io.c:5707
const char * lang_charset_cubrid_name(const INTL_CODESET codeset)
#define LA_PAGE_EXST_IN_ACTIVE_LOG
Definition: log_applier.c:90
static float la_get_avg(int *array, int size)
Definition: log_applier.c:7406
static int la_find_archive_num(int *arv_log_num, LOG_PAGEID pageid)
Definition: log_applier.c:823
char * or_unpack_mem_value(char *buf, DB_VALUE *value)
void fileio_make_log_info_name(char *log_info_name_p, const char *log_path_p, const char *db_name_p)
Definition: file_io.c:5815
LOG_REC_UNDOREDO undoredo
Definition: log_record.hpp:200
bool last_is_end_of_record
Definition: log_applier.c:320
int db_datetime_to_string(char *buf, int bufsize, DB_DATETIME *datetime)
Definition: db_date.c:4225
char db_release[REL_MAX_RELEASE_LENGTH]
void ws_init_repl_objs(void)
Definition: work_space.c:5323
void er_stack_pop(void)
#define LA_RETRY_ON_ERROR(error)
Definition: log_applier.h:34
int max_mem_size
Definition: log_applier.c:315
bool LSA_GE(const log_lsa *plsa1, const log_lsa *plsa2)
Definition: log_lsa.hpp:181
void fileio_make_log_archive_name(char *log_archive_name_p, const char *log_path_p, const char *db_name_p, int archive_number)
Definition: file_io.c:5758
int db_query_column_count(DB_QUERY_RESULT *result)
Definition: db_query.c:3134
static char * la_get_hostname_from_log_path(char *log_path)
Definition: log_applier.c:6252
#define LA_LOG_IS_IN_ARCHIVE(pageid)
Definition: log_applier.c:114
static int la_remove_archive_logs(const char *db_name, int last_deleted_arv_num, int nxarv_num, int max_arv_count_to_delete)
Definition: log_applier.c:7303
int or_get_offset_internal(OR_BUF *buf, int *error, int offset_size)
static int la_apply_insert_log(LA_ITEM *item)
Definition: log_applier.c:5152
#define MSGCAT_LOG_LOGINFO_REMOVE_REASON
MOP Au_user
Definition: authenticate.c:343
LA_CACHE_PB * cache_pb
Definition: log_applier.c:318
static int la_init_cache_log_buffer(LA_CACHE_PB *cache_pb, int slb_cnt, int slb_size)
Definition: log_applier.c:2532
static void error(const char *msg)
Definition: gencat.c:331
PGLENGTH db_iopagesize
int locator_repl_flush_all(void)
Definition: locator_cl.c:5500
LOG_PHY_PAGEID nxarv_phy_pageid
static char la_slave_db_name[DB_MAX_IDENTIFIER_LENGTH+1]
Definition: log_applier.c:422
static void la_clear_applied_info(LA_APPLY *apply)
Definition: log_applier.c:3382
static int rc
Definition: serial.c:50
static int la_get_overflow_recdes(LOG_RECORD_HEADER *lrec, void *logs, RECDES *recdes, unsigned int rcvindex)
Definition: log_applier.c:4226
#define ER_INTERRUPTED
Definition: error_code.h:51
static unsigned int log_pageid_hash(const void *key, unsigned int htsize)
Definition: log_applier.c:2504
int status
Definition: log_applier.c:337
char * class_name
Definition: log_applier.c:243
LOG_LSA append_lsa
Definition: log_applier.c:398
LA_ITEM * tail
Definition: log_applier.c:262
static LA_ITEM * la_get_next_repl_item_from_list(LA_ITEM *item)
Definition: log_applier.c:5935
DB_OTMPL * dbt_create_object_internal(DB_OBJECT *classobj)
int db_execute_with_values(const char *CSQL_query, DB_QUERY_RESULT **result, DB_QUERY_ERROR *query_error, int arg_count, DB_VALUE *vals)
Definition: db_query.c:1511
#define AU_SELECT
Definition: authenticate.h:69
FILEIO_LOCKF_TYPE fileio_unlock_la_dbname(int *lockf_vdes, char *db_name, bool clear_owner)
Definition: file_io.c:1691
#define ARG_FILE_LINE
Definition: error_manager.h:44
static char database_name[MAX_HA_DBINFO_LENGTH]
Definition: cas_execute.c:387
void db_sprint_value(const db_value *value, string_buffer &sb)
int sm_partitioned_class_type(DB_OBJECT *classop, int *partition_type, char *keyattr, MOP **partitions)
#define snprintf_dots_truncate(dest, max_len,...)
Definition: porting.h:323
#define LOGPAGEID_MAX
void ws_decache(MOP mop)
Definition: work_space.c:2701
const char * logwr_log_ha_filestat_to_string(enum LOG_HA_FILESTAT val)
Definition: log_writer.c:2041
bool log_unzip(LOG_ZIP *log_unzip, LOG_ZIP_SIZE_T length, void *data)
Definition: log_compress.c:123
time_t last_time_archive_deleted
Definition: log_applier.c:307
int cur_repl
Definition: log_applier.c:299
#define MSGCAT_LOG_MAX_ARCHIVES_HAS_BEEN_EXCEEDED
#define AU_ENABLE(save)
Definition: authenticate.h:113
INT16 PGLENGTH
#define LA_DEFAULT_CACHE_BUFFER_SIZE
Definition: log_applier.c:82
#define LOG_IS_DIFF_UNDOREDO_TYPE(type)
Definition: log_record.hpp:424
static LA_ITEM * la_new_repl_item(LOG_LSA *lsa, LOG_LSA *target_lsa)
Definition: log_applier.c:3016
int db_get_client_type(void)
Definition: db_admin.c:489
LOG_LSA lsa
Definition: log_applier.c:249
int packed_key_value_length
Definition: log_applier.c:246
#define LA_STATUS_IDLE
Definition: log_applier.c:94
WS_REPL_FLUSH_ERR * ws_get_repl_error_from_error_link(void)
Definition: work_space.c:5075
void log_zip_free(LOG_ZIP *log_zip)
Definition: log_compress.c:265
static void la_free_all_repl_items_except_head(LA_APPLY *apply)
Definition: log_applier.c:3304
void * object
Definition: work_space.h:123
PAGEID pageid
Definition: log_record.hpp:156
#define free_and_init(ptr)
Definition: memory_alloc.h:147
static int la_expand_cache_log_buffer(LA_CACHE_PB *cache_pb, int slb_cnt, int slb_size)
Definition: log_applier.c:1168
#define strlen(s1)
Definition: intl_support.c:43
char * prm_get_string_value(PARAM_ID prm_id)
void LSA_SET_NULL(log_lsa *lsa_ptr)
Definition: log_lsa.hpp:146
#define LA_MAX_REPL_ITEMS
Definition: log_applier.c:100
SM_COMPONENT header
Definition: class_object.h:441
bool LSA_GT(const log_lsa *plsa1, const log_lsa *plsa2)
Definition: log_lsa.hpp:188
static int la_update_query_execute(const char *sql, bool au_disable)
Definition: log_applier.c:5329
bool is_shutdown
#define LOG_IS_REDO_RECORD_TYPE(type)
Definition: log_record.hpp:416
unsigned int date
Definition: dbtype_def.h:776
static LA_ITEM * la_get_next_repl_item_from_log(LA_ITEM *item, LOG_LSA *last_lsa)
Definition: log_applier.c:5941
FILEIO_LOCKF_TYPE fileio_lock_la_dbname(int *lockf_vdes, char *db_name, char *log_path)
Definition: file_io.c:1545
DB_VALUE key
Definition: log_applier.c:248
#define DB_CURSOR_SUCCESS
Definition: dbtype_def.h:166
enum intl_codeset INTL_CODESET
Definition: intl_support.h:190
bool log_diff(LOG_ZIP_SIZE_T undo_length, const void *undo_data, LOG_ZIP_SIZE_T redo_length, void *redo_data)
Definition: log_compress.c:201
static int la_flush_repl_items(bool immediate)
Definition: log_applier.c:4685
static int la_check_duplicated(const char *logpath, const char *dbname, int *lockf_vdes, int *last_deleted_arv_num)
Definition: log_applier.c:6664
LA_RECDES_POOL la_recdes_pool
Definition: log_applier.c:418
bool prm_get_bool_value(PARAM_ID prm_id)
bool is_loaded
Definition: tde.h:148
char magic[CUBRID_MAGIC_MAX_LENGTH]
#define INT_ALIGNMENT
Definition: memory_alloc.h:61
static LOG_REC_HA_SERVER_STATE * la_get_ha_server_state(LOG_PAGE *pgptr, LOG_LSA *lsa)
Definition: log_applier.c:4654
#define LC_IS_FLUSH_UPDATE(operation)
Definition: locator.h:125
#define ZIP_CHECK(length)
Definition: log_compress.h:39
#define AU_SAVE_AND_DISABLE(save)
Definition: authenticate.h:126
void er_clear(void)
static int la_disk_to_obj(MOBJ classobj, RECDES *record, DB_OTMPL *def, DB_VALUE *key)
Definition: log_applier.c:3703
#define ONE_K
Definition: porting.h:62
#define ER_TM_SERVER_DOWN_UNILATERALLY_ABORTED
Definition: error_code.h:171
#define OR_GET_MVCC_REPID_AND_FLAG(ptr)
LA_ARV_LOG arv_log
Definition: log_applier.c:285
bool is_role_changed
Definition: log_applier.c:323
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
char * msgcat_message(int cat_id, int set_id, int msg_id)
TDE_DATA_KEY_SET data_keys
Definition: tde.h:149
static int la_set_repl_log(LOG_PAGE *log_pgptr, int log_type, int tranid, LOG_LSA *lsa)
Definition: log_applier.c:3423
const char * prm_get_name(PARAM_ID prm_id)
static int la_check_time_commit(struct timeval *time, unsigned int threshold)
Definition: log_applier.c:6606
#define DB_IS_NULL(value)
Definition: dbtype.h:63
#define OR_GET_OFFSET_SIZE(ptr)
#define ER_HA_LA_STOPPED_BY_SIGNAL
Definition: error_code.h:1293
LOG_LSA eof_lsa
static int la_log_io_open(const char *vlabel, int flags, int mode)
LOG_HEADER * log_hdr
Definition: log_applier.c:220
INT16 type
static void la_init(const char *log_path, const int max_mem_size)
Definition: log_applier.c:6781
char * strdup(const char *str)
Definition: porting.c:901
int log_dump_log_info(const char *logname_info, bool also_stdout, const char *fmt,...)
Definition: log_comm.c:205
char magic[CUBRID_MAGIC_MAX_LENGTH]
static LA_APPLY * la_add_apply_list(int tranid)
Definition: log_applier.c:2893
LOG_RCVINDEX rcvindex
Definition: log_record.hpp:155
DB_DATETIME * db_get_datetime(const DB_VALUE *value)
#define FILEIO_PATH_SEPARATOR(path)
Definition: file_io.h:78
static int la_update_ha_apply_info_log_record_time(time_t new_time)
Definition: log_applier.c:1888
#define LA_MOVE_INSIDE_RECORD(rec, dest_offset, src_offset)
Definition: log_applier.c:158
#define IO_MAX_PAGE_SIZE
#define ER_HA_LA_INVALID_REPL_LOG_RECORD
Definition: error_code.h:1287
#define LA_WS_CULL_MOPS_PER_APPLY_MIN
Definition: log_applier.c:109
LA_COMMIT * prev
Definition: log_applier.c:269
MOP sm_Root_class_mop
int cache_buffer_size
Definition: log_applier.c:319
void ws_filter_dirty(void)
Definition: work_space.c:1859
DB_VALUE pkey_value
Definition: work_space.h:76
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
void la_print_log_arv_header(const char *database_name, LOG_ARV_HEADER *hdr, bool verbose)
Definition: log_applier.c:7018
int db_make_int(DB_VALUE *value, const int num)
#define LA_QUERY_BUF_SIZE
Definition: log_applier.c:98
LOG_LSA committed_lsa
Definition: log_applier.c:396
LA_ITEM * next
Definition: log_applier.c:238
static bool la_applier_need_shutdown
Definition: log_applier.c:420
static int la_log_record_process(LOG_RECORD_HEADER *lrec, LOG_LSA *final, LOG_PAGE *pg_ptr)
Definition: log_applier.c:5999
#define LC_INSERT_OPERATION_TYPE(p)
Definition: locator_cl.h:53
LA_CACHE_BUFFER * buffer_area
Definition: log_applier.c:192
enum ha_server_state HA_SERVER_STATE
Definition: boot.h:126
#define OR_BOUND_BIT_FLAG
time_t util_str_to_time_since_epoch(char *str)
Definition: util_func.c:310
TRANID next_trid
#define LA_NUM_DELAY_HISTORY
Definition: log_applier.c:103
static int la_update_ha_last_applied_info(void)
Definition: log_applier.c:2065
#define LANG_SYS_CODESET
#define LA_PAGE_EXST_IN_ARCHIVE_LOG
Definition: log_applier.c:91
unsigned long commit_counter
Definition: log_applier.c:333
static int la_get_ha_apply_info(const char *log_path, const char *prefix_name, LA_HA_APPLY_INFO *ha_apply_info)
Definition: log_applier.c:1505
static void la_init_ha_apply_info(LA_HA_APPLY_INFO *ha_apply_info)
Definition: log_applier.c:597
static bool la_is_repl_lists_empty()
Definition: log_applier.c:2841
static void la_decache_page_buffers(LOG_PAGEID from, LOG_PAGEID to)
Definition: log_applier.c:1428
bool required_lsa_changed
Definition: log_applier.c:336
#define CUB_MAXHOSTNAMELEN
Definition: porting.h:379
static void la_unlink_repl_item(LA_APPLY *apply, LA_ITEM *item)
Definition: log_applier.c:3232
#define LA_LOG_READ_ALIGN(result, offset, pageid, log_pgptr)
Definition: log_applier.c:131
#define LC_IS_FLUSH_INSERT(operation)
Definition: locator.h:121
static void la_get_adaptive_time_commit_interval(int *time_commit_interval, int *delay_hist)
Definition: log_applier.c:7428
#define DB_CURSOR_END
Definition: dbtype_def.h:167
LA_COMMIT * next
Definition: log_applier.c:268
void la_print_log_header(const char *database_name, LOG_HEADER *hdr, bool verbose)
Definition: log_applier.c:6960
int item_type
Definition: log_applier.c:242
static bool la_restart_on_bulk_flush_error(int errid)
Definition: log_applier.c:2271
static void la_shutdown(void)
Definition: log_applier.c:6845
#define ER_TDE_CIPHER_IS_NOT_LOADED
Definition: error_code.h:1613
int tde_decrypt_log_page(const LOG_PAGE *logpage_cipher, TDE_ALGORITHM tde_algo, LOG_PAGE *logpage_plain)
Definition: tde.c:1027
#define ER_NET_SERVER_COMM_ERROR
Definition: error_code.h:265
int last_deleted_archive_num
Definition: log_applier.c:305
#define LA_LOCK_SUFFIX
Definition: log_applier.c:96
time_t log_commit_time
Definition: log_applier.c:335
static int la_log_io_read(char *vname, int vdes, void *io_pgptr, LOG_PHY_PAGEID pageid, int pagesize)
Definition: log_applier.c:668
bool sysprm_find_err_in_integer_list(PARAM_ID prm_id, int error_code)
static int la_get_recdes(LOG_LSA *lsa, LOG_PAGE *pgptr, RECDES *recdes, unsigned int *rcvindex, char *rec_type)
Definition: log_applier.c:4583
static int la_insert_ha_apply_info(DB_DATETIME *creation_time)
Definition: log_applier.c:1707
int fileio_open(const char *vol_label_p, int flags, int mode)
Definition: file_io.c:1957
#define LA_LOG_READ_ADD_ALIGN(result, add, offset, pageid, log_pgptr)
Definition: log_applier.c:143
int db_ping_server(int client_val, int *server_val)
Definition: db_admin.c:983
int apply_state
Definition: log_applier.c:314
#define PATH_SEPARATOR
Definition: porting.h:347
void la_print_delay_info(LOG_LSA working_lsa, LOG_LSA target_lsa, float process_rate)
Definition: log_applier.c:7269
static int la_does_page_exist(LOG_PAGEID pageid)
Definition: log_applier.c:2742
LOG_LSA chkpt_lsa
DB_DATETIME creation_time
Definition: log_applier.c:394
static int la_find_required_lsa(LOG_LSA *required_lsa)
Definition: log_applier.c:1462
std::int64_t offset
Definition: log_lsa.hpp:37
SIGNAL_HANDLER_FUNCTION os_set_signal_handler(const int sig_no, SIGNAL_HANDLER_FUNCTION sig_handler)
Definition: porting.c:1333
const char ** p
Definition: dynamic_load.c:945
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
char db_name[256]
Definition: log_applier.c:393
#define THREAD_CALLING_CONVENTION
Definition: porting.h:714
int or_advance(OR_BUF *buf, int offset)
#define ER_HA_LA_UNEXPECTED_EOF_IN_ARCHIVE_LOG
Definition: error_code.h:1285
#define ERR_MSG_SIZE
unsigned int time
Definition: dbtype_def.h:777
LOG_LSA final_lsa
Definition: log_applier.c:291
const TRANID LOG_SYSTEM_TRANID
static unsigned long la_get_mem_size(void)
Definition: log_applier.c:6479
#define OR_GET_BOUND_BIT(bitptr, element)
int db_commit_transaction(void)
Definition: db_admin.c:1091
const char * css_ha_applier_state_string(HA_LOG_APPLIER_STATE state)
int variable_count
Definition: class_object.h:738
void ws_free_repl_flush_error(WS_REPL_FLUSH_ERR *flush_err)
Definition: work_space.c:5115
LA_COMMIT * commit_head
Definition: log_applier.c:303
char * envvar_confdir_file(char *path, size_t size, const char *filename)
static DB_VALUE * la_get_item_pk_value(LA_ITEM *item)
Definition: log_applier.c:3077
bool mark_will_del
static LA_CACHE_PB * la_init_cache_pb(void)
Definition: log_applier.c:2478
#define LA_OUT_VALUE_COUNT