CUBRID Engine  latest
log_tran_table.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_tran_table.c -
21  */
22 
23 #ident "$Id$"
24 
25 
26 #if !defined(WINDOWS)
27 #define __STDC_FORMAT_MACROS
28 #include <inttypes.h>
29 #endif
30 
31 #include "config.h"
32 
33 #include <stdio.h>
34 #include <stddef.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <string.h>
38 #include <fcntl.h>
39 #include <time.h>
40 #include <limits.h>
41 #if defined(SOLARIS)
42 /* for MAXHOSTNAMELEN */
43 #include <netdb.h>
44 #endif /* SOLARIS */
45 #include <sys/stat.h>
46 #include <assert.h>
47 
48 #include "dbtran_def.h"
49 #include "log_impl.h"
50 #include "log_lsa.hpp"
51 #include "log_manager.h"
52 #include "log_system_tran.hpp"
54 #include "object_representation.h"
55 #include "error_manager.h"
56 #include "system_parameter.h"
57 #include "xserver_interface.h"
58 #include "file_manager.h"
59 #include "query_manager.h"
60 #include "query_monitoring.hpp"
61 #include "partition_sr.h"
62 #include "btree_load.h"
63 #include "serial.h"
64 #include "show_scan.h"
65 #include "boot_sr.h"
66 #include "tz_support.h"
67 #include "db_date.h"
68 #include "dbtype.h"
69 #if defined (SERVER_MODE)
70 #include "server_support.h"
71 #endif // SERVER_MODE
72 #include "string_buffer.hpp"
73 #if defined (SA_MODE)
74 #include "transaction_cl.h" /* for interrupt */
75 #endif /* defined (SA_MODE) */
76 #include "thread_entry.hpp"
77 #include "thread_manager.hpp"
78 #include "xasl.h"
79 #include "xasl_cache.h"
80 
81 #define RMUTEX_NAME_TDES_TOPOP "TDES_TOPOP"
82 
83 #define NUM_ASSIGNED_TRAN_INDICES log_Gl.trantable.num_assigned_indices
84 #define NUM_TOTAL_TRAN_INDICES log_Gl.trantable.num_total_indices
85 
86 #if !defined(SERVER_MODE)
87 #define pthread_mutex_init(a, b)
88 #define pthread_mutex_destroy(a)
89 #define pthread_mutex_lock(a) 0
90 #define pthread_mutex_trylock(a) 0
91 #define pthread_mutex_unlock(a)
92 #endif /* not SERVER_MODE */
93 
94 static const int LOG_MAX_NUM_CONTIGUOUS_TDES = INT_MAX / sizeof (LOG_TDES);
95 static const float LOG_EXPAND_TRANTABLE_RATIO = 1.25; /* Increase table by 25% */
96 static const int LOG_TOPOPS_STACK_INCREMENT = 3; /* No more than 3 nested top system operations */
98 
99 static const unsigned int LOGTB_RETRY_SLAM_MAX_TIMES = 10;
100 
101 static int logtb_expand_trantable (THREAD_ENTRY * thread_p, int num_new_indices);
102 static int logtb_allocate_tran_index (THREAD_ENTRY * thread_p, TRANID trid, TRAN_STATE state,
103  const BOOT_CLIENT_CREDENTIAL * client_credential, TRAN_STATE * current_state,
104  int wait_msecs, TRAN_ISOLATION isolation);
105 static LOG_ADDR_TDESAREA *logtb_allocate_tdes_area (int num_indices);
106 static void logtb_initialize_trantable (TRANTABLE * trantable_p);
107 static int logtb_initialize_system_tdes (THREAD_ENTRY * thread_p);
108 static void logtb_set_number_of_assigned_tran_indices (int num_trans);
111 static void logtb_set_number_of_total_tran_indices (int num_total_trans);
112 static void logtb_set_loose_end_tdes (LOG_TDES * tdes);
113 static bool logtb_is_interrupted_tdes (THREAD_ENTRY * thread_p, LOG_TDES * tdes, bool clear, bool * continue_checking);
114 static void logtb_dump_tdes_distribute_transaction (FILE * out_fp, int global_tran_id, LOG_2PC_COORDINATOR * coord);
115 static void logtb_dump_top_operations (FILE * out_fp, LOG_TOPOPS_STACK * topops_p);
116 static void logtb_dump_tdes (FILE * out_fp, LOG_TDES * tdes);
117 static void logtb_set_tdes (THREAD_ENTRY * thread_p, LOG_TDES * tdes, const BOOT_CLIENT_CREDENTIAL * client_credential,
118  int wait_msecs, TRAN_ISOLATION isolation);
119 
120 static void logtb_tran_free_update_stats (LOG_TRAN_UPDATE_STATS * log_upd_stats);
121 static void logtb_tran_clear_update_stats (LOG_TRAN_UPDATE_STATS * log_upd_stats);
122 static unsigned int logtb_tran_btid_hash_func (const void *key, const unsigned int ht_size);
123 static int logtb_tran_btid_hash_cmp_func (const void *key1, const void *key2);
124 static LOG_TRAN_CLASS_COS *logtb_tran_create_class_cos (THREAD_ENTRY * thread_p, const OID * class_oid);
126 static int logtb_tran_update_delta_hash_func (THREAD_ENTRY * thread_p, void *data, void *args);
127 static int logtb_tran_load_global_stats_func (THREAD_ENTRY * thread_p, void *data, void *args);
128 static int logtb_tran_reset_cos_func (THREAD_ENTRY * thread_p, void *data, void *args);
129 static int logtb_load_global_statistics_to_tran (THREAD_ENTRY * thread_p);
130 static int logtb_create_unique_stats_from_repr (THREAD_ENTRY * thread_p, OID * class_oid);
132  bool load_at_creation);
133 static void *logtb_global_unique_stat_alloc (void);
134 static int logtb_global_unique_stat_free (void *unique_stat);
135 static int logtb_global_unique_stat_init (void *unique_stat);
136 static int logtb_global_unique_stat_key_copy (void *src, void *dest);
137 static void logtb_free_tran_mvcc_info (LOG_TDES * tdes);
138 
139 static void logtb_assign_subtransaction_mvccid (THREAD_ENTRY * thread_p, MVCC_INFO * curr_mvcc_info, MVCCID mvcc_subid);
140 
141 static int logtb_check_kill_tran_auth (THREAD_ENTRY * thread_p, int tran_id, bool * has_authorization);
142 static void logtb_find_thread_entry_mapfunc (THREAD_ENTRY & thread_ref, bool & stop_mapper, int tran_index,
143  bool except_me, REFPTR (THREAD_ENTRY, found_ptr));
144 
145 /*
146  * logtb_realloc_topops_stack - realloc stack of top system operations
147  *
148  * return: stack or NULL
149  *
150  * tdes(in): State structure of transaction to realloc stack
151  * num_elms(in):
152  *
153  * Note: Realloc the current transaction top system operation stack by
154  * the given number of entries.
155  */
156 void *
157 logtb_realloc_topops_stack (LOG_TDES * tdes, int num_elms)
158 {
159  size_t size;
160  void *newptr;
161 
162  if (num_elms < LOG_TOPOPS_STACK_INCREMENT)
163  {
164  num_elms = LOG_TOPOPS_STACK_INCREMENT;
165  }
166 
167  size = tdes->topops.max + num_elms;
168  size = size * sizeof (*tdes->topops.stack);
169 
170  newptr = (LOG_TOPOPS_ADDRESSES *) realloc (tdes->topops.stack, size);
171  if (newptr != NULL)
172  {
173  tdes->topops.stack = (LOG_TOPOPS_ADDRESSES *) newptr;
174  if (tdes->topops.max == 0)
175  {
176  tdes->topops.last = -1;
177  }
178  tdes->topops.max += num_elms;
179  }
180  else
181  {
183  return NULL;
184  }
185  return tdes->topops.stack;
186 }
187 
188 /*
189  * logtb_allocate_tdes_area -
190  *
191  * return:
192  *
193  * num_indices(in):
194  *
195  * Note:
196  */
197 static LOG_ADDR_TDESAREA *
198 logtb_allocate_tdes_area (int num_indices)
199 {
200  LOG_ADDR_TDESAREA *area; /* Contiguous area for new transaction indices */
201  LOG_TDES *tdes; /* Transaction descriptor */
202  int i, tran_index;
203 
204  /*
205  * Allocate an area for the transaction descriptors, set the address of
206  * each transaction descriptor, and keep the address of the area for
207  * deallocation purposes at shutdown time.
208  */
209  area = (LOG_ADDR_TDESAREA *) malloc (sizeof (LOG_ADDR_TDESAREA));
210  if (area == NULL)
211  {
213  return NULL;
214  }
215 
216  area->tdesarea = new LOG_TDES[num_indices];
217  if (area->tdesarea == NULL)
218  {
220  return NULL;
221  }
222  area->next = log_Gl.trantable.area;
223 
224  /*
225  * Initialize every newly created transaction descriptor index
226  */
227  for (i = 0, tran_index = NUM_TOTAL_TRAN_INDICES; i < num_indices; tran_index++, i++)
228  {
229  tdes = log_Gl.trantable.all_tdes[tran_index] = &area->tdesarea[i];
230  logtb_initialize_tdes (tdes, i);
231  }
232 
233  return area;
234 }
235 
236 /*
237  * logtb_expand_trantable - expand the transaction table
238  *
239  * return: NO_ERROR if all OK, ER_ status otherwise
240  *
241  * num_new_indices(in): Number of indices of expansion.
242  * (i.e., threads/clients of execution)
243  *
244  * Note: Expand the transaction table with the number of given indices.
245  */
246 static int
247 logtb_expand_trantable (THREAD_ENTRY * thread_p, int num_new_indices)
248 {
249  LOG_ADDR_TDESAREA *area; /* Contiguous area for new transaction indices */
250  int total_indices; /* Total number of transaction indices */
251  int i;
252  int error_code = NO_ERROR;
253 
254 #if defined(SERVER_MODE)
255  /*
256  * When second time this function invoked during normal processing,
257  * just return.
258  */
259  total_indices = MAX_NTRANS;
260  if (log_Gl.rcv_phase == LOG_RESTARTED && total_indices <= NUM_TOTAL_TRAN_INDICES)
261  {
262  return NO_ERROR;
263  }
264 #endif /* SERVER_MODE */
265 
266  while (num_new_indices > LOG_MAX_NUM_CONTIGUOUS_TDES)
267  {
268  error_code = logtb_expand_trantable (thread_p, LOG_MAX_NUM_CONTIGUOUS_TDES);
269  if (error_code != NO_ERROR)
270  {
271  goto error;
272  }
273  num_new_indices -= LOG_MAX_NUM_CONTIGUOUS_TDES;
274  }
275 
276  if (num_new_indices <= 0)
277  {
278  return NO_ERROR;
279  }
280 
281 #if defined(SERVER_MODE)
283  {
284  total_indices = NUM_TOTAL_TRAN_INDICES + num_new_indices;
285  }
286 #else /* SERVER_MODE */
287  total_indices = NUM_TOTAL_TRAN_INDICES + num_new_indices;
288 #endif
289 
290  /*
291  * NOTE that this realloc is OK since we are in a critical section.
292  * Nobody should have pointer to transaction table
293  */
294  i = total_indices * sizeof (*log_Gl.trantable.all_tdes);
296  if (log_Gl.trantable.all_tdes == NULL)
297  {
299  error_code = ER_OUT_OF_VIRTUAL_MEMORY;
300  goto error;
301  }
302 
303  area = logtb_allocate_tdes_area (num_new_indices);
304  if (area == NULL)
305  {
306  error_code = ER_OUT_OF_VIRTUAL_MEMORY;
307  goto error;
308  }
309 
310  /*
311  * Notify other modules of new number of transaction indices
312  */
313 #if defined(ENABLE_UNUSED_FUNCTION)
314  error_code = wfg_alloc_nodes (thread_p, total_indices);
315  if (error_code != NO_ERROR)
316  {
317  /* *INDENT-OFF* */
318  delete [] area->tdesarea;
319  /* *INDENT-ON* */
320  free_and_init (area);
321  goto error;
322  }
323 #endif
324 
325  if (qmgr_allocate_tran_entries (thread_p, total_indices) != NO_ERROR)
326  {
327  /* *INDENT-OFF* */
328  delete [] area->tdesarea;
329  /* *INDENT-ON* */
330  free_and_init (area);
331  error_code = ER_FAILED;
332  goto error;
333  }
334 
335  log_Gl.trantable.area = area;
338 
339  // make sure MVCC table resizes if necessary
341 
342  return error_code;
343 
344  /* **** */
345 error:
346  return error_code;
347 }
348 
349 /*
350  * logtb_define_trantable - define the transaction table
351  *
352  * return: nothing
353  *
354  * num_expected_tran_indices(in): Number of expected concurrent transactions
355  * (i.e., threads/clients of execution)
356  * num_expected_locks(in): Number of expected locks
357  *
358  * Note: Define the transaction table which is used to support the
359  * number of expected transactions.
360  */
361 void
362 logtb_define_trantable (THREAD_ENTRY * thread_p, int num_expected_tran_indices, int num_expected_locks)
363 {
365 
366  LOG_CS_ENTER (thread_p);
367  TR_TABLE_CS_ENTER (thread_p);
368 
370  {
371  logpb_finalize_pool (thread_p);
372  }
373 
374  (void) logtb_define_trantable_log_latch (thread_p, num_expected_tran_indices);
375 
377 
378  TR_TABLE_CS_EXIT (thread_p);
379  LOG_CS_EXIT (thread_p);
380 }
381 
382 /*
383  * logtb_define_trantable_log_latch - define the transaction table
384  *
385  * return: NO_ERROR if all OK, ER status otherwise
386  *
387  * num_expected_tran_indices(in): Number of expected concurrent transactions
388  * (i.e., threads/clients of execution)
389  * num_expected_locks(in): Number of expected locks
390  *
391  * Note: This function is only called by the log manager when the log
392  * latch has already been acquired. (See logtb_define_trantable for
393  * other uses).
394  */
395 int
396 logtb_define_trantable_log_latch (THREAD_ENTRY * thread_p, int num_expected_tran_indices)
397 {
398  int error_code = NO_ERROR;
399 
400  assert (LOG_CS_OWN_WRITE_MODE (thread_p));
401 
402  /*
403  * for XA support: there is prepared transaction after recovery.
404  * so, can not recreate transaction description
405  * table after recovery.
406  *
407  * Total number of transaction descriptor is set to the value of
408  * MAX_NTRANS
409  */
410  num_expected_tran_indices = MAX (num_expected_tran_indices, MAX_NTRANS);
411 
412  num_expected_tran_indices = MAX (num_expected_tran_indices, LOG_SYSTEM_TRAN_INDEX + 1);
413 
414  /* If there is an already defined table, free such a table */
415  if (log_Gl.trantable.area != NULL)
416  {
417  logtb_undefine_trantable (thread_p);
418  }
419  else
420  {
421  /* Initialize the transaction table as empty */
423  }
424 
425  /*
426  * Create an area to keep the number of desired transaction descriptors
427  */
428 
429  error_code = logtb_expand_trantable (thread_p, num_expected_tran_indices);
430  if (error_code != NO_ERROR)
431  {
432  /*
433  * Unable to create transaction table to hold the desired number
434  * of indices. Probably, a lot of indices were requested.
435  * try again with defaults.
436  */
437  if (log_Gl.trantable.area != NULL)
438  {
439  logtb_undefine_trantable (thread_p);
440  }
441 
442 #if defined(SERVER_MODE)
443  if (num_expected_tran_indices <= LOG_ESTIMATE_NACTIVE_TRANS || log_Gl.rcv_phase == LOG_RESTARTED)
444 #else /* SERVER_MODE */
445  if (num_expected_tran_indices <= LOG_ESTIMATE_NACTIVE_TRANS)
446 #endif /* SERVER_MODE */
447  {
448  /* Out of memory */
449  logpb_fatal_error (thread_p, true, ARG_FILE_LINE, "log_def_trantable");
451  }
452  else
453  {
455  return error_code;
456  }
457  }
458 
460 
461  /*
462  * Assign the first entry for the system transaction. System transaction
463  * has an infinite timeout
464  */
465  error_code = logtb_initialize_system_tdes (thread_p);
466  if (error_code != NO_ERROR)
467  {
469  logpb_fatal_error (thread_p, true, ARG_FILE_LINE, "log_def_trantable");
470  return error_code;
471  }
472 
474 
476 
477  /* Initialize the lock manager and the page buffer pool */
478  error_code = lock_initialize ();
479  if (error_code != NO_ERROR)
480  {
481  goto error;
482  }
483  error_code = pgbuf_initialize ();
484  if (error_code != NO_ERROR)
485  {
486  goto error;
487  }
488  error_code = file_manager_init ();
489  if (error_code != NO_ERROR)
490  {
491  goto error;
492  }
493  return error_code;
494 
495 error:
496  logtb_undefine_trantable (thread_p);
497  logpb_fatal_error (thread_p, true, ARG_FILE_LINE, "log_def_trantable");
498 
499  return error_code;
500 }
501 
502 /*
503  * logtb_initialize_trantable -
504  *
505  * return: nothing
506  *
507  * trantable_p(in/out):
508  *
509  * Note: .
510  */
511 static void
513 {
514  trantable_p->num_total_indices = 0;
515  trantable_p->num_assigned_indices = 1;
516  trantable_p->num_coord_loose_end_indices = 0;
517  trantable_p->num_prepared_loose_end_indices = 0;
518  trantable_p->hint_free_index = 0;
519  trantable_p->num_interrupts = 0;
520  trantable_p->area = NULL;
521  trantable_p->all_tdes = NULL;
522 }
523 
524 /*
525  * logtb_initialize_system_tdes -
526  *
527  * return: NO_ERROR if all OK, ER status otherwise
528  *
529  * Note: .
530  */
531 static int
533 {
534  LOG_TDES *tdes;
535 
537  if (tdes == NULL)
538  {
540  logpb_fatal_error (thread_p, true, ARG_FILE_LINE, "log_initialize_system_tdes");
542  }
543 
544  logtb_clear_tdes (thread_p, tdes);
546  tdes->trid = LOG_SYSTEM_TRANID;
547  tdes->mvccinfo.reset ();
548  tdes->isloose_end = true;
551  tdes->client_id = -1;
552  tdes->client.set_system_internal ();
553  tdes->query_timeout = 0;
556 
557  return NO_ERROR;
558 }
559 
560 /*
561  * logtb_undefine_trantable - undefine the transaction table
562  *
563  * return: nothing
564  *
565  * Note: Undefine and free the transaction table space.
566  */
567 void
569 {
571  LOG_TDES *tdes; /* Transaction descriptor */
572  int i;
573 
575  lock_finalize ();
576  pgbuf_finalize ();
578 
579  if (log_Gl.trantable.area != NULL)
580  {
581  /*
582  * If any one of the transaction indices has coordinator info,
583  * free this area
584  */
585  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
586  {
587  /*
588  * If there is any memory allocated in the transaction descriptor,
589  * release it
590  */
591  tdes = log_Gl.trantable.all_tdes[i];
592  if (tdes != NULL)
593  {
594 #if defined(SERVER_MODE)
595  assert (tdes->tran_index == i);
596 #endif
597 
598  logtb_finalize_tdes (thread_p, tdes);
599  }
600  }
601 
602 #if defined(ENABLE_UNUSED_FUNCTION)
603  wfg_free_nodes (thread_p);
604 #endif
605 
606  if (log_Gl.trantable.all_tdes != NULL)
607  {
609  }
610 
611  area = log_Gl.trantable.area;
612  while (area != NULL)
613  {
614  log_Gl.trantable.area = area->next;
615  /* *INDENT-OFF* */
616  delete[] area->tdesarea;
617  /* *INDENT-ON* */
618  free_and_init (area);
619  area = log_Gl.trantable.area;
620  }
621  }
622 
624 }
625 
626 /*
627  * logtb_get_number_assigned_tran_indices - find number of transaction indices
628  *
629  * return: number of transaction indices
630  *
631  */
632 int
634 {
635  /* Do not use TR_TABLE_CS_ENTER()/TR_TABLE_CS_EXIT(), Estimated value is sufficient for the caller */
637 }
638 
639 /*
640  * logtb_set_number_of_assigned_tran_indices - set the number of tran indices
641  *
642  * return: nothing
643  * num_trans(in): the number of assigned tran indices
644  *
645  * Note: Callers have to call this function in the 'TR_TABLE' critical section.
646  */
647 static void
649 {
651 }
652 
653 /*
654  * logtb_increment_number_of_assigned_tran_indices -
655  * increment the number of tran indices
656  *
657  * return: nothing
658  *
659  * Note: Callers have to call this function in the 'TR_TABLE' critical section.
660  */
661 static void
663 {
665 }
666 
667 /*
668  * logtb_decrement_number_of_assigned_tran_indices -
669  * decrement the number of tran indices
670  *
671  * return: nothing
672  *
673  * Note: Callers have to call this function in the 'TR_TABLE' critical section.
674  */
675 static void
677 {
679 }
680 
681 /*
682  * logtb_get_number_of_total_tran_indices - find number of total transaction
683  * indices
684  *
685  * return: nothing
686  *
687  * Note: Find number of total transaction indices in the transaction
688  * table. Note that some of this indices may have not been
689  * assigned. See logtb_get_number_assigned_tran_indices.
690  */
691 int
693 {
695 }
696 
697 /*
698  * logtb_set_number_of_total_tran_indices - set the number of total tran indices
699  *
700  * return: nothing
701  * num_trans(in): the number of total tran indices
702  *
703  * Note: Callers have to call this function in the 'TR_TABLE' critical section.
704  */
705 static void
707 {
708  log_Gl.trantable.num_total_indices = num_total_trans;
709 }
710 
711 #if defined(ENABLE_UNUSED_FUNCTION)
712 /*
713  * logtb_am_i_sole_tran - Check if no other transactions are running
714  *
715  * return: If true, return as did TR_TABLE_CS_ENTER()
716  * but not TR_TABLE_CS_EXIT()
717  *
718  * Note: Check if no other transactions are running, that is, i am a
719  * sole transaction. If you get true by this function, you
720  * should call logtb_i_am_not_sole_tran() to exit the critical
721  * section (TR_TABLE_CS_EIXT())
722  */
723 bool
724 logtb_am_i_sole_tran (THREAD_ENTRY * thread_p)
725 {
726  TR_TABLE_CS_ENTER (thread_p);
727 
728  if (NUM_ASSIGNED_TRAN_INDICES <= 2)
729  {
730  return true;
731  }
732 
733  return false;
734 }
735 
736 /*
737  * logtb_i_am_not_sole_tran -
738  *
739  * return:
740  *
741  * NOTE:
742  */
743 void
744 logtb_i_am_not_sole_tran (THREAD_ENTRY * thread_p)
745 {
746  TR_TABLE_CS_EXIT (thread_p);
747 }
748 #endif /* ENABLE_UNUSED_FUNCTION */
749 
750 bool
752 {
753  const char *db_user;
754 
755  db_user = logtb_find_current_client_name (thread_p);
756  return (db_user != NULL && !strcasecmp (db_user, "DBA"));
757 }
758 
759 /*
760  * logtb_assign_tran_index - assign a transaction index for a sequence of
761  * transactions (thread of execution.. a client)
762  *
763  * return: transaction index
764  *
765  * trid(in): Transaction identifier or NULL_TRANID
766  * state(in): Transaction state (Usually active)
767  * client_prog_name(in): Name of the client program or NULL
768  * client_user_name(in): Name of the client user or NULL
769  * client_host_name(in): Name of the client host or NULL
770  * client_process_id(in): Identifier of the process of the host where the
771  * client transaction runs.
772  * current_state(in/out): Set as a side effect to state of transaction, when
773  * a valid pointer is given.
774  * wait_msecs(in): Wait for at least this number of milliseconds to acquire a
775  * lock. Negative value is infinite
776  * isolation(in): Isolation level. One of the following:
777  * TRAN_SERIALIZABLE
778  * TRAN_REPEATABLE_READ
779  * TRAN_READ_COMMITTED
780  *
781  * Note:Assign a transaction index for a sequence of transactions
782  * (i.e., a client) and initialize the state structure for the
783  * first transaction in the sequence. If trid is equal to
784  * NULL_TRANID, a transaction is assigned to the assigned
785  * structure and the transaction is declared active; otherwise,
786  * the given transaction with the given state is assigned to the
787  * index.
788  *
789  * This function must be called when a client is restarted.
790  */
791 int
793  const BOOT_CLIENT_CREDENTIAL * client_credential, TRAN_STATE * current_state, int wait_msecs,
794  TRAN_ISOLATION isolation)
795 {
796  int tran_index; /* The allocated transaction index */
797 
798 #if defined(SERVER_MODE)
799  if (thread_p == NULL)
800  {
801  thread_p = thread_get_thread_entry_info ();
802  }
803 #endif /* SERVER_MODE */
804 
806 
807  TR_TABLE_CS_ENTER (thread_p);
808  tran_index =
809  logtb_allocate_tran_index (thread_p, trid, state, client_credential, current_state, wait_msecs, isolation);
810  TR_TABLE_CS_EXIT (thread_p);
811 
812  if (tran_index != NULL_TRAN_INDEX)
813  {
814  LOG_SET_CURRENT_TRAN_INDEX (thread_p, tran_index);
815  }
816  else
817  {
819  }
820 
821  return tran_index;
822 }
823 
824 /*
825  * logtb_set_tdes -
826  *
827  * return:
828  *
829  * tdes(in/out): Transaction descriptor
830  * client_prog_name(in): the name of the client program
831  * client_host_name(in): the name of the client host
832  * client_user_name(in): the name of the client user
833  * client_process_id(in): the process id of the client
834  * wait_msecs(in): Wait for at least this number of milliseconds to acquire a lock.
835  * isolation(in): Isolation level
836  */
837 static void
838 logtb_set_tdes (THREAD_ENTRY * thread_p, LOG_TDES * tdes, const BOOT_CLIENT_CREDENTIAL * client_credential,
839  int wait_msecs, TRAN_ISOLATION isolation)
840 {
841 #if defined(SERVER_MODE)
842  CSS_CONN_ENTRY *conn;
843 #endif /* SERVER_MODE */
844 
845  if (client_credential == NULL)
846  {
847  client_credential = &log_Client_credential;
848  }
849  tdes->client.set_ids (*client_credential);
850  tdes->is_user_active = false;
851 #if defined(SERVER_MODE)
852  if (thread_p == NULL)
853  {
854  thread_p = thread_get_thread_entry_info ();
855  }
856 
857  conn = thread_p->conn_entry;
858  if (conn != NULL)
859  {
860  tdes->client_id = conn->client_id;
861  }
862  else
863  {
864  tdes->client_id = -1;
865  }
866 #else /* SERVER_MODE */
867  tdes->client_id = -1;
868 #endif /* SERVER_MODE */
869  tdes->wait_msecs = wait_msecs;
870  tdes->isolation = isolation;
871  tdes->isloose_end = false;
872  tdes->interrupt = false;
873  tdes->topops.stack = NULL;
874  tdes->topops.max = 0;
875  tdes->topops.last = -1;
876  tdes->m_modified_classes.clear ();
877  tdes->num_transient_classnames = 0;
878  tdes->first_save_entry = NULL;
879  tdes->lob_locator_root.init ();
880  tdes->m_log_postpone_cache.reset ();
881 }
882 
883 /*
884  * logtb_allocate_tran_index - allocate a transaction index for a sequence of
885  * transactions (thread of execution.. a client)
886  *
887  * return: tran_index or NULL_TRAN_INDEX
888  *
889  * trid(in): Transaction identifier or NULL_TRANID
890  * state(in): Transaction state (Usually active)
891  * client_prog_name(in): Name of the client program or NULL
892  * client_user_name(in): Name of the client user or NULL
893  * client_host_name(in): Name of the client host or NULL
894  * client_process_id(in): Identifier of the process of the host where the
895  * client transaction runs.
896  * current_state(in/out): Set as a side effect to state of transaction, when
897  * a valid pointer is given.
898  * wait_msecs(in): Wait for at least this number of milliseconds to acquire a
899  * lock. That is, wait this much before the transaction
900  * is timed out. Negative value is infinite.
901  * isolation(in): Isolation level. One of the following:
902  * TRAN_SERIALIZABLE
903  * TRAN_REPEATABLE_READ
904  * TRAN_READ_COMMITTED
905  *
906  * Note:Allocate a transaction index for a sequence of transactions
907  * (i.e., a client) and initialize the state structure for the
908  * first transaction in the sequence. If trid is equal to
909  * NULL_TRANID, a transaction is assigned to the assigned
910  * structure and the transaction is declared active; otherwise,
911  * the given transaction with the given state is assigned to the
912  * index. If the given client user has a dangling entry due to
913  * client loose ends, this index is attached to it.
914  *
915  * This function is only called by the log manager when the log
916  * latch has already been acquired. (See logtb_assign_tran_index)
917  */
918 static int
920  const BOOT_CLIENT_CREDENTIAL * client_credential, TRAN_STATE * current_state, int wait_msecs,
921  TRAN_ISOLATION isolation)
922 {
923  int i;
924  int visited_loop_start_pos;
925  LOG_TDES *tdes; /* Transaction descriptor */
926  int tran_index; /* The assigned index */
927  int save_tran_index; /* Save as a good index to assign */
928 
929 #if defined(SERVER_MODE)
930  if (thread_p == NULL)
931  {
932  thread_p = thread_get_thread_entry_info ();
933  }
934 #endif /* SERVER_MODE */
935 
936  save_tran_index = tran_index = NULL_TRAN_INDEX;
937 
938  /* Is there any free index ? */
940  {
941 #if defined(SERVER_MODE)
942  /* When normal processing, we never expand trantable */
944  {
946  return NULL_TRAN_INDEX;
947  }
948 #endif /* SERVER_MODE */
949 
950  i = (int) (((float) NUM_TOTAL_TRAN_INDICES * LOG_EXPAND_TRANTABLE_RATIO) + 0.5);
951  if (logtb_expand_trantable (thread_p, i) != NO_ERROR)
952  {
953  /* Out of memory or something like that */
954  return NULL_TRAN_INDEX;
955  }
956  }
957 
958  /*
959  * Note that we could have found the entry already and it may be stored in
960  * tran_index.
961  */
962  for (i = log_Gl.trantable.hint_free_index, visited_loop_start_pos = 0;
963  tran_index == NULL_TRAN_INDEX && visited_loop_start_pos < 2; i = (i + 1) % NUM_TOTAL_TRAN_INDICES)
964  {
966  {
967  tran_index = i;
968  }
970  {
971  visited_loop_start_pos++;
972  }
973  }
974 
975  if (tran_index != NULL_TRAN_INDEX)
976  {
978 
980 
981  tdes = LOG_FIND_TDES (tran_index);
982  if (tdes == NULL)
983  {
985  return NULL_TRAN_INDEX;
986  }
987 
988  tdes->tran_index = tran_index;
989  logtb_clear_tdes (thread_p, tdes);
990  logtb_set_tdes (thread_p, tdes, client_credential, wait_msecs, isolation);
991 
992  if (trid == NULL_TRANID)
993  {
994  /* Assign a new transaction identifier for the new index */
995  logtb_get_new_tran_id (thread_p, tdes);
996  state = TRAN_ACTIVE;
997  }
998  else
999  {
1000  tdes->trid = trid;
1001  tdes->state = state;
1002  }
1003 
1004  if (current_state)
1005  {
1006  *current_state = state;
1007  }
1008 
1009  LOG_SET_CURRENT_TRAN_INDEX (thread_p, tran_index);
1010 
1012  }
1013 
1014  return tran_index;
1015 }
1016 
1017 int
1019 {
1020  LOG_TDES *tdes;
1021  int tran_index;
1022 
1023  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
1024  tdes = LOG_FIND_TDES (tran_index);
1025 
1026  if (tdes == NULL)
1027  {
1028  return db_Disable_modifications;
1029  }
1030 
1031  return tdes->disable_modifications;
1032 }
1033 
1034 /*
1035  * logtb_rv_find_allocate_tran_index - find/alloc a transaction during the recovery
1036  * analysis process
1037  *
1038  * return: The transaction descriptor
1039  *
1040  * trid(in): The desired transaction identifier
1041  * log_lsa(in): Log address where the transaction was seen in the log
1042  *
1043  * Note: Find or allocate the transaction descriptor for the given
1044  * transaction identifier. If the descriptor was allocated, it is
1045  * assumed that this is the first time the transaction is seen.
1046  * Thus, the head of the transaction in the log is located at the
1047  * givel location (i.e., log_lsa.pageid, log_offset).
1048  * This function should be called only by the recovery process
1049  * (the analysis phase).
1050  */
1051 LOG_TDES *
1053 {
1054  LOG_TDES *tdes; /* Transaction descriptor */
1055  int tran_index;
1056 
1057  assert (trid != NULL_TRANID);
1058 
1059  if (logtb_is_system_worker_tranid (trid))
1060  {
1061  // *INDENT-OFF*
1063  // *INDENT-ON*
1064  }
1065 
1066  /*
1067  * If this is the first time, the transaction is seen. Assign a new
1068  * index to describe it and assume that the transaction was active
1069  * at the time of the crash, and thus it will be unilaterally aborted
1070  */
1071  tran_index = logtb_find_tran_index (thread_p, trid);
1072  if (tran_index == NULL_TRAN_INDEX)
1073  {
1074  /* Define the index */
1075  tran_index =
1078  tdes = LOG_FIND_TDES (tran_index);
1079  if (tran_index == NULL_TRAN_INDEX || tdes == NULL)
1080  {
1081  /*
1082  * Unable to assign a transaction index. The recovery process
1083  * cannot continue
1084  */
1085  logpb_fatal_error (thread_p, true, ARG_FILE_LINE, "log_recovery_find_or_alloc");
1086  return NULL;
1087  }
1088  else
1089  {
1090  LSA_COPY (&tdes->head_lsa, log_lsa);
1091  }
1092  }
1093  else
1094  {
1095  tdes = LOG_FIND_TDES (tran_index);
1096  }
1097 
1098  return tdes;
1099 }
1100 
1101 /*
1102  * logtb_rv_assign_mvccid_for_undo_recovery () - Assign an MVCCID for
1103  * transactions that need to
1104  * undo at recovery.
1105  *
1106  * return : Void.
1107  * thread_p (in) : Thread entry.
1108  * mvccid (in) : Assigned MVCCID.
1109  */
1110 void
1112 {
1113  LOG_TDES *tdes = LOG_FIND_CURRENT_TDES (thread_p);
1114 
1115  assert (tdes != NULL);
1116  assert (MVCCID_IS_VALID (mvccid));
1117 
1118  tdes->mvccinfo.id = mvccid;
1119 }
1120 
1121 /*
1122  * logtb_release_tran_index - return an assigned transaction index
1123  *
1124  * return: nothing
1125  *
1126  * tran_index(in): Transaction index
1127  *
1128  * Note: Return a transaction index which was used for a sequence of
1129  * transactions (i.e., a client).
1130  *
1131  * This function must be called when a client is shutdown (i.e.,
1132  * unregistered).
1133  */
1134 void
1135 logtb_release_tran_index (THREAD_ENTRY * thread_p, int tran_index)
1136 {
1137  LOG_TDES *tdes; /* Transaction descriptor */
1138 
1139  qmgr_clear_trans_wakeup (thread_p, tran_index, true, false);
1140  heap_chnguess_clear (thread_p, tran_index);
1141 
1142  tdes = LOG_FIND_TDES (tran_index);
1143  if (tran_index != LOG_SYSTEM_TRAN_INDEX && tdes != NULL)
1144  {
1145  tdes->mvccinfo.reset ();
1146  TR_TABLE_CS_ENTER (thread_p);
1147 
1148  /*
1149  * Free the top system operation stack since the transaction entry may
1150  * not be freed (i.e., left as loose end distributed transaction)
1151  */
1152  if (tdes->topops.max != 0)
1153  {
1154  free_and_init (tdes->topops.stack);
1155  tdes->topops.max = 0;
1156  tdes->topops.last = -1;
1157  }
1158 
1159  if (LOG_ISTRAN_2PC_PREPARE (tdes))
1160  {
1161  tdes->isloose_end = true;
1163  }
1164  else
1165  {
1167  {
1168  tdes->isloose_end = true;
1170  }
1171  else
1172  {
1173  logtb_free_tran_index (thread_p, tran_index);
1174  tdes->client.reset ();
1175  tdes->is_user_active = false;
1176  }
1177  }
1178 
1179  TR_TABLE_CS_EXIT (thread_p);
1180  }
1181 }
1182 
1183 /*
1184  * logtb_free_tran_index - free a transaction index
1185  *
1186  * return: nothing
1187  *
1188  * tran_index(in): Transaction index
1189  *
1190  * Note: Free a transaction index which was used for a sequence of
1191  * transactions (i.e., a client).
1192  *
1193  * This function is only called by the log manager when the log
1194  * latch has already been acquired. (See logtb_release_tran_index
1195  * for other cases).
1196  */
1197 void
1198 logtb_free_tran_index (THREAD_ENTRY * thread_p, int tran_index)
1199 {
1200  LOG_TDES *tdes; /* Transaction descriptor */
1201  int log_tran_index;
1202 
1203 #if defined(SERVER_MODE)
1204  if (thread_p == NULL)
1205  {
1206  thread_p = thread_get_thread_entry_info ();
1207  }
1208 #endif /* SERVER_MODE */
1209 
1210  log_tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
1211 
1212  tdes = LOG_FIND_TDES (tran_index);
1213  if (tran_index > NUM_TOTAL_TRAN_INDICES || tdes == NULL || tdes->trid == NULL_TRANID)
1214  {
1215 #if defined(CUBRID_DEBUG)
1216  er_log_debug (ARG_FILE_LINE, "log_free_tran_index: Unknown index = %d. Operation is ignored", tran_index);
1217 #endif /* CUBRID_DEBUG */
1218  return;
1219  }
1220 
1221  logtb_clear_tdes (thread_p, tdes);
1222  if (tdes->repl_records)
1223  {
1224  free_and_init (tdes->repl_records);
1225  }
1226  tdes->num_repl_records = 0;
1227  if (tdes->topops.max != 0)
1228  {
1229  free_and_init (tdes->topops.stack);
1230  tdes->topops.max = 0;
1231  tdes->topops.last = -1;
1232  }
1233 
1234  if (tran_index != LOG_SYSTEM_TRAN_INDEX)
1235  {
1236  tdes->trid = NULL_TRANID;
1237  tdes->client_id = -1;
1238 
1239  TR_TABLE_CS_ENTER (thread_p);
1241  if (log_Gl.trantable.hint_free_index > tran_index)
1242  {
1243  log_Gl.trantable.hint_free_index = tran_index;
1244  }
1245  TR_TABLE_CS_EXIT (thread_p);
1246 
1247  if (log_tran_index == tran_index)
1248  {
1249  if (!LOG_ISRESTARTED ())
1250  {
1251  log_tran_index = LOG_SYSTEM_TRAN_INDEX;
1252  }
1253  else
1254  {
1255  log_tran_index = NULL_TRAN_INDEX;
1256  }
1257 
1258  LOG_SET_CURRENT_TRAN_INDEX (thread_p, log_tran_index);
1259  }
1260  }
1261 }
1262 
1263 /*
1264  * logtb_free_tran_index_with_undo_lsa - free tranindex with lsa
1265  *
1266  * return: nothing
1267  *
1268  * undo_lsa(in): Undo log sequence address
1269  *
1270  * Note: Remove the transaction index associated with the undo LSA.
1271  * This function execute a sequential search on the transaction
1272  * table to find out the transaction with such lsa. This
1273  * sequential scan is OK since this function is only called when
1274  * a system error happens, which in principle never happen.
1275  */
1276 void
1278 {
1279  int i;
1280  LOG_TDES *tdes; /* Transaction descriptor */
1281 
1282  TR_TABLE_CS_ENTER (thread_p);
1283 
1284  if (undo_lsa != NULL && !LSA_ISNULL (undo_lsa))
1285  {
1286  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
1287  {
1288  if (i != LOG_SYSTEM_TRAN_INDEX)
1289  {
1290  tdes = log_Gl.trantable.all_tdes[i];
1291  if (tdes != NULL && tdes->trid != NULL_TRANID && tdes->state == TRAN_UNACTIVE_UNILATERALLY_ABORTED
1292  && LSA_EQ (undo_lsa, &tdes->undo_nxlsa))
1293  {
1294  logtb_free_tran_index (thread_p, i);
1295  }
1296  }
1297  }
1298  }
1299 
1300  TR_TABLE_CS_EXIT (thread_p);
1301 }
1302 
1303 /*
1304  * logtb_dump_tdes -
1305  *
1306  * return: nothing
1307  *
1308  * tdes(in):
1309  *
1310  * Note:
1311  */
1312 static void
1313 logtb_dump_tdes (FILE * out_fp, LOG_TDES * tdes)
1314 {
1315  fprintf (out_fp,
1316  "Tran_index = %2d, Trid = %d,\n State = %s,\n Isolation = %s,\n"
1317  " Wait_msecs = %d, isloose_end = %d,\n Head_lsa = %lld|%d, Tail_lsa = %lld|%d,"
1318  " Postpone_lsa = %lld|%d,\n SaveLSA = %lld|%d, UndoNextLSA = %lld|%d,\n"
1319  " Client_User: (Type = %d, User = %s, Program = %s, Login = %s, Host = %s, Pid = %d)\n",
1320  tdes->tran_index, tdes->trid, log_state_string (tdes->state), log_isolation_string (tdes->isolation),
1321  tdes->wait_msecs, tdes->isloose_end, (long long int) tdes->head_lsa.pageid, (int) tdes->head_lsa.offset,
1322  (long long int) tdes->tail_lsa.pageid, (int) tdes->tail_lsa.offset, (long long int) tdes->posp_nxlsa.pageid,
1323  (int) tdes->posp_nxlsa.offset, (long long int) tdes->savept_lsa.pageid, (int) tdes->savept_lsa.offset,
1324  (long long int) tdes->undo_nxlsa.pageid, (int) tdes->undo_nxlsa.offset, tdes->client.client_type,
1325  tdes->client.get_db_user (), tdes->client.get_program_name (), tdes->client.get_login_name (),
1326  tdes->client.get_host_name (), tdes->client.process_id);
1327 
1328  if (tdes->topops.max != 0 && tdes->topops.last >= 0)
1329  {
1330  logtb_dump_top_operations (out_fp, &tdes->topops);
1331  }
1332 
1333  if (tdes->gtrid != LOG_2PC_NULL_GTRID || tdes->coord != NULL)
1334  {
1335  logtb_dump_tdes_distribute_transaction (out_fp, tdes->gtrid, tdes->coord);
1336  }
1337 }
1338 
1339 /*
1340  * logtb_dump_top_operations -
1341  *
1342  * return: nothing
1343  *
1344  * tdes(in):
1345  *
1346  * Note:
1347  */
1348 static void
1349 logtb_dump_top_operations (FILE * out_fp, LOG_TOPOPS_STACK * topops_p)
1350 {
1351  int i;
1352 
1353  fprintf (out_fp, " Active top system operations for tran:\n");
1354  for (i = topops_p->last; i >= 0; i--)
1355  {
1356  fprintf (out_fp, " Head = %lld|%d, Posp_Head = %lld|%d\n",
1357  LSA_AS_ARGS (&topops_p->stack[i].lastparent_lsa), LSA_AS_ARGS (&topops_p->stack[i].posp_lsa));
1358  }
1359 }
1360 
1361 /*
1362  * logtb_dump_tdes_distribute_transaction -
1363  *
1364  * return: nothing
1365  *
1366  * tdes(in):
1367  *
1368  * Note:
1369  */
1370 static void
1371 logtb_dump_tdes_distribute_transaction (FILE * out_fp, int global_tran_id, LOG_2PC_COORDINATOR * coord)
1372 {
1373  int i;
1374  char *particp_id; /* Participant identifier */
1375 
1376  /* This is a distributed transaction */
1377  if (coord != NULL)
1378  {
1379  fprintf (out_fp, " COORDINATOR SITE(or NESTED PARTICIPANT SITE)");
1380  }
1381  else
1382  {
1383  fprintf (out_fp, " PARTICIPANT SITE");
1384  }
1385 
1386  fprintf (out_fp, " of global tranid = %d\n", global_tran_id);
1387 
1388  if (coord != NULL)
1389  {
1390  fprintf (out_fp, " Num_participants = %d, Partids = ", coord->num_particps);
1391  for (i = 0; i < coord->num_particps; i++)
1392  {
1393  particp_id = ((char *) coord->block_particps_ids + i * coord->particp_id_length);
1394  if (i == 0)
1395  {
1396  fprintf (out_fp, " %s", log_2pc_sprintf_particp (particp_id));
1397  }
1398  else
1399  {
1400  fprintf (out_fp, ", %s", log_2pc_sprintf_particp (particp_id));
1401  }
1402  }
1403  fprintf (out_fp, "\n");
1404 
1405  if (coord->ack_received)
1406  {
1407  fprintf (out_fp, " Acknowledgement vector =");
1408  for (i = 0; i < coord->num_particps; i++)
1409  {
1410  if (i == 0)
1411  {
1412  fprintf (out_fp, " %d", coord->ack_received[i]);
1413  }
1414  else
1415  {
1416  fprintf (out_fp, ", %d", coord->ack_received[i]);
1417  }
1418  }
1419  }
1420  fprintf (out_fp, "\n");
1421  }
1422 }
1423 
1424 /*
1425  * xlogtb_dump_trantable - dump the transaction table
1426  *
1427  * return: nothing
1428  *
1429  * Note: Dump the transaction state table.
1430  * This function is used for debugging purposes.
1431  */
1432 void
1433 xlogtb_dump_trantable (THREAD_ENTRY * thread_p, FILE * out_fp)
1434 {
1435  int i;
1436  LOG_TDES *tdes; /* Transaction descriptor */
1437 
1438  fprintf (out_fp, "\n ** DUMPING TABLE OF ACTIVE TRANSACTIONS **\n");
1439 
1440  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
1441 
1442  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
1443  {
1444  tdes = log_Gl.trantable.all_tdes[i];
1445  if (tdes == NULL || tdes->trid == NULL_TRANID)
1446  {
1447  fprintf (out_fp, "Tran_index = %2d... Free transaction index\n", i);
1448  }
1449  else
1450  {
1451  logtb_dump_tdes (out_fp, tdes);
1452  }
1453  }
1454 
1455  TR_TABLE_CS_EXIT (thread_p);
1456 
1457  fprintf (out_fp, "\n");
1458 }
1459 
1460 /*
1461  * logtb_free_tran_mvcc_info - free transaction MVCC info
1462  *
1463  * return: nothing..
1464  *
1465  * tdes(in/out): Transaction descriptor
1466  */
1467 static void
1469 {
1470  MVCC_INFO *curr_mvcc_info = &tdes->mvccinfo;
1471 
1472  curr_mvcc_info->snapshot.m_active_mvccs.finalize ();
1473  curr_mvcc_info->sub_ids.clear ();
1474 }
1475 
1476 /*
1477  * logtb_clear_tdes - clear the transaction descriptor
1478  *
1479  * return: nothing..
1480  *
1481  * tdes(in/out): Transaction descriptor
1482  */
1483 void
1485 {
1486  int i, j;
1487  DB_VALUE *dbval;
1488  HL_HEAPID save_heap_id;
1489 
1490  tdes->isloose_end = false;
1491  tdes->state = TRAN_ACTIVE;
1492  LSA_SET_NULL (&tdes->head_lsa);
1493  LSA_SET_NULL (&tdes->tail_lsa);
1494  LSA_SET_NULL (&tdes->undo_nxlsa);
1495  LSA_SET_NULL (&tdes->posp_nxlsa);
1496  LSA_SET_NULL (&tdes->savept_lsa);
1497  LSA_SET_NULL (&tdes->topop_lsa);
1499  tdes->topops.last = -1;
1500  tdes->gtrid = LOG_2PC_NULL_GTRID;
1501  tdes->gtrinfo.info_length = 0;
1502  if (tdes->gtrinfo.info_data != NULL)
1503  {
1505  }
1506  if (tdes->coord != NULL)
1507  {
1508  log_2pc_free_coord_info (tdes);
1509  }
1510  tdes->m_multiupd_stats.clear ();
1511  if (tdes->interrupt == (int) true)
1512  {
1513  tdes->interrupt = false;
1514 #if defined (HAVE_ATOMIC_BUILTINS)
1515  ATOMIC_INC_32 (&log_Gl.trantable.num_interrupts, -1);
1516 #else
1517  TR_TABLE_CS_ENTER (thread_p);
1519  TR_TABLE_CS_EXIT (thread_p);
1520 #endif
1521  }
1522  tdes->m_modified_classes.clear ();
1523 
1524  for (i = 0; i < tdes->cur_repl_record; i++)
1525  {
1526  if (tdes->repl_records[i].repl_data)
1527  {
1528  free_and_init (tdes->repl_records[i].repl_data);
1529  }
1530  }
1531 
1532  save_heap_id = db_change_private_heap (thread_p, 0);
1533  for (i = 0; i < tdes->num_exec_queries && i < MAX_NUM_EXEC_QUERY_HISTORY; i++)
1534  {
1535  if (tdes->bind_history[i].vals == NULL)
1536  {
1537  continue;
1538  }
1539 
1540  dbval = tdes->bind_history[i].vals;
1541  for (j = 0; j < tdes->bind_history[i].size; j++)
1542  {
1543  db_value_clear (dbval);
1544  dbval++;
1545  }
1546 
1547  db_private_free_and_init (thread_p, tdes->bind_history[i].vals);
1548  tdes->bind_history[i].size = 0;
1549  }
1550  (void) db_change_private_heap (thread_p, save_heap_id);
1551 
1552  tdes->cur_repl_record = 0;
1553  tdes->append_repl_recidx = -1;
1554  tdes->fl_mark_repl_recidx = -1;
1555  LSA_SET_NULL (&tdes->repl_insert_lsa);
1556  LSA_SET_NULL (&tdes->repl_update_lsa);
1557  tdes->first_save_entry = NULL;
1558  tdes->query_timeout = 0;
1559  tdes->query_start_time = 0;
1560  tdes->tran_start_time = 0;
1561  XASL_ID_SET_NULL (&tdes->xasl_id);
1562  tdes->waiting_for_res = NULL;
1564  tdes->num_exec_queries = 0;
1565  tdes->suppress_replication = 0;
1566  tdes->m_log_postpone_cache.reset ();
1567 
1569 
1570  assert (tdes->mvccinfo.id == MVCCID_NULL);
1571 
1573  {
1574  tdes->disable_modifications = 0;
1575  }
1576  else
1577  {
1579  }
1580  tdes->has_deadlock_priority = false;
1581 
1582  tdes->num_log_records_written = 0;
1583 
1589 }
1590 
1591 /*
1592  * logtb_initialize_tdes - initialize the transaction descriptor
1593  *
1594  * return: nothing..
1595  *
1596  * tdes(in/out): Transaction descriptor
1597  * tran_index(in): Transaction index
1598  */
1599 void
1600 logtb_initialize_tdes (LOG_TDES * tdes, int tran_index)
1601 {
1602  int i, r;
1603 
1604  tdes->tran_index = tran_index;
1605  tdes->trid = NULL_TRANID;
1606  tdes->isloose_end = false;
1607  tdes->coord = NULL;
1608  tdes->client_id = -1;
1609  tdes->gtrid = LOG_2PC_NULL_GTRID;
1610  tdes->gtrinfo.info_length = 0;
1611  tdes->gtrinfo.info_data = NULL;
1612  tdes->interrupt = false;
1614  tdes->isolation = TRAN_SERIALIZABLE;
1615  LSA_SET_NULL (&tdes->head_lsa);
1616  LSA_SET_NULL (&tdes->tail_lsa);
1617  LSA_SET_NULL (&tdes->undo_nxlsa);
1618  LSA_SET_NULL (&tdes->posp_nxlsa);
1619  LSA_SET_NULL (&tdes->savept_lsa);
1620  LSA_SET_NULL (&tdes->topop_lsa);
1622 
1624  assert (r == NO_ERROR);
1625 
1626  tdes->topops.stack = NULL;
1627  tdes->topops.last = -1;
1628  tdes->topops.max = 0;
1629  tdes->num_unique_btrees = 0;
1630  tdes->max_unique_btrees = 0;
1631  tdes->m_multiupd_stats.construct ();
1632  tdes->num_transient_classnames = 0;
1633  tdes->num_repl_records = 0;
1634  tdes->cur_repl_record = 0;
1635  tdes->append_repl_recidx = -1;
1636  tdes->fl_mark_repl_recidx = -1;
1637  tdes->repl_records = NULL;
1638  LSA_SET_NULL (&tdes->repl_insert_lsa);
1639  LSA_SET_NULL (&tdes->repl_update_lsa);
1640  tdes->first_save_entry = NULL;
1641  tdes->suppress_replication = 0;
1642  tdes->lob_locator_root.init ();
1643  tdes->query_timeout = 0;
1644  tdes->query_start_time = 0;
1645  tdes->tran_start_time = 0;
1646  XASL_ID_SET_NULL (&tdes->xasl_id);
1647  tdes->waiting_for_res = NULL;
1650  tdes->num_exec_queries = 0;
1651 
1652  for (i = 0; i < MAX_NUM_EXEC_QUERY_HISTORY; i++)
1653  {
1654  tdes->bind_history[i].size = 0;
1655  tdes->bind_history[i].vals = NULL;
1656  }
1657  tdes->has_deadlock_priority = false;
1658 
1659  tdes->num_log_records_written = 0;
1660 
1661  tdes->mvccinfo.init ();
1662 
1663  tdes->log_upd_stats.cos_count = 0;
1667 
1668  tdes->log_upd_stats.stats_count = 0;
1672 
1675  tdes->log_upd_stats.classes_cos_hash = mht_create ("Tran_classes_cos", 101, oid_hash, oid_compare_equals);
1676 
1678  tdes->is_user_active = false;
1679 
1685 }
1686 
1687 /*
1688  * logtb_finalize_tdes - finalize the transaction descriptor
1689  *
1690  * return: nothing.
1691  *
1692  * thread_p(in):
1693  * tdes(in/out): Transaction descriptor
1694  */
1695 void
1697 {
1698  int r;
1699 
1700  logtb_clear_tdes (thread_p, tdes);
1703 
1704  r = rmutex_finalize (&tdes->rmutex_topop);
1705  assert (r == NO_ERROR);
1706 
1707  if (tdes->topops.max != 0)
1708  {
1709  free_and_init (tdes->topops.stack);
1710  tdes->topops.max = 0;
1711  tdes->topops.last = -1;
1712  }
1713 }
1714 
1715 /*
1716  * logtb_get_new_tran_id - assign a new transaction identifier
1717  *
1718  * return: tranid
1719  *
1720  * tdes(in/out): Transaction descriptor
1721  */
1722 int
1724 {
1725 #if defined (HAVE_ATOMIC_BUILTINS)
1726  int trid, next_trid;
1727 
1728  logtb_clear_tdes (thread_p, tdes);
1729 
1730  do
1731  {
1732  trid = VOLATILE_ACCESS (log_Gl.hdr.next_trid, int);
1733 
1734  next_trid = trid + 1;
1735  if (next_trid < 0)
1736  {
1737  /* an overflow happened. starts with its base */
1738  next_trid = LOG_SYSTEM_TRANID + 1;
1739  }
1740 
1741  /* Need to check (trid < LOG_SYSTEM_TRANID + 1) for robustness. If log_Gl.hdr.next_trid was reset to 0 (see
1742  * log_rv_analysis_log_end), this prevents us from correctly generating trids. */
1743  }
1744  while (!ATOMIC_CAS_32 (&log_Gl.hdr.next_trid, trid, next_trid) || (trid < LOG_SYSTEM_TRANID + 1));
1745 
1746  assert (LOG_SYSTEM_TRANID + 1 <= trid && trid <= DB_INT32_MAX);
1747 
1748  tdes->trid = trid;
1749  return trid;
1750 #else
1751  TR_TABLE_CS_ENTER (thread_p);
1752 
1753  logtb_clear_tdes (thread_p, tdes);
1754 
1755  tdes->trid = log_Gl.hdr.next_trid++;
1756  /* check overflow */
1757  if (tdes->trid < 0)
1758  {
1759  tdes->trid = LOG_SYSTEM_TRANID + 1;
1760  /* set MVCC next id to null */
1761  log_Gl.hdr.next_trid = tdes->trid + 1;
1762  }
1763 
1764  TR_TABLE_CS_EXIT (thread_p);
1765 
1766  return tdes->trid;
1767 #endif
1768 }
1769 
1770 /*
1771  * logtb_find_tran_index - find index of transaction
1772  *
1773  * return: tran index
1774  *
1775  * trid(in): Transaction identifier
1776  *
1777  * Note: Find the index of a transaction. This function execute a
1778  * sequential search in the transaction table to find out the
1779  * transaction index. The function bypasses the search if the
1780  * trid belongs to the current transaction.
1781  *
1782  * The assumption of this function is that the transaction table
1783  * is not very big and that most of the time the search is
1784  * avoided. if this assumption becomes false, we may need to
1785  * define a hash table from trid to tdes to speed up the
1786  * search.
1787  */
1788 int
1790 {
1791  int i;
1792  int tran_index = NULL_TRAN_INDEX; /* The transaction index */
1793  LOG_TDES *tdes; /* Transaction descriptor */
1794 
1795  assert (trid != NULL_TRANID);
1796 
1797  /* Avoid searching as much as possible */
1798  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
1799  tdes = LOG_FIND_TDES (tran_index);
1800  if (tdes == NULL || tdes->trid != trid)
1801  {
1802  tran_index = NULL_TRAN_INDEX;
1803 
1804  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
1805  /* Search the transaction table for such transaction */
1806  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
1807  {
1808  tdes = log_Gl.trantable.all_tdes[i];
1809  if (tdes != NULL && tdes->trid != NULL_TRANID && tdes->trid == trid)
1810  {
1811  tran_index = i;
1812  break;
1813  }
1814  }
1815  TR_TABLE_CS_EXIT (thread_p);
1816  }
1817 
1818  return tran_index;
1819 }
1820 
1821 #if defined (ENABLE_UNUSED_FUNCTION)
1822 /*
1823  * logtb_find_tran_index_host_pid - find index of transaction
1824  *
1825  * return: tran index
1826  *
1827  * host_name(in): Name of host machine
1828  * process_id(in): Process id of client
1829  *
1830  * Note: Find the index of a transaction. This function executes a
1831  * sequential search in the transaction table to find out the
1832  * transaction index given only the host machine and process id.
1833  *
1834  * The assumption of this function is that the transaction table
1835  * is not very big and that most of the time the search is
1836  * avoided. It is currently only being used during client
1837  * restart to insure that no badly behaving clients manage to
1838  * have two open connections at the same time.
1839  */
1840 int
1841 logtb_find_tran_index_host_pid (THREAD_ENTRY * thread_p, const char *host_name, int process_id)
1842 {
1843  int i;
1844  int tran_index = NULL_TRAN_INDEX; /* The transaction index */
1845  LOG_TDES *tdes; /* Transaction descriptor */
1846 
1847  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
1848  /* Search the transaction table for such transaction */
1849  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
1850  {
1851  tdes = log_Gl.trantable.all_tdes[i];
1852  if (tdes != NULL && tdes->trid != NULL_TRANID && tdes->client.process_id == process_id
1853  && strcmp (tdes->client.get_host_name (), host_name) == 0)
1854  {
1855  tran_index = i;
1856  break;
1857  }
1858  }
1859  TR_TABLE_CS_EXIT (thread_p);
1860 
1861  return tran_index;
1862 }
1863 #endif /* ENABLE_UNUSED_FUNCTION */
1864 
1865 /*
1866  * logtb_find_tranid - find TRANID of transaction index
1867  *
1868  * return: TRANID
1869  *
1870  * tran_index(in): Index of transaction
1871  */
1872 TRANID
1873 logtb_find_tranid (int tran_index)
1874 {
1875  LOG_TDES *tdes; /* Transaction descriptor */
1876  TRANID trid = NULL_TRANID; /* Transaction index */
1877 
1878  tdes = LOG_FIND_TDES (tran_index);
1879  if (tdes != NULL)
1880  {
1881  trid = tdes->trid;
1882  }
1883  return trid;
1884 }
1885 
1886 /*
1887  * logtb_find_current_tranid - find current transaction identifier
1888  *
1889  * return: TRANID
1890  */
1891 TRANID
1893 {
1894  return logtb_find_tranid (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
1895 }
1896 
1897 #if defined (ENABLE_UNUSED_FUNCTION)
1898 /*
1899  * logtb_count_clients_with_type - count number of transaction indices
1900  * with client type
1901  * return: number of clients
1902  */
1903 int
1904 logtb_count_clients_with_type (THREAD_ENTRY * thread_p, int client_type)
1905 {
1906  LOG_TDES *tdes;
1907  int i, count;
1908 
1909  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
1910 
1911  count = 0;
1912  for (i = 0; i < log_Gl.trantable.num_total_indices; i++)
1913  {
1914  tdes = log_Gl.trantable.all_tdes[i];
1915  if (tdes != NULL && tdes->trid != NULL_TRANID)
1916  {
1917  if (tdes->client.client_type == client_type)
1918  {
1919  count++;
1920  }
1921  }
1922  }
1923  TR_TABLE_CS_EXIT (thread_p);
1924  return count;
1925 }
1926 #endif /* ENABLE_UNUSED_FUNCTION */
1927 
1928 /*
1929  * logtb_count_clients - count number of transaction indices
1930  * return: number of clients
1931  */
1932 int
1934 {
1935  LOG_TDES *tdes;
1936  int i, count;
1937 
1938  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
1939 
1940  count = 0;
1941  for (i = 0; i < log_Gl.trantable.num_total_indices; i++)
1942  {
1943  tdes = log_Gl.trantable.all_tdes[i];
1944  if (tdes != NULL && tdes->trid != NULL_TRANID)
1945  {
1947  {
1948  count++;
1949  }
1950  }
1951  }
1952  TR_TABLE_CS_EXIT (thread_p);
1953  return count;
1954 }
1955 
1956 /*
1957  * logtb_count_not_allowed_clients_in_maintenance_mode -
1958  * count number of transaction indices
1959  * connection not allowed client in maintenancemode.
1960  * return: number of clients
1961  */
1962 int
1964 {
1965  LOG_TDES *tdes;
1966  int i, count;
1967 
1968  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
1969 
1970  count = 0;
1971  for (i = 0; i < log_Gl.trantable.num_total_indices; i++)
1972  {
1973  tdes = log_Gl.trantable.all_tdes[i];
1974  if (tdes != NULL && tdes->trid != NULL_TRANID)
1975  {
1977  tdes->client.client_type))
1978  {
1979  count++;
1980  }
1981  }
1982  }
1983  TR_TABLE_CS_EXIT (thread_p);
1984  return count;
1985 }
1986 
1987 /*
1988  * logtb_find_client_type - find client type of transaction index
1989  *
1990  * return: client type
1991  *
1992  * tran_index(in): Index of transaction
1993  */
1994 int
1995 logtb_find_client_type (int tran_index)
1996 {
1997  LOG_TDES *tdes;
1998 
1999  tdes = LOG_FIND_TDES (tran_index);
2000  if (tdes != NULL && tdes->trid != NULL_TRANID)
2001  {
2002  return tdes->client.client_type;
2003  }
2004  return -1;
2005 }
2006 
2007 /*
2008  * logtb_find_client_name - find client name of transaction index
2009  *
2010  * return: client name
2011  *
2012  * tran_index(in): Index of transaction
2013  */
2014 const char *
2015 logtb_find_client_name (int tran_index)
2016 {
2017  LOG_TDES *tdes;
2018 
2019  tdes = LOG_FIND_TDES (tran_index);
2020  if (tdes != NULL && tdes->trid != NULL_TRANID)
2021  {
2022  return tdes->client.get_db_user ();
2023  }
2024  return NULL;
2025 }
2026 
2027 /*
2028  * logtb_set_user_name - set client name of transaction index
2029  *
2030  * return:
2031  *
2032  * tran_index(in): Index of transaction
2033  * user_name(in):
2034  */
2035 void
2036 logtb_set_user_name (int tran_index, const char *user_name)
2037 {
2038  LOG_TDES *tdes;
2039 
2040  tdes = LOG_FIND_TDES (tran_index);
2041  if (tdes != NULL && tdes->trid != NULL_TRANID)
2042  {
2043  // *INDENT-OFF*
2044  tdes->client.set_user ((user_name) ? user_name : clientids::UNKNOWN_ID);
2045  // *INDENT-ON*
2046  }
2047  return;
2048 }
2049 
2050 /*
2051  * logtb_set_current_user_name - set client name of current transaction
2052  *
2053  * return:
2054  */
2055 void
2056 logtb_set_current_user_name (THREAD_ENTRY * thread_p, const char *user_name)
2057 {
2058  logtb_set_user_name (LOG_FIND_THREAD_TRAN_INDEX (thread_p), user_name);
2059 }
2060 
2061 /*
2062  * logtb_set_current_user_active() - set active state of current user
2063  *
2064  * return:
2065  * thread_p(in):
2066  * is_user_active(in):
2067  */
2068 void
2069 logtb_set_current_user_active (THREAD_ENTRY * thread_p, bool is_user_active)
2070 {
2071  int tran_index;
2072  LOG_TDES *tdes;
2073 
2074  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2075  tdes = LOG_FIND_TDES (tran_index);
2076 
2077  tdes->is_user_active = is_user_active;
2078 }
2079 
2080 /*
2081  * logtb_find_client_hostname - find client hostname of transaction index
2082  *
2083  * return: client hostname
2084  *
2085  * tran_index(in): Index of transaction
2086  */
2087 const char *
2089 {
2090  LOG_TDES *tdes;
2091 
2092  tdes = LOG_FIND_TDES (tran_index);
2093  if (tdes != NULL && tdes->trid != NULL_TRANID)
2094  {
2095  return tdes->client.get_host_name ();
2096  }
2097  return NULL;
2098 }
2099 
2100 /*
2101  * logtb_find_client_name_host_pid - find client identifiers(user_name,
2102  * host_name, host_pid) OF TRANSACTION INDEX
2103  *
2104  * return: NO_ERROR if all OK, ER_ status otherwise
2105  *
2106  * tran_index(in): Index of transaction
2107  * client_prog_name(out): Name of the client program
2108  * client_user_name(out): Name of the client user
2109  * client_host_name(out): Name of the client host
2110  * client_pid(out): Identifier of the process of the host where the client
2111  * client transaction runs.
2112  *
2113  * Note: Find the client user name, host name, and process identifier
2114  * associated with the given transaction index.
2115  *
2116  * The above pointers are valid until the client is unregister.
2117  */
2118 int
2119 logtb_find_client_name_host_pid (int tran_index, const char **client_prog_name, const char **client_user_name,
2120  const char **client_host_name, int *client_pid)
2121 {
2122  LOG_TDES *tdes; /* Transaction descriptor */
2123 
2124  tdes = LOG_FIND_TDES (tran_index);
2125 
2126  if (tdes == NULL || tdes->trid == NULL_TRANID)
2127  {
2128  // *INDENT-OFF*
2129  *client_prog_name = clientids::UNKNOWN_ID;
2130  *client_user_name = clientids::UNKNOWN_ID;
2131  *client_host_name = clientids::UNKNOWN_ID;
2132  // *INDENT-ON*
2133  *client_pid = -1;
2134  return ER_FAILED;
2135  }
2136 
2137  *client_prog_name = tdes->client.get_program_name ();
2138  *client_user_name = tdes->client.get_db_user ();
2139  *client_host_name = tdes->client.get_host_name ();
2140  *client_pid = tdes->client.process_id;
2141 
2142  return NO_ERROR;
2143 }
2144 
2145 #if defined (SERVER_MODE)
2146 /* logtb_find_client_tran_name_host_pid - same as logtb_find_client_name_host_pid, but also gets tran_index.
2147  */
2148 int
2149 logtb_find_client_tran_name_host_pid (int &tran_index, const char **client_prog_name, const char **client_user_name,
2150  const char **client_host_name, int *client_pid)
2151 {
2152  tran_index = logtb_get_current_tran_index ();
2153  return logtb_find_client_name_host_pid (tran_index, client_prog_name, client_user_name, client_host_name, client_pid);
2154 }
2155 #endif // SERVER_MODE
2156 
2157 /*
2158  * logtb_find_client_ids - find client identifiers OF TRANSACTION INDEX
2159  *
2160  * return: NO_ERROR if all OK, ER_ status otherwise
2161  *
2162  * tran_index(in): Index of transaction
2163  * client_info(out): pointer to CLIENTIDS structure
2164  *
2165  */
2166 int
2167 logtb_get_client_ids (int tran_index, CLIENTIDS * client_info)
2168 {
2169  LOG_TDES *tdes;
2170 
2171  tdes = LOG_FIND_TDES (tran_index);
2172  if (tdes == NULL || tdes->trid == NULL_TRANID)
2173  {
2174  return ER_FAILED;
2175  }
2176 
2177  *client_info = tdes->client;
2178 
2179  return NO_ERROR;
2180 }
2181 
2182 /*
2183  * xlogtb_get_pack_tran_table - return transaction info stored on transaction table
2184  *
2185  * return: NO_ERROR if all OK, ER status otherwise
2186  *
2187  * buffer_p(in/out): returned buffer poitner
2188  * size_p(in/out): returned buffer size
2189  *
2190  * Note: This is a support function which is used mainly for the
2191  * killtran utility. It returns a variety of client information
2192  * of transactions. This will be displayed by killtran so that
2193  * the user can select which transaction id needs to be aborted.
2194  *
2195  * The buffer is allocated using malloc and must be freed by the
2196  * caller.
2197  */
2198 int
2199 xlogtb_get_pack_tran_table (THREAD_ENTRY * thread_p, char **buffer_p, int *size_p, int include_query_exec_info)
2200 {
2201  int error_code = NO_ERROR;
2202  int num_clients = 0, num_clients_packed = 0;
2203  int i;
2204  int size;
2205  char *buffer, *ptr;
2206  LOG_TDES *tdes; /* Transaction descriptor */
2207  int num_total_indices;
2208 #if defined(SERVER_MODE)
2209  INT64 current_msec = 0;
2210  TRAN_QUERY_EXEC_INFO *query_exec_info = NULL;
2211  XASL_CACHE_ENTRY *ent = NULL;
2212 #endif
2213 
2214  /* Note, we'll be in a critical section while we gather the data but the section ends as soon as we return the data.
2215  * This means that the transaction table can change after the information is used. */
2216 
2217  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
2218 
2219  num_total_indices = NUM_TOTAL_TRAN_INDICES;
2220 #if defined(SERVER_MODE)
2221  if (include_query_exec_info)
2222  {
2223  query_exec_info = (TRAN_QUERY_EXEC_INFO *) calloc (num_total_indices, sizeof (TRAN_QUERY_EXEC_INFO));
2224 
2225  if (query_exec_info == NULL)
2226  {
2227  error_code = ER_OUT_OF_VIRTUAL_MEMORY;
2228  goto error;
2229  }
2230 
2231  current_msec = log_get_clock_msec ();
2232  }
2233 #endif
2234 
2235  size = OR_INT_SIZE; /* Number of client transactions */
2236 
2237  /* Find size of needed buffer */
2238  for (i = 0; i < num_total_indices; i++)
2239  {
2240  tdes = log_Gl.trantable.all_tdes[i];
2241  if (tdes == NULL || tdes->trid == NULL_TRANID || tdes->tran_index == LOG_SYSTEM_TRAN_INDEX)
2242  {
2243  /* The index is not assigned or is system transaction (no-client) */
2244  continue;
2245  }
2246 
2247  size += (3 * OR_INT_SIZE /* tran index + tran state + process id */
2249  + OR_INT_SIZE + DB_ALIGN (PATH_MAX, INT_ALIGNMENT)
2252 
2253 #if defined(SERVER_MODE)
2254  if (include_query_exec_info)
2255  {
2256  if (tdes->query_start_time > 0)
2257  {
2258  query_exec_info[i].query_time = (float) (current_msec - tdes->query_start_time) / 1000.0f;
2259  }
2260 
2261  if (tdes->tran_start_time > 0)
2262  {
2263  query_exec_info[i].tran_time = (float) (current_msec - tdes->tran_start_time) / 1000.0f;
2264  }
2265 
2266  lock_get_lock_holder_tran_index (thread_p, &query_exec_info[i].wait_for_tran_index_string, tdes->tran_index,
2267  tdes->waiting_for_res);
2268 
2269  if (!XASL_ID_IS_NULL (&tdes->xasl_id))
2270  {
2271  /* retrieve query statement in the xasl_cache entry */
2272  error_code = xcache_find_sha1 (thread_p, &tdes->xasl_id.sha1, XASL_CACHE_SEARCH_GENERIC, &ent, NULL);
2273  if (error_code != NO_ERROR)
2274  {
2275  ASSERT_ERROR ();
2276  goto error;
2277  }
2278 
2279  /* entry can be NULL, if xasl cache entry is deleted */
2280  if (ent != NULL)
2281  {
2282  if (ent->sql_info.sql_hash_text != NULL)
2283  {
2284  char *sql = ent->sql_info.sql_hash_text;
2285 
2286  if (qmgr_get_sql_id (thread_p, &query_exec_info[i].sql_id, sql, (int) strlen (sql)) != NO_ERROR)
2287  {
2288  goto error;
2289  }
2290 
2291  if (ent->sql_info.sql_user_text != NULL)
2292  {
2293  sql = ent->sql_info.sql_user_text;
2294  }
2295 
2296  /* copy query string */
2297  query_exec_info[i].query_stmt = strdup (sql);
2298  if (query_exec_info[i].query_stmt == NULL)
2299  {
2300  error_code = ER_OUT_OF_VIRTUAL_MEMORY;
2301  goto error;
2302  }
2303  }
2304  xcache_unfix (thread_p, ent);
2305  ent = NULL;
2306  }
2307 
2308  /* structure copy */
2309  XASL_ID_COPY (&query_exec_info[i].xasl_id, &tdes->xasl_id);
2310  }
2311  else
2312  {
2313  XASL_ID_SET_NULL (&query_exec_info[i].xasl_id);
2314  }
2315 
2316  size += (2 * OR_FLOAT_SIZE /* query time + tran time */
2317  + or_packed_string_length (query_exec_info[i].wait_for_tran_index_string, NULL)
2318  + or_packed_string_length (query_exec_info[i].query_stmt, NULL)
2319  + or_packed_string_length (query_exec_info[i].sql_id, NULL) + OR_XASL_ID_SIZE);
2320  }
2321 #endif
2322  num_clients++;
2323  }
2324 
2325  /* Now allocate the area and pack the information */
2326  buffer = (char *) malloc (size);
2327  if (buffer == NULL)
2328  {
2330  error_code = ER_OUT_OF_VIRTUAL_MEMORY;
2331  goto error;
2332  }
2333 
2334  ptr = buffer;
2335  ptr = or_pack_int (ptr, num_clients);
2336 
2337  /* Find size of needed buffer */
2338  for (i = 0; i < num_total_indices; i++)
2339  {
2340  tdes = log_Gl.trantable.all_tdes[i];
2341  if (tdes == NULL || tdes->trid == NULL_TRANID || tdes->tran_index == LOG_SYSTEM_TRAN_INDEX)
2342  {
2343  /* The index is not assigned or is system transaction (no-client) */
2344  continue;
2345  }
2346 
2347  ptr = or_pack_int (ptr, tdes->tran_index);
2348  ptr = or_pack_int (ptr, tdes->state);
2349  ptr = or_pack_int (ptr, tdes->client.process_id);
2350  ptr = or_pack_string_with_length (ptr, tdes->client.get_db_user (), tdes->client.db_user.size ());
2351  ptr = or_pack_string_with_length (ptr, tdes->client.get_program_name (), tdes->client.program_name.size ());
2352  ptr = or_pack_string_with_length (ptr, tdes->client.get_login_name (), tdes->client.login_name.size ());
2353  ptr = or_pack_string_with_length (ptr, tdes->client.get_host_name (), tdes->client.host_name.size ());
2354 
2355 #if defined(SERVER_MODE)
2356  if (include_query_exec_info)
2357  {
2358  ptr = or_pack_float (ptr, query_exec_info[i].query_time);
2359  ptr = or_pack_float (ptr, query_exec_info[i].tran_time);
2360  ptr = or_pack_string (ptr, query_exec_info[i].wait_for_tran_index_string);
2361  ptr = or_pack_string (ptr, query_exec_info[i].query_stmt);
2362  ptr = or_pack_string (ptr, query_exec_info[i].sql_id);
2363  OR_PACK_XASL_ID (ptr, &query_exec_info[i].xasl_id);
2364  }
2365 #endif
2366 
2367  num_clients_packed++;
2368  assert (num_clients_packed <= num_clients);
2369  assert (ptr <= buffer + size);
2370  }
2371 
2372  assert (num_clients_packed == num_clients);
2373  assert (num_total_indices == NUM_TOTAL_TRAN_INDICES);
2374  assert (ptr <= buffer + size);
2375 
2376  *buffer_p = buffer;
2377  *size_p = CAST_BUFLEN (ptr - buffer);
2378 
2379 error:
2380  TR_TABLE_CS_EXIT (thread_p);
2381 
2382 #if defined(SERVER_MODE)
2383  if (query_exec_info != NULL)
2384  {
2385  for (i = 0; i < num_total_indices; i++)
2386  {
2387  if (query_exec_info[i].wait_for_tran_index_string)
2388  {
2389  free_and_init (query_exec_info[i].wait_for_tran_index_string);
2390  }
2391  if (query_exec_info[i].query_stmt)
2392  {
2393  free_and_init (query_exec_info[i].query_stmt);
2394  }
2395  if (query_exec_info[i].sql_id)
2396  {
2397  free_and_init (query_exec_info[i].sql_id);
2398  }
2399  }
2400  free_and_init (query_exec_info);
2401  }
2402 
2403  if (ent != NULL)
2404  {
2405  xcache_unfix (thread_p, ent);
2406  }
2407 #endif
2408 
2409  return error_code;
2410 }
2411 
2412 /*
2413  * logtb_find_current_client_type - find client type of current transaction
2414  *
2415  * return: client type
2416  */
2417 int
2419 {
2421 }
2422 
2423 /*
2424  * logtb_find_current_client_name - find client name of current transaction
2425  *
2426  * return: client name
2427  */
2428 const char *
2430 {
2432 }
2433 
2434 /*
2435  * logtb_find_current_client_hostname - find client hostname of current transaction
2436  *
2437  * return: client hostname
2438  */
2439 const char *
2441 {
2443 }
2444 
2445 /*
2446  * logtb_find_current_tran_lsa - find current transaction log sequence address
2447  *
2448  * return: LOG_LSA *
2449  */
2450 LOG_LSA *
2452 {
2453  LOG_TDES *tdes; /* Transaction descriptor */
2454 
2455  tdes = LOG_FIND_CURRENT_TDES (thread_p);
2456  return ((tdes != NULL) ? &tdes->tail_lsa : NULL);
2457 }
2458 
2459 /*
2460  * logtb_find_state - find the state of the transaction
2461  *
2462  * return: TRAN_STATE
2463  *
2464  * tran_index(in): transaction index
2465  */
2466 TRAN_STATE
2467 logtb_find_state (int tran_index)
2468 {
2469  LOG_TDES *tdes; /* Transaction descriptor */
2470 
2471  tdes = LOG_FIND_TDES (tran_index);
2472  if (tdes != NULL)
2473  {
2474  return tdes->state;
2475  }
2476  else
2477  {
2478  return TRAN_UNACTIVE_UNKNOWN;
2479  }
2480 }
2481 
2482 /*
2483  * xlogtb_reset_wait_msecs - reset future waiting times
2484  *
2485  * return: The old wait_msecs.
2486  *
2487  * wait_msecs(in): Wait for at least this number of milliseconds to acquire a lock
2488  * before the transaction is timed out.
2489  * A negative value (e.g., -1) means wait forever until a lock
2490  * is granted or transaction is selected as a victim of a
2491  * deadlock.
2492  * A value of zero means do not wait at all, timeout immediately
2493  * (in milliseconds)
2494  *
2495  * Note:Reset the default waiting time for the current transaction index(client).
2496  */
2497 int
2498 xlogtb_reset_wait_msecs (THREAD_ENTRY * thread_p, int wait_msecs)
2499 {
2500  LOG_TDES *tdes; /* Transaction descriptor */
2501  int old_wait_msecs; /* The old waiting time to be returned */
2502  int tran_index;
2503 
2504  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2505  tdes = LOG_FIND_TDES (tran_index);
2506  if (tdes == NULL)
2507  {
2509  return -1;
2510  }
2511 
2512  old_wait_msecs = tdes->wait_msecs;
2513  tdes->wait_msecs = wait_msecs;
2514 
2515  return old_wait_msecs;
2516 }
2517 
2518 /*
2519  * logtb_find_wait_msecs - find waiting times for given transaction
2520  *
2521  * return: wait_msecs...
2522  *
2523  * tran_index(in): Index of transaction
2524  */
2525 int
2526 logtb_find_wait_msecs (int tran_index)
2527 {
2528  LOG_TDES *tdes; /* Transaction descriptor */
2529 
2530  tdes = LOG_FIND_TDES (tran_index);
2531  if (tdes != NULL)
2532  {
2533  return tdes->wait_msecs;
2534  }
2535  else
2536  {
2537  assert (false);
2538  return 0;
2539  }
2540 }
2541 
2542 /*
2543  * logtb_find_interrupt -
2544  *
2545  * return :
2546  *
2547  * tran_index(in):
2548  * interrupt(out):
2549  *
2550  */
2551 int
2552 logtb_find_interrupt (int tran_index, bool * interrupt)
2553 {
2554  LOG_TDES *tdes;
2555 
2556  assert (interrupt);
2557 
2558  tdes = LOG_FIND_TDES (tran_index);
2559  if (tdes == NULL || tdes->trid == NULL_TRANID)
2560  {
2561  return ER_FAILED;
2562  }
2563  else
2564  {
2565  *interrupt = tdes->interrupt ? true : false;
2566  }
2567 
2568  return NO_ERROR;
2569 }
2570 
2571 /*
2572  * logtb_find_log_records_count - find log records count for given transaction
2573  *
2574  * return: num_log_records_written...
2575  *
2576  * tran_index(in): Index of transaction
2577  */
2578 int
2580 {
2581  LOG_TDES *tdes; /* Transaction descriptor */
2582 
2583  tdes = LOG_FIND_TDES (tran_index);
2584  if (tdes != NULL)
2585  {
2586  return tdes->num_log_records_written;
2587  }
2588  else
2589  {
2590  return 0;
2591  }
2592 }
2593 
2594 /*
2595  * xlogtb_reset_isolation - reset consistency of transaction
2596  *
2597  * return: error code.
2598  *
2599  * isolation(in): New Isolation level. One of the following:
2600  * TRAN_SERIALIZABLE
2601  * TRAN_REPEATABLE_READ
2602  * TRAN_READ_COMMITTED
2603  *
2604  * Note:Reset the default isolation level for the current transaction index (client).
2605  *
2606  * Note/Warning: This function must be called when the current transaction has
2607  * not been done any work (i.e, just after restart, commit, or
2608  * abort), otherwise, its isolation behaviour will be undefined.
2609  */
2610 int
2612 {
2613  TRAN_ISOLATION old_isolation;
2614  int error_code = NO_ERROR;
2615  LOG_TDES *tdes; /* Transaction descriptor */
2616  int tran_index;
2617 
2618  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2619  tdes = LOG_FIND_TDES (tran_index);
2620 
2621  if (IS_VALID_ISOLATION_LEVEL (isolation) && tdes != NULL)
2622  {
2623  old_isolation = tdes->isolation;
2624  tdes->isolation = isolation;
2625  }
2626  else
2627  {
2630  }
2631 
2632  return error_code;
2633 }
2634 
2635 /*
2636  * logtb_find_isolation - find the isolation level for given trans
2637  *
2638  * return: isolation
2639  *
2640  * tran_index(in):Index of transaction
2641  */
2643 logtb_find_isolation (int tran_index)
2644 {
2645  LOG_TDES *tdes; /* Transaction descriptor */
2646 
2647  tdes = LOG_FIND_TDES (tran_index);
2648  if (tdes != NULL)
2649  {
2650  return tdes->isolation;
2651  }
2652  else
2653  {
2654  return TRAN_UNKNOWN_ISOLATION;
2655  }
2656 }
2657 
2658 /*
2659  * logtb_find_current_isolation - find the isolation level for current
2660  * transaction
2661  *
2662  * return: isolation...
2663  *
2664  * Note: Find the isolation level for the current transaction
2665  */
2668 {
2669  int tran_index;
2670 
2671  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2672  return logtb_find_isolation (tran_index);
2673 }
2674 
2675 /*
2676  * xlogtb_set_interrupt - indicate interrupt to a future caller of current
2677  * transaction
2678  *
2679  * return: nothing
2680  *
2681  * set(in): true for set and false for clear
2682  *
2683  * Note: Set the interrupt falg for the current execution, so that the
2684  * next caller obtains an interrupt.
2685  */
2686 void
2687 xlogtb_set_interrupt (THREAD_ENTRY * thread_p, int set)
2688 {
2689  logtb_set_tran_index_interrupt (thread_p, LOG_FIND_THREAD_TRAN_INDEX (thread_p), set);
2690 }
2691 
2692 /*
2693  * logtb_set_tran_index_interrupt - indicate interrupt to a future caller for an
2694  * specific transaction index
2695  *
2696  * return: false is returned when the tran_index is not associated
2697  * with a transaction
2698  *
2699  * tran_index(in): Transaction index
2700  * set(in): true for set and false for clear
2701  *
2702  * Note:Set the interrupt flag for the execution of the given transaction,
2703  * so that the next caller obtains an interrupt.
2704  */
2705 bool
2706 logtb_set_tran_index_interrupt (THREAD_ENTRY * thread_p, int tran_index, bool set)
2707 {
2708  LOG_TDES *tdes; /* Transaction descriptor */
2709 
2710  if (tran_index == LOG_SYSTEM_TRAN_INDEX)
2711  {
2712 #if defined (SERVER_MODE)
2713  assert (false);
2714 #endif // SERVER_MODE
2715  return false;
2716  }
2717 
2718  if (log_Gl.trantable.area != NULL)
2719  {
2720  tdes = LOG_FIND_TDES (tran_index);
2721  if (tdes != NULL && tdes->trid != NULL_TRANID)
2722  {
2723  if (tdes->interrupt != (int) set)
2724  {
2725 #if defined (HAVE_ATOMIC_BUILTINS)
2726  tdes->interrupt = (int) set;
2727  if (set == true)
2728  {
2729  ATOMIC_INC_32 (&log_Gl.trantable.num_interrupts, 1);
2730  }
2731  else
2732  {
2733  ATOMIC_INC_32 (&log_Gl.trantable.num_interrupts, -1);
2734  }
2735 #else
2736  TR_TABLE_CS_ENTER (thread_p);
2737 
2738  tdes->interrupt = set;
2739  if (set == true)
2740  {
2742  }
2743  else
2744  {
2746  }
2747 
2748  TR_TABLE_CS_EXIT (thread_p);
2749 #endif
2750  }
2751 
2752  if (set == true)
2753  {
2757  }
2758 
2759  return true;
2760  }
2761  }
2762 
2763  return false;
2764 }
2765 
2766 /*
2767  * logtb_is_interrupted_tdes -
2768  *
2769  * return:
2770  *
2771  * tdes(in/out):
2772  * clear(in/out):
2773  * continue_checking(out):
2774  *
2775  * Note:
2776  */
2777 static bool
2778 logtb_is_interrupted_tdes (THREAD_ENTRY * thread_p, LOG_TDES * tdes, bool clear, bool * continue_checking)
2779 {
2780  bool interrupt;
2781  INT64 now;
2782 #if !defined(SERVER_MODE)
2783  struct timeval tv;
2784 
2785 #else /* SERVER_MODE */
2786  /* vacuum threads should not be interruptible (unless this is still recovery). */
2788 #endif /* SERVER_MODE */
2789 
2790  interrupt = tdes->interrupt;
2791  if (!LOG_ISTRAN_ACTIVE (tdes))
2792  {
2793  interrupt = false;
2794 
2796  {
2797  *continue_checking = true;
2798  }
2799  else
2800  {
2801  *continue_checking = false;
2802  }
2803  }
2804  else if (interrupt == true && clear == true)
2805  {
2806  tdes->interrupt = false;
2807 
2808 #if !defined (HAVE_ATOMIC_BUILTINS)
2809  TR_TABLE_CS_ENTER (thread_p);
2811 #else
2812  ATOMIC_INC_32 (&log_Gl.trantable.num_interrupts, -1);
2813 #endif
2814 
2816  {
2817  *continue_checking = true;
2818  }
2819  else
2820  {
2821  *continue_checking = false;
2822  }
2823 
2824 #if !defined (HAVE_ATOMIC_BUILTINS)
2825  TR_TABLE_CS_EXIT (thread_p);
2826 #endif
2827  }
2828  else if (interrupt == false && tdes->query_timeout > 0)
2829  {
2830  /* In order to prevent performance degradation, we use log_Clock_msec set by thread_log_clock_thread instead of
2831  * calling gettimeofday here if the system supports atomic built-ins. */
2832 #if defined(SERVER_MODE)
2833  now = log_get_clock_msec ();
2834 #else /* SERVER_MODE */
2835  gettimeofday (&tv, NULL);
2836  now = (tv.tv_sec * 1000LL) + (tv.tv_usec / 1000LL);
2837 #endif /* !SERVER_MODE */
2838  if (tdes->query_timeout < now)
2839  {
2841  "logtb_is_interrupted_tdes: timeout %lld milliseconds delayed (expected=%lld, now=%lld)",
2842  now - tdes->query_timeout, tdes->query_timeout, now);
2843  interrupt = true;
2844  }
2845  }
2846  return interrupt;
2847 }
2848 
2849 /*
2850  * logtb_is_interrupted - find if execution must be stopped due to
2851  * an interrupt (^C)
2852  *
2853  * return:
2854  *
2855  * clear(in): true if the interrupt should be cleared.
2856  * continue_checking(in): Set as a side effect to true if there are more
2857  * interrupts to check or to false if there are not
2858  * more interrupts.
2859  *
2860  * Note: Find if the current execution must be stopped due to an interrupt (^C). If clear is true, the interruption flag
2861  * is cleared; This is the expected case, once someone is notified, we do not have to keep the flag on.
2862  *
2863  * If the transaction is not active, false is returned. For example, in the middle of an undo action, the
2864  * transaction will not be interrupted. The recovery manager will interrupt the transaction at the end of the undo
2865  * action... in this case the transaction will be partially aborted.
2866  */
2867 bool
2868 logtb_is_interrupted (THREAD_ENTRY * thread_p, bool clear, bool * continue_checking)
2869 {
2870  LOG_TDES *tdes; /* Transaction descriptor */
2871  int tran_index;
2872 
2873  if (log_Gl.trantable.area == NULL)
2874  {
2875  return false;
2876  }
2877  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2878  tdes = LOG_FIND_TDES (tran_index);
2879  if (tdes == NULL)
2880  {
2881  return false;
2882  }
2883 
2884  return logtb_is_interrupted_tdes (thread_p, tdes, clear, continue_checking);
2885 }
2886 
2887 /*
2888  * logtb_is_interrupted_tran - find if the execution of the given transaction
2889  * must be stopped due to an interrupt (^C)
2890  *
2891  * return:
2892  *
2893  * clear(in): true if the interrupt should be cleared.
2894  * continue_checking(in): Set as a side effect to true if there are more
2895  * interrupts to check or to false if there are not
2896  * more interrupts.
2897  * tran_index(in):
2898  *
2899  * Note: Find if the execution of the given transaction must be stopped due to an interrupt (^C). If clear is true, the
2900  * interruption flag is cleared; This is the expected case, once someone is notified, we do not have to keep the
2901  * flag on.
2902  * This function is called to see if a transaction that is waiting (e.g., suspended on a lock) on an event must
2903  * be interrupted.
2904  */
2905 bool
2906 logtb_is_interrupted_tran (THREAD_ENTRY * thread_p, bool clear, bool * continue_checking, int tran_index)
2907 {
2908  LOG_TDES *tdes; /* Transaction descriptor */
2909 
2910  tdes = LOG_FIND_TDES (tran_index);
2911  if (log_Gl.trantable.area == NULL || tdes == NULL)
2912  {
2913  return false;
2914  }
2915 
2916  return logtb_is_interrupted_tdes (thread_p, tdes, clear, continue_checking);
2917 }
2918 
2919 /*
2920  * xlogtb_set_suppress_repl_on_transaction - set or unset suppress_replication flag
2921  * on transaction descriptor
2922  *
2923  * return: nothing
2924  *
2925  * set(in): non-zero to set, zero to unset
2926  */
2927 void
2929 {
2931 }
2932 
2933 /*
2934  * logtb_set_suppress_repl_on_transaction - set or unset suppress_replication flag
2935  * on transaction descriptor
2936  *
2937  * return: false is returned when the tran_index is not associated
2938  * with a transaction
2939  *
2940  * tran_index(in): Transaction index
2941  * set(in): non-zero to set, zero to unset
2942  */
2943 bool
2944 logtb_set_suppress_repl_on_transaction (THREAD_ENTRY * thread_p, int tran_index, int set)
2945 {
2946  LOG_TDES *tdes; /* Transaction descriptor */
2947 
2948  if (log_Gl.trantable.area != NULL)
2949  {
2950  tdes = LOG_FIND_TDES (tran_index);
2951  if (tdes != NULL && tdes->trid != NULL_TRANID)
2952  {
2953  if (tdes->suppress_replication != set)
2954  {
2955  tdes->suppress_replication = set;
2956  }
2957  return true;
2958  }
2959  }
2960  return false;
2961 }
2962 
2963 
2964 /*
2965  * logtb_is_active - is transaction active ?
2966  *
2967  * return:
2968  *
2969  * trid(in): Transaction identifier
2970  *
2971  * Note: Find if given transaction is an active one. This function
2972  * execute a sequential search in the transaction table to find
2973  * out the given transaction. The function bypasses the search if
2974  * the given trid is current transaction.
2975  *
2976  * Note: The assumption of this function is that the transaction table
2977  * is not very big and that most of the time the search is
2978  * avoided. if this assumption becomes false, we may need to
2979  * define a hash table from trid to tdes to speed up the search.
2980  */
2981 bool
2983 {
2984  int i;
2985  LOG_TDES *tdes; /* Transaction descriptor */
2986  bool active = false;
2987  int tran_index;
2988 
2989  if (!LOG_ISRESTARTED ())
2990  {
2991  return false;
2992  }
2993 
2994  /* Avoid searching as much as possible */
2995  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
2996  tdes = LOG_FIND_TDES (tran_index);
2997  if (tdes != NULL && tdes->trid == trid)
2998  {
2999  active = LOG_ISTRAN_ACTIVE (tdes);
3000  }
3001  else
3002  {
3003  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
3004  /* Search the transaction table for such transaction */
3005  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
3006  {
3007  tdes = log_Gl.trantable.all_tdes[i];
3008  if (tdes != NULL && tdes->trid != NULL_TRANID && tdes->trid == trid)
3009  {
3010  active = LOG_ISTRAN_ACTIVE (tdes);
3011  break;
3012  }
3013  }
3014  TR_TABLE_CS_EXIT (thread_p);
3015  }
3016 
3017  return active;
3018 }
3019 
3020 /*
3021  * logtb_is_current_active - is current transaction active ?
3022  *
3023  * return:
3024  *
3025  * Note: Find if the current transaction is an active one.
3026  */
3027 bool
3029 {
3030  LOG_TDES *tdes; /* Transaction descriptor */
3031  int tran_index;
3032 
3033  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
3034  tdes = LOG_FIND_TDES (tran_index);
3035 
3036  if (tdes != NULL && LOG_ISTRAN_ACTIVE (tdes))
3037  {
3038  return true;
3039  }
3040  else
3041  {
3042  assert (tdes == NULL || tdes->is_active_worker_transaction ());
3043  return false;
3044  }
3045 }
3046 
3047 /*
3048  * logtb_istran_finished - is transaction finished?
3049  *
3050  * return:
3051  *
3052  * trid(in): Transaction identifier
3053  *
3054  * Note: Find if given transaction exists. That is, find if the
3055  * transaction has completely finished its execution.
3056  * Note that this function differs from log_istran_active in
3057  * that a transaction in commit or abort state is not active but
3058  * it is still alive (i.e., has not done completely).
3059  * This function execute a sequential search in the transaction
3060  * table to find out the given transaction. The function bypasses
3061  * the search if the given trid is current transaction.
3062  *
3063  * The assumption of this function is that the transaction table
3064  * is not very big and that most of the time the search is
3065  * avoided. if this assumption becomes false, we may need to
3066  * define a hash table from trid to tdes to speed up the search.
3067  */
3068 bool
3070 {
3071  int i;
3072  LOG_TDES *tdes; /* Transaction descriptor */
3073  bool active = true;
3074  int tran_index;
3075 
3076  /* Avoid searching as much as possible */
3077  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
3078  tdes = LOG_FIND_TDES (tran_index);
3079  if (tdes != NULL && tdes->trid == trid)
3080  {
3081  active = false;
3082  }
3083  else
3084  {
3085  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
3086  /* Search the transaction table for such transaction */
3087  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
3088  {
3089  tdes = log_Gl.trantable.all_tdes[i];
3090  if (tdes != NULL && tdes->trid != NULL_TRANID && tdes->trid == trid)
3091  {
3092  active = false;
3093  break;
3094  }
3095  }
3096  TR_TABLE_CS_EXIT (thread_p);
3097  }
3098 
3099  return active;
3100 }
3101 
3102 /*
3103  * logtb_has_updated - has transaction updated the database ?
3104  *
3105  * return:
3106  *
3107  */
3108 bool
3110 {
3111  LOG_TDES *tdes; /* Transaction descriptor */
3112  int tran_index;
3113 
3114  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
3115  tdes = LOG_FIND_TDES (tran_index);
3116  if (tdes != NULL && !LSA_ISNULL (&tdes->tail_lsa))
3117  {
3118  return true;
3119  }
3120  else
3121  {
3122  return false;
3123  }
3124 }
3125 
3126 /*
3127  * logtb_disable_update -
3128  * return: none
3129  */
3130 void
3132 {
3134  er_log_debug (ARG_FILE_LINE, "logtb_disable_update: db_Disable_modifications = %d\n", db_Disable_modifications);
3135 }
3136 
3137 /*
3138  * logtb_enable_update -
3139  * return: none
3140  */
3141 void
3143 {
3145  {
3147  er_log_debug (ARG_FILE_LINE, "logtb_enable_update: db_Disable_modifications = %d\n", db_Disable_modifications);
3148  }
3149 }
3150 
3151 /*
3152  * logtb_set_to_system_tran_index - set to tran index system
3153  *
3154  * return: nothing
3155  *
3156  * Note: The current log_tran_index is set to the system transaction index.
3157  */
3158 void
3160 {
3162 }
3163 
3164 /*
3165  * logtb_tran_free_update_stats () - Free logged list of update statistics.
3166  *
3167  * return : Void.
3168  * log_upd_stats (in) : List of logged update statistics records.
3169  */
3170 static void
3172 {
3173  LOG_TRAN_CLASS_COS_CHUNK *cos_chunk = NULL, *next_cos_chunk = NULL;
3174  LOG_TRAN_BTID_UNIQUE_STATS_CHUNK *stats_chunk = NULL, *next_stats_chunk = NULL;
3175 
3176  logtb_tran_clear_update_stats (log_upd_stats);
3177 
3178  /* free count optimization structure */
3179  cos_chunk = log_upd_stats->cos_first_chunk;
3180  if (cos_chunk != NULL)
3181  {
3182  for (; cos_chunk != NULL; cos_chunk = next_cos_chunk)
3183  {
3184  next_cos_chunk = cos_chunk->next_chunk;
3185  free (cos_chunk);
3186  }
3187  log_upd_stats->cos_first_chunk = NULL;
3188  log_upd_stats->cos_current_chunk = NULL;
3189  log_upd_stats->cos_count = 0;
3190  }
3191  if (log_upd_stats->classes_cos_hash != NULL)
3192  {
3193  mht_destroy (log_upd_stats->classes_cos_hash);
3194  log_upd_stats->classes_cos_hash = NULL;
3195  }
3196 
3197  /* free unique statistics structure */
3198  stats_chunk = log_upd_stats->stats_first_chunk;
3199  if (stats_chunk != NULL)
3200  {
3201  for (; stats_chunk != NULL; stats_chunk = next_stats_chunk)
3202  {
3203  next_stats_chunk = stats_chunk->next_chunk;
3204  free (stats_chunk);
3205  }
3206  log_upd_stats->stats_first_chunk = NULL;
3207  log_upd_stats->stats_current_chunk = NULL;
3208  log_upd_stats->stats_count = 0;
3209  }
3210  if (log_upd_stats->unique_stats_hash != NULL)
3211  {
3212  mht_destroy (log_upd_stats->unique_stats_hash);
3213  log_upd_stats->unique_stats_hash = NULL;
3214  }
3215 }
3216 
3217 /*
3218  * logtb_tran_clear_update_stats () - Clear logged update statistics.
3219  * Entries are not actually freed, they are
3220  * appended to a list of free entries ready
3221  * to be reused.
3222  *
3223  * return : Void.
3224  * log_upd_stats (in) : Pointer to update statistics log.
3225  */
3226 static void
3228 {
3229  /* clear count optimization structure */
3230  log_upd_stats->cos_current_chunk = log_upd_stats->cos_first_chunk;
3231  log_upd_stats->cos_count = 0;
3232  if (log_upd_stats->classes_cos_hash != NULL)
3233  {
3234  mht_clear (log_upd_stats->classes_cos_hash, NULL, NULL);
3235  }
3236 
3237  /* clear unique statistics structure */
3238  log_upd_stats->stats_current_chunk = log_upd_stats->stats_first_chunk;
3239  log_upd_stats->stats_count = 0;
3240  if (log_upd_stats->unique_stats_hash != NULL)
3241  {
3242  mht_clear (log_upd_stats->unique_stats_hash, NULL, NULL);
3243  }
3244 }
3245 
3246 /*
3247  * logtb_tran_btid_hash_func() - Hash function for BTIDs
3248  * return: hash value
3249  * key(in): BTID to hash
3250  * ht_size(in): Size of hash table
3251  */
3252 static unsigned int
3253 logtb_tran_btid_hash_func (const void *key, const unsigned int ht_size)
3254 {
3255  return ((BTID *) key)->vfid.fileid % ht_size;
3256 }
3257 
3258 /*
3259  * logtb_tran_btid_hash_func() - Comparison function for BTIDs (equal or not)
3260  * return: 0 not equal, 1 otherwise
3261  * key1(in): left key
3262  * key2(in): right key
3263  */
3264 static int
3265 logtb_tran_btid_hash_cmp_func (const void *key1, const void *key2)
3266 {
3267  return BTID_IS_EQUAL ((BTID *) key1, (BTID *) key2);
3268 }
3269 
3270 /*
3271  * logtb_tran_create_btid_unique_stats () - allocates memory and initializes
3272  * statistics associated with btid
3273  *
3274  * return : The address of newly created statistics structure or NULL
3275  * in case of error.
3276  * thread_p(in) :
3277  * btid (in) : Id of unique index for which the statistics will be
3278  * created
3279  */
3282 {
3283  LOG_TRAN_BTID_UNIQUE_STATS *unique_stats = NULL;
3284  LOG_TDES *tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
3285 
3286  if (btid == NULL)
3287  {
3288  assert (false);
3289  return NULL;
3290  }
3291 
3293  {
3295 
3298  {
3299  /* reuse the old chunk */
3301  }
3302  else
3303  {
3304  /* if the entire allocated space was exhausted then alloc a new chunk */
3305  int size =
3307  1) * sizeof (LOG_TRAN_BTID_UNIQUE_STATS);
3308  chunk = (LOG_TRAN_BTID_UNIQUE_STATS_CHUNK *) malloc (size);
3309 
3310  if (chunk == NULL)
3311  {
3313  return NULL;
3314  }
3315  if (tdes->log_upd_stats.stats_first_chunk == NULL)
3316  {
3317  tdes->log_upd_stats.stats_first_chunk = chunk;
3318  }
3319  else
3320  {
3322  }
3323  chunk->next_chunk = NULL;
3324  }
3325  tdes->log_upd_stats.stats_current_chunk = chunk;
3326  }
3327 
3328  /* get a new entry */
3329  unique_stats =
3331 
3332  BTID_COPY (&unique_stats->btid, btid);
3333  unique_stats->deleted = false;
3334 
3335  /* init transaction local statistics */
3336  unique_stats->tran_stats.num_keys = 0;
3337  unique_stats->tran_stats.num_oids = 0;
3338  unique_stats->tran_stats.num_nulls = 0;
3339 
3340  /* init global statistics */
3341  unique_stats->global_stats.num_keys = -1;
3342  unique_stats->global_stats.num_oids = -1;
3343  unique_stats->global_stats.num_nulls = -1;
3344 
3345  /* Store the new entry in hash */
3346  if (mht_put (tdes->log_upd_stats.unique_stats_hash, &unique_stats->btid, unique_stats) == NULL)
3347  {
3348  return NULL;
3349  }
3350 
3351  return unique_stats;
3352 }
3353 
3354 /*
3355  * logtb_tran_create_class_cos () - creates a new count optimization state entry
3356  * for a class
3357  *
3358  * return : return the adddress of newly created entry
3359  * thread_p(in) :
3360  * class_oid (in) : OID of the class for which the entry will be created
3361  */
3362 static LOG_TRAN_CLASS_COS *
3363 logtb_tran_create_class_cos (THREAD_ENTRY * thread_p, const OID * class_oid)
3364 {
3365  LOG_TDES *tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
3366  LOG_TRAN_CLASS_COS *entry = NULL;
3367 
3369  {
3370  LOG_TRAN_CLASS_COS_CHUNK *chunk = NULL;
3372  {
3373  /* reuse the old chunk */
3375  }
3376  else
3377  {
3378  /* if the entire allocated space was exhausted then alloc a new chunk */
3379  int size = sizeof (LOG_TRAN_CLASS_COS_CHUNK) + (COS_CLASSES_CHUNK_SIZE - 1) * sizeof (LOG_TRAN_CLASS_COS);
3380  chunk = (LOG_TRAN_CLASS_COS_CHUNK *) malloc (size);
3381 
3382  if (chunk == NULL)
3383  {
3385  return NULL;
3386  }
3387  if (tdes->log_upd_stats.cos_first_chunk == NULL)
3388  {
3389  tdes->log_upd_stats.cos_first_chunk = chunk;
3390  }
3391  else
3392  {
3394  }
3395  chunk->next_chunk = NULL;
3396  }
3397  tdes->log_upd_stats.cos_current_chunk = chunk;
3398  }
3399 
3400  /* get a new entry */
3402 
3403  /* init newly created entry */
3404  COPY_OID (&entry->class_oid, class_oid);
3405  entry->count_state = COS_NOT_LOADED;
3406 
3407  if (mht_put (tdes->log_upd_stats.classes_cos_hash, &entry->class_oid, entry) == NULL)
3408  {
3409  return NULL;
3410  }
3411 
3412  return entry;
3413 }
3414 
3415 /*
3416  * logtb_tran_find_class_cos () - searches the hash of count optimization states
3417  * for a specific class oid
3418  *
3419  * return : address of found (or newly created) entry or null
3420  * otherwise
3421  * thread_p(in) :
3422  * class_oid (in) : OID of the class for which the entry will be created
3423  * create(in) : true if the caller needs a new entry to be created if not
3424  * found an already existing one
3425  */
3427 logtb_tran_find_class_cos (THREAD_ENTRY * thread_p, const OID * class_oid, bool create)
3428 {
3429  LOG_TDES *tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
3430  LOG_TRAN_CLASS_COS *entry = NULL;
3431 
3432  assert (tdes != NULL && class_oid != NULL);
3433 
3434  /* search */
3435  entry = (LOG_TRAN_CLASS_COS *) mht_get (tdes->log_upd_stats.classes_cos_hash, class_oid);
3436 
3437  if (entry == NULL && create)
3438  {
3439  /* create if not found */
3440  entry = logtb_tran_create_class_cos (thread_p, class_oid);
3441  }
3442 
3443  return entry;
3444 }
3445 
3446 /*
3447  * logtb_tran_find_btid_stats () - searches the hash of statistics for a
3448  * specific index.
3449  *
3450  * return : address of found (or newly created) statistics or null
3451  * otherwise
3452  * thread_p(in) :
3453  * btid (in) : index id to be searched
3454  * create(in) : true if the caller needs a new entry to be created if not
3455  * found an already existing one
3456  */
3458 logtb_tran_find_btid_stats (THREAD_ENTRY * thread_p, const BTID * btid, bool create)
3459 {
3460  LOG_TRAN_BTID_UNIQUE_STATS *unique_stats = NULL;
3461  LOG_TDES *tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
3462 
3463  if (btid == NULL)
3464  {
3465  return NULL;
3466  }
3467 
3468  /* search */
3469  unique_stats = (LOG_TRAN_BTID_UNIQUE_STATS *) mht_get (tdes->log_upd_stats.unique_stats_hash, btid);
3470 
3471  if (unique_stats == NULL && create)
3472  {
3473  /* create if not found */
3474  unique_stats = logtb_tran_create_btid_unique_stats (thread_p, btid);
3475  }
3476 
3477  return unique_stats;
3478 }
3479 
3480 /*
3481  * logtb_tran_update_btid_unique_stats () - updates statistics associated with
3482  * the given btid
3483  *
3484  * return : error code or NO_ERROR
3485  * thread_p(in) :
3486  * btid (in) : index id to be searched
3487  * n_keys(in) : number of keys to be added to statistics
3488  * n_oids(in) : number of oids to be added to statistics
3489  * n_nulls(in) : number of nulls to be added to statistics
3490  *
3491  * Note: the statistics are searched and created if they not exist.
3492  */
3493 int
3494 logtb_tran_update_btid_unique_stats (THREAD_ENTRY * thread_p, const BTID * btid, int n_keys, int n_oids, int n_nulls)
3495 {
3496  /* search and create if not found */
3497  LOG_TRAN_BTID_UNIQUE_STATS *unique_stats = logtb_tran_find_btid_stats (thread_p, btid, true);
3498 
3499  if (unique_stats == NULL)
3500  {
3501  return ER_FAILED;
3502  }
3503 
3504  /* update statistics */
3505  unique_stats->tran_stats.num_keys += n_keys;
3506  unique_stats->tran_stats.num_oids += n_oids;
3507  unique_stats->tran_stats.num_nulls += n_nulls;
3508 
3509  return NO_ERROR;
3510 }
3511 
3512 /*
3513  * logtb_tran_update_unique_stats () - updates statistics associated with
3514  * the given class and btid
3515  *
3516  * return : error code or NO_ERROR
3517  * thread_p(in) :
3518  * btid (in) : B-tree id to be searched
3519  * n_keys(in) : number of keys to be added to statistics
3520  * n_oids(in) : number of oids to be added to statistics
3521  * n_nulls(in) : number of nulls to be added to statistics
3522  * write_to_log : if true then new statistics wil be written to log
3523  *
3524  * Note: the statistics are searched and created if they not exist.
3525  */
3526 int
3527 logtb_tran_update_unique_stats (THREAD_ENTRY * thread_p, const BTID * btid, int n_keys, int n_oids, int n_nulls,
3528  bool write_to_log)
3529 {
3530  int error = NO_ERROR;
3531 
3532  /* update statistics */
3533  error = logtb_tran_update_btid_unique_stats (thread_p, btid, n_keys, n_oids, n_nulls);
3534  if (error != NO_ERROR)
3535  {
3536  return error;
3537  }
3538 
3539  if (write_to_log)
3540  {
3541  /* log statistics */
3542  char undo_rec_buf[3 * OR_INT_SIZE + OR_BTID_ALIGNED_SIZE + MAX_ALIGNMENT];
3543  char redo_rec_buf[3 * OR_INT_SIZE + OR_BTID_ALIGNED_SIZE + MAX_ALIGNMENT];
3544  RECDES undo_rec, redo_rec;
3545 
3546  undo_rec.area_size = ((3 * OR_INT_SIZE) + OR_BTID_ALIGNED_SIZE);
3547  undo_rec.data = PTR_ALIGN (undo_rec_buf, MAX_ALIGNMENT);
3548 
3549  redo_rec.area_size = ((3 * OR_INT_SIZE) + OR_BTID_ALIGNED_SIZE);
3550  redo_rec.data = PTR_ALIGN (redo_rec_buf, MAX_ALIGNMENT);
3551 
3552  btree_rv_mvcc_save_increments (btid, -n_keys, -n_oids, -n_nulls, &undo_rec);
3553 
3554  /* todo: remove me. redo has no use */
3555  /*btree_rv_mvcc_save_increments (btid, n_keys, n_oids, n_nulls, &redo_rec);
3556 
3557  log_append_undoredo_data2 (thread_p, RVBT_MVCC_INCREMENTS_UPD, NULL, NULL, -1, undo_rec.length, redo_rec.length,
3558  undo_rec.data, redo_rec.data); */
3560  undo_rec.data);
3561  }
3562 
3563  return error;
3564 }
3565 
3566 // *INDENT-OFF*
3567 int
3569  bool write_to_log)
3570 {
3571  if (ustats.is_zero ())
3572  {
3573  return NO_ERROR;
3574  }
3575  return logtb_tran_update_unique_stats (thread_p, &btid, (int) ustats.get_key_count (), (int) ustats.get_row_count (),
3576  (int) ustats.get_null_count (), write_to_log);
3577 }
3578 
3579 int
3580 logtb_tran_update_unique_stats (THREAD_ENTRY * thread_p, const multi_index_unique_stats &multi_stats, bool write_to_log)
3581 {
3582  int error = NO_ERROR;
3583  for (const auto &it : multi_stats.get_map ())
3584  {
3585  error = logtb_tran_update_unique_stats (thread_p, it.first, it.second, write_to_log);
3586  if (error != NO_ERROR)
3587  {
3588  ASSERT_ERROR ();
3589  return error;
3590  }
3591  }
3592  return NO_ERROR;
3593 }
3594 // *INDENT-ON*
3595 
3596 /*
3597  * logtb_tran_update_delta_hash_func () - updates statistics associated with
3598  * the given btid by local statistics
3599  *
3600  * return : error code or NO_ERROR
3601  * thread_p(in) :
3602  * data(in) : unique statistics
3603  * args(in) : not used
3604  *
3605  * Note: This is a function that is called for each element during the hash
3606  * iteration.
3607  */
3608 static int
3609 logtb_tran_update_delta_hash_func (THREAD_ENTRY * thread_p, void *data, void *args)
3610 {
3611  LOG_TRAN_BTID_UNIQUE_STATS *unique_stats = (LOG_TRAN_BTID_UNIQUE_STATS *) data;
3612  int error_code = NO_ERROR;
3613 
3614  if (unique_stats->deleted)
3615  {
3616  /* ignore if deleted */
3617  return NO_ERROR;
3618  }
3619 
3620  error_code =
3621  logtb_update_global_unique_stats_by_delta (thread_p, &unique_stats->btid, unique_stats->tran_stats.num_oids,
3622  unique_stats->tran_stats.num_nulls, unique_stats->tran_stats.num_keys,
3623  true);
3624 
3625  return error_code;
3626 }
3627 
3628 /*
3629  * logtb_tran_update_all_global_unique_stats () - update global statistics
3630  * by local statistics for all
3631  * indexes found in transaction's
3632  * unique statistics hash
3633  *
3634  * return : error code or NO_ERROR
3635  * thread_p(in) :
3636  *
3637  * Note: this function must be called at the end of transaction (commit)
3638  */
3639 int
3641 {
3642  LOG_TDES *tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
3643  int error_code = NO_ERROR;
3644  bool old_check_interrupt;
3645 
3646  if (tdes == NULL)
3647  {
3648  return ER_FAILED;
3649  }
3650 
3651  /* We have to disable interrupt while reflecting unique stats. Please notice that the transaction is still in
3652  * TRAN_ACTIVE state and it may be previously interrupted but user eventually issues commit. The transaction should
3653  * successfully complete commit in spite of interrupt. */
3654  old_check_interrupt = logtb_set_check_interrupt (thread_p, false);
3655 
3656  error_code =
3658 
3659  (void) logtb_set_check_interrupt (thread_p, old_check_interrupt);
3660 
3661  return error_code;
3662 }
3663 
3664 /*
3665  * logtb_tran_load_global_stats_func () - load global statistics into the
3666  * current transaction for a given class.
3667  *
3668  * return : error code or NO_ERROR
3669  * thread_p(in) :
3670  * data(in) : count optimization state entry
3671  * args(in) : not used
3672  *
3673  * Note: This function is called for each element of the count optimization
3674  * states hash. If the statistics were successfully loaded then set state
3675  * to COS_LOADED. In case of a partitioned class, statistics for each
3676  * partition are loaded.
3677  */
3678 static int
3679 logtb_tran_load_global_stats_func (THREAD_ENTRY * thread_p, void *data, void *args)
3680 {
3681  int error_code = NO_ERROR, idx;
3682  PRUNING_CONTEXT context;
3683  LOG_TRAN_CLASS_COS *entry = NULL, *new_entry = NULL;
3684  OR_CLASSREP *classrepr = NULL;
3685  int classrepr_cacheindex = -1;
3686  bool clear_pcontext = false;
3687 
3688  entry = (LOG_TRAN_CLASS_COS *) data;
3689  if (entry->count_state != COS_TO_LOAD)
3690  {
3691  return NO_ERROR;
3692  }
3693 
3694  /* get class representation to find partition information */
3695  classrepr = heap_classrepr_get (thread_p, &entry->class_oid, NULL, NULL_REPRID, &classrepr_cacheindex);
3696  if (classrepr == NULL)
3697  {
3698  goto cleanup;
3699  }
3700 
3701  if (classrepr->has_partition_info > 0)
3702  {
3703  partition_init_pruning_context (&context);
3704  clear_pcontext = true;
3705 
3706  /* In case of partitioned class load statistics for each partition */
3707  error_code = partition_load_pruning_context (thread_p, &entry->class_oid, DB_PARTITIONED_CLASS, &context);
3708  if (error_code != NO_ERROR)
3709  {
3710  goto cleanup;
3711  }
3712  }
3713 
3714  if (classrepr->has_partition_info > 0 && context.count > 0)
3715  {
3716  for (idx = 0; idx < context.count; idx++)
3717  {
3718  if (OID_ISNULL (&context.partitions[idx].class_oid))
3719  {
3720  continue;
3721  }
3722  new_entry = logtb_tran_find_class_cos (thread_p, &context.partitions[idx].class_oid, true);
3723  if (new_entry == NULL)
3724  {
3725  error_code = ER_FAILED;
3726  goto cleanup;
3727  }
3728 
3729  error_code = logtb_create_unique_stats_from_repr (thread_p, &entry->class_oid);
3730  if (error_code != NO_ERROR)
3731  {
3732  goto cleanup;
3733  }
3734 
3735  new_entry->count_state = COS_LOADED;
3736  }
3737  }
3738 
3739  error_code = logtb_create_unique_stats_from_repr (thread_p, &entry->class_oid);
3740  if (error_code != NO_ERROR)
3741  {
3742  goto cleanup;
3743  }
3744 
3745  entry->count_state = COS_LOADED;
3746 
3747 cleanup:
3748  if (clear_pcontext == true)
3749  {
3751  }
3752  if (classrepr != NULL)
3753  {
3754  heap_classrepr_free_and_init (classrepr, &classrepr_cacheindex);
3755  }
3756 
3757  return error_code;
3758 }
3759 
3760 /*
3761  * logtb_load_global_statistics_to_tran () - load global statistics into the
3762  * current transaction for all classes
3763  * with COS_TO_LOAD count optimization
3764  * state.
3765  *
3766  * return : error code or NO_ERROR
3767  * thread_p(in) :
3768  *
3769  * Note: The statistics will be loaded only for classes that have COS_TO_LOAD
3770  * count optimization state. This function is used when a snapshot is
3771  * taken.
3772  */
3773 static int
3775 {
3776  int error_code = NO_ERROR;
3777  LOG_TDES *tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
3778 
3779  if (tdes == NULL)
3780  {
3781  return ER_FAILED;
3782  }
3783 
3784  error_code =
3786  if (error_code != NO_ERROR)
3787  {
3788  return error_code;
3789  }
3790 
3791  return error_code;
3792 }
3793 
3794 /*
3795  * logtb_invalidate_snapshot_data () - Make sure MVCC is invalidated.
3796  *
3797  * return : Void.
3798  * thread_p (in) : Thread entry.
3799  */
3800 int
3802 {
3803  /* Get transaction descriptor */
3804  LOG_TDES *tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
3805 
3806  if (tdes == NULL || tdes->isolation >= TRAN_REPEATABLE_READ)
3807  {
3808  /* Nothing to do */
3809  return NO_ERROR;
3810  }
3811 
3812  if (tdes->mvccinfo.snapshot.valid)
3813  {
3814  /* Invalidate snapshot */
3815  tdes->mvccinfo.snapshot.valid = false;
3817  }
3818 
3819  return NO_ERROR;
3820 }
3821 
3822 /*
3823  * xlogtb_get_mvcc_snapshot () - Make sure snapshot is generated.
3824  *
3825  * return : Void.
3826  * thread_p (in) : Thread entry.
3827  */
3828 int
3830 {
3831  /* Get transaction descriptor */
3832  MVCC_SNAPSHOT *snapshot = logtb_get_mvcc_snapshot (thread_p);
3833  int error_code = NO_ERROR;
3834 
3835  if (snapshot == NULL)
3836  {
3837  ASSERT_ERROR_AND_SET (error_code);
3838  }
3839  return error_code;
3840 }
3841 
3842 /*
3843  * logtb_find_current_mvccid - find current transaction MVCC id
3844  *
3845  * return: MVCCID
3846  *
3847  * thread_p(in):
3848  */
3849 MVCCID
3851 {
3852  LOG_TDES *tdes;
3853  MVCCID id = MVCCID_NULL;
3854 
3855  tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
3856  if (tdes != NULL)
3857  {
3858  if (!tdes->mvccinfo.sub_ids.empty ())
3859  {
3860  id = tdes->mvccinfo.sub_ids.back ();
3861  }
3862  else
3863  {
3864  id = tdes->mvccinfo.id;
3865  }
3866  }
3867 
3868  return id;
3869 }
3870 
3871 /*
3872  * logtb_get_current_mvccid - return current transaction MVCC id. Assign
3873  * a new ID if not previously set.
3874  *
3875  * return: current MVCCID
3876  *
3877  * thread_p(in):
3878  */
3879 MVCCID
3881 {
3882  LOG_TDES *tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
3883  MVCC_INFO *curr_mvcc_info = &tdes->mvccinfo;
3884 
3885 #if defined (SA_MODE)
3886  /* We shouldn't be here */
3887  assert (false);
3888 #endif /* SA_MODE */
3889  assert (tdes != NULL && curr_mvcc_info != NULL);
3890 
3891  if (MVCCID_IS_VALID (curr_mvcc_info->id) == false)
3892  {
3893  curr_mvcc_info->id = log_Gl.mvcc_table.get_new_mvccid ();
3894  }
3895 
3896  if (!tdes->mvccinfo.sub_ids.empty ())
3897  {
3898  return tdes->mvccinfo.sub_ids.back ();
3899  }
3900 
3901  return curr_mvcc_info->id;
3902 }
3903 
3904 /*
3905  * logtb_is_current_mvccid - check whether given mvccid is current mvccid
3906  *
3907  * return: bool
3908  *
3909  * thread_p(in): thread entry
3910  * mvccid(in): MVCC id
3911  */
3912 bool
3914 {
3915  LOG_TDES *tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
3916  MVCC_INFO *curr_mvcc_info;
3917 
3918  assert (tdes != NULL);
3919 
3920  curr_mvcc_info = &tdes->mvccinfo;
3921  if (curr_mvcc_info->id == mvccid)
3922  {
3923  return true;
3924  }
3925  else if (curr_mvcc_info->sub_ids.size () > 0)
3926  {
3927  for (size_t i = 0; i < curr_mvcc_info->sub_ids.size (); i++)
3928  {
3929  if (curr_mvcc_info->sub_ids[i] == mvccid)
3930  {
3931  return true;
3932  }
3933  }
3934  }
3935 
3936  return false;
3937 }
3938 
3939 /*
3940  * logtb_get_mvcc_snapshot - get MVCC snapshot
3941  *
3942  * return: MVCC snapshot
3943  *
3944  * thread_p(in): thread entry
3945  */
3946 MVCC_SNAPSHOT *
3948 {
3949  LOG_TDES *tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
3950 
3951  if (!tdes->is_active_worker_transaction ())
3952  {
3953  /* System transactions do not have snapshots */
3954  return NULL;
3955  }
3956 
3957  assert (tdes != NULL);
3958 
3959  if (!tdes->mvccinfo.snapshot.valid)
3960  {
3962  }
3963 
3964  return &tdes->mvccinfo.snapshot;
3965 
3966 }
3967 
3968 /*
3969  * logtb_complete_mvcc () - Called at commit or rollback, completes MVCC info
3970  * for current transaction.
3971  *
3972  * return : Void.
3973  * thread_p (in) : Thread entry.
3974  * tdes (in) : Transaction descriptor.
3975  * committed (in) : True if transaction was committed false if it was aborted.
3976  */
3977 void
3978 logtb_complete_mvcc (THREAD_ENTRY * thread_p, LOG_TDES * tdes, bool committed)
3979 {
3980  MVCC_INFO *curr_mvcc_info = NULL;
3981  mvcctable *mvcc_table = &log_Gl.mvcc_table;
3982  MVCC_SNAPSHOT *p_mvcc_snapshot = NULL;
3983  MVCCID mvccid;
3984  int tran_index;
3985  TSC_TICKS start_tick, end_tick;
3986  TSCTIMEVAL tv_diff;
3987  UINT64 tran_complete_time;
3988  bool is_perf_tracking = false;
3989 
3990  assert (tdes != NULL);
3991 
3992  is_perf_tracking = perfmon_is_perf_tracking ();
3993  if (is_perf_tracking)
3994  {
3995  tsc_getticks (&start_tick);
3996  }
3997 
3998  curr_mvcc_info = &tdes->mvccinfo;
3999  mvccid = curr_mvcc_info->id;
4000 
4001  tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p);
4002 
4003  if (MVCCID_IS_VALID (mvccid))
4004  {
4005  mvcc_table->complete_mvcc (tran_index, mvccid, committed);
4006  }
4007  else
4008  {
4009 #if defined(SA_MODE)
4010  if (committed && logtb_tran_update_all_global_unique_stats (thread_p) != NO_ERROR)
4011  {
4012  assert (false);
4013  }
4014 #else /* !SA_MODE */ /* SERVER_MODE */
4015  if (committed)
4016  {
4017  /* There is one unique index that can be modified with no MVCCID being generated: db_serial primary key. This
4018  * could happen in a transaction that only does a create serial and commits. Next code makes sure serial
4019  * index statistics are reflected. */
4020  BTID serial_index_btid = BTID_INITIALIZER;
4021  LOG_TRAN_BTID_UNIQUE_STATS *serial_unique_stats = NULL;
4022 
4023  /* Get serial index BTID. */
4024  serial_get_index_btid (&serial_index_btid);
4025  assert (!BTID_IS_NULL (&serial_index_btid));
4026 
4027  /* Get statistics for serial unique index. */
4028  serial_unique_stats = logtb_tran_find_btid_stats (thread_p, &serial_index_btid, false);
4029  if (serial_unique_stats != NULL)
4030  {
4031  /* Reflect serial unique statistics. */
4032  if (logtb_update_global_unique_stats_by_delta (thread_p, &serial_index_btid,
4033  serial_unique_stats->tran_stats.num_oids,
4034  serial_unique_stats->tran_stats.num_nulls,
4035  serial_unique_stats->tran_stats.num_keys,
4036  true) != NO_ERROR)
4037  {
4038  /* No errors are permitted here. */
4039  assert (false);
4040 
4041  /* Fall through to do everything we would do in case of no error. */
4042  }
4043  }
4044  }
4045 #endif /* SERVER_MODE */
4046 
4047  /* atomic set transaction lowest active MVCCID */
4049  }
4050 
4052 
4053  p_mvcc_snapshot = &(curr_mvcc_info->snapshot);
4054  if (p_mvcc_snapshot->valid)
4055  {
4057  }
4058 
4059  curr_mvcc_info->reset ();
4060 
4062 
4063  if (is_perf_tracking)
4064  {
4065  tsc_getticks (&end_tick);
4066  tsc_elapsed_time_usec (&tv_diff, end_tick, start_tick);
4067  tran_complete_time = tv_diff.tv_sec * 1000000LL + tv_diff.tv_usec;
4068  if (tran_complete_time > 0)
4069  {
4070  perfmon_add_stat (thread_p, PSTAT_LOG_TRAN_COMPLETE_TIME_COUNTERS, tran_complete_time);
4071  }
4072  }
4073 }
4074 
4075 /*
4076  * logtb_set_loose_end_tdes -
4077  *
4078  * return:
4079  *
4080  * tdes(in/out):
4081  *
4082  * Note:
4083  */
4084 static void
4086 {
4087  if (LOG_ISTRAN_2PC_PREPARE (tdes))
4088  {
4089  tdes->isloose_end = true;
4091 #if !defined(NDEBUG)
4093  {
4094  fprintf (stdout,
4095  "\n*** Transaction = %d (index = %d) is prepared to commit as gobal tran = %d\n"
4096  " The coordinator site (maybe the client user = %s) needs to attach\n"
4097  " to this transaction and either commit or abort it. ***\n", tdes->trid, tdes->tran_index,
4098  tdes->gtrid, tdes->client.get_db_user ());
4099  fflush (stdout);
4100  }
4101 #endif
4102  }
4104  {
4105  tdes->isloose_end = true;
4107 #if !defined(NDEBUG)
4109  {
4110  fprintf (stdout,
4111  "\n*** Transaction = %d (index = %d) needs to complete informing participants\n"
4112  " about its fate = %s and collect participant acknowledgements.\n"
4113  " This transaction has been disassociated from the client user = %s.\n"
4114  " The transaction will be completely finished by the system ***\n", tdes->trid,
4115  tdes->tran_index, ((LOG_ISTRAN_COMMITTED (tdes)) ? "COMMIT" : "ABORT"), tdes->client.get_db_user ());
4116  fflush (stdout);
4117  }
4118 #endif
4119  }
4120 }
4121 
4122 /*
4123  * logtb_set_num_loose_end_trans - set the number of loose end transactions
4124  *
4125  * return: num loose ends
4126  *
4127  * Note: The number of loose ends transactions is set by searching the
4128  * transaction table.
4129  */
4130 int
4132 {
4133  int i;
4134  int r;
4135  LOG_TDES *tdes; /* Transaction descriptor */
4136 
4137  TR_TABLE_CS_ENTER (thread_p);
4138 
4141 
4142  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
4143  {
4144  if (i != LOG_SYSTEM_TRAN_INDEX)
4145  {
4146  tdes = log_Gl.trantable.all_tdes[i];
4147  if (tdes != NULL && tdes->trid != NULL_TRANID)
4148  {
4149  logtb_set_loose_end_tdes (tdes);
4150  }
4151  }
4152  }
4153 
4155 
4156  TR_TABLE_CS_EXIT (thread_p);
4157 
4158  return r;
4159 }
4160 
4161 /*
4162  * log_find_unilaterally_largest_undo_lsa - find maximum lsa address to undo
4163  *
4164  * return:
4165  *
4166  * Note: Find the maximum log sequence address to undo during the undo
4167  * crash recovery phase.
4168  */
4169 void
4171 {
4172  // *INDENT-OFF*
4173  int i;
4174  LOG_TDES *tdes; /* Transaction descriptor */
4175 
4176  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
4177 
4178  LSA_SET_NULL (&max_undo_lsa);
4179 
4180  auto max_undo_lsa_func = [&] (log_tdes & tdes)
4181  {
4182  if (LSA_LT (&max_undo_lsa, &tdes.undo_nxlsa))
4183  {
4184  max_undo_lsa = tdes.undo_nxlsa;
4185  }
4186  };
4187 
4188  /* Check active transactions. */
4189  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
4190  {
4191  if (i != LOG_SYSTEM_TRAN_INDEX)
4192  {
4193  tdes = log_Gl.trantable.all_tdes[i];
4194  if (tdes != NULL && tdes->trid != NULL_TRANID
4196  {
4197  max_undo_lsa_func (*tdes);
4198  }
4199  }
4200  }
4201  /* Check system worker transactions. */
4202  log_system_tdes::map_all_tdes (max_undo_lsa_func);
4203 
4204  TR_TABLE_CS_EXIT (thread_p);
4205  // *INDENT-ON*
4206 }
4207 
4208 /*
4209  * logtb_find_smallest_lsa - smallest lsa address of all active transactions
4210  *
4211  * return:
4212  *
4213  * lsa(in):
4214  *
4215  */
4216 void
4218 {
4219  int i;
4220  LOG_TDES *tdes; /* Transaction descriptor */
4221  LOG_LSA *min_lsa = NULL; /* The smallest lsa value */
4222 
4223  LSA_SET_NULL (lsa);
4224 
4225  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
4226 
4227  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
4228  {
4229  if (i != LOG_SYSTEM_TRAN_INDEX)
4230  {
4231  tdes = log_Gl.trantable.all_tdes[i];
4232 
4233  if (tdes != NULL && tdes->trid != NULL_TRANID && !LSA_ISNULL (&tdes->head_lsa)
4234  && (min_lsa == NULL || LSA_LT (&tdes->head_lsa, min_lsa)))
4235  {
4236  min_lsa = &tdes->head_lsa;
4237  }
4238  }
4239  }
4240 
4241  if (min_lsa != NULL)
4242  {
4243  LSA_COPY (lsa, min_lsa);
4244  }
4245 
4246  TR_TABLE_CS_EXIT (thread_p);
4247 }
4248 
4249 /*
4250  * logtb_tran_prepare_count_optim_classes - prepare classes for count
4251  * optimization (for unique statistics
4252  * loading)
4253  *
4254  * return: error code
4255  *
4256  * thread_p(in): thread entry
4257  * classes(in): classes names list
4258  * flags(in): flags associated with class names
4259  * n_classes(in): number of classes names
4260  *
4261  * Note: This function is called at prefetch request. It receives a list of
4262  * classes and for each class the COS_TO_LOAD flag will be set if the
4263  * statistics were not already loaded. The statistics will be loaded at
4264  * snapshot.
4265  */
4266 int
4267 logtb_tran_prepare_count_optim_classes (THREAD_ENTRY * thread_p, const char **classes, LC_PREFETCH_FLAGS * flags,
4268  int n_classes)
4269 {
4270  int idx;
4271  OID class_oid;
4272  LC_FIND_CLASSNAME find;
4273  LOG_TRAN_CLASS_COS *class_cos = NULL;
4274 
4275  for (idx = n_classes - 1; idx >= 0; idx--)
4276  {
4277  if (!(flags[idx] & LC_PREF_FLAG_COUNT_OPTIM))
4278  {
4279  continue;
4280  }
4281 
4282  /* get class OID from class name */
4283  find = xlocator_find_class_oid (thread_p, classes[idx], &class_oid, NULL_LOCK);
4284  switch (find)
4285  {
4286  case LC_CLASSNAME_ERROR:
4287  return ER_FAILED;
4288 
4289  case LC_CLASSNAME_EXIST:
4290  if (OID_ISNULL (&class_oid))
4291  {
4292  /* The class OID could not be retrieved. Return error. */
4293  return ER_FAILED;
4294  }
4295  else
4296  {
4297  /* search for class statistics (create if not exist). */
4298  class_cos = logtb_tran_find_class_cos (thread_p, &class_oid, true);
4299  if (class_cos == NULL)
4300  {
4301  /* something wrong happened. Just return error */
4302  return ER_FAILED;
4303  }
4304 
4305  /* Mark class for unique statistics loading. The statistics will be loaded when snapshot will be taken */
4306  if (class_cos->count_state != COS_LOADED)
4307  {
4308  class_cos->count_state = COS_TO_LOAD;
4309  }
4310  }
4311  break;
4312 
4313  default:
4314  break;
4315  }
4316  }
4317 
4318  return NO_ERROR;
4319 }
4320 
4321 /*
4322  * logtb_tran_reset_cos_func - working function for
4323  * logtb_tran_reset_count_optim_state
4324  *
4325  * return:
4326  * data(in): count optimization state entry.
4327  * args(in): not used.
4328  *
4329  * thread_p(in): thread entry
4330  */
4331 static int
4332 logtb_tran_reset_cos_func (THREAD_ENTRY * thread_p, void *data, void *args)
4333 {
4334  ((LOG_TRAN_CLASS_COS *) data)->count_state = COS_NOT_LOADED;
4335 
4336  return NO_ERROR;
4337 }
4338 
4339 /*
4340  * logtb_tran_reset_count_optim_state - reset count optimization state for all
4341  * class statistics instances
4342  *
4343  * return:
4344  *
4345  * thread_p(in): thread entry
4346  */
4347 void
4349 {
4350  LOG_TDES *tdes = LOG_FIND_TDES (LOG_FIND_THREAD_TRAN_INDEX (thread_p));
4351 
4353 }
4354 
4355 /*
4356  * logtb_create_unique_stats_from_repr - create unique statistics instances
4357  * for all unique indexes of a class
4358  *
4359  * return: error code
4360  *
4361  * thread_p(in) : thread entry
4362  * class_oid(in) : class for which the unique statistics will be created
4363  */
4364 static int
4366 {
4367  OR_CLASSREP *classrepr = NULL;
4368  int error_code = NO_ERROR, idx, classrepr_cacheindex = -1;
4369  LOG_TRAN_BTID_UNIQUE_STATS *unique_stats = NULL;
4370 
4371  /* get class representation to find the total number of indexes */
4372  classrepr = heap_classrepr_get (thread_p, class_oid, NULL, NULL_REPRID, &classrepr_cacheindex);
4373  if (classrepr == NULL)
4374  {
4375  goto exit_on_error;
4376  }
4377 
4378  for (idx = classrepr->n_indexes - 1; idx >= 0; idx--)
4379  {
4380  if (btree_is_unique_type (classrepr->indexes[idx].type))
4381  {
4382  unique_stats = logtb_tran_find_btid_stats (thread_p, &classrepr->indexes[idx].btid, true);
4383  if (unique_stats == NULL)
4384  {
4385  error_code = ER_FAILED;
4386  goto exit_on_error;
4387  }
4388  error_code =
4389  logtb_get_global_unique_stats (thread_p, &unique_stats->btid, &unique_stats->global_stats.num_oids,
4390  &unique_stats->global_stats.num_nulls, &unique_stats->global_stats.num_keys);
4391  if (error_code != NO_ERROR)
4392  {
4393  goto exit_on_error;
4394  }
4395  }
4396  }
4397 
4398  /* free class representation */
4399  heap_classrepr_free_and_init (classrepr, &classrepr_cacheindex);
4400 
4401  return NO_ERROR;
4402 
4403 exit_on_error:
4404  if (classrepr != NULL)
4405  {
4406  heap_classrepr_free_and_init (classrepr, &classrepr_cacheindex);
4407  }
4408 
4409  return (error_code == NO_ERROR && (error_code = er_errid ()) == NO_ERROR) ? ER_FAILED : error_code;
4410 }
4411 
4412 #if defined(ENABLE_UNUSED_FUNCTION)
4413 /*
4414  * logtb_find_largest_lsa - largest lsa address of all active transactions
4415  *
4416  * return: LOG_LSA *
4417  *
4418  * Note: Find the largest LSA address of all active transactions.
4419  */
4420 LOG_LSA *
4421 logtb_find_largest_lsa (THREAD_ENTRY * thread_p)
4422 {
4423  int i;
4424  LOG_TDES *tdes; /* Transaction descriptor */
4425  LOG_LSA *max_lsa = NULL; /* The largest lsa value */
4426 
4427  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
4428  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
4429  {
4430  if (i != LOG_SYSTEM_TRAN_INDEX)
4431  {
4432  tdes = log_Gl.trantable.all_tdes[i];
4433  if (tdes != NULL && tdes->trid != NULL_TRANID && !LSA_ISNULL (&tdes->tail_lsa)
4434  && (max_lsa == NULL || LSA_GT (&tdes->tail_lsa, max_lsa)))
4435  {
4436  max_lsa = &tdes->tail_lsa;
4437  }
4438  }
4439  }
4440  TR_TABLE_CS_EXIT (thread_p);
4441 
4442  return max_lsa;
4443 }
4444 #endif /* ENABLE_UNUSED_FUNCTION */
4445 
4446 /*
4447  * logtb_find_smallest_and_largest_active_pages - smallest and larger active pages
4448  *
4449  * return: nothing...
4450  *
4451  * smallest(in/out): smallest active log page
4452  * largest(in/out): largest active log page
4453  *
4454  * Note: Find the smallest and larger active pages.
4455  */
4456 void
4458 {
4459  int i;
4460  LOG_TDES *tdes; /* Transaction descriptor */
4461 
4462  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
4463 
4464  *smallest = *largest = NULL_PAGEID;
4465 
4466  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
4467  {
4468  if (i != LOG_SYSTEM_TRAN_INDEX)
4469  {
4470  tdes = log_Gl.trantable.all_tdes[i];
4471  if (tdes != NULL && tdes->trid != NULL_TRANID && !LSA_ISNULL (&tdes->head_lsa))
4472  {
4473  if (*smallest == NULL_PAGEID || tdes->head_lsa.pageid < *smallest)
4474  {
4475  *smallest = tdes->head_lsa.pageid;
4476  }
4477  if (*largest == NULL_PAGEID || tdes->tail_lsa.pageid > *largest)
4478  {
4479  *largest = tdes->tail_lsa.pageid;
4480  }
4481  if (*largest == NULL_PAGEID || tdes->posp_nxlsa.pageid > *largest)
4482  {
4483  *largest = tdes->posp_nxlsa.pageid;
4484  }
4485  }
4486  }
4487  }
4488 
4489  TR_TABLE_CS_EXIT (thread_p);
4490 }
4491 
4492 /*
4493  * logtb_has_deadlock_priority -
4494  *
4495  * return: whether this transaction has deadlock priority
4496  */
4497 bool
4499 {
4500  LOG_TDES *tdes; /* Transaction descriptor */
4501 
4502  tdes = LOG_FIND_TDES (tran_index);
4503  if (tdes)
4504  {
4505  return tdes->has_deadlock_priority;
4506  }
4507 
4508  return false;
4509 }
4510 
4511 /*
4512  *logtb_get_new_subtransaction_mvccid - assign a new sub-transaction MVCCID
4513  *
4514  * return: error code
4515  *
4516  * thread_p(in): Thread entry
4517  * curr_mvcc_info(in): current MVCC info
4518  *
4519  * Note: If transaction MVCCID is NULL then a new transaction MVCCID is
4520  * allocated first.
4521  */
4522 void
4524 {
4525  MVCCID mvcc_subid;
4526  mvcctable *mvcc_table;
4527 
4528  assert (curr_mvcc_info != NULL);
4529 
4530  mvcc_table = &log_Gl.mvcc_table;
4531 
4532  // curr_mvcc_info->id must be valid too!
4533  if (MVCCID_IS_VALID (curr_mvcc_info->id))
4534  {
4535  mvcc_subid = mvcc_table->get_new_mvccid ();
4536  }
4537  else
4538  {
4539  mvcc_table->get_two_new_mvccid (curr_mvcc_info->id, mvcc_subid);
4540  }
4541 
4542  logtb_assign_subtransaction_mvccid (thread_p, curr_mvcc_info, mvcc_subid);
4543 }
4544 
4545 /*
4546  * logtb_assign_subtransaction_mvccid () - Assign sub-transaction MVCCID.
4547  *
4548  * return : Error code.
4549  * thread_p (in) : Thread entry.
4550  * curr_mvcc_info (in) : Current transaction MVCC information.
4551  * mvcc_subid (in) : Sub-transaction MVCCID.
4552  */
4553 static void
4554 logtb_assign_subtransaction_mvccid (THREAD_ENTRY * thread_p, MVCC_INFO * curr_mvcc_info, MVCCID mvcc_subid)
4555 {
4556  assert (curr_mvcc_info != NULL);
4557  assert (MVCCID_IS_VALID (curr_mvcc_info->id));
4558  curr_mvcc_info->sub_ids.push_back (mvcc_subid);
4559 }
4560 
4561 /*
4562  * logtb_complete_sub_mvcc () - Called at end of sub-transaction
4563  *
4564  * return : Void.
4565  * thread_p (in) : Thread entry.
4566  * tdes (in) : Transaction descriptor.
4567  */
4568 void
4570 {
4571  MVCC_INFO *curr_mvcc_info = NULL;
4572  MVCCID mvcc_sub_id;
4573  mvcctable *mvcc_table = &log_Gl.mvcc_table;
4574 
4575  assert (tdes != NULL);
4576 
4577  curr_mvcc_info = &tdes->mvccinfo;
4578  mvcc_sub_id = curr_mvcc_info->sub_ids.back ();
4579 
4580  mvcc_table->complete_sub_mvcc (mvcc_sub_id);
4581  curr_mvcc_info->sub_ids.pop_back ();
4582 
4583  if (tdes->mvccinfo.snapshot.valid)
4584  {
4585  /* adjust snapshot to reflect committed sub-transaction, since the parent transaction didn't finished yet */
4586  MVCC_SNAPSHOT *snapshot = &tdes->mvccinfo.snapshot;
4587  if (mvcc_sub_id >= snapshot->highest_completed_mvccid)
4588  {
4589  snapshot->highest_completed_mvccid = mvcc_sub_id;
4591  }
4592  snapshot->m_active_mvccs.set_inactive_mvccid (mvcc_sub_id);
4593  }
4594 }
4595 
4596 /*
4597  * logtb_global_unique_stat_alloc () - allocate a new structure of unique
4598  * statistics for a btree
4599  * returns: new pointer or NULL on error
4600  */
4601 static void *
4603 {
4604  GLOBAL_UNIQUE_STATS *unique_stat;
4605 
4606  unique_stat = (GLOBAL_UNIQUE_STATS *) malloc (sizeof (GLOBAL_UNIQUE_STATS));
4607  if (unique_stat == NULL)
4608  {
4610  return NULL;
4611  }
4612 
4613  pthread_mutex_init (&unique_stat->mutex, NULL);
4614  return (void *) unique_stat;
4615 }
4616 
4617 /*
4618  * logtb_global_unique_stat_free () - free a global unique statistics of a btree
4619  * returns: error code or NO_ERROR
4620  * unique_stat(in): global unique statistics entry to free
4621  * (GLOBAL_UNIQUE_STATS)
4622  */
4623 static int
4625 {
4626  if (unique_stat != NULL)
4627  {
4628  pthread_mutex_destroy (&((GLOBAL_UNIQUE_STATS *) unique_stat)->mutex);
4629  free (unique_stat);
4630  return NO_ERROR;
4631  }
4632  else
4633  {
4634  return ER_FAILED;
4635  }
4636 }
4637 
4638 /*
4639  * logtb_global_unique_stat_init () - initialize global unique statistics element
4640  * returns: error code or NO_ERROR
4641  * unique_stat(in): global unique statistics element
4642  */
4643 static int
4645 {
4646  GLOBAL_UNIQUE_STATS *unique_stat_p = (GLOBAL_UNIQUE_STATS *) unique_stat;
4647 
4648  if (unique_stat == NULL)
4649  {
4650  return ER_FAILED;
4651  }
4652 
4653  /* initialize fields */
4654  BTID_SET_NULL (&unique_stat_p->btid);
4655  unique_stat_p->unique_stats.num_nulls = 0;
4656  unique_stat_p->unique_stats.num_keys = 0;
4657  unique_stat_p->unique_stats.num_oids = 0;
4658  LSA_SET_NULL (&unique_stat_p->last_log_lsa);
4659 
4660  return NO_ERROR;
4661 }
4662 
4663 /*
4664  * logtb_global_unique_stat_key_copy () - copy a global unique statistics key
4665  * returns: error code or NO_ERROR
4666  * src(in): source
4667  * dest(in): destination
4668  */
4669 static int
4670 logtb_global_unique_stat_key_copy (void *src, void *dest)
4671 {
4672  if (src == NULL || dest == NULL)
4673  {
4674  return ER_FAILED;
4675  }
4676 
4677  BTID_COPY ((BTID *) dest, (BTID *) src);
4678 
4679  /* all ok */
4680  return NO_ERROR;
4681 }
4682 
4683 /*
4684  * logtb_initialize_global_unique_stats_table () - Creates and initializes
4685  * global structure for global
4686  * unique statistics
4687  * return: error code
4688  * thread_p (in) :
4689  */
4690 int
4692 {
4693  int ret = NO_ERROR;
4695 
4697  {
4698  return NO_ERROR;
4699  }
4700  edesc->of_local_next = offsetof (GLOBAL_UNIQUE_STATS, stack);
4701  edesc->of_next = offsetof (GLOBAL_UNIQUE_STATS, next);
4702  edesc->of_del_tran_id = offsetof (GLOBAL_UNIQUE_STATS, del_id);
4703  edesc->of_key = offsetof (GLOBAL_UNIQUE_STATS, btid);
4704  edesc->of_mutex = offsetof (GLOBAL_UNIQUE_STATS, mutex);
4705  edesc->using_mutex = LF_EM_USING_MUTEX;
4709  edesc->f_uninit = NULL;
4711  edesc->f_key_cmp = btree_compare_btids;
4712  edesc->f_hash = btree_hash_btid;
4713  edesc->f_duplicate = NULL;
4714 
4715  /* initialize freelist */
4717  if (ret != NO_ERROR)
4718  {
4719  return ret;
4720  }
4721 
4722  /* initialize hash table */
4723  ret =
4726  if (ret != NO_ERROR)
4727  {
4729  return ret;
4730  }
4731 
4734 
4735  return ret;
4736 }
4737 
4738 /*
4739  * logtb_finalize_global_unique_stats_table () - Finalize global structure for
4740  * global unique statistics
4741  * return: error code
4742  * thread_p (in) :
4743  */
4744 void
4746 {
4748  {
4749  /* destroy hash and freelist */
4752 
4754  }
4755 }
4756 
4757 /*
4758  * logtb_get_global_unique_stats_entry () - returns the entry into the global
4759  * unique statistics associated with
4760  * the given btid
4761  * return: the entry associated with btid or NULL in case of error
4762  * thread_p (in) :
4763  * btid (in) : the btree id for which the entry will be returned
4764  * load_at_creation (in) : if true and there is no entry in hash for btid then
4765  * load statistics from btree header into hash
4766  *
4767  * NOTE: The statistics are searched in the global hash. If they are found
4768  * then the found entry is returned. Otherwise a new entry will be
4769  * created and inserted into hash. If load_at_creation is true then the
4770  * statistics will be loaded from btree header.
4771  *
4772  * NOTE: !!! DO NOT CALL THIS FUNCTION IF YOU HAVE A LATCH ON THE BTREE
4773  * HEADER. THIS CAN CAUSE A DEADLOCK BETWEEN THE LATCH AND THE MUTEX !!!
4774  */
4775 static GLOBAL_UNIQUE_STATS *
4776 logtb_get_global_unique_stats_entry (THREAD_ENTRY * thread_p, BTID * btid, bool load_at_creation)
4777 {
4778  int error_code = NO_ERROR;
4780  GLOBAL_UNIQUE_STATS *stats = NULL;
4781  int num_oids, num_nulls, num_keys;
4782 
4783  assert (btid != NULL);
4784 
4785 #if !defined(NDEBUG)
4786  {
4787  VPID root_vpid;
4788  root_vpid.pageid = btid->root_pageid;
4789  root_vpid.volid = btid->vfid.volid;
4790  assert (!pgbuf_is_page_fixed_by_thread (thread_p, &root_vpid));
4791  }
4792 #endif
4793 
4794  error_code = lf_hash_find (t_entry, &log_Gl.unique_stats_table.unique_stats_hash, btid, (void **) &stats);
4795  if (error_code != NO_ERROR)
4796  {
4797  return NULL;
4798  }
4799  if (stats == NULL)
4800  {
4801  if (load_at_creation)
4802  {
4803  error_code = btree_get_unique_statistics (thread_p, btid, &num_oids, &num_nulls, &num_keys);
4804  if (error_code != NO_ERROR)
4805  {
4806  return NULL;
4807  }
4808  }
4809  error_code =
4810  lf_hash_find_or_insert (t_entry, &log_Gl.unique_stats_table.unique_stats_hash, btid, (void **) &stats, NULL);
4811  if (error_code != NO_ERROR || stats == NULL)
4812  {
4813  return NULL;
4814  }
4815  if (load_at_creation)
4816  {
4817  stats->unique_stats.num_oids = num_oids;
4818  stats->unique_stats.num_nulls = num_nulls;
4819  stats->unique_stats.num_keys = num_keys;
4820  }
4821  }
4822 
4823  return stats;
4824 }
4825 
4826 /*
4827  * logtb_get_global_unique_stats () - returns the global unique statistics for
4828  * the given btid
4829  * return: error code
4830  * thread_p (in) :
4831  * btid (in) : the btree id for which the statistics will be returned
4832  * num_oids (in) : address of an integer that will receive the global number
4833  * of oids for the given btid
4834  * num_nulls (in) : address of an integer that will receive the global number
4835  * of nulls for the given btid
4836  * num_keys (in) : address of an integer that will receive the global number
4837  * of keys for the given btid
4838  */
4839 int
4840 logtb_get_global_unique_stats (THREAD_ENTRY * thread_p, BTID * btid, int *num_oids, int *num_nulls, int *num_keys)
4841 {
4842  int error_code = NO_ERROR;
4843  GLOBAL_UNIQUE_STATS *stats = NULL;
4844 
4845  assert (btid != NULL);
4846 
4847  stats = logtb_get_global_unique_stats_entry (thread_p, btid, true);
4848  if (stats == NULL)
4849  {
4850  return ER_FAILED;
4851  }
4852 
4853  *num_oids = stats->unique_stats.num_oids;
4854  *num_nulls = stats->unique_stats.num_nulls;
4855  *num_keys = stats->unique_stats.num_keys;
4856 
4857  pthread_mutex_unlock (&stats->mutex);
4858 
4859  return error_code;
4860 }
4861 
4862 /*
4863  * logtb_rv_update_global_unique_stats_by_abs () - updates the global unique
4864  * statistics associated with
4865  * the given btid by absolute
4866  * values. used for recovery.
4867  * return: error code
4868  * thread_p (in) :
4869  * btid (in) : the btree id for which the statistics will be updated
4870  * num_oids (in) : the new number of oids
4871  * num_nulls (in) : the new number of nulls
4872  * num_keys (in) : the new number of keys
4873  */
4874 int
4875 logtb_rv_update_global_unique_stats_by_abs (THREAD_ENTRY * thread_p, BTID * btid, int num_oids, int num_nulls,
4876  int num_keys)
4877 {
4878  int error_code = NO_ERROR;
4879  GLOBAL_UNIQUE_STATS *stats = NULL;
4880 
4881  /* Because we update the statistics with absolute values (this means that we override old values) we don't need to
4882  * load from btree header old values and, therefore, we give a 'false' value to 'load_at_creation' parameter */
4883  stats = logtb_get_global_unique_stats_entry (thread_p, btid, false);
4884  if (stats == NULL)
4885  {
4886  return ER_FAILED;
4887  }
4888 
4890  {
4891  /* Here we assume that we are at recovery stage */
4893  }
4894 
4896  {
4898  "Update stats for index (%d, %d|%d) to nulls=%d, oids=%d, keys=%d. LSA=%lld|%d.\n",
4899  btid->root_pageid, btid->vfid.volid, btid->vfid.fileid, num_nulls, num_oids, num_keys,
4900  (long long int) stats->last_log_lsa.pageid, (int) stats->last_log_lsa.offset);
4901  }
4902 
4903  stats->unique_stats.num_oids = num_oids;
4904  stats->unique_stats.num_nulls = num_nulls;
4905  stats->unique_stats.num_keys = num_keys;
4906 
4907  pthread_mutex_unlock (&stats->mutex);
4908 
4909  return error_code;
4910 }
4911 
4912 /*
4913  * logtb_update_global_unique_stats_by_delta () - updates the global unique
4914  * statistics associated with the
4915  * given btid by delta values
4916  * return: error code
4917  * thread_p (in) :
4918  * btid (in) : the btree id for which the statistics will be updated
4919  * oid_delta (in) : the delta of oids that will be added
4920  * null_delta (in) : the delta of nulls that will be added
4921  * key_delta (in) : the delta of keys that will be added
4922  * log (in) : true if we need to log the changes
4923  */
4924 int
4925 logtb_update_global_unique_stats_by_delta (THREAD_ENTRY * thread_p, BTID * btid, int oid_delta, int null_delta,
4926  int key_delta, bool log)
4927 {
4928  int error_code = NO_ERROR;
4929  GLOBAL_UNIQUE_STATS *stats = NULL;
4930  LOG_TDES *tdes = LOG_FIND_CURRENT_TDES (thread_p);
4931  int num_oids, num_nulls, num_keys;
4932 
4933  if (oid_delta == 0 && key_delta == 0 && null_delta == 0)
4934  {
4935  return NO_ERROR;
4936  }
4937 
4938  stats = logtb_get_global_unique_stats_entry (thread_p, btid, true);
4939  if (stats == NULL)
4940  {
4941  return ER_FAILED;
4942  }
4943 
4944  num_oids = stats->unique_stats.num_oids + oid_delta;
4945  num_nulls = stats->unique_stats.num_nulls + null_delta;
4946  num_keys = stats->unique_stats.num_keys + key_delta;
4947 
4948  if (log)
4949  {
4950  RECDES undo_rec, redo_rec;
4951  char undo_rec_buf[(3 * OR_INT_SIZE) + OR_BTID_ALIGNED_SIZE + BTREE_MAX_ALIGN], *datap = NULL;
4952  char redo_rec_buf[(3 * OR_INT_SIZE) + OR_BTID_ALIGNED_SIZE + BTREE_MAX_ALIGN];
4953 
4954  /* although we don't change the btree header, we still need to log here the new values of statistics so that they
4955  * can be recovered at recover stage. For undo purposes we log the increments. */
4956  undo_rec.data = NULL;
4957  undo_rec.area_size = 3 * OR_INT_SIZE + OR_BTID_ALIGNED_SIZE;
4958  undo_rec.data = PTR_ALIGN (undo_rec_buf, BTREE_MAX_ALIGN);
4959 
4960  undo_rec.length = 0;
4961  datap = (char *) undo_rec.data;
4962  OR_PUT_BTID (datap, btid);
4963  datap += OR_BTID_ALIGNED_SIZE;
4964  OR_PUT_INT (datap, null_delta);
4965  datap += OR_INT_SIZE;
4966  OR_PUT_INT (datap, oid_delta);
4967  datap += OR_INT_SIZE;
4968  OR_PUT_INT (datap, key_delta);
4969  datap += OR_INT_SIZE;
4970  undo_rec.length = CAST_BUFLEN (datap - undo_rec.data);
4971 
4972  redo_rec.data = NULL;
4973  redo_rec.area_size = 3 * OR_INT_SIZE + OR_BTID_ALIGNED_SIZE;
4974  redo_rec.data = PTR_ALIGN (redo_rec_buf, BTREE_MAX_ALIGN);
4975 
4976  redo_rec.length = 0;
4977  datap = (char *) redo_rec.data;
4978  OR_PUT_BTID (datap, btid);
4979  datap += OR_BTID_ALIGNED_SIZE;
4980  OR_PUT_INT (datap, num_nulls);
4981  datap += OR_INT_SIZE;
4982  OR_PUT_INT (datap, num_oids);
4983  datap += OR_INT_SIZE;
4984  OR_PUT_INT (datap, num_keys);
4985  datap += OR_INT_SIZE;
4986  redo_rec.length = CAST_BUFLEN (datap - redo_rec.data);
4987 
4989  redo_rec.length, undo_rec.data, redo_rec.data);
4990  LSA_COPY (&stats->last_log_lsa, &tdes->tail_lsa);
4991  }
4993  {
4994  /* Here we assume that we are at recovery stage */
4996  }
4997 
4999  {
5001  "Update stats for index (%d, %d|%d) by nulls=%d, "
5002  "oids=%d, keys=%d to nulls=%d, oids=%d, keys=%d. LSA=%lld|%d.\n", btid->root_pageid,
5003  btid->vfid.volid, btid->vfid.fileid, null_delta, oid_delta, key_delta, num_nulls, num_oids,
5004  num_keys, (long long int) stats->last_log_lsa.pageid, (int) stats->last_log_lsa.offset);
5005  }
5006 
5007  stats->unique_stats.num_oids = num_oids;
5008  stats->unique_stats.num_nulls = num_nulls;
5009  stats->unique_stats.num_keys = num_keys;
5010 
5011  pthread_mutex_unlock (&stats->mutex);
5012 
5013  return error_code;
5014 }
5015 
5016 /*
5017  * logtb_delete_global_unique_stats () - deletes the entry associated with
5018  * the given btid from global unique
5019  * statistics hash
5020  * return: error code
5021  * thread_p (in) :
5022  * btid (in) : the btree id for which the statistics entry will be deleted
5023  */
5024 int
5026 {
5028  int error = NO_ERROR;
5029 
5030  assert (!BTID_IS_NULL (btid));
5031 
5032 #if !defined(NDEBUG)
5033  {
5034  VPID root_vpid;
5035  root_vpid.pageid = btid->root_pageid;
5036  root_vpid.volid = btid->vfid.volid;
5037  assert (!pgbuf_is_page_fixed_by_thread (thread_p, &root_vpid));
5038  }
5039 #endif
5040 
5041  error = lf_hash_delete (t_entry, &log_Gl.unique_stats_table.unique_stats_hash, btid, NULL);
5042  if (error != NO_ERROR)
5043  {
5044  return error;
5045  }
5046 
5047  return NO_ERROR;
5048 }
5049 
5050 /*
5051  * logtb_reflect_global_unique_stats_to_btree () - reflects the global
5052  * statistics into the btree
5053  * header
5054  * return: error code
5055  * thread_p (in) :
5056  */
5057 int
5059 {
5060  int error = NO_ERROR;
5063  GLOBAL_UNIQUE_STATS *stats = NULL;
5064 
5066  {
5067  return NO_ERROR;
5068  }
5069 
5070  // reflecting stats should not be interrupted
5071  bool save_check_interrupt = logtb_set_check_interrupt (thread_p, false);
5072 
5074  for (stats = (GLOBAL_UNIQUE_STATS *) lf_hash_iterate (&it); stats != NULL;
5075  stats = (GLOBAL_UNIQUE_STATS *) lf_hash_iterate (&it))
5076  {
5077  /* reflect only if some changes were logged */
5078  if (!LSA_ISNULL (&stats->last_log_lsa))
5079  {
5080  error = btree_reflect_global_unique_statistics (thread_p, stats, false);
5081  if (error != NO_ERROR)
5082  {
5083  ASSERT_ERROR ();
5084 
5085  // must unlock entry
5086  pthread_mutex_unlock (&stats->mutex);
5087 
5088  // finish transaction
5089  lf_tran_end_with_mb (t_entry);
5090  break;
5091  }
5092  LSA_SET_NULL (&stats->last_log_lsa);
5093  }
5094  }
5095 
5096  (void) logtb_set_check_interrupt (thread_p, save_check_interrupt);
5097 
5098  return error;
5099 }
5100 
5101 /*
5102  * logtb_does_active_user_exist - check whether the specified user is active user
5103  * or not. active user means it is in trantable now.
5104  *
5105  * return: true for existed
5106  * thread_p(in):
5107  * user_name(in): the specified user name
5108  *
5109  */
5110 bool
5111 xlogtb_does_active_user_exist (THREAD_ENTRY * thread_p, const char *user_name)
5112 {
5113  int i;
5114  LOG_TDES *tdes; /* Transaction descriptor */
5115  bool existed = false;
5116 
5117  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
5118 
5119  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
5120  {
5121  tdes = log_Gl.trantable.all_tdes[i];
5122  if (tdes != NULL && tdes->is_user_active && strcmp (tdes->client.get_db_user (), user_name) == 0)
5123  {
5124  existed = true;
5125  break;
5126  }
5127  }
5128  TR_TABLE_CS_EXIT (thread_p);
5129 
5130  return existed;
5131 }
5132 
5133 #if !defined (NDEBUG) && !defined (WINDOWS)
5134 int
5135 logtb_collect_local_clients (int **local_clients_pids)
5136 {
5137  LOG_TDES *tdes; /* Transaction descriptor */
5138  int i, num_client;
5139  int *table;
5140 
5141  *local_clients_pids = NULL;
5142 
5143  table = (int *) malloc (NUM_TOTAL_TRAN_INDICES * sizeof (int));
5144  if (table == NULL)
5145  {
5146  return ER_FAILED;
5147  }
5148 
5149  memset (table, 0, NUM_TOTAL_TRAN_INDICES * sizeof (int));
5150 
5151  for (i = 0, num_client = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
5152  {
5153  tdes = log_Gl.trantable.all_tdes[i];
5154  if (tdes != NULL && tdes->client.process_id > 0 && !tdes->client.host_name.empty ()
5155  && (strcmp (tdes->client.get_host_name (), boot_Host_name) == 0
5156  || strcmp (tdes->client.get_host_name (), "localhost") == 0))
5157  {
5158  table[num_client++] = tdes->client.process_id;
5159  }
5160  }
5161 
5162  *local_clients_pids = table;
5163  return num_client;
5164 }
5165 #endif /* !defined (NDEBUG) && !defined (WINDOWS) */
5166 
5167 /*
5168  * logtb_descriptors_start_scan () - start scan function for tran descriptors
5169  * return: NO_ERROR, or ER_code
5170  *
5171  * thread_p(in):
5172  * type(in):
5173  * arg_values(in):
5174  * arg_cnt(in):
5175  * ptr(in/out):
5176  */
5177 int
5178 logtb_descriptors_start_scan (THREAD_ENTRY * thread_p, int type, DB_VALUE ** arg_values, int arg_cnt, void **ptr)
5179 {
5181  int i, idx, msecs, error = NO_ERROR;
5182  char buf[512];
5183  const char *str;
5184  time_t tval;
5185  INT64 i64val;
5186  XASL_ID xasl_val;
5187  DB_DATETIME time_val;
5188  void *ptr_val;
5189  LOG_TDES *tdes;
5190  DB_VALUE *vals = NULL;
5191  const int num_cols = 46;
5192 
5193  *ptr = NULL;
5194 
5195  ctx = showstmt_alloc_array_context (thread_p, NUM_TOTAL_TRAN_INDICES, num_cols);
5196  if (ctx == NULL)
5197  {
5198  error = er_errid ();
5199  return error;
5200  }
5201 
5202  TR_TABLE_CS_ENTER_READ_MODE (thread_p);
5203 
5204  for (i = 0; i < NUM_TOTAL_TRAN_INDICES; i++)
5205  {
5206  tdes = log_Gl.trantable.all_tdes[i];
5207  if (tdes == NULL || tdes->trid == NULL_TRANID)
5208  {
5209  /* The index is not assigned or is system transaction (no-client) */
5210  continue;
5211  }
5212 
5213  idx = 0;
5214  vals = showstmt_alloc_tuple_in_context (thread_p, ctx);
5215  if (vals == NULL)
5216  {
5217  error = er_errid ();
5218  goto exit_on_error;
5219  }
5220 
5221  /* Tran_index */
5222  db_make_int (&vals[idx], tdes->tran_index);
5223  idx++;
5224 
5225  /* Tran_id */
5226  db_make_int (&vals[idx], tdes->trid);
5227  idx++;
5228 
5229  /* Is_loose_end */
5230  db_make_int (&vals[idx], tdes->isloose_end);
5231  idx++;
5232 
5233  /* State */
5234  db_make_string (&vals[idx], log_state_short_string (tdes->state));
5235  idx++;
5236 
5237  /* isolation */
5238  db_make_string (&vals[idx], log_isolation_string (tdes->isolation));
5239  idx++;
5240 
5241  /* Wait_msecs */
5242  db_make_int (&vals[idx], tdes->wait_msecs);
5243  idx++;
5244 
5245  /* Head_lsa */
5246  lsa_to_string (buf, sizeof (buf), &tdes->head_lsa);
5247  error = db_make_string_copy (&vals[idx], buf);
5248  idx++;
5249  if (error != NO_ERROR)
5250  {
5251  goto exit_on_error;
5252  }
5253 
5254  /* Tail_lsa */
5255  lsa_to_string (buf, sizeof (buf), &tdes->tail_lsa);
5256  error = db_make_string_copy (&vals[idx], buf);
5257  idx++;
5258  if (error != NO_ERROR)
5259  {
5260  goto exit_on_error;
5261  }
5262 
5263  /* Undo_next_lsa */
5264  lsa_to_string (buf, sizeof (buf), &tdes->undo_nxlsa);
5265  error = db_make_string_copy (&vals[idx], buf);
5266  idx++;
5267  if (error != NO_ERROR)
5268  {
5269  goto exit_on_error;
5270  }
5271 
5272  /* Postpone_next_lsa */
5273  lsa_to_string (buf, sizeof (buf), &tdes->posp_nxlsa);
5274  error = db_make_string_copy (&vals[idx], buf);
5275  idx++;
5276  if (error != NO_ERROR)
5277  {
5278  goto exit_on_error;
5279  }
5280 
5281  /* Savepoint_lsa */
5282  lsa_to_string (buf, sizeof (buf), &tdes->savept_lsa);
5283  error = db_make_string_copy (&vals[idx], buf);
5284  idx++;
5285  if (error != NO_ERROR)
5286  {
5287  goto exit_on_error;
5288  }
5289 
5290  /* Topop_lsa */
5291  lsa_to_string (buf, sizeof (buf), &tdes->topop_lsa);
5292  error = db_make_string_copy (&vals[idx], buf);
5293  idx++;
5294  if (error != NO_ERROR)
5295  {
5296  goto exit_on_error;
5297  }
5298 
5299  /* Tail_top_result_lsa */
5300  lsa_to_string (buf, sizeof (buf), &tdes->tail_topresult_lsa);
5301  error = db_make_string_copy (&vals[idx], buf);
5302  idx++;
5303  if (error != NO_ERROR)
5304  {
5305  goto exit_on_error;
5306  }
5307 
5308  /* Client_id */
5309  db_make_int (&vals[idx], tdes->client_id);
5310  idx++;
5311 
5312  /* Client_type */
5314  error = db_make_string_copy (&vals[idx], str);
5315  idx++;
5316  if (error != NO_ERROR)
5317  {
5318  goto exit_on_error;
5319  }
5320 
5321  /* Client_info */
5322  error = db_make_string_copy (&vals[idx], tdes->client.get_client_info ());
5323  idx++;
5324  if (error != NO_ERROR)
5325  {
5326  goto exit_on_error;
5327  }
5328 
5329  /* Client_db_user */
5330  error = db_make_string_copy (&vals[idx], tdes->client.get_db_user ());
5331  idx++;
5332  if (error != NO_ERROR)
5333  {
5334  goto exit_on_error;
5335  }
5336 
5337  /* Client_program */
5338  error = db_make_string_copy (&vals[idx], tdes->client.get_program_name ());
5339  idx++;
5340  if (error != NO_ERROR)
5341  {
5342  goto exit_on_error;
5343  }
5344 
5345  /* Client_login_user */
5346  error = db_make_string_copy (&vals[idx], tdes->client.get_login_name ());
5347  idx++;
5348  if (error != NO_ERROR)
5349  {
5350  goto exit_on_error;
5351  }
5352 
5353  /* Client_host */
5354  error = db_make_string_copy (&vals[idx], tdes->client.get_host_name ());
5355  idx++;
5356  if (error != NO_ERROR)
5357  {
5358  goto exit_on_error;
5359  }
5360 
5361  /* Client_pid */
5362  db_make_int (&vals[idx], tdes->client.process_id);
5363  idx++;
5364 
5365  /* Topop_depth */
5366  db_make_int (&vals[idx], tdes->topops.last + 1);
5367  idx++;
5368 
5369  /* Num_unique_btrees */
5370  db_make_int (&vals[idx], tdes->num_unique_btrees);
5371  idx++;
5372 
5373  /* Max_unique_btrees */
5374  db_make_int (&vals[idx], tdes->max_unique_btrees);
5375  idx++;
5376 
5377  /* Interrupt */
5378  db_make_int (&vals[idx], tdes->interrupt);
5379  idx++;
5380 
5381  /* Num_transient_classnames */
5382  db_make_int (&vals[idx], tdes->num_transient_classnames);
5383  idx++;
5384 
5385  /* Repl_max_records */
5386  db_make_int (&vals[idx], tdes->num_repl_records);
5387  idx++;
5388 
5389  /* Repl_records */
5390  ptr_val = tdes->repl_records;
5391  if (ptr_val == NULL)
5392  {
5393  db_make_null (&vals[idx]);
5394  }
5395  else
5396  {
5397  snprintf (buf, sizeof (buf), "0x%08" PRIx64, (UINT64) ptr_val);
5398  error = db_make_string_copy (&vals[idx], buf);
5399  if (error != NO_ERROR)
5400  {
5401  goto exit_on_error;
5402  }
5403  }
5404  idx++;
5405 
5406  /* Repl_current_index */
5407  db_make_int (&vals[idx], tdes->cur_repl_record);
5408  idx++;
5409 
5410  /* Repl_append_index */
5411  db_make_int (&vals[idx], tdes->append_repl_recidx);
5412  idx++;
5413 
5414  /* Repl_flush_marked_index */
5415  db_make_int (&vals[idx], tdes->fl_mark_repl_recidx);
5416  idx++;
5417 
5418  /* Repl_insert_lsa */
5419  lsa_to_string (buf, sizeof (buf), &tdes->repl_insert_lsa);
5420  error = db_make_string_copy (&vals[idx], buf);
5421  idx++;
5422  if (error != NO_ERROR)
5423  {
5424  goto exit_on_error;
5425  }
5426 
5427  /* Repl_update_lsa */
5428  lsa_to_string (buf, sizeof (buf), &tdes->repl_update_lsa);
5429  error = db_make_string_copy (&vals[idx], buf);
5430  idx++;
5431  if (error != NO_ERROR)
5432  {
5433  goto exit_on_error;
5434  }
5435 
5436  /* First_save_entry */
5437  ptr_val = tdes->first_save_entry;
5438  if (ptr_val == NULL)
5439  {
5440  db_make_null (&vals[idx]);
5441  }
5442  else
5443  {
5444  snprintf (buf, sizeof (buf), "0x%08" PRIx64, (UINT64) ptr_val);
5445  error = db_make_string_copy (&vals[idx], buf);
5446  if (error != NO_ERROR)
5447  {
5448  goto exit_on_error;
5449  }
5450  }
5451  idx++;
5452 
5453  /* Tran_unique_stats */
5454  if (tdes->m_multiupd_stats.empty ())
5455  {
5456  db_make_null (&vals[idx]);
5457  }
5458  else
5459  {
5461  tdes->m_multiupd_stats.to_string (strbuf);
5462  error = db_make_string (&vals[idx], strbuf.release_ptr ());
5463  vals[idx].need_clear = true;
5464  if (error != NO_ERROR)
5465  {
5466  goto exit_on_error;
5467  }
5468  }
5469  idx++;
5470 
5471  /* modified class list */
5472  if (tdes->m_modified_classes.empty ())
5473  {
5474  db_make_null (&vals[idx]);
5475  }
5476  else
5477  {
5478  (void) db_make_string (&vals[idx], tdes->m_modified_classes.to_string ());
5479  vals[idx].need_clear = true;
5480  }
5481  idx++;
5482 
5483  /* Num_temp_files */
5484  db_make_int (&vals[idx], file_get_tran_num_temp_files (thread_p));
5485  idx++;
5486 
5487  /* Waiting_for_res */
5488  ptr_val = tdes->waiting_for_res;
5489  if (ptr_val == NULL)
5490  {
5491  db_make_null (&vals[idx]);
5492  }
5493  else
5494  {
5495  snprintf (buf, sizeof (buf), "0x%08" PRIx64, (UINT64) ptr_val);
5496  error = db_make_string_copy (&vals[idx], buf);
5497  if (error != NO_ERROR)
5498  {
5499  goto exit_on_error;
5500  }
5501  }
5502  idx++;
5503 
5504  /* Has_deadlock_priority */
5505  db_make_int (&vals[idx], tdes->has_deadlock_priority);
5506  idx++;
5507 
5508  /* Suppress_replication */
5509  db_make_int (&vals[idx], tdes->suppress_replication);
5510  idx++;
5511 
5512  /* Query_timeout */
5513  i64val = tdes->query_timeout;
5514  if (i64val <= 0)
5515  {
5516  db_make_null (&vals[idx]);
5517  }
5518  else
5519  {
5520  tval = i64val / 1000;
5521  msecs = i64val % 1000;
5522  db_localdatetime_msec (&tval, msecs, &time_val);
5523  db_make_datetime (&vals[idx], &time_val);
5524  }
5525  idx++;
5526 
5527  /* Query_start_time */
5528  i64val = tdes->query_start_time;
5529  if (i64val <= 0)
5530  {
5531  db_make_null (&vals[idx]);
5532  }
5533  else
5534  {
5535  tval = i64val / 1000;
5536  msecs = i64val % 1000;
5537  db_localdatetime_msec (&tval, msecs, &time_val);
5538  db_make_datetime (&vals[idx], &time_val);
5539  }
5540  idx++;
5541 
5542  /* Tran_start_time */
5543  i64val = tdes->tran_start_time;
5544  if (i64val <= 0)
5545  {
5546  db_make_null (&vals[idx]);
5547  }
5548  else
5549  {
5550  tval = i64val / 1000;
5551  msecs = i64val % 1000;
5552  db_localdatetime_msec (&tval, msecs, &time_val);
5553  db_make_datetime (&vals[idx], &time_val);
5554  }
5555  idx++;
5556 
5557  /* Xasl_id */
5558  XASL_ID_COPY (&xasl_val, &tdes->xasl_id);
5559  if (XASL_ID_IS_NULL (&xasl_val))
5560  {
5561  db_make_null (&vals[idx]);
5562  }
5563  else
5564  {
5565  snprintf (buf, sizeof (buf), "sha1 = %08x | %08x | %08x | %08x | %08x, time_stored = %d sec %d usec",
5566  SHA1_AS_ARGS (&xasl_val.sha1), CACHE_TIME_AS_ARGS (&xasl_val.time_stored));
5567  error = db_make_string_copy (&vals[idx], buf);
5568  if (error != NO_ERROR)
5569  {
5570  goto exit_on_error;
5571  }
5572  }
5573  idx++;
5574 
5575  /* Disable_modifications */
5576  db_make_int (&vals[idx], tdes->disable_modifications);
5577  idx++;
5578 
5579  /* Abort_reason */
5581  db_make_string (&vals[idx], str);
5582  idx++;
5583 
5584  assert (idx == num_cols);
5585  }
5586 
5587 
5588  TR_TABLE_CS_EXIT (thread_p);
5589 
5590  *ptr = ctx;
5591  return NO_ERROR;
5592 
5593 exit_on_error:
5594  TR_TABLE_CS_EXIT (thread_p);
5595 
5596  if (ctx != NULL)
5597  {
5598  showstmt_free_array_context (thread_p, ctx);
5599  }
5600 
5601  return error;
5602 }
5603 
5604 /*
5605  * tran_abort_reason_to_string() - return the string alias of enum value
5606  *
5607  * return: constant string
5608  *
5609  * val(in): the enum value
5610  */
5611 const char *
5613 {
5614  switch (val)
5615  {
5616  case TRAN_NORMAL:
5617  return "NORMAL";
5619  return "ABORT_DUE_DEADLOCK";
5621  return "ABORT_DUE_ROLLBACK_ON_ESCALATION";
5622  }
5623  return "UNKNOWN";
5624 }
5625 
5626 /*
5627  * logtb_check_class_for_rr_isolation_err () - Check if the class have to be checked against serializable conflicts
5628  *
5629  * return : true if the class is not root/trigger/user class, otherwise false
5630  * class_oid (in) : Class object identifier.
5631  *
5632  * Note: Do not check system classes that are not part of catalog for rr isolation level error. Isolation consistency
5633  * is secured using locks anyway. These classes are in a way related to table schema's and can be accessed
5634  * before the actual classes. db_user instances are fetched to check authorizations, while db_root and db_trigger
5635  * are accessed when triggers are modified.
5636  * The RR isolation has to check if an instance that we want to lock was modified by concurrent transaction.
5637  * If the instance was modified, then this means we have an isolation conflict. The check must verify last
5638  * instance version visibility over transaction snapshot. The version is visible if and only if it was not
5639  * modified by concurrent transaction. To check visibility, we must first generate a transaction snapshot.
5640  * Since instances from these classes are accessed before locking tables, the snapshot is generated before
5641  * transaction is blocked on table lock. The results will then seem to be inconsistent with most cases when table
5642  * locks are acquired before snapshot.
5643  */
5644 bool
5646 {
5647  assert (class_oid != NULL && !OID_ISNULL (class_oid));
5648 
5652  {
5653  return true;
5654  }
5655 
5656  return false;
5657 }
5658 
5659 void
5660 logtb_slam_transaction (THREAD_ENTRY * thread_p, int tran_index)
5661 {
5662  logtb_set_tran_index_interrupt (thread_p, tran_index, true);
5664 #if defined (SERVER_MODE)
5665  css_shutdown_conn_by_tran_index (tran_index);
5666 #endif // SERVER_MODE
5667 }
5668 
5669 /*
5670  * logtb_check_kill_tran_auth () - User who is not DBA can kill only own transaction
5671  * return: NO_ERROR or error code
5672  * thread_p(in):
5673  * tran_id(in):
5674  * has_authorization(out):
5675  */
5676 static int
5677 logtb_check_kill_tran_auth (THREAD_ENTRY * thread_p, int tran_id, bool * has_authorization)
5678 {
5679  const char *tran_client_name;
5680  const char *current_client_name;
5681 
5682  assert (has_authorization);
5683 
5684  *has_authorization = false;
5685 
5686  if (logtb_am_i_dba_client (thread_p) == true)
5687  {
5688  *has_authorization = true;
5689  return NO_ERROR;
5690  }
5691 
5692  tran_client_name = logtb_find_client_name (tran_id);
5693  current_client_name = logtb_find_current_client_name (thread_p);
5694 
5695  if (tran_client_name == NULL || current_client_name == NULL)
5696  {
5698  }
5699 
5700  if (strcasecmp (tran_client_name, current_client_name) == 0)
5701  {
5702  *has_authorization = true;
5703  }
5704 
5705  return NO_ERROR;
5706 }
5707 
5708 /*
5709  * xlogtb_kill_tran_index() - Kill given transaction.
5710  * return:
5711  * kill_tran_index(in):
5712  * kill_user(in):
5713  * kill_host(in):
5714  * kill_pid(id):
5715  */
5716 int
5717 xlogtb_kill_tran_index (THREAD_ENTRY * thread_p, int kill_tran_index, char *kill_user_p, char *kill_host_p,
5718  int kill_pid)
5719 {
5720  const char *slam_progname_p; /* Client program name for tran */
5721  const char *slam_user_p; /* Client user name for tran */
5722  const char *slam_host_p; /* Client host for tran */
5723  int slam_pid; /* Client process id for tran */
5724  bool signaled = false;
5725  int error_code = NO_ERROR;
5726  bool killed = false;
5727  size_t i;
5728 
5729  if (kill_tran_index == NULL_TRAN_INDEX || kill_user_p == NULL || kill_host_p == NULL || strcmp (kill_user_p, "") == 0
5730  || strcmp (kill_host_p, "") == 0)
5731  {
5732  /*
5733  * Not enough information to kill specific transaction..
5734  *
5735  * For now.. I am setting an er_set..since I have so many files out..and
5736  * I cannot compile more junk..
5737  */
5740  }
5741 
5742  if (kill_tran_index == LOG_SYSTEM_TRAN_INDEX)
5743  {
5744  // cannot kill system transaction; not even if this is dba
5746  return ER_KILL_TR_NOT_ALLOWED;
5747  }
5748 
5749  signaled = false;
5750  for (i = 0; i < LOGTB_RETRY_SLAM_MAX_TIMES && error_code == NO_ERROR && !killed; i++)
5751  {
5752  if (logtb_find_client_name_host_pid (kill_tran_index, &slam_progname_p, &slam_user_p, &slam_host_p, &slam_pid) !=
5753  NO_ERROR)
5754  {
5755  if (signaled == false)
5756  {
5758  kill_user_p, kill_host_p, kill_pid);
5759  error_code = ER_CSS_KILL_UNKNOWN_TRANSACTION;
5760  }
5761  else
5762  {
5763  killed = true;
5764  }
5765  break;
5766  }
5767 
5768  if (kill_pid == slam_pid && strcmp (kill_user_p, slam_user_p) == 0 && strcmp (kill_host_p, slam_host_p) == 0)
5769  {
5770  logtb_slam_transaction (thread_p, kill_tran_index);
5771  signaled = true;
5772  }
5773  else
5774  {
5775  if (signaled == false)
5776  {
5777  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CSS_KILL_DOES_NOTMATCH, 8, kill_tran_index, kill_user_p,
5778  kill_host_p, kill_pid, kill_tran_index, slam_user_p, slam_host_p, slam_pid);
5779  error_code = ER_CSS_KILL_DOES_NOTMATCH;
5780  }
5781  else
5782  {
5783  killed = true;
5784  }
5785  break;
5786  }
5787  thread_sleep_for (std::chrono::seconds (1));
5788  }
5789 
5790  if (error_code == NO_ERROR && !killed)
5791  {
5792  error_code = ER_FAILED; /* timeout */
5793  }
5794 
5795  return error_code;
5796 }
5797 
5798 /*
5799  * xlogtb_kill_or_interrupt_tran() -
5800  * return:
5801  * thread_p(in):
5802  * tran_index(in):
5803  * is_dba_group_member(in):
5804  * kill_query_only(in):
5805  */
5806 int
5807 xlogtb_kill_or_interrupt_tran (THREAD_ENTRY * thread_p, int tran_index, bool is_dba_group_member, bool interrupt_only)
5808 {
5809  int error;
5810  bool interrupt, has_authorization;
5811  bool is_trx_exists;
5812  KILLSTMT_TYPE kill_type;
5813  size_t i;
5814 
5815  if (tran_index == LOG_SYSTEM_TRAN_INDEX)
5816  {
5817  // cannot kill system transaction; not even if this is dba
5819  return ER_KILL_TR_NOT_ALLOWED;
5820  }
5821 
5822  if (!is_dba_group_member)
5823  {
5824  error = logtb_check_kill_tran_auth (thread_p, tran_index, &has_authorization);
5825  if (error != NO_ERROR)
5826  {
5827  return error;
5828  }
5829 
5830  if (has_authorization == false)
5831  {
5833  return ER_KILL_TR_NOT_ALLOWED;
5834  }
5835  }
5836 
5837  is_trx_exists = logtb_set_tran_index_interrupt (thread_p, tran_index, true);
5838 
5839  kill_type = interrupt_only ? KILLSTMT_QUERY : KILLSTMT_TRAN;
5840  if (kill_type == KILLSTMT_TRAN)
5841  {
5842 #if defined (SERVER_MODE)
5843  css_shutdown_conn_by_tran_index (tran_index);
5844 #endif // SERVER_MODE
5845  }
5846 
5847  for (i = 0; i < LOGTB_RETRY_SLAM_MAX_TIMES; i++)
5848  {
5849  thread_sleep_for (std::chrono::seconds (1));
5850 
5851  if (logtb_find_interrupt (tran_index, &interrupt) != NO_ERROR)
5852  {
5853  break;
5854  }
5855  if (interrupt == false)
5856  {
5857  break;
5858  }
5859  }
5860 
5861  if (i == LOGTB_RETRY_SLAM_MAX_TIMES)
5862  {
5863  return ER_FAILED; /* timeout */
5864  }
5865 
5866  if (is_trx_exists == false)
5867  {
5868  /*
5869  * Note that the following error will be ignored by
5870  * sthread_kill_or_interrupt_tran().
5871  */
5872  return ER_FAILED;
5873  }
5874 
5875  return NO_ERROR;
5876 }
5877 
5878 //
5879 // logtb_find_thread_entry_mapfunc - function mapped over thread manager's entries to find thread belonging to given
5880 // transaction index
5881 //
5882 // thread_ref (in) : thread entry
5883 // stop_mapper (out) : output true to stop mapping
5884 // tran_index (in) : searched transaction index
5885 // except_me (in) : true to accept current transaction, false otherwise
5886 // found_ptr (out) : saves pointer to found thread entry
5887 //
5888 static void
5889 logtb_find_thread_entry_mapfunc (THREAD_ENTRY & thread_ref, bool & stop_mapper, int tran_index, bool except_me,
5890  REFPTR (THREAD_ENTRY, found_ptr))
5891 {
5892  if (thread_ref.tran_index != tran_index)
5893  {
5894  // not this
5895  return;
5896  }
5897  if (except_me && thread_ref.is_on_current_thread ())
5898  {
5899  // not me
5900  return;
5901  }
5902  // found
5903  found_ptr = &thread_ref;
5904  stop_mapper = true; // stop searching
5905 }
5906 
5907 //
5908 // logtb_find_thread_by_tran_index - find thread entry by transaction index
5909 //
5910 // return : NULL or pointer to found thread
5911 // tran_index (in) : searched transaction index
5912 //
5913 THREAD_ENTRY *
5915 {
5916  THREAD_ENTRY *found_thread = NULL;
5917  thread_get_manager ()->map_entries (logtb_find_thread_entry_mapfunc, tran_index, false, found_thread);
5918  return found_thread;
5919 }
5920 
5921 //
5922 // thread_find_entry_by_tran_index_except_me - find thread entry by transaction index; ignore current thread
5923 //
5924 // return : NULL or pointer to found thread
5925 // tran_index (in) : searched transaction index
5926 //
5927 THREAD_ENTRY *
5929 {
5930  THREAD_ENTRY *found_thread = NULL;
5931  thread_get_manager ()->map_entries (logtb_find_thread_entry_mapfunc, tran_index, true, found_thread);
5932  return found_thread;
5933 }
5934 
5935 #if defined (SERVER_MODE)
5936 //
5937 // logtb_wakeup_thread_with_tran_index - find thread by transaction index and wake it
5938 //
5939 // tran_index (in) : searched transaction index
5940 // resume_reason (in) : the reason thread is resumed
5941 void
5942 logtb_wakeup_thread_with_tran_index (int tran_index, thread_resume_suspend_status resume_reason)
5943 {
5944  // find thread with transaction index; ignore current thread
5946  if (thread_p == NULL)
5947  {
5948  // not found
5949  return;
5950  }
5951 
5952  thread_wakeup (thread_p, resume_reason);
5953 }
5954 #endif // SERVER_MODE
5955 
5956 /*
5957  * logtb_get_current_tran_index() - get transaction index of current thread
5958  * return:
5959  */
5960 int
5962 {
5964  assert (thread_p != NULL);
5965 
5966  return thread_p->tran_index;
5967 }
5968 
5969 /*
5970  * logtb_set_current_tran_index - set transaction index on current thread
5971  */
5972 void
5973 logtb_set_current_tran_index (THREAD_ENTRY * thread_p, int tran_index)
5974 {
5975  if (thread_p == NULL)
5976  {
5977  thread_p = thread_get_thread_entry_info ();
5978  }
5979  thread_p->tran_index = tran_index;
5980 }
5981 
5982 /*
5983  * logtb_set_check_interrupt() -
5984  * return:
5985  * flag(in):
5986  */
5987 bool
5989 {
5990 #if defined (SERVER_MODE)
5991  bool old_val = true;
5992 
5993  if (BO_IS_SERVER_RESTARTED ())
5994  {
5995  if (thread_p == NULL)
5996  {
5997  thread_p = thread_get_thread_entry_info ();
5998  }
5999 
6000  /* safe guard: vacuum workers should not check for interrupt */
6001  assert (flag == false || !VACUUM_IS_THREAD_VACUUM (thread_p));
6002  old_val = thread_p->check_interrupt;
6003  thread_p->check_interrupt = flag;
6004  }
6005 
6006  return old_val;
6007 #else // not SERVER_MODE = SA_MODE
6008  return tran_set_check_interrupt (flag);
6009 #endif // not SERVER_MODE = SA_MODE
6010 }
6011 
6012 /*
6013  * logtb_get_check_interrupt() -
6014  * return:
6015  */
6016 bool
6018 {
6019 #if defined (SERVER_MODE)
6020  bool ret_val = true;
6021 
6022  if (BO_IS_SERVER_RESTARTED ())
6023  {
6024  if (thread_p == NULL)
6025  {
6026  thread_p = thread_get_thread_entry_info ();
6027  }
6028 
6029  ret_val = thread_p->check_interrupt;
6030  }
6031 
6032  return ret_val;
6033 #else // not SERVER_MODE = SA_MODE
6034  return tran_get_check_interrupt ();
6035 #endif // not SERVER_MODE = SA_MODE
6036 }
6037 
6038 LOG_TDES *
6040 {
6041  if (thread_p == NULL)
6042  {
6043  thread_p = thread_get_thread_entry_info ();
6044  }
6045  // if requesting system tran_index and this is a system worker, return its own log_tdes
6046  if (thread_p->tran_index == LOG_SYSTEM_TRAN_INDEX && thread_p->get_system_tdes () != NULL)
6047  {
6048  return thread_p->get_system_tdes ()->get_tdes ();
6049  }
6050  else
6051  {
6053  }
6054 }
6055 
6056 // *INDENT-OFF*
6057 // C++
6058 
6059 bool
6060 log_tdes::is_active_worker_transaction () const
6061 {
6062  return tran_index > LOG_SYSTEM_TRAN_INDEX && tran_index < log_Gl.trantable.num_total_indices;
6063 }
6064 
6065 bool
6066 log_tdes::is_system_transaction () const
6067 {
6068  return tran_index == LOG_SYSTEM_TRAN_INDEX;
6069 }
6070 
6071 bool
6072 log_tdes::is_system_main_transaction () const
6073 {
6074  return is_system_transaction () && trid == LOG_SYSTEM_TRANID;
6075 }
6076 
6077 bool
6078 log_tdes::is_system_worker_transaction () const
6079 {
6080  return is_system_transaction () && trid < NULL_ATTRID;
6081 }
6082 
6083 bool
6084 log_tdes::is_allowed_sysop () const
6085 {
6086  return is_active_worker_transaction () || is_system_worker_transaction ();
6087 }
6088 
6089 bool
6090 log_tdes::is_under_sysop () const
6091 {
6092  return topops.last >= 0;
6093 }
6094 
6095 bool
6096 log_tdes::is_allowed_undo () const
6097 {
6098  return is_active_worker_transaction () || is_under_sysop ();
6099 }
6100 
6101 void
6102 log_tdes::lock_topop ()
6103 {
6104  if (LOG_ISRESTARTED () && is_active_worker_transaction ())
6105  {
6106  int r = rmutex_lock (NULL, &rmutex_topop);
6107  assert (r == NO_ERROR);
6108  }
6109 }
6110 
6111 void
6112 log_tdes::unlock_topop ()
6113 {
6114  if (LOG_ISRESTARTED () && is_active_worker_transaction ())
6115  {
6116  int r = rmutex_unlock (NULL, &rmutex_topop);
6117  assert (r == NO_ERROR);
6118  }
6119 }
6120 
6121 void
6122 log_tdes::on_sysop_start ()
6123 {
6124  assert (is_allowed_sysop ());
6125 
6126  if (is_system_worker_transaction () && topops.last < 0)
6127  {
6128  if (!LOG_ISRESTARTED ())
6129  {
6130  /* The links are used at recovery. */
6131  return;
6132  }
6133 
6134  // make sure all links to previous records are lost
6135  assert (topops.last == -1);
6142  }
6143 }
6144 
6145 void
6146 log_tdes::on_sysop_end ()
6147 {
6148  assert (is_allowed_sysop ());
6149  if (is_system_worker_transaction() && topops.last < 0)
6150  {
6151  // make sure this system operation cannot be linked
6152  assert (topops.last == -1);
6157  }
6158 }
6159 
6160 void
6161 log_tdes::lock_global_oldest_visible_mvccid ()
6162 {
6164  {
6167  }
6168 }
6169 
6170 void
6171 log_tdes::unlock_global_oldest_visible_mvccid ()
6172 {
6174  {
6178  }
6179 }
6180 // *INDENT-ON*
#define HEADER
Definition: btree_load.h:100
MVCCID logtb_find_current_mvccid(THREAD_ENTRY *thread_p)
#define rmutex_finalize(a)
void logtb_define_trantable(THREAD_ENTRY *thread_p, int num_expected_tran_indices, int num_expected_locks)
const char * logtb_find_current_client_hostname(THREAD_ENTRY *thread_p)
int logtb_get_global_unique_stats(THREAD_ENTRY *thread_p, BTID *btid, int *num_oids, int *num_nulls, int *num_keys)
int num_coord_loose_end_indices
Definition: log_impl.h:584
MVCCID recent_snapshot_lowest_active_mvccid
Definition: mvcc.h:202
int logtb_assign_tran_index(THREAD_ENTRY *thread_p, TRANID trid, TRAN_STATE state, const BOOT_CLIENT_CREDENTIAL *client_credential, TRAN_STATE *current_state, int wait_msecs, TRAN_ISOLATION isolation)
void xlogtb_set_suppress_repl_on_transaction(THREAD_ENTRY *thread_p, int set)
#define OR_BTID_ALIGNED_SIZE
LOG_TRAN_CLASS_COS buffer[1]
Definition: log_impl.h:419
void logtb_release_tran_index(THREAD_ENTRY *thread_p, int tran_index)
int db_make_datetime(DB_VALUE *value, const DB_DATETIME *datetime)
int tran_index
Definition: log_impl.h:465
MVCCID highest_completed_mvccid
Definition: mvcc.h:172
cubthread::entry * thread_get_thread_entry_info(void)
#define NO_ERROR
Definition: error_code.h:46
int xcache_find_sha1(THREAD_ENTRY *thread_p, const SHA1Hash *sha1, const XASL_CACHE_SEARCH_MODE search_mode, XASL_CACHE_ENTRY **xcache_entry, xasl_cache_rt_check_result *rt_check)
Definition: xasl_cache.c:791
int mht_map_no_key(THREAD_ENTRY *thread_p, const MHT_TABLE *ht, int(*map_func)(THREAD_ENTRY *thread_p, void *data, void *args), void *func_args)
Definition: memory_hash.c:2231
int cur_repl_record
Definition: log_impl.h:506
bool logtb_is_active(THREAD_ENTRY *thread_p, TRANID trid)
int area_size
static int logtb_allocate_tran_index(THREAD_ENTRY *thread_p, TRANID trid, TRAN_STATE state, const BOOT_CLIENT_CREDENTIAL *client_credential, TRAN_STATE *current_state, int wait_msecs, TRAN_ISOLATION isolation)
struct lob_rb_root lob_locator_root
Definition: log_impl.h:516
#define pthread_mutex_destroy(a)
LOG_TDES * tdesarea
Definition: log_impl.h:573
int mht_clear(MHT_TABLE *ht, int(*rem_func)(const void *key, void *data, void *args), void *func_args)
Definition: memory_hash.c:1180
static unsigned int logtb_tran_btid_hash_func(const void *key, const unsigned int ht_size)
char * release_ptr()
int logtb_count_clients(THREAD_ENTRY *thread_p)
void log_append_undoredo_data2(THREAD_ENTRY *thread_p, LOG_RCVINDEX rcvindex, const VFID *vfid, PAGE_PTR pgptr, PGLENGTH offset, int undo_length, int redo_length, const void *undo_data, const void *redo_data)
Definition: log_manager.c:1861
MHT_TABLE * unique_stats_hash
Definition: log_impl.h:439
int logtb_find_log_records_count(int tran_index)
int logtb_get_number_assigned_tran_indices(void)
void finalize()
Definition: mvcc_table.cpp:211
void log_find_unilaterally_largest_undo_lsa(THREAD_ENTRY *thread_p, LOG_LSA &max_undo_lsa)
TRANTABLE trantable
Definition: log_impl.h:650
#define BO_IS_SERVER_RESTARTED()
Definition: boot_sr.h:84
void lock_finalize(void)
#define LOG_ESTIMATE_NACTIVE_TRANS
Definition: log_impl.h:112
int logtb_invalidate_snapshot_data(THREAD_ENTRY *thread_p)
int num_total_indices
Definition: log_impl.h:581
void logtb_set_current_user_name(THREAD_ENTRY *thread_p, const char *user_name)
LOG_UNIQUE_STATS global_stats
Definition: log_impl.h:377
static void logtb_find_thread_entry_mapfunc(THREAD_ENTRY &thread_ref, bool &stop_mapper, int tran_index, bool except_me, REFPTR(THREAD_ENTRY, found_ptr))
#define RMUTEX_NAME_TDES_TOPOP
#define LOG_ISTRAN_COMMITTED(tdes)
Definition: log_impl.h:185
DB_VALUE * vals
Definition: dbtype_def.h:1100
#define ASSERT_ERROR()
#define ER_CSS_KILL_BAD_INTERFACE
Definition: error_code.h:848
void qmgr_clear_trans_wakeup(THREAD_ENTRY *thread_p, int tran_index, bool is_tran_died, bool is_abort)
static void logtb_tran_free_update_stats(LOG_TRAN_UPDATE_STATS *log_upd_stats)
#define ER_KILL_TR_NOT_ALLOWED
Definition: error_code.h:1476
TRAN_ISOLATION logtb_find_current_isolation(THREAD_ENTRY *thread_p)
void css_shutdown_conn_by_tran_index(int tran_index)
unsigned int of_local_next
Definition: lock_free.h:66
void lf_hash_destroy(LF_HASH_TABLE *table)
Definition: lock_free.c:1933
void logpb_fatal_error(THREAD_ENTRY *thread_p, bool logexit, const char *file_name, const int lineno, const char *fmt,...)
#define L_cuserid
Definition: porting.h:58
bool LSA_EQ(const log_lsa *plsa1, const log_lsa *plsa2)
Definition: log_lsa.hpp:160
int TRANID
void unlock_global_oldest_visible()
Definition: mvcc_table.cpp:639
#define rmutex_unlock(a, b)
void get_two_new_mvccid(MVCCID &first, MVCCID &second)
Definition: mvcc_table.cpp:580
int info_length
Definition: log_2pc.h:59
void showstmt_free_array_context(THREAD_ENTRY *thread_p, SHOWSTMT_ARRAY_CONTEXT *ctx)
Definition: show_scan.c:373
SHA1Hash sha1
THREAD_ENTRY * logtb_find_thread_by_tran_index(int tran_index)
const char * boot_client_type_to_string(BOOT_CLIENT_TYPE type)
Definition: boot_sr.c:5950
static void logtb_set_number_of_total_tran_indices(int num_total_trans)
LOG_TRAN_UPDATE_STATS log_upd_stats
Definition: log_impl.h:534
LF_ENTRY_INITIALIZE_FUNC f_init
Definition: lock_free.h:90
LOG_TRAN_CLASS_COS_CHUNK * next_chunk
Definition: log_impl.h:418
void LSA_COPY(log_lsa *plsa1, const log_lsa *plsa2)
Definition: log_lsa.hpp:139
LOG_LSA repl_update_lsa
Definition: log_impl.h:511
const char * tran_abort_reason_to_string(TRAN_ABORT_REASON val)
enum db_client_type BOOT_CLIENT_TYPE
void xlogtb_dump_trantable(THREAD_ENTRY *thread_p, FILE *out_fp)
#define LOG_ISTRAN_2PC_IN_SECOND_PHASE(tdes)
Definition: log_impl.h:204
bool is_global_oldest_visible_locked() const
Definition: mvcc_table.cpp:646
LOG_2PC_COORDINATOR * coord
Definition: log_impl.h:489
int partition_load_pruning_context(THREAD_ENTRY *thread_p, const OID *class_oid, int pruning_type, PRUNING_CONTEXT *pinfo)
Definition: partition.c:2249
LOG_TRAN_BTID_UNIQUE_STATS_CHUNK * stats_first_chunk
Definition: log_impl.h:436
void logtb_free_tran_index_with_undo_lsa(THREAD_ENTRY *thread_p, const LOG_LSA *undo_lsa)
LOG_LSA sysop_start_postpone_lsa
Definition: log_impl.h:448
void logtb_tran_reset_count_optim_state(THREAD_ENTRY *thread_p)
LOG_TRAN_CLASS_COS * logtb_tran_find_class_cos(THREAD_ENTRY *thread_p, const OID *class_oid, bool create)
static const int LOG_TOPOPS_STACK_INCREMENT
static API_MUTEX mutex
Definition: api_util.c:72
unsigned int btree_hash_btid(void *btid, int hash_size)
Definition: btree.c:32874
#define ER_FAILED
Definition: error_code.h:47
void * lf_hash_iterate(LF_HASH_TABLE_ITERATOR *it)
Definition: lock_free.c:2388
const int LOG_SYSTEM_TRAN_INDEX
LOG_GLOBAL log_Gl
LOG_HEADER hdr
Definition: log_impl.h:653
#define NULL_TRANID
TRAN_ABORT_REASON tran_abort_reason
Definition: log_impl.h:526
static int logtb_global_unique_stat_key_copy(void *src, void *dest)
static const float LOG_EXPAND_TRANTABLE_RATIO
void logtb_slam_transaction(THREAD_ENTRY *thread_p, int tran_index)
int btree_reflect_global_unique_statistics(THREAD_ENTRY *thread_p, GLOBAL_UNIQUE_STATS *unique_stat_info, bool only_active_tran)
Definition: btree.c:14049
LF_ENTRY_UNINITIALIZE_FUNC f_uninit
Definition: lock_free.h:93
#define ER_TM_TOO_MANY_CLIENTS
Definition: error_code.h:1032
int disable_modifications
Definition: log_impl.h:524
int logtb_get_current_tran_index(void)
LOG_LSA topop_lsa
Definition: log_impl.h:479
bool has_deadlock_priority
Definition: log_impl.h:536
bool logtb_has_deadlock_priority(int tran_index)
#define TRAN_DEFAULT_ISOLATION_LEVEL()
Definition: dbtran_def.h:58
pthread_mutex_t mutex
Definition: log_impl.h:619
#define TR_TABLE_CS_ENTER_READ_MODE(thread_p)
Definition: log_impl.h:89
static BOOT_CLIENT_CREDENTIAL log_Client_credential
int xlogtb_kill_tran_index(THREAD_ENTRY *thread_p, int kill_tran_index, char *kill_user_p, char *kill_host_p, int kill_pid)
static int logtb_create_unique_stats_from_repr(THREAD_ENTRY *thread_p, OID *class_oid)
int lf_hash_find(LF_TRAN_ENTRY *tran, LF_HASH_TABLE *table, void *key, void **entry)
Definition: lock_free.c:1987
LOG_TRAN_BTID_UNIQUE_STATS_CHUNK * stats_current_chunk
Definition: log_impl.h:437
char * or_pack_string(char *ptr, const char *string)
const void * mht_put(MHT_TABLE *ht, const void *key, void *data)
Definition: memory_hash.c:1778
static void logtb_set_tdes(THREAD_ENTRY *thread_p, LOG_TDES *tdes, const BOOT_CLIENT_CREDENTIAL *client_credential, int wait_msecs, TRAN_ISOLATION isolation)
const char * log_state_short_string(TRAN_STATE state)
Definition: log_comm.c:152
int num_repl_records
Definition: log_impl.h:505
struct log_tran_btid_unique_stats LOG_TRAN_BTID_UNIQUE_STATS
Definition: log_impl.h:370
bool logtb_is_system_worker_tranid(TRANID trid)
Definition: log_impl.h:1121
int file_manager_init(void)
void lf_hash_create_iterator(LF_HASH_TABLE_ITERATOR *iterator, LF_TRAN_ENTRY *tran_entry, LF_HASH_TABLE *table)
Definition: lock_free.c:2368
#define ASSERT_ERROR_AND_SET(error_code)
Definition: lock_free.h:63
TRANID logtb_find_current_tranid(THREAD_ENTRY *thread_p)
LF_ENTRY_FREE_FUNC f_free
Definition: lock_free.h:87
int max_unique_btrees
Definition: log_impl.h:493
int logtb_reflect_global_unique_stats_to_btree(THREAD_ENTRY *thread_p)
bool xlogtb_does_active_user_exist(THREAD_ENTRY *thread_p, const char *user_name)
int num_assigned_indices
Definition: log_impl.h:582
Definition: lock_free.h:120
INT64 log_get_clock_msec(void)
const char * get_host_name() const
void LOG_CS_ENTER(THREAD_ENTRY *thread_p)
#define VACUUM_IS_THREAD_VACUUM
Definition: vacuum.h:215
void log_append_undo_data2(THREAD_ENTRY *thread_p, LOG_RCVINDEX rcvindex, const VFID *vfid, PAGE_PTR pgptr, PGLENGTH offset, int length, const void *data)
Definition: log_manager.c:1933
#define ER_INTERRUPTING
Definition: error_code.h:1229
LOG_LSA analysis_last_aborted_sysop_lsa
Definition: log_impl.h:455
int logtb_update_global_unique_stats_by_delta(THREAD_ENTRY *thread_p, BTID *btid, int oid_delta, int null_delta, int key_delta, bool log)
#define MVCCID_NULL
const int LOG_2PC_NULL_GTRID
Definition: log_2pc.h:40
int qmgr_allocate_tran_entries(THREAD_ENTRY *thread_p, int num_new_entries)
cubthread::manager * thread_get_manager(void)
void build_mvcc_info(log_tdes &tdes)
Definition: mvcc_table.cpp:224
bool logtb_is_interrupted(THREAD_ENTRY *thread_p, bool clear, bool *continue_checking)
GLOBAL_UNIQUE_STATS_TABLE unique_stats_table
Definition: log_impl.h:685
KILLSTMT_TYPE
LOG_LSA tail_lsa
Definition: log_impl.h:473
log_postpone_cache m_log_postpone_cache
Definition: log_impl.h:543
LOG_ADDR_TDESAREA * next
Definition: log_impl.h:574
struct timeval TSCTIMEVAL
Definition: tsc_timer.h:40
char * data
#define pthread_mutex_init(a, b)
void logtb_find_smallest_lsa(THREAD_ENTRY *thread_p, LOG_LSA *lsa)
LOG_TDES * LOG_FIND_TDES(int tran_index)
Definition: log_impl.h:1095
struct log_tran_btid_unique_stats_chunk LOG_TRAN_BTID_UNIQUE_STATS_CHUNK
Definition: log_impl.h:393
void tsc_elapsed_time_usec(TSCTIMEVAL *tv, TSC_TICKS end_tick, TSC_TICKS start_tick)
Definition: tsc_timer.c:101
static int logtb_tran_update_delta_hash_func(THREAD_ENTRY *thread_p, void *data, void *args)
TRAN_STATE logtb_find_state(int tran_index)
bool valid
Definition: mvcc.h:178
int32_t pageid
Definition: dbtype_def.h:879
enum lc_prefetch_flags LC_PREFETCH_FLAGS
Definition: locator.h:339
#define lf_tran_end_with_mb(entry)
Definition: lock_free.h:198
INT32 root_pageid
#define LSA_AS_ARGS(lsa_ptr)
Definition: log_lsa.hpp:78
SYNC_RMUTEX rmutex_topop
Definition: log_impl.h:485
int logtb_is_tran_modification_disabled(THREAD_ENTRY *thread_p)
bool block_global_oldest_active_until_commit
Definition: log_impl.h:538
void logtb_finalize_global_unique_stats_table(THREAD_ENTRY *thread_p)
#define MAX_NTRANS
int logtb_find_client_name_host_pid(int tran_index, const char **client_prog_name, const char **client_user_name, const char **client_host_name, int *client_pid)
#define BTID_IS_EQUAL(b1, b2)
int er_errid(void)
static void logtb_dump_top_operations(FILE *out_fp, LOG_TOPOPS_STACK *topops_p)
static void logtb_decrement_number_of_assigned_tran_indices()
static void logtb_dump_tdes(FILE *out_fp, LOG_TDES *tdes)
MVCCID id
Definition: mvcc.h:197
const block_allocator PRIVATE_BLOCK_ALLOCATOR
const char * log_state_string(TRAN_STATE state)
Definition: log_comm.c:125
#define PTR_ALIGN(addr, boundary)
Definition: memory_alloc.h:77
SHOWSTMT_ARRAY_CONTEXT * showstmt_alloc_array_context(THREAD_ENTRY *thread_p, int num_total, int num_cols)
Definition: show_scan.c:336
void * block_particps_ids
Definition: log_2pc.h:68
bool LSA_LT(const log_lsa *plsa1, const log_lsa *plsa2)
Definition: log_lsa.hpp:174
#define er_log_debug(...)
void logtb_clear_tdes(THREAD_ENTRY *thread_p, LOG_TDES *tdes)
HL_HEAPID db_change_private_heap(THREAD_ENTRY *thread_p, HL_HEAPID heap_id)
Definition: memory_alloc.c:337
stat_type get_key_count() const
static const int LOG_MAX_NUM_CONTIGUOUS_TDES
tx_transient_class_registry m_modified_classes
Definition: log_impl.h:502
int logtb_set_num_loose_end_trans(THREAD_ENTRY *thread_p)
int logtb_define_trantable_log_latch(THREAD_ENTRY *thread_p, int num_expected_tran_indices)
void * logtb_realloc_topops_stack(LOG_TDES *tdes, int num_elms)
void complete_mvcc(int tran_index, MVCCID mvccid, bool committed)
Definition: mvcc_table.cpp:466
void logtb_set_current_user_active(THREAD_ENTRY *thread_p, bool is_user_active)
LOG_LSA lastparent_lsa
Definition: log_impl.h:331
void _er_log_debug(const char *file_name, const int line_no, const char *fmt,...)
thread_resume_suspend_status
LF_ENTRY_DESCRIPTOR unique_stats_descriptor
Definition: log_impl.h:632
#define MAX_ALIGNMENT
Definition: memory_alloc.h:70
int xlogtb_reset_wait_msecs(THREAD_ENTRY *thread_p, int wait_msecs)
#define COPY_OID(dest_oid_ptr, src_oid_ptr)
Definition: oid.h:63
INT64 query_start_time
Definition: log_impl.h:520
#define OR_FLOAT_SIZE
static LOG_TRAN_CLASS_COS * logtb_tran_create_class_cos(THREAD_ENTRY *thread_p, const OID *class_oid)
void pgbuf_finalize(void)
Definition: page_buffer.c:1528
void btree_rv_mvcc_save_increments(const BTID *btid, int key_delta, int oid_delta, int null_delta, RECDES *recdes)
Definition: btree_load.c:645
static void logtb_set_loose_end_tdes(LOG_TDES *tdes)
void THREAD_ENTRY
mvcctable mvcc_table
Definition: log_impl.h:684
#define NULL_PAGEID
void set_user(const char *db_user)
int logtb_tran_update_all_global_unique_stats(THREAD_ENTRY *thread_p)
LOG_LSA tail_topresult_lsa
Definition: log_impl.h:480
#define SHA1_AS_ARGS(sha1)
Definition: sha1.h:56
#define TR_TABLE_CS_ENTER(thread_p)
Definition: log_impl.h:88
LOG_TDES ** all_tdes
Definition: log_impl.h:595
#define NUM_ASSIGNED_TRAN_INDICES
#define GLOBAL_UNIQUE_STATS_HASH_SIZE
Definition: log_impl.h:644
void log_2pc_free_coord_info(log_tdes *tdes)
Definition: log_2pc.c:1611
unsigned int of_del_tran_id
Definition: lock_free.h:72
const char * logtb_find_client_hostname(int tran_index)
char boot_Host_name[CUB_MAXHOSTNAMELEN]
Definition: boot_cl.c:158
int db_make_string(DB_VALUE *value, DB_CONST_C_CHAR str)
void logtb_get_new_subtransaction_mvccid(THREAD_ENTRY *thread_p, MVCC_INFO *curr_mvcc_info)
void mht_destroy(MHT_TABLE *ht)
Definition: memory_hash.c:1140
bool logtb_get_check_interrupt(THREAD_ENTRY *thread_p)
COUNT_OPTIM_STATE count_state
Definition: log_impl.h:407
void partition_clear_pruning_context(PRUNING_CONTEXT *pinfo)
Definition: partition.c:2380
char * or_pack_float(char *ptr, float number)
int lf_hash_init(LF_HASH_TABLE *table, LF_FREELIST *freelist, unsigned int hash_size, LF_ENTRY_DESCRIPTOR *edesc)
Definition: lock_free.c:1873
int client_id
Definition: log_impl.h:481
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
void logtb_find_smallest_and_largest_active_pages(THREAD_ENTRY *thread_p, LOG_PAGEID *smallest, LOG_PAGEID *largest)
#define pthread_mutex_unlock(a)
int pgbuf_initialize(void)
Definition: page_buffer.c:1311
db_client_type client_type
void logtb_disable_update(THREAD_ENTRY *thread_p)
char * log_2pc_sprintf_particp(void *particp_id)
Definition: log_2pc.c:162
int logtb_get_client_ids(int tran_index, CLIENTIDS *client_info)
void logtb_set_user_name(int tran_index, const char *user_name)
int gtrid
Definition: log_impl.h:482
const char * get_program_name() const
#define XASL_ID_COPY(X1, X2)
Definition: xasl.h:562
#define BOOT_NORMAL_CLIENT_TYPE(client_type)
Definition: boot.h:33
#define assert(x)
static int logtb_tran_btid_hash_cmp_func(const void *key1, const void *key2)
LOG_RECVPHASE rcv_phase
Definition: log_impl.h:662
LF_ENTRY_KEY_COPY_FUNC f_key_copy
Definition: lock_free.h:96
int logtb_descriptors_start_scan(THREAD_ENTRY *thread_p, int type, DB_VALUE **arg_values, int arg_cnt, void **ptr)
int or_packed_string_length(const char *string, int *strlen)
int32_t fileid
Definition: dbtype_def.h:886
void thread_sleep_for(Duration d)
#define BOOT_IS_ALLOWED_CLIENT_TYPE_IN_MT_MODE(host1, host2, client_type)
Definition: boot.h:91
static const char * UNKNOWN_ID
LOG_TRAN_BTID_UNIQUE_STATS * logtb_tran_find_btid_stats(THREAD_ENTRY *thread_p, const BTID *btid, bool create)
void logtb_enable_update(THREAD_ENTRY *thread_p)
void set_inactive_mvccid(MVCCID mvccid)
LOG_LSA undo_nxlsa
Definition: log_impl.h:474
void logtb_finalize_tdes(THREAD_ENTRY *thread_p, LOG_TDES *tdes)
#define LOG_ISTRAN_ACTIVE(tdes)
Definition: log_impl.h:182
const char * logtb_find_current_client_name(THREAD_ENTRY *thread_p)
LF_ENTRY_KEY_COMPARE_FUNC f_key_cmp
Definition: lock_free.h:99
void xlogtb_set_interrupt(THREAD_ENTRY *thread_p, int set)
unsigned int of_next
Definition: lock_free.h:69
LC_FIND_CLASSNAME xlocator_find_class_oid(THREAD_ENTRY *thread_p, const char *classname, OID *class_oid, LOCK lock)
Definition: locator_sr.c:1033
int num_exec_queries
Definition: log_impl.h:529
int logtb_get_new_tran_id(THREAD_ENTRY *thread_p, LOG_TDES *tdes)
CACHE_TIME time_stored
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
void LOG_CS_EXIT(THREAD_ENTRY *thread_p)
#define REFPTR(T, name)
Definition: porting.h:1089
static GLOBAL_UNIQUE_STATS * logtb_get_global_unique_stats_entry(THREAD_ENTRY *thread_p, BTID *btid, bool load_at_creation)
bool logtb_am_i_dba_client(THREAD_ENTRY *thread_p)
int btree_get_unique_statistics(THREAD_ENTRY *thread_p, BTID *btid, int *oid_cnt, int *null_cnt, int *key_cnt)
Definition: btree.c:6199
#define NUM_TOTAL_TRAN_INDICES
int btree_compare_btids(void *mem_btid1, void *mem_btid2)
Definition: btree.c:21777
int logtb_tran_update_unique_stats(THREAD_ENTRY *thread_p, const BTID *btid, int n_keys, int n_oids, int n_nulls, bool write_to_log)
lf_tran_entry * thread_get_tran_entry(cubthread::entry *thread_p, int entry_idx)
#define BTID_INITIALIZER
void lsa_to_string(char *buf, int buf_size, const log_lsa *lsa)
Definition: log_lsa.cpp:28
const char * get_client_info() const
bool logtb_set_suppress_repl_on_transaction(THREAD_ENTRY *thread_p, int tran_index, int set)
void set_system_internal()
#define DB_INT32_MAX
Definition: dbtype_def.h:633
void xcache_unfix(THREAD_ENTRY *thread_p, XASL_CACHE_ENTRY *xcache_entry)
Definition: xasl_cache.c:1083
int logtb_tran_update_btid_unique_stats(THREAD_ENTRY *thread_p, const BTID *btid, int n_keys, int n_oids, int n_nulls)
bool tran_get_check_interrupt(void)
LOG_TRAN_BTID_UNIQUE_STATS_CHUNK * next_chunk
Definition: log_impl.h:396
#define OR_XASL_ID_SIZE
Definition: xasl.h:578
#define TRAN_LOCK_INFINITE_WAIT
Definition: log_comm.h:29
LOG_LSA savept_lsa
Definition: log_impl.h:478
multi_index_unique_stats m_multiupd_stats
Definition: log_impl.h:494
void logtb_undefine_trantable(THREAD_ENTRY *thread_p)
DB_TRAN_ISOLATION
Definition: dbtran_def.h:26
void reset()
Definition: mvcc.c:691
#define CACHE_TIME_AS_ARGS(ct)
Definition: cache_time.h:35
int db_Disable_modifications
Definition: db_macro.c:90
int lock_initialize(void)
MVCC_INFO mvccinfo
Definition: log_impl.h:463
int logtb_tran_prepare_count_optim_classes(THREAD_ENTRY *thread_p, const char **classes, LC_PREFETCH_FLAGS *flags, int n_classes)
bool logtb_has_updated(THREAD_ENTRY *thread_p)
std::string db_user
volatile sig_atomic_t num_interrupts
Definition: log_impl.h:592
short volid
Definition: dbtype_def.h:880
mvcc_active_tran m_active_mvccs
Definition: mvcc.h:174
LOG_LSA last_log_lsa
Definition: log_impl.h:623
int xlogtb_get_mvcc_snapshot(THREAD_ENTRY *thread_p)
void logtb_initialize_tdes(LOG_TDES *tdes, int tran_index)
int num_prepared_loose_end_indices
Definition: log_impl.h:586
LOG_LSA posp_nxlsa
Definition: log_impl.h:476
#define heap_classrepr_free_and_init(class_repr, idxp)
Definition: heap_file.h:91
MVCC_SNAPSHOT * logtb_get_mvcc_snapshot(THREAD_ENTRY *thread_p)
std::int64_t pageid
Definition: log_lsa.hpp:36
LOG_TDES * logtb_rv_find_allocate_tran_index(THREAD_ENTRY *thread_p, TRANID trid, const LOG_LSA *log_lsa)
MVCCID logtb_get_current_mvccid(THREAD_ENTRY *thread_p)
static void cleanup(int signo)
Definition: broker.c:717
static log_tdes * rv_get_or_alloc_tdes(TRANID trid)
INT64 LOG_PAGEID
int logtb_find_wait_msecs(int tran_index)
void * mht_get(MHT_TABLE *ht, const void *key)
Definition: memory_hash.c:1419
LF_TRAN_SYSTEM global_unique_stats_Ts
Definition: lock_free.c:52
#define NULL
Definition: freelistheap.h:34
int logtb_collect_local_clients(int **local_clients_pids)
UINT64 MVCCID
bool is_user_active
Definition: log_impl.h:539
int lf_hash_find_or_insert(LF_TRAN_ENTRY *tran, LF_HASH_TABLE *table, void *key, void **entry, int *inserted)
Definition: lock_free.c:2101
stat_type get_null_count() const
static int logtb_initialize_system_tdes(THREAD_ENTRY *thread_p)
int num_unique_btrees
Definition: log_impl.h:492
int num_log_records_written
Definition: log_impl.h:532
#define rmutex_lock(a, b)
void tsc_getticks(TSC_TICKS *tck)
Definition: tsc_timer.c:81
bool logtb_is_current_active(THREAD_ENTRY *thread_p)
STATIC_INLINE bool perfmon_is_perf_tracking(void) __attribute__((ALWAYS_INLINE))
VFID vfid
int logtb_find_client_type(int tran_index)
void pgbuf_force_to_check_for_interrupts(void)
Definition: page_buffer.c:4750
int logtb_find_interrupt(int tran_index, bool *interrupt)
bool LSA_ISNULL(const log_lsa *lsa_ptr)
Definition: log_lsa.hpp:153
static bool logtb_is_interrupted_tdes(THREAD_ENTRY *thread_p, LOG_TDES *tdes, bool clear, bool *continue_checking)
#define BTID_SET_NULL(btid)
LC_FIND_CLASSNAME
unsigned int of_mutex
Definition: lock_free.h:78
bool logtb_set_check_interrupt(THREAD_ENTRY *thread_p, bool flag)
LF_ENTRY_DUPLICATE_KEY_HANDLER f_duplicate
Definition: lock_free.h:106
void initialize()
Definition: mvcc_table.cpp:183
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
#define OR_PUT_BTID(ptr, btid)
static int logtb_global_unique_stat_free(void *unique_stat)
const char * logtb_find_client_name(int tran_index)
int lf_freelist_init(LF_FREELIST *freelist, int initial_blocks, int block_size, LF_ENTRY_DESCRIPTOR *edesc, LF_TRAN_SYSTEM *tran_system)
Definition: lock_free.c:666
LOG_LSA head_lsa
Definition: log_impl.h:472
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
#define COS_CLASSES_CHUNK_SIZE
Definition: log_impl.h:410
std::string program_name
void partition_init_pruning_context(PRUNING_CONTEXT *pinfo)
Definition: partition.c:2164
static int logtb_expand_trantable(THREAD_ENTRY *thread_p, int num_new_indices)
static void logtb_free_tran_mvcc_info(LOG_TDES *tdes)
void logtb_free_tran_index(THREAD_ENTRY *thread_p, int tran_index)
LOG_UNIQUE_STATS tran_stats
Definition: log_impl.h:376
DB_VALUE * showstmt_alloc_tuple_in_context(THREAD_ENTRY *thread_p, SHOWSTMT_ARRAY_CONTEXT *ctx)
Definition: show_scan.c:402
LOG_LSA analysis_last_aborted_sysop_start_lsa
Definition: log_impl.h:456
LF_HASH_TABLE unique_stats_hash
Definition: log_impl.h:631
stat_type get_row_count() const
bool logtb_istran_finished(THREAD_ENTRY *thread_p, TRANID trid)
unsigned int oid_hash(const void *key_oid, unsigned int htsize)
Definition: oid.c:294
static void logtb_assign_subtransaction_mvccid(THREAD_ENTRY *thread_p, MVCC_INFO *curr_mvcc_info, MVCCID mvcc_subid)
OR_PARTITION * partitions
Definition: partition_sr.h:76
int * ack_received
Definition: log_2pc.h:69
#define NULL_OFFSET
int using_mutex
Definition: lock_free.h:81
need_clear_type need_clear
Definition: dbtype_def.h:1084
CLIENTIDS client
Definition: log_impl.h:484
#define LOG_SET_CURRENT_TRAN_INDEX(thrd, index)
Definition: log_impl.h:178
OR_CLASSREP * heap_classrepr_get(THREAD_ENTRY *thread_p, const OID *class_oid, RECDES *class_recdes, REPR_ID reprid, int *idx_incache)
Definition: heap_file.c:2299
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
#define ER_LOG_UNKNOWN_TRANINDEX
Definition: error_code.h:913
void init()
Definition: mvcc.c:685
static void logtb_increment_number_of_assigned_tran_indices()
void logtb_set_to_system_tran_index(THREAD_ENTRY *thread_p)
#define LOG_ISTRAN_2PC_INFORMING_PARTICIPANTS(tdes)
Definition: log_impl.h:220
EXECUTION_INFO sql_info
Definition: xasl_cache.h:103
int hint_free_index
Definition: log_impl.h:587
XASL_ID xasl_id
Definition: log_impl.h:522
TRAN_ISOLATION logtb_find_isolation(int tran_index)
struct log_repl * repl_records
Definition: log_impl.h:509
#define NULL_REPRID
void * info_data
Definition: log_2pc.h:60
void heap_chnguess_clear(THREAD_ENTRY *thread_p, int tran_index)
Definition: heap_file.c:15416
int oid_compare_equals(const void *key_oid1, const void *key_oid2)
Definition: oid.c:310
#define LOG_ISTRAN_2PC_PREPARE(tdes)
Definition: log_impl.h:217
int logtb_find_current_client_type(THREAD_ENTRY *thread_p)
#define CAST_BUFLEN
Definition: porting.h:471
#define NULL_TRAN_INDEX
void map_entries(Func &&func, Args &&...args)
DB_VALUE_ARRAY bind_history[MAX_NUM_EXEC_QUERY_HISTORY]
Definition: log_impl.h:530
static int logtb_load_global_statistics_to_tran(THREAD_ENTRY *thread_p)
bool LOG_CS_OWN_WRITE_MODE(THREAD_ENTRY *thread_p)
int append_repl_recidx
Definition: log_impl.h:507
static void error(const char *msg)
Definition: gencat.c:331
LF_ENTRY_HASH_FUNC f_hash
Definition: lock_free.h:102
LOG_TRAN_BTID_UNIQUE_STATS buffer[1]
Definition: log_impl.h:397
static LOG_ADDR_TDESAREA * logtb_allocate_tdes_area(int num_indices)
char * or_pack_int(char *ptr, int number)
STATIC_INLINE void perfmon_inc_stat(THREAD_ENTRY *thread_p, PERF_STAT_ID psid) __attribute__((ALWAYS_INLINE))
const char * log_isolation_string(TRAN_ISOLATION isolation)
Definition: log_comm.c:176
void logtb_set_current_tran_index(THREAD_ENTRY *thread_p, int tran_index)
LOG_TDES * LOG_FIND_CURRENT_TDES(THREAD_ENTRY *thread_p=NULL)
Definition: log_impl.h:1115
int logtb_delete_global_unique_stats(THREAD_ENTRY *thread_p, BTID *btid)
#define LOG_FIND_THREAD_TRAN_INDEX(thrd)
Definition: perf_monitor.h:158
INT64 tran_start_time
Definition: log_impl.h:521
int fl_mark_repl_recidx
Definition: log_impl.h:508
#define ARG_FILE_LINE
Definition: error_manager.h:44
static int logtb_global_unique_stat_init(void *unique_stat)
LF_ENTRY_ALLOC_FUNC f_alloc
Definition: lock_free.h:84
#define ER_MVCC_LOG_INVALID_ISOLATION_LEVEL
Definition: error_code.h:1483
LOG_TDES * logtb_get_system_tdes(THREAD_ENTRY *thread_p)
bool logtb_is_current_mvccid(THREAD_ENTRY *thread_p, MVCCID mvccid)
int lock_get_lock_holder_tran_index(THREAD_ENTRY *thread_p, char **out_buf, int waiter_index, LK_RES *res)
#define BOOT_WRITE_ON_STANDY_CLIENT_TYPE(client_type)
Definition: boot.h:81
LOG_TOPOPS_STACK topops
Definition: log_impl.h:486
bool is_zero() const
int wait_msecs
Definition: log_impl.h:471
bool logtb_check_class_for_rr_isolation_err(const OID *class_oid)
void * first_save_entry
Definition: log_impl.h:512
const char * get_login_name() const
LOG_ADDR_TDESAREA * area
Definition: log_impl.h:594
char * sql_hash_text
Definition: xasl_cache.h:76
MHT_TABLE * classes_cos_hash
Definition: log_impl.h:432
const char * get_db_user() const
#define BTREE_MAX_ALIGN
Definition: btree_load.h:66
int logtb_get_number_of_total_tran_indices(void)
bool isloose_end
Definition: log_impl.h:468
void lock_global_oldest_visible()
Definition: mvcc_table.cpp:633
struct log_tdes LOG_TDES
Definition: log_impl.h:459
static void logtb_tran_clear_update_stats(LOG_TRAN_UPDATE_STATS *log_upd_stats)
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define LOG_ISRESTARTED()
Definition: log_impl.h:232
#define DB_ALIGN(offset, align)
Definition: memory_alloc.h:84
LOG_LSA repl_insert_lsa
Definition: log_impl.h:510
#define strlen(s1)
Definition: intl_support.c:43
#define BTID_COPY(btid_ptr1, btid_ptr2)
int logtb_initialize_global_unique_stats_table(THREAD_ENTRY *thread_p)
int xlogtb_reset_isolation(THREAD_ENTRY *thread_p, TRAN_ISOLATION isolation)
void LSA_SET_NULL(log_lsa *lsa_ptr)
Definition: log_lsa.hpp:146
char * or_pack_string_with_length(char *ptr, const char *string, int length)
bool pgbuf_is_page_fixed_by_thread(THREAD_ENTRY *thread_p, const VPID *vpid_p)
LOG_UNIQUE_STATS unique_stats
Definition: log_impl.h:622
TRANID trid
Definition: log_impl.h:466
LF_FREELIST unique_stats_freelist
Definition: log_impl.h:633
int db_make_string_copy(DB_VALUE *value, DB_CONST_C_CHAR str)
bool LSA_GT(const log_lsa *plsa1, const log_lsa *plsa2)
Definition: log_lsa.hpp:188
LOG_RCV_TDES rcv
Definition: log_impl.h:541
int logtb_count_not_allowed_clients_in_maintenance_mode(THREAD_ENTRY *thread_p)
bool logpb_is_pool_initialized(void)
int suppress_replication
Definition: log_impl.h:514
void lf_freelist_destroy(LF_FREELIST *freelist)
Definition: lock_free.c:711
MVCC_SNAPSHOT snapshot
Definition: mvcc.h:194
INT64 query_timeout
Definition: log_impl.h:518
bool prm_get_bool_value(PARAM_ID prm_id)
#define INT_ALIGNMENT
Definition: memory_alloc.h:61
#define OR_PUT_INT(ptr, val)
static LOG_TRAN_BTID_UNIQUE_STATS * logtb_tran_create_btid_unique_stats(THREAD_ENTRY *thread_p, const BTID *btid)
int logtb_rv_update_global_unique_stats_by_abs(THREAD_ENTRY *thread_p, BTID *btid, int num_oids, int num_nulls, int num_keys)
static int logtb_tran_reset_cos_func(THREAD_ENTRY *thread_p, void *data, void *args)
LOG_TRAN_CLASS_COS_CHUNK * cos_first_chunk
Definition: log_impl.h:430
volatile sig_atomic_t interrupt
Definition: log_impl.h:498
int file_get_tran_num_temp_files(THREAD_ENTRY *thread_p)
void reset_transaction_lowest_active(int tran_index)
Definition: mvcc_table.cpp:594
void logtb_complete_sub_mvcc(THREAD_ENTRY *thread_p, LOG_TDES *tdes)
LOG_2PC_GTRINFO gtrinfo
Definition: log_impl.h:488
const size_t LOG_USERNAME_MAX
const container_type & get_map() const
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
static void logtb_initialize_trantable(TRANTABLE *trantable_p)
std::string host_name
bool oid_check_cached_class_oid(const int cache_id, const OID *oid)
Definition: oid.c:327
#define XASL_ID_IS_NULL(X)
Definition: xasl.h:560
bool logtb_is_interrupted_tran(THREAD_ENTRY *thread_p, bool clear, bool *continue_checking, int tran_index)
void to_string(string_buffer &strbuf) const
#define NULL_ATTRID
int num_transient_classnames
Definition: log_impl.h:504
#define ER_CSS_CONN_SHUTDOWN
Definition: error_code.h:1018
void alloc_transaction_lowest_active()
Definition: mvcc_table.cpp:198
#define IS_VALID_ISOLATION_LEVEL(isolation_level)
Definition: dbtran_def.h:54
static void logtb_set_number_of_assigned_tran_indices(int num_trans)
LOG_TOPOPS_ADDRESSES * stack
Definition: log_impl.h:351
STATIC_INLINE void perfmon_add_stat(THREAD_ENTRY *thread_p, PERF_STAT_ID psid, UINT64 amount) __attribute__((ALWAYS_INLINE))
char * strdup(const char *str)
Definition: porting.c:901
TRAN_ISOLATION isolation
Definition: log_impl.h:470
int lf_hash_delete(LF_TRAN_ENTRY *tran, LF_HASH_TABLE *table, void *key, int *success)
Definition: lock_free.c:2181
TRAN_STATE state
Definition: log_impl.h:469
TRAN_STATE
Definition: log_comm.h:36
#define BTID_IS_NULL(btid)
LK_RES * waiting_for_res
Definition: log_impl.h:523
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
int db_make_int(DB_VALUE *value, const int num)
bool logtb_set_tran_index_interrupt(THREAD_ENTRY *thread_p, int tran_index, bool set)
void logtb_complete_mvcc(THREAD_ENTRY *thread_p, LOG_TDES *tdes, bool committed)
int qmgr_get_sql_id(THREAD_ENTRY *thread_p, char **sql_id_buf, char *query, size_t sql_len)
short volid
Definition: dbtype_def.h:887
void thread_wakeup(cubthread::entry *thread_p, thread_resume_suspend_status resume_reason)
#define VOLATILE_ACCESS(v, t)
Definition: area_alloc.c:85
#define ER_CSS_KILL_UNKNOWN_TRANSACTION
Definition: error_code.h:849
int logtb_find_tran_index(THREAD_ENTRY *thread_p, TRANID trid)
char * sql_user_text
Definition: xasl_cache.h:77
#define OID_ISNULL(oidp)
Definition: oid.h:81
TRANID next_trid
LOG_TRAN_CLASS_COS_CHUNK * cos_current_chunk
Definition: log_impl.h:431
#define MVCCID_FORWARD(id)
void logpb_finalize_pool(THREAD_ENTRY *thread_p)
#define rmutex_initialize(a, b)
void file_manager_final(void)
Definition: file_manager.c:869
#define CUB_MAXHOSTNAMELEN
Definition: porting.h:379
void set_ids(db_client_type type, const char *client_info, const char *db_user, const char *program_name, const char *login_name, const char *host_name, int process_id)
std::string login_name
LOG_LSA * logtb_find_current_tran_lsa(THREAD_ENTRY *thread_p)
int xlogtb_kill_or_interrupt_tran(THREAD_ENTRY *thread_p, int tran_index, bool is_dba_group_member, bool interrupt_only)
static int logtb_tran_load_global_stats_func(THREAD_ENTRY *thread_p, void *data, void *args)
LOG_LSA tran_start_postpone_lsa
Definition: log_impl.h:450
std::vector< MVCCID > sub_ids
Definition: mvcc.h:205
#define TR_TABLE_CS_EXIT(thread_p)
Definition: log_impl.h:90
void logtb_rv_assign_mvccid_for_undo_recovery(THREAD_ENTRY *thread_p, MVCCID mvccid)
#define XASL_ID_SET_NULL(X)
Definition: xasl.h:546
struct log_tran_class_cos LOG_TRAN_CLASS_COS
Definition: log_impl.h:403
static const unsigned int LOGTB_RETRY_SLAM_MAX_TIMES
static int logtb_check_kill_tran_auth(THREAD_ENTRY *thread_p, int tran_id, bool *has_authorization)
static void * logtb_global_unique_stat_alloc(void)
THREAD_ENTRY * logtb_find_thread_by_tran_index_except_me(int tran_index)
void db_localdatetime_msec(time_t *epoch_time, int millisecond, DB_DATETIME *datetime)
Definition: db_date.c:1044
bool btree_is_unique_type(BTREE_TYPE type)
Definition: btree.c:6046
#define MVCCID_IS_VALID(id)
#define LF_EM_USING_MUTEX
Definition: lock_free.h:60
LOG_LSA atomic_sysop_start_lsa
Definition: log_impl.h:454
static void map_all_tdes(const map_func &func)
enum tran_abort_reason TRAN_ABORT_REASON
Definition: log_impl.h:360
std::int64_t offset
Definition: log_lsa.hpp:37
void complete_sub_mvcc(MVCCID mvccid)
Definition: mvcc_table.cpp:542
bool tran_set_check_interrupt(bool flag)
#define ER_CSS_KILL_DOES_NOTMATCH
Definition: error_code.h:850
static void logtb_dump_tdes_distribute_transaction(FILE *out_fp, int global_tran_id, LOG_2PC_COORDINATOR *coord)
const TRANID LOG_SYSTEM_TRANID
struct log_tran_class_cos_chunk LOG_TRAN_CLASS_COS_CHUNK
Definition: log_impl.h:415
int xlogtb_get_pack_tran_table(THREAD_ENTRY *thread_p, char **buffer_p, int *size_p, int include_query_exec_info)
MVCCID get_new_mvccid()
Definition: mvcc_table.cpp:567
TRANID logtb_find_tranid(int tran_index)
#define MAX_NUM_EXEC_QUERY_HISTORY
Definition: log_impl.h:275
unsigned int of_key
Definition: lock_free.h:75
int client_id
void clear(cub_regex_object *&regex, char *&pattern)
#define TRAN_UNIQUE_STATS_CHUNK_SIZE
Definition: log_impl.h:388
#define OR_PACK_XASL_ID(PTR, X)
Definition: xasl.h:581