CUBRID Engine  latest
checksumdb.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  * checksumdb.c - Main for checksum database
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <assert.h>
32 
33 #include "authenticate.h"
34 #include "error_code.h"
35 #include "system_parameter.h"
36 #include "message_catalog.h"
37 #include "db.h"
38 #include "utility.h"
39 #include "parser.h"
40 #include "object_print.h"
41 #include "schema_manager.h"
42 #include "transaction_cl.h"
43 #include "util_func.h"
44 #include "client_support.h"
45 #include "connection_support.h"
46 #include "environment_variable.h"
47 #include "network_interface_cl.h"
48 #include "locator_cl.h"
49 #include "db_value_printer.hpp"
50 #include "mem_block.hpp"
51 #include "string_buffer.hpp"
52 #include "dbtype.h"
53 
54 #define CHKSUM_DEFAULT_LIST_SIZE 10
55 #define CHKSUM_MIN_CHUNK_SIZE 100
56 #define CHKSUM_DEFAULT_TABLE_NAME "db_ha_checksum"
57 #define CHKSUM_SCHEMA_TABLE_SUFFIX "_schema"
58 
59 #define CHKSUM_TABLE_CLASS_NAME_COL "class_name"
60 #define CHKSUM_TABLE_CHUNK_ID_COL "chunk_id"
61 #define CHKSUM_TABLE_LOWER_BOUND_COL "chunk_lower_bound"
62 #define CHKSUM_TABLE_CHUNK_CHECKSUM_COL "chunk_checksum"
63 #define CHKSUM_TABLE_COUNT_COL "chunk_count"
64 #define CHKSUM_TABLE_MASTER_CHEKSUM_COL "master_checksum"
65 #define CHKSUM_TABLE_BEGINS_AT_COL "begins_at"
66 #define CHKSUM_TABLE_ELAPSED_TIME_COL "elapsed_time"
67 
68 #define CHKSUM_TABLE_MASTER_SCHEMA_COL "master_schema_def"
69 #define CHKSUM_TABLE_SCHEMA_COL "schema_def"
70 #define CHKSUM_TABLE_SCHEMA_TIME_COL "collected_time"
71 #define CHKSUM_TABLE_SCHEMA_REPID_COL "representation_id"
72 
73 #define CHKSUM_STOP_ON_ERROR(err, arg) (((err) != NO_ERROR) && \
74  ((ER_IS_SERVER_DOWN_ERROR(err) == true) || \
75  ((arg)->cont_on_err == false)))
76 
77 #define CHKSUM_PRINT_AND_LOG(fp, ...) \
78  do {\
79  fprintf(stdout, __VA_ARGS__);\
80  fprintf(fp, __VA_ARGS__);\
81  }while (0)
82 
85 {
91 };
92 
93 typedef struct chksum_arg CHKSUM_ARG;
94 struct chksum_arg
95 {
99  bool resume;
104 };
105 
109 
110 static int chksum_drop_and_create_checksum_table (void);
111 static int chksum_init_checksum_tables (bool resume);
112 static int chksum_get_prev_checksum_results (void);
113 static CHKSUM_RESULT *chksum_get_checksum_result (const char *table_name);
114 static void chksum_free_results (CHKSUM_RESULT * results);
115 static bool chksum_need_skip_table (const char *table_name, CHKSUM_ARG * chksum_arg);
116 static int chksum_set_initial_chunk_id_and_lower_bound (PARSER_CONTEXT * parser, const char *table_name,
117  DB_CONSTRAINT * pk_cons, int *chunk_id,
118  PARSER_VARCHAR ** lower_bound);
119 static PARSER_VARCHAR *chksum_print_pk_list (PARSER_CONTEXT * parser, DB_CONSTRAINT * pk, int *pk_col_cnt,
120  bool include_decs);
121 static PARSER_VARCHAR *chksum_print_select_last_chunk (PARSER_CONTEXT * parser, const char *table_name,
122  PARSER_VARCHAR * pk_list, PARSER_VARCHAR * pk_orderby,
123  PARSER_VARCHAR * prev_lower_bound, int limit);
124 static PARSER_VARCHAR *chksum_print_checksum_query (PARSER_CONTEXT * parser, const char *table_name,
125  DB_ATTRIBUTE * attributes, PARSER_VARCHAR * lower_bound,
126  int chunk_id, int chunk_size);
128  int pk_col_cnt);
130  PARSER_VARCHAR * orig_lower_bound);
132 static PARSER_VARCHAR *chksum_get_next_lower_bound (PARSER_CONTEXT * parser, const char *table_name,
133  DB_CONSTRAINT * pk_cons, PARSER_VARCHAR * prev_lower_bound,
134  int chunk_size, int *exec_error);
135 static PARSER_VARCHAR *chksum_get_initial_lower_bound (PARSER_CONTEXT * parser, const char *table_name,
136  DB_CONSTRAINT * pk_cons, int *exec_error);
138  int chunk_id);
140  int chunk_id, int master_checksum);
141 static int chksum_update_master_checksum (PARSER_CONTEXT * parser, const char *table_name, int chunk_id);
142 static int chksum_set_repl_info_and_demote_table_lock (const char *table_name, const char *checksum_query,
143  const OID * class_oidp);
144 static int chksum_update_current_schema_definition (const char *table_name, int repid);
145 static int chksum_insert_schema_definition (const char *table_name, int repid);
146 static int chksum_calculate_checksum (PARSER_CONTEXT * parser, const OID * class_oidp, const char *table_name,
147  DB_ATTRIBUTE * attributes, PARSER_VARCHAR * lower_bound, int chunk_id,
148  int chunk_size);
149 static int chksum_start (CHKSUM_ARG * chksum_arg);
150 static int chksum_report (const char *command_name, const char *database);
151 static int chksum_report_summary (FILE * fp);
152 static int chksum_report_diff (FILE * fp);
153 static int chksum_report_schema_diff (FILE * fp);
154 static void chksum_report_header (FILE * fp, const char *database);
155 static FILE *chksum_report_open_file (const char *command_name);
156 
157 
158 static FILE *
159 chksum_report_open_file (const char *command_name)
160 {
161  FILE *fp;
162  char file_name[PATH_MAX];
163  char file_path[PATH_MAX];
164 
165  snprintf (file_name, PATH_MAX, "%s_report.log", command_name);
166  envvar_logdir_file (file_path, PATH_MAX, file_name);
167 
168  fp = fopen (file_path, "a");
169 
170  return fp;
171 }
172 
173 static void
174 chksum_report_header (FILE * fp, const char *database)
175 {
176  time_t report_time;
177  struct tm *report_tm_p;
179 
180  report_time = time (NULL);
181  report_tm_p = localtime (&report_time);
182 
183  state = css_ha_server_state ();
184 
185  CHKSUM_PRINT_AND_LOG (fp, "=================================" "===============================\n");
186  CHKSUM_PRINT_AND_LOG (fp, " target DB: %s (state: %s)\n", database, css_ha_server_state_string (state));
187  CHKSUM_PRINT_AND_LOG (fp, " report time: %04d-%02d-%02d %02d:%02d:%02d\n", report_tm_p->tm_year + 1900,
188  report_tm_p->tm_mon + 1, report_tm_p->tm_mday, report_tm_p->tm_hour, report_tm_p->tm_min,
189  report_tm_p->tm_sec);
190  CHKSUM_PRINT_AND_LOG (fp, " checksum table name: %s, %s\n", chksum_result_Table_name, chksum_schema_Table_name);
191  CHKSUM_PRINT_AND_LOG (fp, "=================================" "===============================\n\n");
192 
193  return;
194 }
195 
196 static int
198 {
199 #define QUERY_BUF_SIZE 1024
200  DB_QUERY_RESULT *query_result = NULL;
201  DB_QUERY_ERROR query_error;
202  DB_VALUE out_value;
203  int res, error = NO_ERROR;
204  char query_buf[QUERY_BUF_SIZE];
205 
206  CHKSUM_PRINT_AND_LOG (fp, "------------------------\n");
207  CHKSUM_PRINT_AND_LOG (fp, " different table schema\n");
208  CHKSUM_PRINT_AND_LOG (fp, "------------------------\n");
209 
210  snprintf (query_buf, sizeof (query_buf),
212  CHKSUM_TABLE_MASTER_SCHEMA_COL " FROM %s WHERE " CHKSUM_TABLE_SCHEMA_COL " IS NULL OR "
214 
215  res = db_execute (query_buf, &query_result, &query_error);
216  if (res > 0)
217  {
218  int pos, out_val_idx;
219  char time_buf[256];
220 
221  pos = db_query_first_tuple (query_result);
222  while (pos == DB_CURSOR_SUCCESS)
223  {
224  out_val_idx = 0;
225 
226  /* class name */
227  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
228  if (error != NO_ERROR)
229  {
230  db_query_end (query_result);
231  return error;
232  }
233 
234  CHKSUM_PRINT_AND_LOG (fp, "<table name>\n%s\n", db_get_string (&out_value));
235  db_value_clear (&out_value);
236 
237  /* collected time */
238  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
239  if (error != NO_ERROR)
240  {
241  db_query_end (query_result);
242  return error;
243  }
244 
245  if (DB_IS_NULL (&out_value))
246  {
247  snprintf (time_buf, sizeof (time_buf), "UNKNOWN");
248  }
249  else
250  {
251  db_datetime_to_string (time_buf, sizeof (time_buf), db_get_datetime (&out_value));
252  }
253  db_value_clear (&out_value);
254 
255  /* current schema */
256  CHKSUM_PRINT_AND_LOG (fp, "<current schema - collected at %s>\n", time_buf);
257  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
258  if (error != NO_ERROR)
259  {
260  db_query_end (query_result);
261  return error;
262  }
263 
264  if (DB_IS_NULL (&out_value))
265  {
266  CHKSUM_PRINT_AND_LOG (fp, "NULL\n");
267  }
268  else
269  {
270  CHKSUM_PRINT_AND_LOG (fp, "%s\n", db_get_string (&out_value));
271  }
272  db_value_clear (&out_value);
273 
274  /* master schema */
275  CHKSUM_PRINT_AND_LOG (fp, "<schema from master>\n");
276  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
277  if (error != NO_ERROR)
278  {
279  db_query_end (query_result);
280  return error;
281  }
282 
283  if (DB_IS_NULL (&out_value))
284  {
285  CHKSUM_PRINT_AND_LOG (fp, "NULL\n");
286  }
287  else
288  {
289  CHKSUM_PRINT_AND_LOG (fp, "%s\n", db_get_string (&out_value));
290  }
291  db_value_clear (&out_value);
292 
293  pos = db_query_next_tuple (query_result);
294  CHKSUM_PRINT_AND_LOG (fp, "\n");
295  }
296  db_query_end (query_result);
297 
299  "* Due to schema inconsistency, the checksum "
300  "difference of the above table(s) may not be reported.\n");
301  }
302  else if (res == 0)
303  {
304  CHKSUM_PRINT_AND_LOG (fp, "NONE\n\n");
305  db_query_end (query_result);
306  }
307  else
308  {
309  error = res;
310  CHKSUM_PRINT_AND_LOG (fp, "ERROR\n\n");
311  }
312 
313  return error;
314 #undef QUERY_BUF_SIZE
315 }
316 
317 static int
319 {
320 #define QUERY_BUF_SIZE 1024
321  DB_QUERY_RESULT *query_result = NULL;
322  DB_QUERY_ERROR query_error;
323  DB_VALUE out_value;
324  int res, error = NO_ERROR;
325  char query_buf[QUERY_BUF_SIZE];
326 
327  CHKSUM_PRINT_AND_LOG (fp, "-------------------------------" "---------------------------------\n");
328  CHKSUM_PRINT_AND_LOG (fp, "table name\tdiff chunk id\tchunk lower bound\n");
329  CHKSUM_PRINT_AND_LOG (fp, "-------------------------------" "---------------------------------\n");
330 
331  snprintf (query_buf, sizeof (query_buf),
335 
336  res = db_execute (query_buf, &query_result, &query_error);
337  if (res > 0)
338  {
339  int pos, out_val_idx;
340 
341  pos = db_query_first_tuple (query_result);
342  while (pos == DB_CURSOR_SUCCESS)
343  {
344  out_val_idx = 0;
345 
346  /* class name */
347  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
348  if (error != NO_ERROR)
349  {
350  db_query_end (query_result);
351  return error;
352  }
353  CHKSUM_PRINT_AND_LOG (fp, "%-15s ", db_get_string (&out_value));
354  db_value_clear (&out_value);
355 
356  /* chunk id */
357  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
358  if (error != NO_ERROR)
359  {
360  db_query_end (query_result);
361  return error;
362  }
363  CHKSUM_PRINT_AND_LOG (fp, "%-15d ", db_get_int (&out_value));
364  db_value_clear (&out_value);
365 
366  /* lower bound */
367  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
368  if (error != NO_ERROR)
369  {
370  db_query_end (query_result);
371  return error;
372  }
373  CHKSUM_PRINT_AND_LOG (fp, "%s\n", db_get_string (&out_value));
374  db_value_clear (&out_value);
375 
376  pos = db_query_next_tuple (query_result);
377  }
378  CHKSUM_PRINT_AND_LOG (fp, "\n");
379  db_query_end (query_result);
380  }
381  else if (res == 0)
382  {
383  CHKSUM_PRINT_AND_LOG (fp, "NONE\n\n");
384  db_query_end (query_result);
385  }
386  else
387  {
388  error = res;
389  CHKSUM_PRINT_AND_LOG (fp, "ERROR\n\n");
390  }
391 
392  return error;
393 #undef QUERY_BUF_SIZE
394 }
395 
396 static int
398 {
399 #define QUERY_BUF_SIZE 1024
400  DB_QUERY_RESULT *query_result = NULL;
401  DB_QUERY_ERROR query_error;
402  DB_VALUE out_value;
403  int num_chunks;
404  int res, error = NO_ERROR;
405  char query_buf[QUERY_BUF_SIZE];
406 
408  "-------------------------------------------------" "-------------------------------------\n");
409  CHKSUM_PRINT_AND_LOG (fp, "table name\ttotal # of chunks\t# of diff chunks\t" "total/avg/min/max time\n");
411  "-------------------------------------------------" "-------------------------------------\n");
412 
413  snprintf (query_buf, sizeof (query_buf),
414  "SELECT " CHKSUM_TABLE_CLASS_NAME_COL ", " "COUNT (*), " "COUNT(CASE WHEN " CHKSUM_TABLE_MASTER_CHEKSUM_COL
415  " <> " CHKSUM_TABLE_CHUNK_CHECKSUM_COL " OR " CHKSUM_TABLE_CHUNK_CHECKSUM_COL " IS NULL THEN 1 END), "
416  " SUM (" CHKSUM_TABLE_ELAPSED_TIME_COL "), " " MIN (" CHKSUM_TABLE_ELAPSED_TIME_COL "), " " MAX ("
419 
420  res = db_execute (query_buf, &query_result, &query_error);
421  if (res > 0)
422  {
423  int pos, error, out_val_idx;
424 
425  pos = db_query_first_tuple (query_result);
426  while (pos == DB_CURSOR_SUCCESS)
427  {
428  out_val_idx = 0;
429 
430  /* class_name */
431  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
432  if (error != NO_ERROR)
433  {
434  db_query_end (query_result);
435  return error;
436  }
437  CHKSUM_PRINT_AND_LOG (fp, "%-15s ", db_get_string (&out_value));
438  db_value_clear (&out_value);
439 
440  /* total num of chunks */
441  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
442  if (error != NO_ERROR)
443  {
444  db_query_end (query_result);
445  return error;
446  }
447  num_chunks = db_get_int (&out_value);
448  CHKSUM_PRINT_AND_LOG (fp, "%-23d ", num_chunks);
449  db_value_clear (&out_value);
450 
451  /* total num of diff chunk */
452  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
453  if (error != NO_ERROR)
454  {
455  db_query_end (query_result);
456  return error;
457  }
458  CHKSUM_PRINT_AND_LOG (fp, "%-23d ", db_get_int (&out_value));
459  db_value_clear (&out_value);
460 
461  /* total elapsed time */
462  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
463  if (error != NO_ERROR)
464  {
465  db_query_end (query_result);
466  return error;
467  }
468 
469  CHKSUM_PRINT_AND_LOG (fp, "%d / %d ", db_get_int (&out_value), db_get_int (&out_value) / num_chunks);
470  db_value_clear (&out_value);
471 
472  /* min elapsed time */
473  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
474  if (error != NO_ERROR)
475  {
476  db_query_end (query_result);
477  return error;
478  }
479 
480  CHKSUM_PRINT_AND_LOG (fp, "/ %d ", db_get_int (&out_value));
481  db_value_clear (&out_value);
482 
483  /* max elapsed time */
484  error = db_query_get_tuple_value (query_result, out_val_idx++, &out_value);
485  if (error != NO_ERROR)
486  {
487  db_query_end (query_result);
488  return error;
489  }
490 
491  CHKSUM_PRINT_AND_LOG (fp, "/ %d (ms)\n", db_get_int (&out_value));
492  db_value_clear (&out_value);
493 
494  pos = db_query_next_tuple (query_result);
495  }
496 
497  CHKSUM_PRINT_AND_LOG (fp, "\n");
498  db_query_end (query_result);
499  }
500  else if (res == 0)
501  {
502  CHKSUM_PRINT_AND_LOG (fp, "NONE\n\n");
503  db_query_end (query_result);
504  }
505  else
506  {
507  error = res;
508  CHKSUM_PRINT_AND_LOG (fp, "ERROR\n\n");
509  }
510 
511  return error;
512 #undef QUERY_BUF_SIZE
513 }
514 
515 static int
516 chksum_report (const char *command_name, const char *database)
517 {
518  FILE *fp;
519  char err_msg[LINE_MAX];
520  char *missing_table = NULL;
521  int error = NO_ERROR;
522 
523  fp = chksum_report_open_file (command_name);
524  if (fp == NULL)
525  {
526  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CHKSUM_GENERIC_ERR, 2, "Failed to open a report file", ER_FAILED);
527  return ER_FAILED;
528  }
529 
532  {
533  missing_table = chksum_result_Table_name;
534  }
536  {
537  missing_table = chksum_schema_Table_name;
538  }
539 
540  if (missing_table != NULL)
541  {
542  snprintf (err_msg, sizeof (err_msg), "Cannot find table %s", missing_table);
543 
544  error = er_errid ();
546  return error;
547  }
548 
549  chksum_report_header (fp, database);
550 
551  error = chksum_report_schema_diff (fp);
552  if (error != NO_ERROR)
553  {
554  goto exit;
555  }
556 
557  error = chksum_report_diff (fp);
558  if (error != NO_ERROR)
559  {
560  goto exit;
561  }
562 
563  error = chksum_report_summary (fp);
564 
565 exit:
566  fflush (fp);
567  fclose (fp);
568 
569  return error;
570 }
571 
572 /*
573  * chksum_init_checksum_tables () -
574  * - validate and initialize checksum tables
575  * return:
576  */
577 static int
579 {
580  DB_OBJECT *classobj;
581  char err_msg[LINE_MAX];
582  int error = NO_ERROR;
583  char *invalid_table = NULL;
584  char *missing_table = NULL;
585 
586  /* check checksum result table */
588  if (classobj != NULL)
589  {
598  {
599  invalid_table = chksum_result_Table_name;
600  error = er_errid ();
601  goto end;
602  }
603  }
604  else if (resume == true)
605  {
606  /* resumed but no checksum table */
607  missing_table = chksum_result_Table_name;
608  error = er_errid ();
609  goto end;
610  }
611 
612  /* check checksum schema table */
614  if (classobj != NULL)
615  {
621  {
622  invalid_table = chksum_schema_Table_name;
623  error = er_errid ();
624  goto end;
625  }
626  }
627  else if (resume == true)
628  {
629  missing_table = chksum_schema_Table_name;
630  error = er_errid ();
631  goto end;
632  }
633 
634  if (resume == false)
635  {
637  if (error != NO_ERROR)
638  {
639  snprintf (err_msg, sizeof (err_msg), "Failed to drop and create checksum tables");
640  }
641  }
642 
643 end:
644  if (error != NO_ERROR)
645  {
646  if (invalid_table != NULL)
647  {
648  snprintf (err_msg, sizeof (err_msg), "Invalid checksum table [%s] exists", invalid_table);
649  }
650  else if (missing_table != NULL && resume == true)
651  {
652  snprintf (err_msg, sizeof (err_msg), "Failed to resume calculation. Table [%s] not found", missing_table);
653  }
654 
656  }
657 
658  return error;
659 }
660 
661 /*
662  * chksum_create_table () -
663  * - create checksum tables
664  * return:
665  */
666 static int
668 {
669 #define QUERY_BUF_SIZE 2048
670  DB_QUERY_RESULT *query_result = NULL;
671  DB_QUERY_ERROR query_error;
672  int res, error = NO_ERROR;
673  char query_buf[QUERY_BUF_SIZE];
674 
675  snprintf (query_buf, sizeof (query_buf), "DROP TABLE IF EXISTS %s;" /* 0 */
676  "CREATE TABLE %s" /* 1 */
677  "(%s VARCHAR (255) NOT NULL," /* 2 */
678  " %s INT NOT NULL," /* 3 */
679  " %s VARCHAR," /* 4 */
680  " %s INT NOT NULL," /* 5 */
681  " %s INT," /* 6 */
682  " %s INT," /* 7 */
683  " %s DATETIME DEFAULT sys_datetime," /* 8 */
684  " %s INT," /* 9 */
685  " CONSTRAINT UNIQUE INDEX (%s, %s));" /* 10, 11 */
686  "DROP TABLE IF EXISTS %s;" /* 12 */
687  "CREATE TABLE %s" /* 13 */
688  "(%s VARCHAR (255) NOT NULL," /* 14 */
689  " %s INT NOT NULL," /* 15 */
690  " %s VARCHAR," /* 16 */
691  " %s VARCHAR," /* 17 */
692  " %s DATETIME," /* 18 */
693  " PRIMARY KEY (%s, %s));", /* 19, 20 */
694  chksum_result_Table_name, /* 0 */
695  chksum_result_Table_name, /* 1 */
699  CHKSUM_TABLE_COUNT_COL, /* 5 */
705  CHKSUM_TABLE_CHUNK_ID_COL, /* 11 */
706  chksum_schema_Table_name, /* 12 */
707  chksum_schema_Table_name, /* 13 */
710  CHKSUM_TABLE_SCHEMA_COL, /* 16 */
715 
716  res = db_execute (query_buf, &query_result, &query_error);
717  if (res >= 0)
718  {
719  db_query_end (query_result);
720  error = db_commit_transaction ();
721  }
722  else
723  {
724  error = res;
725  }
726 
727  return error;
728 
729 #undef QUERY_BUF_SIZE
730 }
731 
732 
733 /*
734  * chksum_free_results () -
735  * - free memory used for previous checksum results
736  * return:
737  */
738 static void
740 {
741  CHKSUM_RESULT *res, *next_res;
742 
743  res = results;
744  while (res != NULL)
745  {
746  next_res = res->next;
747 
748  if (res->last_lower_bound != NULL)
749  {
751  }
752 
753  free_and_init (res);
754 
755  res = next_res;
756  }
757 
758  return;
759 }
760 
761 /*
762  * chksum_get_checksum_result ()
763  * - get previous checksum result for a table
764  * return: checksum result
765  * table_name(in): source table name
766  */
767 static CHKSUM_RESULT *
768 chksum_get_checksum_result (const char *table_name)
769 {
770  CHKSUM_RESULT *res;
771 
772  if (chksum_Prev_results == NULL || table_name == NULL)
773  {
774  return NULL;
775  }
776 
777  res = chksum_Prev_results;
778  while (res != NULL)
779  {
780  if (strcmp (res->class_name, table_name) == 0)
781  {
782  return res;
783  }
784 
785  res = res->next;
786  }
787 
788  return NULL;
789 }
790 
791 /*
792  * chksum_get_prev_checksum_results ()
793  * - get previous checksum results
794  * return: error
795  */
796 static int
798 {
799 #define QUERY_BUF_SIZE 2048
800 
801  CHKSUM_RESULT *checksum_result = NULL;
802  DB_QUERY_RESULT *query_result = NULL;
803  DB_QUERY_ERROR query_error;
804  int res, error = NO_ERROR;
805  char query_buf[QUERY_BUF_SIZE];
806  DB_VALUE value;
807 
808  if (chksum_Prev_results != NULL)
809  {
810  chksum_free_results (chksum_Prev_results);
811  }
812 
813  snprintf (query_buf, sizeof (query_buf),
814  "SELECT " "C1." CHKSUM_TABLE_CLASS_NAME_COL ", " "C1." CHKSUM_TABLE_CHUNK_ID_COL ", " "C1."
815  CHKSUM_TABLE_LOWER_BOUND_COL ", " "C1." CHKSUM_TABLE_COUNT_COL " FROM " " %s AS C1 INNER JOIN (SELECT "
816  CHKSUM_TABLE_CLASS_NAME_COL ", " "MAX (" CHKSUM_TABLE_CHUNK_ID_COL ") " "AS MAX_ID FROM %s GROUP BY "
820 
821  res = db_execute (query_buf, &query_result, &query_error);
822  if (res >= 0)
823  {
824  int pos;
825  int out_val_idx;
826  const char *db_string_p = NULL;
827 
828  pos = db_query_first_tuple (query_result);
829  while (pos == DB_CURSOR_SUCCESS)
830  {
831  out_val_idx = 0;
832 
833  checksum_result = (CHKSUM_RESULT *) malloc (sizeof (CHKSUM_RESULT));
834  if (checksum_result == NULL)
835  {
838  break;
839  }
840 
841  memset (checksum_result, 0, sizeof (CHKSUM_RESULT));
842 
843  /* class_name */
844  error = db_query_get_tuple_value (query_result, out_val_idx++, &value);
845  if (error != NO_ERROR)
846  {
847  db_query_end (query_result);
848  return error;
849  }
850 
851  db_string_p = db_get_string (&value);
852  if (db_string_p != NULL)
853  {
854  snprintf (checksum_result->class_name, SM_MAX_IDENTIFIER_LENGTH, "%s", db_string_p);
855  }
856  db_value_clear (&value);
857 
858  /* chunk_id */
859  error = db_query_get_tuple_value (query_result, out_val_idx++, &value);
860  if (error != NO_ERROR)
861  {
862  db_query_end (query_result);
863  return error;
864  }
865 
866  checksum_result->last_chunk_id = db_get_int (&value);
867  db_value_clear (&value);
868 
869  /* chunk_lower_bound */
870  error = db_query_get_tuple_value (query_result, out_val_idx++, &value);
871  if (error != NO_ERROR)
872  {
873  db_query_end (query_result);
874  return error;
875  }
876 
877  db_string_p = db_get_string (&value);
878  if (db_string_p != NULL)
879  {
880  checksum_result->last_lower_bound = strdup (db_string_p);
881  }
882  db_value_clear (&value);
883 
884  /* chunk_count */
885  error = db_query_get_tuple_value (query_result, out_val_idx++, &value);
886  if (error != NO_ERROR)
887  {
888  db_query_end (query_result);
889  return error;
890  }
891 
892  checksum_result->last_chunk_cnt = db_get_int (&value);
893  db_value_clear (&value);
894 
895  checksum_result->next = chksum_Prev_results;
896  chksum_Prev_results = checksum_result;
897 
898  pos = db_query_next_tuple (query_result);
899  }
900  db_query_end (query_result);
901  }
902  else
903  {
904  error = res;
905  }
906 
907  return error;
908 #undef QUERY_BUF_SIZE
909 }
910 
911 /*
912  * chksum_set_intial_chunk_id_and_lower_bound ()
913  * - set initial values to be used for calculating checksum
914  * return: error
915  * parser(in):
916  * table_name(in): source table name
917  * pk_cons(in): primary key constraint info
918  * chunk_id(out):
919  * lower_bound(out): initial starting point
920  */
921 static int
923  int *chunk_id, PARSER_VARCHAR ** lower_bound)
924 {
925  CHKSUM_RESULT *prev_result = NULL;
926  int error = NO_ERROR;
927 
928  assert (lower_bound != NULL);
929 
930  *chunk_id = 0;
931  *lower_bound = NULL;
932 
933  prev_result = chksum_get_checksum_result (table_name);
934  if (prev_result != NULL)
935  {
936  *chunk_id = prev_result->last_chunk_id;
937 
938  assert (prev_result->last_lower_bound != NULL && prev_result->last_lower_bound[0] != '\0');
939 
940  *lower_bound = pt_append_nulstring (parser, NULL, prev_result->last_lower_bound);
941  }
942  else
943  {
944  /* no previous work exists */
945  *lower_bound = chksum_get_initial_lower_bound (parser, table_name, pk_cons, &error);
946  }
947 
948  return error;
949 }
950 
951 /*
952  * chksum_print_pk_list ()
953  * - print primary key column list
954  * return: primary key column list
955  * parser(in):
956  * pk(in): primary key info
957  * pk_col_cnt(out):
958  * include_decs(in): include DESC if exists
959  */
960 static PARSER_VARCHAR *
961 chksum_print_pk_list (PARSER_CONTEXT * parser, DB_CONSTRAINT * pk, int *pk_col_cnt, bool include_decs)
962 {
963  PARSER_VARCHAR *buffer = NULL;
964  DB_ATTRIBUTE **pk_attrs = NULL;
965  const int *asc_desc = NULL;
966  int i;
967 
968  if (parser == NULL)
969  {
970  return NULL;
971  }
972 
973  pk_attrs = db_constraint_attributes (pk);
974  if (pk_attrs == NULL)
975  {
976  return NULL;
977  }
978 
979  asc_desc = db_constraint_asc_desc (pk);
980  if (asc_desc == NULL)
981  {
982  return NULL;
983  }
984 
985  for (i = 0; pk_attrs[i] != NULL; i++)
986  {
987  if (i > 0)
988  {
989  buffer = pt_append_nulstring (parser, buffer, ", ");
990  }
991 
992  buffer = pt_append_nulstring (parser, buffer, db_attribute_name (pk_attrs[i]));
993 
994  if (include_decs == true && asc_desc[i] == 1)
995  {
996  buffer = pt_append_nulstring (parser, buffer, " DESC");
997  }
998  }
999 
1000  if (pk_col_cnt != NULL)
1001  {
1002  *pk_col_cnt = i;
1003  }
1004 
1005  return buffer;
1006 }
1007 
1008 /*
1009  * chksum_print_select_last_chunk ()
1010  * - print a query to get lower bound condition
1011  * return: a query to get lower bound condition
1012  * parser(in):
1013  * table_name(in): source table name
1014  * pk_list(in):
1015  * pk_orderby(in): pk column list used for ORDER BY
1016  * prev_lower_bound(in):
1017  * limit(in): number used for LIMIT
1018  */
1019 static PARSER_VARCHAR *
1021  PARSER_VARCHAR * pk_orderby, PARSER_VARCHAR * prev_lower_bound, int limit)
1022 {
1023  PARSER_VARCHAR *buffer = NULL;
1024  char limit_str[15];
1025 
1026  if (parser == NULL)
1027  {
1028  return NULL;
1029  }
1030 
1031  sprintf (limit_str, "%d", limit);
1032 
1033  buffer = pt_append_nulstring (parser, buffer, "SELECT ");
1034  buffer = pt_append_varchar (parser, buffer, pk_list);
1035 
1036  buffer = pt_append_nulstring (parser, buffer, " FROM ");
1037  buffer = pt_append_nulstring (parser, buffer, table_name);
1038 
1039  if (prev_lower_bound != NULL)
1040  {
1041  buffer = pt_append_nulstring (parser, buffer, " WHERE ");
1042  buffer = pt_append_varchar (parser, buffer, prev_lower_bound);
1043  }
1044 
1045  buffer = pt_append_nulstring (parser, buffer, " ORDER BY ");
1046  buffer = pt_append_varchar (parser, buffer, pk_orderby);
1047 
1048  buffer = pt_append_nulstring (parser, buffer, " LIMIT ");
1049  buffer = pt_append_nulstring (parser, buffer, limit_str);
1050 
1051  return buffer;
1052 }
1053 
1054 /*
1055  * chksum_print_checksum_query ()
1056  * - print a query for calculating checksum
1057  * return: a query for calculating checksum
1058  * parser(in):
1059  * table_name(in): source table name
1060  * attributes(in): attributes info
1061  * lower_bound(in): starting point of chunk
1062  * chunk_id(in):
1063  * chunk_size(in):
1064  */
1065 static PARSER_VARCHAR *
1066 chksum_print_checksum_query (PARSER_CONTEXT * parser, const char *table_name, DB_ATTRIBUTE * attributes,
1067  PARSER_VARCHAR * lower_bound, int chunk_id, int chunk_size)
1068 {
1069  PARSER_VARCHAR *buffer = NULL;
1070  PARSER_VARCHAR *att_list = NULL;
1071  PARSER_VARCHAR *escaped_lower_bound = NULL;
1072  char chunk_id_str[15];
1073  char chunk_size_str[15];
1074 
1075  assert (parser != NULL);
1076 
1077  sprintf (chunk_id_str, "%d", chunk_id);
1078  sprintf (chunk_size_str, "%d", chunk_size);
1079 
1080 
1081  att_list = chksum_print_attribute_list (parser, attributes);
1082  escaped_lower_bound = chksum_get_quote_escaped_lower_bound (parser, lower_bound);
1083 
1084  /* query for calculating checksum */
1085  buffer = pt_append_nulstring (parser, buffer, "REPLACE INTO ");
1086  buffer = pt_append_nulstring (parser, buffer, chksum_result_Table_name);
1087  buffer =
1088  pt_append_nulstring (parser, buffer,
1091  ", " CHKSUM_TABLE_BEGINS_AT_COL ") " "SELECT '");
1092  buffer = pt_append_nulstring (parser, buffer, table_name);
1093  buffer = pt_append_nulstring (parser, buffer, "', ");
1094  buffer = pt_append_nulstring (parser, buffer, chunk_id_str);
1095  buffer = pt_append_nulstring (parser, buffer, ", '");
1096  buffer = pt_append_varchar (parser, buffer, escaped_lower_bound);
1097  buffer =
1098  pt_append_nulstring (parser, buffer,
1099  "', " " count (*), " " BIT_XOR (crc32_result), " " SYS_DATETIME " "FROM"
1100  " (SELECT CRC32(CONCAT_WS('', ");
1101  buffer = pt_append_varchar (parser, buffer, att_list);
1102  buffer = pt_append_nulstring (parser, buffer, ")) AS crc32_result" " FROM ");
1103  buffer = pt_append_nulstring (parser, buffer, table_name);
1104  buffer = pt_append_nulstring (parser, buffer, " WHERE ");
1105  buffer = pt_append_varchar (parser, buffer, lower_bound);
1106  buffer = pt_append_nulstring (parser, buffer, " LIMIT ");
1107  buffer = pt_append_nulstring (parser, buffer, chunk_size_str);
1108  buffer = pt_append_nulstring (parser, buffer, ");");
1109 
1110  /* query for updating elapsed time */
1111  buffer = pt_append_nulstring (parser, buffer, " UPDATE ");
1112  buffer = pt_append_nulstring (parser, buffer, chksum_result_Table_name);
1113  buffer = pt_append_nulstring (parser, buffer, " SET ");
1114  buffer =
1115  pt_append_nulstring (parser, buffer,
1116  CHKSUM_TABLE_ELAPSED_TIME_COL " = SYS_DATETIME - " CHKSUM_TABLE_BEGINS_AT_COL " WHERE "
1118  buffer = pt_append_nulstring (parser, buffer, table_name);
1119  buffer = pt_append_nulstring (parser, buffer, "' AND " CHKSUM_TABLE_CHUNK_ID_COL " = ");
1120  buffer = pt_append_nulstring (parser, buffer, chunk_id_str);
1121  buffer = pt_append_nulstring (parser, buffer, ";");
1122 
1123 
1124  return buffer;
1125 }
1126 
1127 /*
1128  * chksum_print_lower_bound_string ()
1129  * - print lower bound string which will be used
1130  * in WHERE clause of chunking query
1131  * return: lower bound string
1132  * parser(in):
1133  * values(in): value of each attribute
1134  * pk(in): primary key info
1135  * pk_col_cnt(in): the number of columns in primary key
1136  */
1137 static PARSER_VARCHAR *
1139 {
1140  PARSER_VARCHAR *buffer = NULL;
1141  PARSER_VARCHAR *value = NULL;
1142  DB_ATTRIBUTE **pk_attrs = NULL;
1143  const int *asc_desc = NULL;
1144  int i;
1145  int col_cnt = 0;
1146 
1147  if (parser == NULL)
1148  {
1149  return NULL;
1150  }
1151 
1152  pk_attrs = db_constraint_attributes (pk);
1153  if (pk_attrs == NULL)
1154  {
1155  return NULL;
1156  }
1157 
1158  asc_desc = db_constraint_asc_desc (pk);
1159  if (asc_desc == NULL)
1160  {
1161  return NULL;
1162  }
1163 
1164  col_cnt = pk_col_cnt;
1165 
1166  string_buffer sb;
1167  db_value_printer printer (sb);
1168  while (col_cnt > 0)
1169  {
1170  if (col_cnt < pk_col_cnt)
1171  {
1172  buffer = pt_append_nulstring (parser, buffer, " OR ");
1173  }
1174 
1175  buffer = pt_append_nulstring (parser, buffer, "(");
1176  for (i = 0; pk_attrs[i] != NULL && i < col_cnt; i++)
1177  {
1178  if (i > 0)
1179  {
1180  buffer = pt_append_nulstring (parser, buffer, " AND ");
1181  }
1182 
1183  buffer = pt_append_nulstring (parser, buffer, db_attribute_name (pk_attrs[i]));
1184 
1185  if (asc_desc[i] == 1)
1186  {
1187  buffer = pt_append_nulstring (parser, buffer, "<");
1188  }
1189  else
1190  {
1191  buffer = pt_append_nulstring (parser, buffer, ">");
1192  }
1193 
1194  if (col_cnt == pk_col_cnt || i < (col_cnt - 1))
1195  {
1196  buffer = pt_append_nulstring (parser, buffer, "=");
1197  }
1198 
1199  sb.clear ();
1200  printer.describe_value (&values[i]);
1201  buffer = pt_append_nulstring (parser, buffer, sb.get_buffer ());
1202  }
1203 
1204  buffer = pt_append_nulstring (parser, buffer, ")");
1205  col_cnt--;
1206  }
1207 
1208  return buffer;
1209 }
1210 
1211 /*
1212  * chksum_print_attribute_list ()
1213  * - print comma-separated attributes list
1214  * return: attributes list
1215  * parser(in):
1216  * attributes(in):
1217  */
1218 static PARSER_VARCHAR *
1220 {
1221  PARSER_VARCHAR *buffer = NULL;
1222  DB_ATTRIBUTE *att;
1223 
1224  if (parser == NULL)
1225  {
1226  return NULL;
1227  }
1228 
1229  att = attributes;
1230  while (att != NULL)
1231  {
1232  buffer = pt_append_nulstring (parser, buffer, "`");
1233  buffer = pt_append_nulstring (parser, buffer, db_attribute_name (att));
1234  buffer = pt_append_nulstring (parser, buffer, "`");
1235 
1236  att = db_attribute_next (att);
1237  if (att != NULL)
1238  {
1239  buffer = pt_append_nulstring (parser, buffer, ", ");
1240  }
1241  }
1242 
1243  return buffer;
1244 }
1245 
1246 /*
1247  * chksum_get_quote_escaped_lower_bound ()
1248  * - escape single quotes in lower bound string
1249  * return: escaped lower bound string to be used in WHERE clause
1250  * parser(in):
1251  * orig_lower_bound(in):
1252  */
1253 static PARSER_VARCHAR *
1255 {
1256  PARSER_VARCHAR *buffer = NULL;
1257  char *start, *end, *pos;
1258  int length = 0;
1259 
1260  assert (parser != NULL);
1261 
1262  start = (char *) orig_lower_bound->bytes;
1263  end = (char *) orig_lower_bound->bytes + orig_lower_bound->length;
1264 
1265  while (start < end)
1266  {
1267  pos = start;
1268  while (pos != NULL && pos < end && (*pos) != '\'')
1269  {
1270  pos++;
1271  }
1272 
1273  /* a quote found */
1274  if (pos < end)
1275  {
1276  length = pos - start + 1;
1277  buffer = pt_append_bytes (parser, buffer, start, length);
1278  buffer = pt_append_nulstring (parser, buffer, "'");
1279  }
1280  else
1281  {
1282  buffer = pt_append_bytes (parser, buffer, start, end - start);
1283  }
1284 
1285  start = pos + 1;
1286  }
1287 
1288  return buffer;
1289 }
1290 
1291 /*
1292  * chksum_get_next_lower_bound ()
1293  * - get a starting point for a next chunk
1294  * return: lower bound string to be used in WHERE clause
1295  * parser(in):
1296  * table_name(in): source table name
1297  * pk_cons(in): primary key constraint info
1298  * prev_lower_bound(in): previous lower bound
1299  * chunk_size(in):
1300  * exec_error(out): error
1301  */
1302 static PARSER_VARCHAR *
1303 chksum_get_next_lower_bound (PARSER_CONTEXT * parser, const char *table_name, DB_CONSTRAINT * pk_cons,
1304  PARSER_VARCHAR * prev_lower_bound, int chunk_size, int *exec_error)
1305 {
1306  DB_QUERY_RESULT *query_result = NULL;
1307  DB_QUERY_ERROR query_error;
1308  PARSER_VARCHAR *select_last_chunk = NULL;
1309  PARSER_VARCHAR *pk_list = NULL;
1310  PARSER_VARCHAR *pk_orderby = NULL;
1311  PARSER_VARCHAR *lower_bound_str = NULL;
1312  DB_VALUE *out_values = NULL;
1313  char err_msg[LINE_MAX];
1314  char chunk_size_str[15];
1315  int pk_col_cnt = 0;
1316  int res, i;
1317  const char *query;
1318 
1319  *exec_error = NO_ERROR;
1320 
1321  sprintf (chunk_size_str, "%d", chunk_size);
1322 
1323  pk_list = chksum_print_pk_list (parser, pk_cons, &pk_col_cnt, false);
1324  pk_orderby = chksum_print_pk_list (parser, pk_cons, NULL, true);
1325 
1326  select_last_chunk =
1327  chksum_print_select_last_chunk (parser, table_name, pk_list, pk_orderby, prev_lower_bound, chunk_size);
1328 
1329  query = (const char *) pt_get_varchar_bytes (select_last_chunk);
1330  res = db_execute (query, &query_result, &query_error);
1331 
1332  if (prev_lower_bound != NULL && res < chunk_size)
1333  {
1334  /* no more chunk to process */
1335  db_query_end (query_result);
1336 
1337  return NULL;
1338  }
1339  else if (res > 0)
1340  {
1341  int pos, error, col_cnt;
1342 
1343  pos = db_query_last_tuple (query_result);
1344  switch (pos)
1345  {
1346  case DB_CURSOR_SUCCESS:
1347  col_cnt = db_query_column_count (query_result);
1348  assert (col_cnt == pk_col_cnt);
1349 
1350  out_values = (DB_VALUE *) malloc (sizeof (DB_VALUE) * pk_col_cnt);
1351  if (out_values == NULL)
1352  {
1355  break;
1356  }
1357 
1358  error = db_query_get_tuple_valuelist (query_result, pk_col_cnt, out_values);
1359  if (error != NO_ERROR)
1360  {
1361  res = error;
1362  break;
1363  }
1364 
1365  lower_bound_str = chksum_print_lower_bound_string (parser, out_values, pk_cons, pk_col_cnt);
1366  break;
1367  case DB_CURSOR_END:
1368  case DB_CURSOR_ERROR:
1369  default:
1370  res = ER_FAILED;
1371  break;
1372  }
1373  db_query_end (query_result);
1374  }
1375 
1376  if (res < 0)
1377  {
1378  snprintf (err_msg, LINE_MAX, "Failed to get lower bound condition " "for table %s", table_name);
1380 
1381  *exec_error = res;
1382  }
1383 
1384  if (out_values != NULL)
1385  {
1386  for (i = 0; i < pk_col_cnt; i++)
1387  {
1388  db_value_clear (&out_values[i]);
1389  }
1390 
1391  free_and_init (out_values);
1392  }
1393 
1394  return lower_bound_str;
1395 }
1396 
1397 /*
1398  * chksum_get_initial_lower_bound ()
1399  * - get initial starting point for chunking table
1400  * return: lower bound string to be used in WHERE clause
1401  * parser(in):
1402  * table_name(in): source table name
1403  * pk_cons(in): primary key constraint info
1404  * exec_error(out): error
1405  */
1406 static PARSER_VARCHAR *
1408  int *exec_error)
1409 {
1410  return chksum_get_next_lower_bound (parser, table_name, pk_cons, NULL, 1, exec_error);
1411 }
1412 
1413 /*
1414  * chksum_print_select_master_checksum ()
1415  * - print a query to get the calculated checksum
1416  * return: select query
1417  * parser(in):
1418  * table_name(in): source table name
1419  * chunk_id(in):
1420  */
1421 static PARSER_VARCHAR *
1422 chksum_print_select_master_checksum (PARSER_CONTEXT * parser, const char *table_name, int chunk_id)
1423 {
1424  PARSER_VARCHAR *buffer = NULL;
1425  char chunk_id_str[15];
1426 
1427  snprintf (chunk_id_str, sizeof (chunk_id_str), "%d", chunk_id);
1428 
1429  buffer = pt_append_nulstring (parser, buffer, "SELECT chunk_checksum FROM ");
1430  buffer = pt_append_nulstring (parser, buffer, chksum_result_Table_name);
1431  buffer = pt_append_nulstring (parser, buffer, " WHERE class_name = '");
1432  buffer = pt_append_nulstring (parser, buffer, table_name);
1433  buffer = pt_append_nulstring (parser, buffer, "' AND chunk_id = ");
1434  buffer = pt_append_nulstring (parser, buffer, chunk_id_str);
1435 
1436  return buffer;
1437 }
1438 
1439 /*
1440  * chksum_print_update_master_checksum () - print update checksum query
1441  * return: update checksum query
1442  * parser(in):
1443  * table_name(in): source table name
1444  * master_checksum(in): caculated checksum
1445  */
1446 static PARSER_VARCHAR *
1447 chksum_print_update_master_checksum (PARSER_CONTEXT * parser, const char *table_name, int chunk_id, int master_checksum)
1448 {
1449  PARSER_VARCHAR *buffer = NULL;
1450  char chunk_id_str[15];
1451  char master_checksum_str[15];
1452 
1453  snprintf (chunk_id_str, sizeof (chunk_id_str), "%d", chunk_id);
1454  snprintf (master_checksum_str, sizeof (master_checksum_str), "%d", master_checksum);
1455 
1456  buffer = pt_append_nulstring (parser, buffer, "UPDATE /*+ USE_SBR */ ");
1457  buffer = pt_append_nulstring (parser, buffer, chksum_result_Table_name);
1458  buffer = pt_append_nulstring (parser, buffer, " SET " CHKSUM_TABLE_MASTER_CHEKSUM_COL " = ");
1459  buffer = pt_append_nulstring (parser, buffer, master_checksum_str);
1460  buffer = pt_append_nulstring (parser, buffer, " WHERE " CHKSUM_TABLE_CLASS_NAME_COL " = '");
1461  buffer = pt_append_nulstring (parser, buffer, table_name);
1462  buffer = pt_append_nulstring (parser, buffer, "' AND " CHKSUM_TABLE_CHUNK_ID_COL " = ");
1463  buffer = pt_append_nulstring (parser, buffer, chunk_id_str);
1464 
1465  return buffer;
1466 }
1467 
1468 /*
1469  * chksum_update_master_checksum () - update master checksum
1470  * to check integrity
1471  * return: error code
1472  * parser(in):
1473  * table_name(in): source table name
1474  * chunk_id(in):
1475  */
1476 static int
1477 chksum_update_master_checksum (PARSER_CONTEXT * parser, const char *table_name, int chunk_id)
1478 {
1479  PARSER_VARCHAR *update_checksum_query = NULL;
1480  PARSER_VARCHAR *select_checksum_query = NULL;
1481 
1482  DB_QUERY_RESULT *query_result = NULL;
1483  DB_QUERY_ERROR query_error;
1484  DB_VALUE value;
1485 
1486  int master_checksum = 0;
1487  const char *query;
1488  int res, error;
1489  char err_msg[LINE_MAX];
1490 
1491  select_checksum_query = chksum_print_select_master_checksum (parser, table_name, chunk_id);
1492  if (select_checksum_query == NULL)
1493  {
1494  return ER_FAILED;
1495  }
1496 
1497  query = (const char *) pt_get_varchar_bytes (select_checksum_query);
1498  res = db_execute (query, &query_result, &query_error);
1499  if (res >= 0)
1500  {
1501  int pos;
1502 
1503  pos = db_query_first_tuple (query_result);
1504 
1505  switch (pos)
1506  {
1507  case DB_CURSOR_SUCCESS:
1508  error = db_query_get_tuple_value (query_result, 0, &value);
1509  if (error != NO_ERROR)
1510  {
1511  res = error;
1512  break;
1513  }
1514 
1515  master_checksum = db_get_int (&value);
1516  db_value_clear (&value);
1517  break;
1518  case DB_CURSOR_END:
1519  case DB_CURSOR_ERROR:
1520  default:
1521  res = ER_FAILED;
1522  break;
1523  }
1524  db_query_end (query_result);
1525 
1526  update_checksum_query = chksum_print_update_master_checksum (parser, table_name, chunk_id, master_checksum);
1527  if (update_checksum_query == NULL)
1528  {
1529  return ER_FAILED;
1530  }
1531 
1532  query = (const char *) pt_get_varchar_bytes (update_checksum_query);
1533  res = db_execute (query, &query_result, &query_error);
1534  if (res >= 0)
1535  {
1536  db_query_end (query_result);
1537  }
1538  }
1539 
1540  if (res < 0)
1541  {
1542  snprintf (err_msg, LINE_MAX, "Failed to update master checksum. " "(table name: %s, chunk id: %d)", table_name,
1543  chunk_id);
1544 
1546  }
1547 
1548  return res;
1549 }
1550 
1551 /*
1552  * chksum_set_repl_info_and_demote_table_lock -
1553  * return: error code
1554  *
1555  * table_name(in):
1556  * checksum_query(in):
1557  *
1558  * NOTE: insert replication log and release demote table lock to IS lock
1559  */
1560 static int
1561 chksum_set_repl_info_and_demote_table_lock (const char *table_name, const char *checksum_query, const OID * class_oidp)
1562 {
1564  REPL_INFO_SBR repl_stmt;
1565 
1566  repl_stmt.statement_type = CUBRID_STMT_INSERT;
1567  repl_stmt.name = (char *) table_name;
1568  repl_stmt.stmt_text = (char *) checksum_query;
1569  repl_stmt.db_user = db_get_user_name ();
1570  repl_stmt.sys_prm_context = NULL;
1571 
1572  repl_info.repl_info_type = REPL_INFO_TYPE_SBR;
1573  repl_info.info = (char *) &repl_stmt;
1574 
1575  return chksum_insert_repl_log_and_demote_table_lock (&repl_info, class_oidp);
1576 }
1577 
1578 /*
1579  * chksum_update_my_schema_definition - update schema definition of
1580  * a given table using SBR
1581  * return: error code
1582  *
1583  * table_name(in):
1584  */
1585 static int
1586 chksum_update_current_schema_definition (const char *table_name, int repid)
1587 {
1588 #define QUERY_BUF_SIZE 2048
1589  DB_QUERY_RESULT *query_result = NULL;
1590  DB_QUERY_ERROR query_error;
1591  int res, error = NO_ERROR;
1592  char query_buf[QUERY_BUF_SIZE];
1593 
1594  snprintf (query_buf, sizeof (query_buf), "UPDATE /*+ USE_SBR */ %s " /* 1 */
1595  "SET " CHKSUM_TABLE_SCHEMA_COL " = SCHEMA_DEF ('%s'), " /* 2 */
1596  CHKSUM_TABLE_SCHEMA_TIME_COL " = SYS_DATETIME " /* collected time */
1597  "WHERE " CHKSUM_TABLE_CLASS_NAME_COL " = '%s' " /* 3 */
1598  "AND " CHKSUM_TABLE_SCHEMA_REPID_COL " = %d;", /* 4 */
1599  chksum_schema_Table_name, /* 1 */
1600  table_name, table_name, repid); /* 2, 3, 4 */
1601 
1602  res = db_execute (query_buf, &query_result, &query_error);
1603  if (res >= 0)
1604  {
1605  db_query_end (query_result);
1606  }
1607  else
1608  {
1609  error = res;
1610  }
1611 
1612  return error;
1613 
1614 #undef QUERY_BUF_SIZE
1615 }
1616 
1617 /*
1618  * chksum_update_my_schema_definition - insert schema definition of
1619  * a given table and replicate it
1620  * through row-based replication
1621  * return: error code
1622  *
1623  * table_name(in):
1624  * repid(in): only for internal use
1625  */
1626 static int
1627 chksum_insert_schema_definition (const char *table_name, int repid)
1628 {
1629 #define QUERY_BUF_SIZE 2048
1630  DB_QUERY_RESULT *query_result = NULL;
1631  DB_QUERY_ERROR query_error;
1632  int res, error = NO_ERROR;
1633  char query_buf[QUERY_BUF_SIZE];
1634 
1635  snprintf (query_buf, sizeof (query_buf), "REPLACE INTO %s " "SELECT '%s', %d, NULL, SCHEMA_DEF ('%s'), NULL;",
1636  chksum_schema_Table_name, table_name, repid, table_name);
1637 
1638  res = db_execute (query_buf, &query_result, &query_error);
1639  if (res >= 0)
1640  {
1641  db_query_end (query_result);
1642 
1643  res = chksum_update_current_schema_definition (table_name, repid);
1644  if (res < 0)
1645  {
1646  error = res;
1647  }
1648  }
1649  else
1650  {
1651  error = res;
1652  }
1653 
1654  return error;
1655 
1656 #undef QUERY_BUF_SIZE
1657 }
1658 
1659 /*
1660  * chksum_calculate_checksum () - calculate checksum for a chunk
1661  * return: error code
1662  * parser(in):
1663  * class_oidp(in): source table class oid
1664  * table_name(in): source table name
1665  * attributes(in): table attributes
1666  * lower_bound(in): starting point of chunk
1667  * chunk_id(in):
1668  * chunk_size(in):
1669  */
1670 static int
1671 chksum_calculate_checksum (PARSER_CONTEXT * parser, const OID * class_oidp, const char *table_name,
1672  DB_ATTRIBUTE * attributes, PARSER_VARCHAR * lower_bound, int chunk_id, int chunk_size)
1673 {
1674  PARSER_VARCHAR *checksum_query = NULL;
1675  DB_QUERY_RESULT *query_result = NULL;
1676  DB_QUERY_ERROR query_error;
1677  char err_msg[LINE_MAX];
1678  const char *query;
1679  int res;
1680  int error = NO_ERROR;
1681 
1682  checksum_query = chksum_print_checksum_query (parser, table_name, attributes, lower_bound, chunk_id, chunk_size);
1683  if (checksum_query == NULL)
1684  {
1685  return ER_FAILED;
1686  }
1687 
1688  query = (const char *) pt_get_varchar_bytes (checksum_query);
1689 
1690  /*
1691  * write replication log first and release all locks
1692  * to avoid long lock wait of other concurrent clients on active server
1693  */
1694  error = chksum_set_repl_info_and_demote_table_lock (table_name, query, class_oidp);
1695  if (error != NO_ERROR)
1696  {
1697  snprintf (err_msg, LINE_MAX,
1698  "Failed to write a checksum replication log." " (table name: %s, chunk id: %d, lower bound: %s)",
1699  table_name, chunk_id, (char *) pt_get_varchar_bytes (lower_bound));
1701  return error;
1702  }
1703 
1704  res = db_execute (query, &query_result, &query_error);
1705  if (res >= 0)
1706  {
1707  db_query_end (query_result);
1708 
1709  res = chksum_update_master_checksum (parser, table_name, chunk_id);
1710  if (res < 0)
1711  {
1712  error = res;
1713  }
1714  }
1715  else
1716  {
1717  snprintf (err_msg, LINE_MAX, "Failed to calculate checksum. " "(table name: %s, chunk id: %d, lower bound: %s)",
1718  table_name, chunk_id, (char *) pt_get_varchar_bytes (lower_bound));
1719 
1721  error = res;
1722  }
1723 
1724  return error;
1725 }
1726 
1727 /*
1728  * chksum_need_skip_table() -
1729  * return: skip or not
1730  * table_name(in):
1731  * chksum_arg(in):
1732  */
1733 static bool
1734 chksum_need_skip_table (const char *table_name, CHKSUM_ARG * chksum_arg)
1735 {
1736  int i;
1737  bool match_need_skip = false;
1738  dynamic_array *list = NULL;
1739  char table_in_list[SM_MAX_IDENTIFIER_LENGTH];
1740 
1741  if (table_name == NULL || (strcasecmp (table_name, chksum_result_Table_name) == 0)
1742  || (strcasecmp (table_name, chksum_schema_Table_name) == 0))
1743  {
1744  return true;
1745  }
1746 
1747  if (chksum_arg->include_list == NULL && chksum_arg->exclude_list == NULL)
1748  {
1749  return false;
1750  }
1751 
1752  /* cannot have both lists */
1753  assert (chksum_arg->include_list == NULL || chksum_arg->exclude_list == NULL);
1754 
1755  list = chksum_arg->exclude_list;
1756  if (list != NULL)
1757  {
1758  match_need_skip = true;
1759  }
1760  else
1761  {
1762  list = chksum_arg->include_list;
1763  }
1764 
1765  for (i = 0; i < da_size (list); i++)
1766  {
1767  da_get (list, i, table_in_list);
1768  if (strcmp (table_name, table_in_list) == 0)
1769  {
1770  return match_need_skip;
1771  }
1772  }
1773 
1774  return !match_need_skip;
1775 }
1776 
1777 /*
1778  * chksum_start() - calculate checksum values
1779  * to check replication integrity
1780  * return: error code
1781  */
1782 static int
1784 {
1786  DB_OBJLIST *tbl_list = NULL, *tbl = NULL;
1787  DB_OBJECT *classobj = NULL;
1788  DB_CONSTRAINT *constraints = NULL, *pk_cons = NULL;
1789  DB_ATTRIBUTE *attributes = NULL;
1790  PARSER_VARCHAR *lower_bound = NULL, *next_lower_bound = NULL;
1791  OID *class_oidp = NULL;
1792 
1793  char err_msg[LINE_MAX];
1794  const char *table_name = NULL;
1795  int error = NO_ERROR;
1796  int chunk_id = 0;
1797  int repid = -1;
1798  int prev_repid = -1;
1799  bool force_refetch_class_info;
1800 
1801  er_set (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, ER_CHKSUM_GENERIC_ERR, 2, "checksum calculation started", 0);
1802 
1803  if (chksum_init_checksum_tables (chksum_arg->resume) != NO_ERROR)
1804  {
1805  goto exit;
1806  }
1807 
1808  if (chksum_arg->resume == true)
1809  {
1811  if (error != NO_ERROR)
1812  {
1813  snprintf (err_msg, LINE_MAX, "Failed to load previous checksum result");
1815  goto exit;
1816  }
1817  }
1818 
1819  tbl_list = db_fetch_all_classes (DB_FETCH_READ);
1820 
1821  /* commit here to invalidate snapshot captured by db_fetch_all_classes */
1822  error = db_commit_transaction ();
1823  if (error != NO_ERROR)
1824  {
1825  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CHKSUM_GENERIC_ERR, 2, "Failed to get the list of tables", error);
1826  goto exit;
1827  }
1828 
1829  for (tbl = tbl_list; tbl != NULL; tbl = tbl->next)
1830  {
1831  classobj = tbl->op;
1832  if (db_is_system_class (classobj) || db_is_vclass (classobj))
1833  {
1834  continue;
1835  }
1836 
1837  table_name = db_get_class_name (classobj);
1838  if (table_name == NULL)
1839  {
1840  continue;
1841  }
1842 
1843  if (chksum_need_skip_table (table_name, chksum_arg) == true)
1844  {
1845  continue;
1846  }
1847 
1848  prev_repid = -1;
1849  chunk_id = 0;
1850  lower_bound = NULL;
1851  error = NO_ERROR;
1852  force_refetch_class_info = false;
1853 
1854  parser = parser_create_parser ();
1855 
1856  while (true)
1857  {
1858  repid = sm_get_class_repid (classobj);
1859  if (repid == -1)
1860  {
1861  /* the table has been deleted in the middle of calculation */
1862  break;
1863  }
1864  else if (repid != prev_repid || force_refetch_class_info == true)
1865  {
1866  /* schema has been changed or previous tran aborted */
1867  table_name = db_get_class_name (classobj);
1868  attributes = db_get_attributes (classobj);
1869  if (table_name == NULL || attributes == NULL)
1870  {
1871  error = er_errid ();
1873  "Failed to load table information", error);
1874  break;
1875  }
1876 
1877  constraints = db_get_constraints (classobj);
1878  if (constraints == NULL)
1879  {
1880  /* no primary key */
1881  break;
1882  }
1883 
1884  pk_cons = db_constraint_find_primary_key (constraints);
1885  if (pk_cons == NULL)
1886  {
1887  break;
1888  }
1889 
1890  if (prev_repid != repid)
1891  {
1892  error = chksum_insert_schema_definition (table_name, repid);
1893  if (error == NO_ERROR)
1894  {
1895  error = db_commit_transaction ();
1896  }
1897 
1898  if (error != NO_ERROR)
1899  {
1900  snprintf (err_msg, LINE_MAX, "Failed to update schema definition" " of [%s]", table_name);
1902 
1903  (void) db_abort_transaction ();
1904  break;
1905  }
1906 
1907  if (chksum_arg->schema_only == true)
1908  {
1909  break;
1910  }
1911  else
1912  {
1913  /* continue here since commit unlocks the current class and there might be a chance that the
1914  * class is modified. */
1915  prev_repid = repid;
1916  continue;
1917  }
1918  }
1919 
1920  prev_repid = repid;
1921  force_refetch_class_info = false;
1922  }
1923 
1924  if (locator_fetch_class (classobj, DB_FETCH_QUERY_READ) == NULL)
1925  {
1926  snprintf (err_msg, LINE_MAX, "Failed to acquire a table READ lock for [%s]", table_name);
1927 
1928  error = er_errid ();
1930  break;
1931  }
1932 
1933  class_oidp = ws_oid (classobj);
1934 
1935  tran_set_query_timeout (chksum_arg->timeout_msecs);
1936 
1937  if (chunk_id == 0 && lower_bound == NULL)
1938  {
1939  error =
1940  chksum_set_initial_chunk_id_and_lower_bound (parser, table_name, pk_cons, &chunk_id, &lower_bound);
1941  if (error != NO_ERROR)
1942  {
1943  (void) db_abort_transaction ();
1944 
1945  if (error != ER_INTERRUPTED)
1946  {
1947  break;
1948  }
1949 
1950  error = NO_ERROR;
1951  force_refetch_class_info = true;
1952 
1953  SLEEP_MILISEC (0, chksum_arg->sleep_msecs);
1954  continue;
1955  }
1956 
1957  if (lower_bound == NULL)
1958  {
1959  /* no record. abort to unlock class */
1960  (void) db_abort_transaction ();
1961  break;
1962  }
1963  }
1964 
1965  assert (lower_bound != NULL);
1966 
1967  error =
1968  chksum_calculate_checksum (parser, class_oidp, table_name, attributes, lower_bound, chunk_id,
1969  chksum_arg->chunk_size);
1970  if (error != NO_ERROR)
1971  {
1972  (void) db_abort_transaction ();
1973 
1974  if (error != ER_INTERRUPTED)
1975  {
1976  break;
1977  }
1978 
1979  error = NO_ERROR;
1980  force_refetch_class_info = true;
1981 
1982  SLEEP_MILISEC (0, chksum_arg->sleep_msecs);
1983  continue;
1984  }
1985 
1986  next_lower_bound =
1987  chksum_get_next_lower_bound (parser, table_name, pk_cons, lower_bound, chksum_arg->chunk_size, &error);
1988  if (error != NO_ERROR)
1989  {
1990  (void) db_abort_transaction ();
1991 
1992  if (error != ER_INTERRUPTED)
1993  {
1994  break;
1995  }
1996 
1997  error = NO_ERROR;
1998  force_refetch_class_info = true;
1999 
2000  SLEEP_MILISEC (0, chksum_arg->sleep_msecs);
2001  continue;
2002  }
2003 
2004  lower_bound = next_lower_bound;
2005 
2006  error = db_commit_transaction ();
2007  if (error != NO_ERROR)
2008  {
2009  break;
2010  }
2011 
2012  if (lower_bound == NULL)
2013  {
2014  /* move onto the next table */
2015  chunk_id = 0;
2016  break;
2017  }
2018  else
2019  {
2020  chunk_id++;
2021  }
2022 
2023  SLEEP_MILISEC (0, chksum_arg->sleep_msecs);
2024  }
2025 
2026  parser_free_parser (parser);
2027 
2028  if (CHKSUM_STOP_ON_ERROR (error, chksum_arg) == true)
2029  {
2030  break;
2031  }
2032 
2033  if (error != NO_ERROR)
2034  {
2035  snprintf (err_msg, sizeof (err_msg), "Table [%s] skipped due to error", table_name);
2037  }
2038  }
2039 
2040 exit:
2041  if (tbl_list != NULL)
2042  {
2043  db_objlist_free (tbl_list);
2044  }
2045 
2046  if (chksum_Prev_results != NULL)
2047  {
2048  chksum_free_results (chksum_Prev_results);
2049  }
2050 
2051  if (error == NO_ERROR)
2052  {
2053  er_set (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, ER_CHKSUM_GENERIC_ERR, 2, "checksum calculation completed", 0);
2054  }
2055  else
2056  {
2057  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CHKSUM_GENERIC_ERR, 2, "checksum calculation terminated", error);
2058  }
2059 
2060  return error;
2061 }
2062 
2063 /*
2064  * checksumdb() - checksumdb main routine
2065  * return: EXIT_SUCCESS/EXIT_FAILURE
2066  */
2067 int
2069 {
2070 #if defined (WINDOWS)
2073  basename (arg->argv0));
2074 
2075  return EXIT_FAILURE;
2076 #else /* WINDOWS */
2077 #if defined (CS_MODE)
2078  UTIL_ARG_MAP *arg_map = arg->arg_map;
2079  char er_msg_file[PATH_MAX];
2080  const char *database_name = NULL;
2082  char *incl_class_file = NULL;
2083  char *excl_class_file = NULL;
2084  char *checksum_table = NULL;
2085  bool report_only = false;
2087  int error = NO_ERROR;
2088 
2089  memset (&chksum_arg, 0, sizeof (CHKSUM_ARG));
2090 
2091  if (utility_get_option_string_table_size (arg_map) != 1)
2092  {
2093  goto print_checksumdb_usage;
2094  }
2095 
2096  database_name = utility_get_option_string_value (arg_map, OPTION_STRING_TABLE, 0);
2097  if (database_name == NULL)
2098  {
2099  goto print_checksumdb_usage;
2100  }
2101 
2102  if (check_database_name (database_name))
2103  {
2104  goto error_exit;
2105  }
2106 
2107  checksum_table = utility_get_option_string_value (arg_map, CHECKSUM_TABLE_NAME_S, 0);
2108  if (sm_check_name (checksum_table) > 0)
2109  {
2110  snprintf (chksum_result_Table_name, SM_MAX_IDENTIFIER_LENGTH, "%s", checksum_table);
2111  }
2112  else
2113  {
2115  }
2116 
2119  {
2120  assert (false);
2121  goto error_exit;
2122  }
2123 
2124  report_only = utility_get_option_bool_value (arg_map, CHECKSUM_REPORT_ONLY_S);
2125  if (report_only == true)
2126  {
2127  goto begin;
2128  }
2129 
2130  incl_class_file = utility_get_option_string_value (arg_map, CHECKSUM_INCLUDE_CLASS_FILE_S, 0);
2131  excl_class_file = utility_get_option_string_value (arg_map, CHECKSUM_EXCLUDE_CLASS_FILE_S, 0);
2132 
2133  if (incl_class_file != NULL && excl_class_file != NULL)
2134  {
2135  /* cannot have both */
2136  goto print_checksumdb_usage;
2137  }
2138 
2139  if (incl_class_file != NULL)
2140  {
2142  if (util_get_table_list_from_file (incl_class_file, chksum_arg.include_list) != NO_ERROR)
2143  {
2146  incl_class_file);
2147  goto error_exit;
2148  }
2149  }
2150 
2151  if (excl_class_file != NULL)
2152  {
2154  if (util_get_table_list_from_file (excl_class_file, chksum_arg.exclude_list) != NO_ERROR)
2155  {
2158  excl_class_file);
2159  goto error_exit;
2160  }
2161  }
2162 
2164  if (chksum_arg.chunk_size < CHKSUM_MIN_CHUNK_SIZE)
2165  {
2166  goto print_checksumdb_usage;
2167  }
2168 
2169  chksum_arg.resume = utility_get_option_bool_value (arg_map, CHECKSUM_RESUME_S);
2170 
2172 
2174  if (chksum_arg.sleep_msecs < 0)
2175  {
2176  chksum_arg.sleep_msecs = 0;
2177  }
2178 
2180  if (chksum_arg.timeout_msecs < 0)
2181  {
2182  chksum_arg.timeout_msecs = 0;
2183  }
2184 
2186 
2187 begin:
2188  snprintf (er_msg_file, sizeof (er_msg_file) - 1, "%s_%s.err", database_name, arg->command_name);
2189  er_init (er_msg_file, ER_NEVER_EXIT);
2190 
2192 
2194  if (db_login ("DBA", NULL) != NO_ERROR)
2195  {
2196  PRINT_AND_LOG_ERR_MSG ("%s\n", db_error_string (3));
2197  goto error_exit;
2198  }
2199 
2200  /* initialize system parameters */
2201  if (sysprm_load_and_init (database_name, NULL, SYSPRM_LOAD_ALL) != NO_ERROR)
2202  {
2204  error = ER_FAILED;
2205  goto error_exit;
2206  }
2207 
2208  error = db_restart (arg->command_name, TRUE, database_name);
2209  if (error != NO_ERROR)
2210  {
2211  fprintf (stderr, "%s\n", db_error_string (3));
2212  goto error_exit;
2213  }
2214 
2215  db_set_lock_timeout (-1);
2217 
2218  /* initialize system parameters */
2219  if (sysprm_load_and_init (database_name, NULL, SYSPRM_LOAD_ALL) != NO_ERROR)
2220  {
2221  (void) db_shutdown ();
2222 
2223  error = ER_FAILED;
2224  goto error_exit;
2225  }
2226 
2227  if (report_only == true)
2228  {
2229  error = chksum_report (arg->command_name, database_name);
2230  }
2231  else
2232  {
2233  ha_state = css_ha_server_state ();
2234  if (ha_state != HA_SERVER_STATE_ACTIVE)
2235  {
2238  database_name, css_ha_server_state_string (ha_state));
2239 
2240  (void) db_shutdown ();
2241 
2242  error = ER_FAILED;
2243  goto error_exit;
2244  }
2245 
2246  error = chksum_start (&chksum_arg);
2247  }
2248 
2249  if (error != NO_ERROR)
2250  {
2251  (void) db_shutdown ();
2252 
2253  goto error_exit;
2254  }
2255 
2256  if (chksum_arg.include_list != NULL)
2257  {
2258  da_destroy (chksum_arg.include_list);
2259  }
2260 
2261  if (chksum_arg.exclude_list != NULL)
2262  {
2263  da_destroy (chksum_arg.exclude_list);
2264  }
2265 
2266  (void) db_shutdown ();
2267 
2268  return EXIT_SUCCESS;
2269 
2270 print_checksumdb_usage:
2272  basename (arg->argv0));
2274 
2275 error_exit:
2276  if (chksum_arg.include_list != NULL)
2277  {
2278  da_destroy (chksum_arg.include_list);
2279  }
2280 
2281  if (chksum_arg.exclude_list != NULL)
2282  {
2283  da_destroy (chksum_arg.exclude_list);
2284  }
2285 
2286  return EXIT_FAILURE;
2287 #else /* CS_MODE */
2290  basename (arg->argv0));
2291 
2292 error_exit:
2293  return EXIT_FAILURE;
2294 #endif /* !CS_MODE */
2295 #endif /* !WINDOWS */
2296 }
char * envvar_logdir_file(char *path, size_t size, const char *filename)
#define SLEEP_MILISEC(sec, msec)
Definition: util_func.h:40
DB_OBJECT * db_find_class(const char *name)
Definition: db_info.c:133
#define NO_ERROR
Definition: error_code.h:46
char chksum_schema_Table_name[SM_MAX_IDENTIFIER_LENGTH]
Definition: checksumdb.c:108
static bool chksum_need_skip_table(const char *table_name, CHKSUM_ARG *chksum_arg)
Definition: checksumdb.c:1734
#define TRUE
Definition: broker_admin.c:49
int last_chunk_id
Definition: checksumdb.c:88
static PARSER_VARCHAR * chksum_print_attribute_list(PARSER_CONTEXT *parser, DB_ATTRIBUTE *attributes)
Definition: checksumdb.c:1219
void db_set_client_type(int client_type)
Definition: db_admin.c:495
#define PRINT_AND_LOG_ERR_MSG(...)
Definition: util_func.h:49
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
static PARSER_VARCHAR * chksum_print_select_master_checksum(PARSER_CONTEXT *parser, const char *table_name, int chunk_id)
Definition: checksumdb.c:1422
DB_ATTRIBUTE * db_get_attributes(DB_OBJECT *obj)
Definition: db_info.c:908
#define CHKSUM_DEFAULT_TABLE_NAME
Definition: checksumdb.c:56
int db_login(const char *name, const char *password)
Definition: db_admin.c:804
static void begin(char *test_name)
int da_destroy(dynamic_array *da)
#define CHECKSUM_RESUME_S
Definition: utility.h:1587
static PARSER_VARCHAR * chksum_print_checksum_query(PARSER_CONTEXT *parser, const char *table_name, DB_ATTRIBUTE *attributes, PARSER_VARCHAR *lower_bound, int chunk_id, int chunk_size)
Definition: checksumdb.c:1066
PARSER_VARCHAR * pt_append_nulstring(const PARSER_CONTEXT *parser, PARSER_VARCHAR *bstring, const char *nulstring)
Definition: parse_tree.c:1072
int db_get_int(const DB_VALUE *value)
char class_name[SM_MAX_IDENTIFIER_LENGTH]
Definition: checksumdb.c:86
int db_is_vclass(DB_OBJECT *op)
Definition: db_virt.c:681
#define ER_FAILED
Definition: error_code.h:47
#define AU_DISABLE_PASSWORDS
Definition: authenticate.h:140
DB_CONSTRAINT * db_constraint_find_primary_key(DB_CONSTRAINT *constraint)
Definition: db_info.c:1956
static CHKSUM_RESULT * chksum_get_checksum_result(const char *table_name)
Definition: checksumdb.c:768
static int chksum_init_checksum_tables(bool resume)
Definition: checksumdb.c:578
int db_query_end(DB_QUERY_RESULT *result)
Definition: db_query.c:3362
int util_get_table_list_from_file(char *fname, dynamic_array *darray)
Definition: util_common.c:1226
#define SM_MAX_IDENTIFIER_LENGTH
int db_shutdown(void)
Definition: db_admin.c:964
static int chksum_drop_and_create_checksum_table(void)
Definition: checksumdb.c:667
DB_CONSTRAINT * db_get_constraints(DB_OBJECT *obj)
Definition: db_info.c:1909
PARSER_CONTEXT * parser_create_parser(void)
Definition: parse_tree.c:1169
DB_ATTRIBUTE ** db_constraint_attributes(DB_CONSTRAINT *constraint)
Definition: db_info.c:2052
char * info
Definition: replication.h:54
OID * ws_oid(MOP mop)
Definition: work_space.c:2884
PARSER_VARCHAR * pt_append_bytes(const PARSER_CONTEXT *parser, PARSER_VARCHAR *old_string, const char *new_tail, const int new_tail_length)
Definition: parse_tree.c:1014
int check_database_name(const char *name)
Definition: util_common.c:99
#define DB_CURSOR_ERROR
Definition: dbtype_def.h:168
#define CHECKSUM_EXCLUDE_CLASS_FILE_S
Definition: utility.h:1595
bool cont_on_err
Definition: checksumdb.c:100
int er_errid(void)
int util_log_write_errid(int message_id,...)
Definition: util_func.c:468
const char * db_attribute_name(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1065
CHKSUM_RESULT * chksum_Prev_results
Definition: checksumdb.c:106
#define ER_CHKSUM_GENERIC_ERR
Definition: error_code.h:1527
int db_set_lock_timeout(int seconds)
Definition: db_admin.c:1496
int er_init(const char *msglog_filename, int exit_ask)
static int chksum_update_current_schema_definition(const char *table_name, int repid)
Definition: checksumdb.c:1586
int timeout_msecs
Definition: checksumdb.c:98
int utility_get_option_int_value(UTIL_ARG_MAP *arg_map, int arg_ch)
Definition: util_common.c:227
#define CHKSUM_TABLE_BEGINS_AT_COL
Definition: checksumdb.c:65
static int chksum_set_initial_chunk_id_and_lower_bound(PARSER_CONTEXT *parser, const char *table_name, DB_CONSTRAINT *pk_cons, int *chunk_id, PARSER_VARCHAR **lower_bound)
Definition: checksumdb.c:922
void describe_value(const db_value *value)
int last_chunk_cnt
Definition: checksumdb.c:89
void parser_free_parser(PARSER_CONTEXT *parser)
Definition: parse_tree.c:1240
bool schema_only
Definition: checksumdb.c:101
static PARSER_VARCHAR * chksum_get_initial_lower_bound(PARSER_CONTEXT *parser, const char *table_name, DB_CONSTRAINT *pk_cons, int *exec_error)
Definition: checksumdb.c:1407
MOBJ locator_fetch_class(MOP class_mop, DB_FETCH_MODE purpose)
Definition: locator_cl.c:2293
unsigned char bytes[1]
Definition: parse_tree.h:3431
#define CHKSUM_MIN_CHUNK_SIZE
Definition: checksumdb.c:55
#define CHKSUM_PRINT_AND_LOG(fp,...)
Definition: checksumdb.c:77
DB_ATTRIBUTE * db_get_attribute(DB_OBJECT *obj, const char *name)
Definition: db_info.c:791
int db_restart(const char *program, int print_version, const char *volume)
Definition: db_admin.c:868
int sm_get_class_repid(MOP classop)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
static int chksum_calculate_checksum(PARSER_CONTEXT *parser, const OID *class_oidp, const char *table_name, DB_ATTRIBUTE *attributes, PARSER_VARCHAR *lower_bound, int chunk_id, int chunk_size)
Definition: checksumdb.c:1671
#define CHKSUM_TABLE_COUNT_COL
Definition: checksumdb.c:63
bool utility_get_option_bool_value(UTIL_ARG_MAP *arg_map, int arg_ch)
Definition: util_common.c:245
#define assert(x)
int db_query_last_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2374
static void chksum_free_results(CHKSUM_RESULT *results)
Definition: checksumdb.c:739
char * last_lower_bound
Definition: checksumdb.c:87
#define CHKSUM_TABLE_SCHEMA_TIME_COL
Definition: checksumdb.c:70
int da_get(dynamic_array *da, int pos, void *data)
static PARSER_VARCHAR * chksum_print_pk_list(PARSER_CONTEXT *parser, DB_CONSTRAINT *pk, int *pk_col_cnt, bool include_decs)
Definition: checksumdb.c:961
int db_query_first_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2309
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
void db_objlist_free(DB_OBJLIST *list)
Definition: db_admin.c:2612
int sysprm_load_and_init(const char *db_name, const char *conf_file, const int load_flags)
const char * css_ha_server_state_string(HA_SERVER_STATE state)
const char * db_error_string(int level)
Definition: db_admin.c:2116
int checksumdb(UTIL_FUNCTION_ARG *arg)
Definition: checksumdb.c:2068
int da_size(dynamic_array *da)
DB_ATTRIBUTE * db_attribute_next(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1020
#define CHKSUM_TABLE_CLASS_NAME_COL
Definition: checksumdb.c:59
PARSER_VARCHAR * pt_append_varchar(const PARSER_CONTEXT *parser, PARSER_VARCHAR *old_string, const PARSER_VARCHAR *new_tail)
Definition: parse_tree.c:1052
#define CHKSUM_TABLE_CHUNK_ID_COL
Definition: checksumdb.c:60
int db_abort_transaction(void)
Definition: db_admin.c:1114
static PARSER_VARCHAR * chksum_print_select_last_chunk(PARSER_CONTEXT *parser, const char *table_name, PARSER_VARCHAR *pk_list, PARSER_VARCHAR *pk_orderby, PARSER_VARCHAR *prev_lower_bound, int limit)
Definition: checksumdb.c:1020
dynamic_array * da_create(int count, size_t len)
Definition: dynamic_array.c:30
static PARSER_VARCHAR * chksum_get_quote_escaped_lower_bound(PARSER_CONTEXT *parser, PARSER_VARCHAR *orig_lower_bound)
Definition: checksumdb.c:1254
SP_PARSER_CTX * parser
#define NULL
Definition: freelistheap.h:34
int db_execute(const char *CSQL_query, DB_QUERY_RESULT **result, DB_QUERY_ERROR *query_error)
Definition: db_query.c:1836
#define CHECKSUM_SLEEP_S
Definition: utility.h:1589
#define CHKSUM_TABLE_LOWER_BOUND_COL
Definition: checksumdb.c:61
dynamic_array * exclude_list
Definition: checksumdb.c:103
#define CHECKSUM_REPORT_ONLY_S
Definition: utility.h:1601
int sm_check_name(const char *name)
const char * get_buffer() const
#define CHKSUM_TABLE_SCHEMA_REPID_COL
Definition: checksumdb.c:71
static int chksum_report_diff(FILE *fp)
Definition: checksumdb.c:318
int db_is_system_class(MOP op)
Definition: db_info.c:502
char * db_get_user_name(void)
Definition: db_admin.c:1911
int db_query_get_tuple_valuelist(DB_QUERY_RESULT *result, int size, DB_VALUE *value_list)
Definition: db_query.c:3025
int db_set_isolation(DB_TRAN_ISOLATION isolation)
Definition: db_admin.c:1535
#define CHKSUM_TABLE_SCHEMA_COL
Definition: checksumdb.c:69
int utility_get_option_string_table_size(UTIL_ARG_MAP *arg_map)
Definition: util_common.c:305
static PARSER_VARCHAR * chksum_get_next_lower_bound(PARSER_CONTEXT *parser, const char *table_name, DB_CONSTRAINT *pk_cons, PARSER_VARCHAR *prev_lower_bound, int chunk_size, int *exec_error)
Definition: checksumdb.c:1303
static PARSER_VARCHAR * chksum_print_lower_bound_string(PARSER_CONTEXT *parser, DB_VALUE values[], DB_CONSTRAINT *pk, int pk_col_cnt)
Definition: checksumdb.c:1138
int db_datetime_to_string(char *buf, int bufsize, DB_DATETIME *datetime)
Definition: db_date.c:4225
static void chksum_report_header(FILE *fp, const char *database)
Definition: checksumdb.c:174
int db_query_column_count(DB_QUERY_RESULT *result)
Definition: db_query.c:3134
#define CHKSUM_STOP_ON_ERROR(err, arg)
Definition: checksumdb.c:73
#define CHECKSUM_SCHEMA_ONLY_S
Definition: utility.h:1603
static void error(const char *msg)
Definition: gencat.c:331
#define CHKSUM_TABLE_MASTER_SCHEMA_COL
Definition: checksumdb.c:68
#define CHKSUM_TABLE_MASTER_CHEKSUM_COL
Definition: checksumdb.c:64
#define ER_INTERRUPTED
Definition: error_code.h:51
static int chksum_get_prev_checksum_results(void)
Definition: checksumdb.c:797
const unsigned char * pt_get_varchar_bytes(const PARSER_VARCHAR *string)
Definition: parse_tree.c:1089
#define CHKSUM_SCHEMA_TABLE_SUFFIX
Definition: checksumdb.c:57
int db_query_next_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2088
#define ARG_FILE_LINE
Definition: error_manager.h:44
static char database_name[MAX_HA_DBINFO_LENGTH]
Definition: cas_execute.c:387
int repl_info_type
Definition: replication.h:55
static int chksum_report(const char *command_name, const char *database)
Definition: checksumdb.c:516
UTIL_ARG_MAP * arg_map
Definition: utility.h:1698
void tran_set_query_timeout(int)
#define QUERY_BUF_SIZE
int sleep_msecs
Definition: checksumdb.c:97
static PARSER_VARCHAR * chksum_print_update_master_checksum(PARSER_CONTEXT *parser, const char *table_name, int chunk_id, int master_checksum)
Definition: checksumdb.c:1447
#define CHKSUM_DEFAULT_LIST_SIZE
Definition: checksumdb.c:54
#define free_and_init(ptr)
Definition: memory_alloc.h:147
static int chksum_insert_schema_definition(const char *table_name, int repid)
Definition: checksumdb.c:1627
const int * db_constraint_asc_desc(DB_CONSTRAINT *constraint)
Definition: db_info.c:2070
#define CHECKSUM_CHUNK_SIZE_S
Definition: utility.h:1585
#define DB_CURSOR_SUCCESS
Definition: dbtype_def.h:166
static int chksum_report_summary(FILE *fp)
Definition: checksumdb.c:397
HA_SERVER_STATE css_ha_server_state(void)
char * basename(const char *path)
Definition: porting.c:1132
#define CHECKSUM_TABLE_NAME_S
Definition: utility.h:1599
static int chksum_report_schema_diff(FILE *fp)
Definition: checksumdb.c:197
#define CHECKSUM_INCLUDE_CLASS_FILE_S
Definition: utility.h:1593
int i
Definition: dynamic_load.c:954
char * msgcat_message(int cat_id, int set_id, int msg_id)
dynamic_array * include_list
Definition: checksumdb.c:102
#define DB_IS_NULL(value)
Definition: dbtype.h:63
static int chksum_set_repl_info_and_demote_table_lock(const char *table_name, const char *checksum_query, const OID *class_oidp)
Definition: checksumdb.c:1561
char chksum_result_Table_name[SM_MAX_IDENTIFIER_LENGTH]
Definition: checksumdb.c:107
char * strdup(const char *str)
Definition: porting.c:901
DB_DATETIME * db_get_datetime(const DB_VALUE *value)
int chksum_insert_repl_log_and_demote_table_lock(REPL_INFO *repl_info, const OID *class_oidp)
static FILE * chksum_report_open_file(const char *command_name)
Definition: checksumdb.c:159
static int chksum_update_master_checksum(PARSER_CONTEXT *parser, const char *table_name, int chunk_id)
Definition: checksumdb.c:1477
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
int db_query_get_tuple_value(DB_QUERY_RESULT *result, int index, DB_VALUE *value)
Definition: db_query.c:2873
#define OPTION_STRING_TABLE
Definition: utility.h:813
#define CHKSUM_TABLE_ELAPSED_TIME_COL
Definition: checksumdb.c:66
enum ha_server_state HA_SERVER_STATE
Definition: boot.h:126
bool resume
Definition: checksumdb.c:99
#define CHKSUM_TABLE_CHUNK_CHECKSUM_COL
Definition: checksumdb.c:62
int chunk_size
Definition: checksumdb.c:96
DB_OBJLIST * db_fetch_all_classes(DB_FETCH_MODE purpose)
Definition: db_info.c:203
#define DB_CURSOR_END
Definition: dbtype_def.h:167
static int chksum_start(CHKSUM_ARG *chksum_arg)
Definition: checksumdb.c:1783
#define CHECKSUM_TIMEOUT_S
Definition: utility.h:1597
const char * command_name
Definition: utility.h:1699
char * utility_get_option_string_value(UTIL_ARG_MAP *arg_map, int arg_ch, int index)
Definition: util_common.c:266
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
#define CHECKSUM_CONT_ON_ERROR_S
Definition: utility.h:1591
int db_commit_transaction(void)
Definition: db_admin.c:1091
CHKSUM_RESULT * next
Definition: checksumdb.c:90
#define MSGCAT_CATALOG_UTILS