From b59b5a22a9c4277d74f79e32d17be1157e3f3c7b Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Wed, 4 Dec 2024 17:50:41 +0900 Subject: [PATCH 01/20] init --- cubrid/CMakeLists.txt | 1 + sa/CMakeLists.txt | 1 + src/query/parallel_heap_scan.cpp | 86 ++++++++++++++++++++++++++++++++ src/query/parallel_heap_scan.hpp | 29 +++++++++++ 4 files changed, 117 insertions(+) create mode 100644 src/query/parallel_heap_scan.cpp create mode 100644 src/query/parallel_heap_scan.hpp diff --git a/cubrid/CMakeLists.txt b/cubrid/CMakeLists.txt index 9d1b8f8b215..db6e5334197 100644 --- a/cubrid/CMakeLists.txt +++ b/cubrid/CMakeLists.txt @@ -253,6 +253,7 @@ set(QUERY_SOURCES ${QUERY_DIR}/string_regex_re2.cpp ${QUERY_DIR}/vacuum.c ${QUERY_DIR}/xasl_cache.c + ${QUERY_DIR}/parallel_heap_scan.cpp ) set(QUERY_HEADERS ${QUERY_DIR}/query_aggregate.hpp diff --git a/sa/CMakeLists.txt b/sa/CMakeLists.txt index bd781365546..71c4e30f233 100644 --- a/sa/CMakeLists.txt +++ b/sa/CMakeLists.txt @@ -285,6 +285,7 @@ set(QUERY_SOURCES ${QUERY_DIR}/vacuum.c ${QUERY_DIR}/xasl_cache.c ${QUERY_DIR}/xasl_to_stream.c + ${QUERY_DIR}/parallel_heap_scan.cpp ) set(QUERY_HEADERS ${QUERY_DIR}/query_aggregate.hpp diff --git a/src/query/parallel_heap_scan.cpp b/src/query/parallel_heap_scan.cpp new file mode 100644 index 00000000000..ee8cf667b8b --- /dev/null +++ b/src/query/parallel_heap_scan.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2008 Search Solution Corporation + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * subquery_cache.c - Correlated Scalar Subquery Result Cache. + */ + + +#ident "$Id$" +#include +#include +#include +#include "parallel_heap_scan.hpp" + +#include "thread_manager.hpp" +#include "thread_entry_task.hpp" +#include "memory_alloc.h" +#include "memory_private_allocator.hpp" +#include "xasl.h" + +#include "regu_var.hpp" + + +// XXX: SHOULD BE THE LAST INCLUDE HEADER +#include "memory_wrapper.hpp" + +static int regu_var_list_len (REGU_VARIABLE_LIST list); +static int regu_var_list_capture_to_dbvalue_array (REGU_VARIABLE_LIST list, DB_VALUE_ARRAY *dbvalue_array); +static int dbvalue_array_copy_to_regu_var_list (DB_VALUE_ARRAY *dbvalue_array, REGU_VARIABLE_LIST *list); +static REGU_VARIABLE_LIST regu_var_list_clone (REGU_VARIABLE_LIST *list); + +class ParallelHeapScanResultQueueEntry +{ + public: + DB_VALUE_ARRAY pred_val_array; + DB_VALUE_ARRAY rest_val_array; + SCAN_CODE scan_code; + OID curr_oid; + bool valid; + + int capture_pred_regu_var_list (REGU_VARIABLE_LIST *list); + int capture_rest_regu_var_list (REGU_VARIABLE_LIST *list); + int copy_to_pred_regu_var_list (REGU_VARIABLE_LIST *list); + int copy_to_rest_regu_var_list (REGU_VARIABLE_LIST *list); + +}; + +class ParallelHeapScanResultQueue +{ + public: + ParallelHeapScanResultQueueEntry entries[HP_RESULT_QUEUE_SIZE]; + std::mutex mutex; + std::condition_variable cond; + int start; + int end; + int waiting; + + static int init (); + static void destroy (); + static int clear (); + static bool isFull (); + static bool isEmpty (); + static int enqueue (ParallelHeapScanResultQueueEntry *entry); + static int dequeue (ParallelHeapScanResultQueueEntry *entry); +}; + + + + + + diff --git a/src/query/parallel_heap_scan.hpp b/src/query/parallel_heap_scan.hpp new file mode 100644 index 00000000000..056c117b294 --- /dev/null +++ b/src/query/parallel_heap_scan.hpp @@ -0,0 +1,29 @@ +/* + * Copyright 2008 Search Solution Corporation + * Copyright 2016 CUBRID Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * parallel_heap_scan.hpp - Parallel Heap Scan. + */ + +#ifndef _PARALLEL_HEAP_SCAN_H_ +#define _PARALLEL_HEAP_SCAN_H_ + +#define HP_PARALLELISM 1 +#define HP_RESULT_QUEUE_SIZE 11 + +#endif /* _PARALLEL_HEAP_SCAN_H_ */ From 91c54f3f5e19c30d3409e046857d02fc2c20a05e Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Mon, 9 Dec 2024 14:12:00 +0900 Subject: [PATCH 02/20] add classes --- src/query/parallel_heap_scan.cpp | 666 ++++++++++++++++++++++++++++++- 1 file changed, 645 insertions(+), 21 deletions(-) diff --git a/src/query/parallel_heap_scan.cpp b/src/query/parallel_heap_scan.cpp index ee8cf667b8b..a634a5047be 100644 --- a/src/query/parallel_heap_scan.cpp +++ b/src/query/parallel_heap_scan.cpp @@ -32,19 +32,61 @@ #include "memory_alloc.h" #include "memory_private_allocator.hpp" #include "xasl.h" +#include "scan_manager.h" +#include "dbtype.h" +#include "query_reevaluation.hpp" +#include "oid.h" #include "regu_var.hpp" + // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" +#define HP_USE_PRIVATE_ALLOC 0 // 0으로 설정하면 malloc 사용 + +#if HP_USE_PRIVATE_ALLOC +#define HP_ALLOC(thrd, size) db_private_alloc(thrd, size) +#define HP_FREE(thrd, ptr) db_private_free(thrd, ptr) +#else +#define HP_ALLOC(thrd, size) malloc(size) +#define HP_FREE(thrd, ptr) free(ptr) +#endif + static int regu_var_list_len (REGU_VARIABLE_LIST list); -static int regu_var_list_capture_to_dbvalue_array (REGU_VARIABLE_LIST list, DB_VALUE_ARRAY *dbvalue_array); -static int dbvalue_array_copy_to_regu_var_list (DB_VALUE_ARRAY *dbvalue_array, REGU_VARIABLE_LIST *list); static REGU_VARIABLE_LIST regu_var_list_clone (REGU_VARIABLE_LIST *list); -class ParallelHeapScanResultQueueEntry +static SCAN_CODE scan_next_heap_scan_1page_internal (THREAD_ENTRY *thread_p, SCAN_ID *scan_id, VPID *curr_vpid); + +class parallel_heap_scan_context : public cubthread::entry_manager +{ + public: + std::atomic m_tasks_executed; + int m_error_code; + css_conn_entry *m_conn; + int m_orig_tran_index; + parallel_heap_scan_context () = default; + + protected: + void on_create (context_type &context); + void on_retire (context_type &context); + void on_recycle (context_type &context); +}; + +class parallel_heap_scan_task : public cubthread::entry_task +{ + public: + parallel_heap_scan_task () = delete; + parallel_heap_scan_task (parallel_heap_scan_context &context); + ~parallel_heap_scan_task (); + + void execute (cubthread::entry &thread_ref); +}; + +/*************************************************************************************************/ +/* parallel_heap_scan_result_queue_entry */ +class parallel_heap_scan_result_queue_entry { public: DB_VALUE_ARRAY pred_val_array; @@ -52,35 +94,617 @@ class ParallelHeapScanResultQueueEntry SCAN_CODE scan_code; OID curr_oid; bool valid; - - int capture_pred_regu_var_list (REGU_VARIABLE_LIST *list); - int capture_rest_regu_var_list (REGU_VARIABLE_LIST *list); - int copy_to_pred_regu_var_list (REGU_VARIABLE_LIST *list); - int copy_to_rest_regu_var_list (REGU_VARIABLE_LIST *list); + int capture_pred_regu_var_list (REGU_VARIABLE_LIST list); + int capture_rest_regu_var_list (REGU_VARIABLE_LIST list); + int copy_to_pred_regu_var_list (REGU_VARIABLE_LIST list); + int copy_to_rest_regu_var_list (REGU_VARIABLE_LIST list); + void init (int n_pred_val, int n_rest_val); + void clear (); + + private: + void capture_regu_var_list (REGU_VARIABLE_LIST list, DB_VALUE_ARRAY *dbvalue_array); + void copy_to_regu_var_list (DB_VALUE_ARRAY *dbvalue_array, REGU_VARIABLE_LIST list); }; -class ParallelHeapScanResultQueue +void parallel_heap_scan_result_queue_entry::capture_regu_var_list (REGU_VARIABLE_LIST list, + DB_VALUE_ARRAY *dbvalue_array) +{ + REGU_VARIABLE_LIST iter = list; + for (int i = 0; i < dbvalue_array->size; i++) + { + assert (iter); + db_value_clone (iter->value.vfetch_to, &dbvalue_array->vals[i]); + iter = iter->next; + } + return; +} + +void parallel_heap_scan_result_queue_entry::copy_to_regu_var_list (DB_VALUE_ARRAY *dbvalue_array, + REGU_VARIABLE_LIST list) +{ + REGU_VARIABLE_LIST iter = list; + for (int i = 0; i < dbvalue_array->size; i++) + { + assert (iter); + if (!DB_IS_NULL (iter->value.vfetch_to)) + { + pr_clear_value (iter->value.vfetch_to); + } + db_value_clone (&dbvalue_array->vals[i], iter->value.vfetch_to); + iter = iter->next; + } + return; +} + +int parallel_heap_scan_result_queue_entry::capture_pred_regu_var_list (REGU_VARIABLE_LIST list) +{ + capture_regu_var_list (list, &pred_val_array); +} + +int parallel_heap_scan_result_queue_entry::capture_rest_regu_var_list (REGU_VARIABLE_LIST list) +{ + capture_regu_var_list (list, &rest_val_array); +} + +int parallel_heap_scan_result_queue_entry::copy_to_pred_regu_var_list (REGU_VARIABLE_LIST list) +{ + copy_to_regu_var_list (&pred_val_array, list); +} + +int parallel_heap_scan_result_queue_entry::copy_to_rest_regu_var_list (REGU_VARIABLE_LIST list) +{ + copy_to_regu_var_list (&rest_val_array, list); +} + +void parallel_heap_scan_result_queue_entry::init (THREAD_ENTRY *thread_p, int n_pred_val, int n_rest_val) +{ + pred_val_array.size = n_pred_val; + pred_val_array.vals = (DB_VALUE *)HP_ALLOC (thread_p, n_pred_val * sizeof (DB_VALUE)); + rest_val_array.size = n_rest_val; + rest_val_array.vals = (DB_VALUE *)HP_ALLOC (thread_p, n_rest_val * sizeof (DB_VALUE)); + scan_code = S_END; + valid = false; + curr_oid = {0,0,0}; +} +void parallel_heap_scan_result_queue_entry::clear () +{ + db_value_clear_array (&pred_val_array); + db_value_clear_array (&rest_val_array); + scan_code = S_END; + valid = false; + curr_oid = {0,0,0}; +} + +/*************************************************************************************************/ + +/* parallel_heap_scan_result_queue */ +class parallel_heap_scan_result_queue { public: - ParallelHeapScanResultQueueEntry entries[HP_RESULT_QUEUE_SIZE]; - std::mutex mutex; - std::condition_variable cond; - int start; - int end; - int waiting; - - static int init (); - static void destroy (); - static int clear (); + parallel_heap_scan_result_queue_entry entries[HP_RESULT_QUEUE_SIZE]; + class parallel_heap_scan_result_queue_variable + { + public: + int start; + int end; + bool waiting; + int n_entry; + std::mutex mutex; + std::condition_variable cond; + }; + + THREAD_ENTRY *owner_thread_p; + + static parallel_heap_scan_result_queue_variable var; + + ~parallel_heap_scan_result_queue (); + + static int init (THREAD_ENTRY *thread_p, int n_pred, int n_rest); + static void clear (); static bool isFull (); static bool isEmpty (); - static int enqueue (ParallelHeapScanResultQueueEntry *entry); - static int dequeue (ParallelHeapScanResultQueueEntry *entry); + static int enqueue (HEAP_SCAN_ID *hsidp, SCAN_CODE scan_code); + static int dequeue (HEAP_SCAN_ID *hsidp, SCAN_CODE *scan_code); + static int dequeue_immediate (HEAP_SCAN_ID *hsidp, SCAN_CODE *scan_code); + + private: + static void lock () + { + std::lock_guard lock (var.mutex); + } + static void unlock () + { + var.mutex.unlock(); + } + static void wait() + { + var.cond.wait (var.mutex); + } + static void signal() + { + var.cond.notify_one(); + } }; +int parallel_heap_scan_result_queue::init (THREAD_ENTRY *thread_p, int n_pred, int n_rest) +{ + owner_thread_p = thread_p; + for (int i = 0; i < HP_RESULT_QUEUE_SIZE; i++) + { + entries[i].init (owner_thread_p, n_pred, n_rest); + } + lock(); + var.start = var.end = 0; + var.waiting = false; + unlock(); +} +void parallel_heap_scan_result_queue::clear () +{ + lock(); + for (int i = 0; i < HP_RESULT_QUEUE_SIZE; i++) + { + if (entries[i].valid) + { + entries[i].clear (); + } + } + unlock(); +} + +parallel_heap_scan_result_queue::~parallel_heap_scan_result_queue () +{ + clear (); +} + +bool parallel_heap_scan_result_queue::isFull () +{ + return (var.start == (var.end + 1) % HP_RESULT_QUEUE_SIZE); +} +bool parallel_heap_scan_result_queue::isEmpty () +{ + return (var.start == var.end); +} +int parallel_heap_scan_result_queue::enqueue (HEAP_SCAN_ID *hsidp, SCAN_CODE scan_code) +{ + bool need_signal; + lock(); + if (isFull()) + { + var.waiting = true; + wait(); + var.waiting = false; + } + + var.end = (var.end + 1) % HP_RESULT_QUEUE_SIZE; + if (entries[var.end].valid) + { + entries[var.end].clear (); + } + /* copy data from scan_id */ + entries[var.end].valid = true; + entries[var.end].scan_code = scan_code; + COPY_OID (&entries[var.end].curr_oid, &hsidp->curr_oid); + entries[var.end].capture_pred_regu_var_list (hsidp->scan_pred.regu_list); + entries[var.end].capture_rest_regu_var_list (hsidp->rest_regu_list); + + need_signal = var.waiting; + unlock(); + if (need_signal) + { + signal(); + } + return NO_ERROR; +} +int parallel_heap_scan_result_queue::dequeue (HEAP_SCAN_ID *hsidp, SCAN_CODE *scan_code) +{ + bool need_signal; + if (isEmpty()) + { + var.waiting = true; + wait(); + var.waiting = false; + } + + var.start = (var.start + 1) % HP_RESULT_QUEUE_SIZE; + /* copy data from queue */ + entries[var.start].valid = true; + entries[var.start].copy_to_pred_regu_var_list (hsidp->scan_pred.regu_list); + entries[var.start].copy_to_rest_regu_var_list (hsidp->rest_regu_list); + COPY_OID (&entries[var.start].curr_oid, &hsidp->curr_oid); + *scan_code = entries[var.start].scan_code; + + need_signal = var.waiting; + unlock(); + if (need_signal) + { + signal(); + } + return NO_ERROR; +} + +int parallel_heap_scan_result_queue::dequeue_immediate (HEAP_SCAN_ID *hsidp, SCAN_CODE *scan_code) +{ + bool need_signal; + lock(); + if (isEmpty()) + { + unlock(); + return FALSE; + } + var.start = (var.start + 1) % HP_RESULT_QUEUE_SIZE; + /* copy data from queue */ + entries[var.start].valid = true; + entries[var.start].copy_to_pred_regu_var_list (hsidp->scan_pred.regu_list); + entries[var.start].copy_to_rest_regu_var_list (hsidp->rest_regu_list); + COPY_OID (&entries[var.start].curr_oid, &hsidp->curr_oid); + *scan_code = entries[var.start].scan_code; + + need_signal = var.waiting; + unlock(); + if (need_signal) + { + signal(); + } + return TRUE; +} + + + + +static int regu_var_list_len (REGU_VARIABLE_LIST list) +{ + int len = 0; + for (REGU_VARIABLE_LIST iter = list; iter; iter = iter->next) + { + len++; + } + return len; +} +static REGU_VARIABLE_LIST regu_var_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST src) +{ + REGU_VARIABLE_LIST dest_head = NULL; + REGU_VARIABLE_LIST dest_tail = NULL; + + REGU_VARIABLE_LIST current = src; + if (!src) + { + return NULL; + } + + while (current) + { + REGU_VARIABLE_LIST new_node = + (REGU_VARIABLE_LIST) db_private_alloc (thread_p, sizeof (struct regu_variable_list_node)); + if (!new_node) + { + REGU_VARIABLE_LIST temp = dest_head; + while (temp) + { + REGU_VARIABLE_LIST next = temp->next; + if (temp->value.vfetch_to) + { + pr_clear_value (temp->value.vfetch_to); + HP_FREE (thread_p, temp->value.vfetch_to); + } + HP_FREE (thread_p, temp); + temp = next; + } + return NULL; + } + + new_node->value = current->value; + new_node->value.vfetch_to = (DB_VALUE *) db_private_alloc (thread_p, sizeof (DB_VALUE)); + + /* should we clone value? */ + pr_clone_value (current->value.vfetch_to, new_node->value.vfetch_to); + + new_node->next = NULL; + + if (dest_tail) + { + dest_tail->next = new_node; + } + else + { + dest_head = new_node; + } + dest_tail = new_node; + + current = current->next; + } + + return dest_head; +} + +typedef enum +{ + OBJ_GET_WITHOUT_LOCK = 0, + OBJ_REPEAT_GET_WITH_LOCK = 1, + OBJ_GET_WITH_LOCK_COMPLETE = 2 +} OBJECT_GET_STATUS; + +static SCAN_CODE +scan_next_heap_scan_1page_internal (THREAD_ENTRY *thread_p, SCAN_ID *scan_id, VPID *curr_vpid) +{ + HEAP_SCAN_ID *hsidp; + FILTER_INFO data_filter; + RECDES recdes = RECDES_INITIALIZER; + SCAN_CODE sp_scan; + DB_LOGICAL ev_res; + OID current_oid, *p_current_oid = NULL; + MVCC_SCAN_REEV_DATA mvcc_sel_reev_data; + MVCC_REEV_DATA mvcc_reev_data; + UPDDEL_MVCC_COND_REEVAL upd_reev; + OID retry_oid; + LOG_LSA ref_lsa; + bool is_peeking; + OBJECT_GET_STATUS object_get_status; + regu_variable_list_node *p; + + hsidp = &scan_id->s.hsid; + if (scan_id->mvcc_select_lock_needed) + { + COPY_OID (¤t_oid, &hsidp->curr_oid); + p_current_oid = ¤t_oid; + } + else + { + p_current_oid = &hsidp->curr_oid; + } + + /* set data filter information */ + scan_init_filter_info (&data_filter, &hsidp->scan_pred, &hsidp->pred_attrs, scan_id->val_list, scan_id->vd, + &hsidp->cls_oid, 0, NULL, NULL, NULL); + + is_peeking = scan_id->fixed; + if (scan_id->grouped) + { + is_peeking = PEEK; + } + + if (data_filter.val_list) + { + for (p = data_filter.scan_pred->regu_list; p; p = p->next) + { + if (DB_NEED_CLEAR (p->value.vfetch_to)) + { + pr_clear_value (p->value.vfetch_to); + } + } + } + + while (1) + { + COPY_OID (&retry_oid, &hsidp->curr_oid); + object_get_status = OBJ_GET_WITHOUT_LOCK; + +restart_scan_oid: + + /* get next object */ + assert (!scan_id->grouped); + + { + recdes.data = NULL; + assert (scan_id->direction == S_FORWARD); + assert (scan_id->type == S_HEAP_SCAN); + { + sp_scan = + heap_next_1page (thread_p, &hsidp->hfid, curr_vpid, &hsidp->cls_oid, &hsidp->curr_oid, &recdes, + &hsidp->scan_cache, is_peeking); + } + } + + if (sp_scan != S_SUCCESS) + { + /* scan error or end of scan */ + return (sp_scan == S_END) ? S_END : S_ERROR; + } + + if (hsidp->scan_cache.page_watcher.pgptr != NULL) + { + LSA_COPY (&ref_lsa, pgbuf_get_lsa (hsidp->scan_cache.page_watcher.pgptr)); + } + + /* evaluate the predicates to see if the object qualifies */ + scan_id->scan_stats.read_rows++; + + ev_res = eval_data_filter (thread_p, p_current_oid, &recdes, &hsidp->scan_cache, &data_filter); + if (ev_res == V_ERROR) + { + return S_ERROR; + } + + if (is_peeking == PEEK && hsidp->scan_cache.page_watcher.pgptr != NULL + && PGBUF_IS_PAGE_CHANGED (hsidp->scan_cache.page_watcher.pgptr, &ref_lsa)) + { + is_peeking = COPY; + COPY_OID (&hsidp->curr_oid, &retry_oid); + goto restart_scan_oid; + } + + if (scan_id->qualification == QPROC_QUALIFIED) + { + if (ev_res != V_TRUE) /* V_FALSE || V_UNKNOWN */ + { + continue; /* not qualified, continue to the next tuple */ + } + } + else if (scan_id->qualification == QPROC_NOT_QUALIFIED) + { + if (ev_res != V_FALSE) /* V_TRUE || V_UNKNOWN */ + { + continue; /* qualified, continue to the next tuple */ + } + } + else if (scan_id->qualification == QPROC_QUALIFIED_OR_NOT) + { + if (ev_res == V_TRUE) + { + scan_id->qualification = QPROC_QUALIFIED; + } + else if (ev_res == V_FALSE) + { + scan_id->qualification = QPROC_NOT_QUALIFIED; + } + else /* V_UNKNOWN */ + { + /* nop */ + ; + } + } + else + { + /* invalid value; the same as QPROC_QUALIFIED */ + if (ev_res != V_TRUE) /* V_FALSE || V_UNKNOWN */ + { + continue; /* not qualified, continue to the next tuple */ + } + } + + /* Data filter passed. If object should be locked and is not locked yet, lock it. */ + assert (!scan_id->mvcc_select_lock_needed); + + if (mvcc_is_mvcc_disabled_class (&hsidp->cls_oid)) + { + LOCK lock = NULL_LOCK; + int tran_index = LOG_FIND_THREAD_TRAN_INDEX (thread_p); + TRAN_ISOLATION tran_isolation = logtb_find_isolation (tran_index); + + if (scan_id->scan_op_type == S_DELETE || scan_id->scan_op_type == S_UPDATE) + { + lock = X_LOCK; + } + else if (oid_is_serial (&hsidp->cls_oid)) + { + /* S_SELECT is currently handled only for serial, but may be extended to the other non-MVCC classes + * if needed */ + lock = S_LOCK; + } + + if (lock != NULL_LOCK && hsidp->scan_cache.page_watcher.pgptr != NULL) + { + if (tran_isolation == TRAN_READ_COMMITTED && lock == S_LOCK) + { + if (lock_hold_object_instant (thread_p, &hsidp->curr_oid, &hsidp->cls_oid, lock) == LK_GRANTED) + { + lock = NULL_LOCK; + /* object_need_rescan needs to be kept false (page is still fixed, no other transaction could + * have change it) */ + } + } + else + { + if (lock_object (thread_p, &hsidp->curr_oid, &hsidp->cls_oid, lock, LK_COND_LOCK) == LK_GRANTED) + { + /* successfully locked */ + lock = NULL_LOCK; + /* object_need_rescan needs to be kept false (page is still fixed, no other transaction could + * have change it) */ + } + } + } + + if (lock != NULL_LOCK) + { + VPID curr_vpid; + + VPID_SET_NULL (&curr_vpid); + + if (hsidp->scan_cache.page_watcher.pgptr != NULL) + { + pgbuf_get_vpid (hsidp->scan_cache.page_watcher.pgptr, &curr_vpid); + pgbuf_ordered_unfix (thread_p, &hsidp->scan_cache.page_watcher); + } + else + { + if (object_get_status == OBJ_GET_WITHOUT_LOCK) + { + /* page not fixed, recdes was read without lock, object may have changed */ + object_get_status = OBJ_REPEAT_GET_WITH_LOCK; + } + else if (object_get_status == OBJ_REPEAT_GET_WITH_LOCK) + { + /* already read with lock, set flag to continue scanning next object */ + object_get_status = OBJ_GET_WITH_LOCK_COMPLETE; + } + } + + if (lock_object (thread_p, &hsidp->curr_oid, &hsidp->cls_oid, lock, LK_UNCOND_LOCK) != LK_GRANTED) + { + return S_ERROR; + } + + if (!heap_does_exist (thread_p, NULL, &hsidp->curr_oid)) + { + /* not qualified, continue to the next tuple */ + lock_unlock_object_donot_move_to_non2pl (thread_p, &hsidp->curr_oid, &hsidp->cls_oid, lock); + continue; + } + + if (tran_isolation == TRAN_READ_COMMITTED && lock == S_LOCK) + { + /* release acquired lock in RC */ + lock_unlock_object_donot_move_to_non2pl (thread_p, &hsidp->curr_oid, &hsidp->cls_oid, lock); + } + + assert (hsidp->scan_cache.page_watcher.pgptr == NULL); + + if (!VPID_ISNULL (&curr_vpid) + && pgbuf_ordered_fix (thread_p, &curr_vpid, OLD_PAGE, PGBUF_LATCH_READ, + &hsidp->scan_cache.page_watcher) != NO_ERROR) + { + return S_ERROR; + } + + if (object_get_status == OBJ_REPEAT_GET_WITH_LOCK + || (hsidp->scan_cache.page_watcher.pgptr != NULL + && PGBUF_IS_PAGE_CHANGED (hsidp->scan_cache.page_watcher.pgptr, &ref_lsa))) + { + is_peeking = COPY; + COPY_OID (&hsidp->curr_oid, &retry_oid); + goto restart_scan_oid; + } + } + } + + scan_id->scan_stats.qualified_rows++; + if (hsidp->rest_regu_list) + { + /* read the rest of the values from the heap into the attribute cache */ + if (heap_attrinfo_read_dbvalues (thread_p, p_current_oid, &recdes, hsidp->rest_attrs.attr_cache) != NO_ERROR) + { + return S_ERROR; + } + if (is_peeking == PEEK && hsidp->scan_cache.page_watcher.pgptr != NULL + && PGBUF_IS_PAGE_CHANGED (hsidp->scan_cache.page_watcher.pgptr, &ref_lsa)) + { + is_peeking = COPY; + COPY_OID (&hsidp->curr_oid, &retry_oid); + goto restart_scan_oid; + } + /* fetch the rest of the values from the object instance */ + if (scan_id->val_list) + { + if (fetch_val_list (thread_p, hsidp->rest_regu_list, scan_id->vd, &hsidp->cls_oid, p_current_oid, NULL, + PEEK) != NO_ERROR) + { + return S_ERROR; + } + if (is_peeking != 0 && hsidp->scan_cache.page_watcher.pgptr != NULL + && PGBUF_IS_PAGE_CHANGED (hsidp->scan_cache.page_watcher.pgptr, &ref_lsa)) + { + is_peeking = COPY; + COPY_OID (&hsidp->curr_oid, &retry_oid); + goto restart_scan_oid; + } + } + } + return S_SUCCESS; + } +} \ No newline at end of file From e18c422cb940fa143c95088e21901cd9ac1dc415 Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Thu, 12 Dec 2024 15:32:18 +0900 Subject: [PATCH 03/20] private pred_expr, attr_caches --- src/query/parallel_heap_scan.cpp | 973 +++++++++++++++++++++++++++---- src/query/parallel_heap_scan.hpp | 53 ++ src/query/query_executor.c | 44 +- src/query/query_executor.h | 2 + src/query/scan_manager.c | 21 +- src/query/scan_manager.h | 24 + src/storage/heap_file.c | 184 ++++++ src/storage/heap_file.h | 2 + 8 files changed, 1179 insertions(+), 124 deletions(-) diff --git a/src/query/parallel_heap_scan.cpp b/src/query/parallel_heap_scan.cpp index a634a5047be..64593f95966 100644 --- a/src/query/parallel_heap_scan.cpp +++ b/src/query/parallel_heap_scan.cpp @@ -17,7 +17,7 @@ */ /* - * subquery_cache.c - Correlated Scalar Subquery Result Cache. + * parallel_heap_scan.cpp - Parallel Heap Scan */ @@ -27,17 +27,18 @@ #include #include "parallel_heap_scan.hpp" -#include "thread_manager.hpp" #include "thread_entry_task.hpp" #include "memory_alloc.h" #include "memory_private_allocator.hpp" #include "xasl.h" -#include "scan_manager.h" -#include "dbtype.h" #include "query_reevaluation.hpp" #include "oid.h" - +#include "heap_file.h" +#include "fetch.h" #include "regu_var.hpp" +#include "heap_attrinfo.h" +#include "query_executor.h" +#include "xasl_predicate.hpp" @@ -54,35 +55,31 @@ #define HP_FREE(thrd, ptr) free(ptr) #endif -static int regu_var_list_len (REGU_VARIABLE_LIST list); -static REGU_VARIABLE_LIST regu_var_list_clone (REGU_VARIABLE_LIST *list); - -static SCAN_CODE scan_next_heap_scan_1page_internal (THREAD_ENTRY *thread_p, SCAN_ID *scan_id, VPID *curr_vpid); - -class parallel_heap_scan_context : public cubthread::entry_manager +enum ph_pred_expr_types { - public: - std::atomic m_tasks_executed; - int m_error_code; - css_conn_entry *m_conn; - int m_orig_tran_index; - parallel_heap_scan_context () = default; - - protected: - void on_create (context_type &context); - void on_retire (context_type &context); - void on_recycle (context_type &context); + PH_PRED_EXPR = 1, + PH_PRED = 1 << 1, + PH_EVAL_TERM = 1 << 2, + PH_COMP_EVAL_TERM = 1 << 3, + PH_ALSM_EVAL_TERM = 1 << 4, + PH_LIKE_EVAL_TERM = 1 << 5, + PH_RLIKE_EVAL_TERM = 1 << 6, + PH_REGU_VAR = 1 << 7 }; -class parallel_heap_scan_task : public cubthread::entry_task -{ - public: - parallel_heap_scan_task () = delete; - parallel_heap_scan_task (parallel_heap_scan_context &context); - ~parallel_heap_scan_task (); +static int regu_var_list_len (REGU_VARIABLE_LIST list); +static REGU_VARIABLE_LIST regu_var_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST list); +static void regu_var_list_free (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST head); +static void * +pred_expr_clone (THREAD_ENTRY *thread_p, void *src, void *dest, enum ph_pred_expr_types type, + heap_cache_attrinfo *attr_info); +static void pred_expr_free (THREAD_ENTRY *thread_p, PRED_EXPR *src); +static heap_cache_attrinfo *attr_cache_clone (THREAD_ENTRY *thread_p, heap_cache_attrinfo *src); +static void attr_cache_free (THREAD_ENTRY *thread_p, heap_cache_attrinfo *src); +static void link_attr_cache (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST node,heap_cache_attrinfo *old_attr_info, + heap_cache_attrinfo *new_attr_info); +static SCAN_CODE scan_next_heap_scan_1page_internal (THREAD_ENTRY *thread_p, SCAN_ID *scan_id, VPID *curr_vpid); - void execute (cubthread::entry &thread_ref); -}; /*************************************************************************************************/ /* parallel_heap_scan_result_queue_entry */ @@ -95,11 +92,11 @@ class parallel_heap_scan_result_queue_entry OID curr_oid; bool valid; - int capture_pred_regu_var_list (REGU_VARIABLE_LIST list); - int capture_rest_regu_var_list (REGU_VARIABLE_LIST list); - int copy_to_pred_regu_var_list (REGU_VARIABLE_LIST list); - int copy_to_rest_regu_var_list (REGU_VARIABLE_LIST list); - void init (int n_pred_val, int n_rest_val); + void capture_pred_regu_var_list (REGU_VARIABLE_LIST list); + void capture_rest_regu_var_list (REGU_VARIABLE_LIST list); + void copy_to_pred_regu_var_list (REGU_VARIABLE_LIST list); + void copy_to_rest_regu_var_list (REGU_VARIABLE_LIST list); + void init (THREAD_ENTRY *thread_p, int n_pred_val, int n_rest_val); void clear (); private: @@ -129,7 +126,10 @@ void parallel_heap_scan_result_queue_entry::copy_to_regu_var_list (DB_VALUE_ARRA assert (iter); if (!DB_IS_NULL (iter->value.vfetch_to)) { - pr_clear_value (iter->value.vfetch_to); + if (DB_NEED_CLEAR (iter->value.vfetch_to)) + { + pr_clear_value (iter->value.vfetch_to); + } } db_value_clone (&dbvalue_array->vals[i], iter->value.vfetch_to); iter = iter->next; @@ -137,22 +137,22 @@ void parallel_heap_scan_result_queue_entry::copy_to_regu_var_list (DB_VALUE_ARRA return; } -int parallel_heap_scan_result_queue_entry::capture_pred_regu_var_list (REGU_VARIABLE_LIST list) +void parallel_heap_scan_result_queue_entry::capture_pred_regu_var_list (REGU_VARIABLE_LIST list) { capture_regu_var_list (list, &pred_val_array); } -int parallel_heap_scan_result_queue_entry::capture_rest_regu_var_list (REGU_VARIABLE_LIST list) +void parallel_heap_scan_result_queue_entry::capture_rest_regu_var_list (REGU_VARIABLE_LIST list) { capture_regu_var_list (list, &rest_val_array); } -int parallel_heap_scan_result_queue_entry::copy_to_pred_regu_var_list (REGU_VARIABLE_LIST list) +void parallel_heap_scan_result_queue_entry::copy_to_pred_regu_var_list (REGU_VARIABLE_LIST list) { copy_to_regu_var_list (&pred_val_array, list); } -int parallel_heap_scan_result_queue_entry::copy_to_rest_regu_var_list (REGU_VARIABLE_LIST list) +void parallel_heap_scan_result_queue_entry::copy_to_rest_regu_var_list (REGU_VARIABLE_LIST list) { copy_to_regu_var_list (&rest_val_array, list); } @@ -160,9 +160,23 @@ int parallel_heap_scan_result_queue_entry::copy_to_rest_regu_var_list (REGU_VARI void parallel_heap_scan_result_queue_entry::init (THREAD_ENTRY *thread_p, int n_pred_val, int n_rest_val) { pred_val_array.size = n_pred_val; - pred_val_array.vals = (DB_VALUE *)HP_ALLOC (thread_p, n_pred_val * sizeof (DB_VALUE)); + if (n_pred_val > 0) + { + pred_val_array.vals = (DB_VALUE *)HP_ALLOC (thread_p, n_pred_val * sizeof (DB_VALUE)); + } + else + { + pred_val_array.vals = NULL; + } rest_val_array.size = n_rest_val; - rest_val_array.vals = (DB_VALUE *)HP_ALLOC (thread_p, n_rest_val * sizeof (DB_VALUE)); + if (n_rest_val > 0) + { + rest_val_array.vals = (DB_VALUE *)HP_ALLOC (thread_p, n_rest_val * sizeof (DB_VALUE)); + } + else + { + rest_val_array.vals = NULL; + } scan_code = S_END; valid = false; curr_oid = {0,0,0}; @@ -182,66 +196,62 @@ void parallel_heap_scan_result_queue_entry::clear () class parallel_heap_scan_result_queue { public: - parallel_heap_scan_result_queue_entry entries[HP_RESULT_QUEUE_SIZE]; + + ~parallel_heap_scan_result_queue() + { + clear(); + } + class parallel_heap_scan_result_queue_variable { public: int start; int end; bool waiting; - int n_entry; std::mutex mutex; std::condition_variable cond; }; + parallel_heap_scan_result_queue_variable var; - THREAD_ENTRY *owner_thread_p; - - static parallel_heap_scan_result_queue_variable var; - - ~parallel_heap_scan_result_queue (); + void init (THREAD_ENTRY *thread_p, int n_pred, int n_rest); + void clear (); + bool isFull (); + bool isEmpty (); + bool isEmpty_with_lock(); + int enqueue (HEAP_SCAN_ID *hsidp, SCAN_CODE scan_code); + int dequeue (PARALLEL_HEAP_SCAN_ID *phsidp, SCAN_CODE *scan_code); + int dequeue_immediate (PARALLEL_HEAP_SCAN_ID *phsidp, SCAN_CODE *scan_code); + int dequeue_without_lock (PARALLEL_HEAP_SCAN_ID *phsidp, SCAN_CODE *scan_code); - static int init (THREAD_ENTRY *thread_p, int n_pred, int n_rest); - static void clear (); - static bool isFull (); - static bool isEmpty (); - static int enqueue (HEAP_SCAN_ID *hsidp, SCAN_CODE scan_code); - static int dequeue (HEAP_SCAN_ID *hsidp, SCAN_CODE *scan_code); - static int dequeue_immediate (HEAP_SCAN_ID *hsidp, SCAN_CODE *scan_code); + parallel_heap_scan_result_queue(); private: - static void lock () - { - std::lock_guard lock (var.mutex); - } - static void unlock () - { - var.mutex.unlock(); - } - static void wait() - { - var.cond.wait (var.mutex); - } - static void signal() - { - var.cond.notify_one(); - } + parallel_heap_scan_result_queue_entry entries[HP_RESULT_QUEUE_SIZE]; + + THREAD_ENTRY *owner_thread_p; }; -int parallel_heap_scan_result_queue::init (THREAD_ENTRY *thread_p, int n_pred, int n_rest) +parallel_heap_scan_result_queue::parallel_heap_scan_result_queue() +{ + var.start = var.end = 0; + var.waiting = false; +} + +void parallel_heap_scan_result_queue::init (THREAD_ENTRY *thread_p, int n_pred, int n_rest) { owner_thread_p = thread_p; for (int i = 0; i < HP_RESULT_QUEUE_SIZE; i++) { entries[i].init (owner_thread_p, n_pred, n_rest); } - lock(); + std::unique_lock (var.mutex); var.start = var.end = 0; var.waiting = false; - unlock(); } + void parallel_heap_scan_result_queue::clear () { - lock(); + std::unique_lock (var.mutex); for (int i = 0; i < HP_RESULT_QUEUE_SIZE; i++) { if (entries[i].valid) @@ -249,30 +259,35 @@ void parallel_heap_scan_result_queue::clear () entries[i].clear (); } } - unlock(); -} - -parallel_heap_scan_result_queue::~parallel_heap_scan_result_queue () -{ - clear (); + var.start = var.end = 0; + var.waiting = false; } bool parallel_heap_scan_result_queue::isFull () { return (var.start == (var.end + 1) % HP_RESULT_QUEUE_SIZE); } + bool parallel_heap_scan_result_queue::isEmpty () { return (var.start == var.end); } + +bool parallel_heap_scan_result_queue::isEmpty_with_lock() +{ + std::unique_lock lock (var.mutex); + return var.start == var.end; +} + int parallel_heap_scan_result_queue::enqueue (HEAP_SCAN_ID *hsidp, SCAN_CODE scan_code) { bool need_signal; - lock(); - if (isFull()) + std::unique_lock lock (var.mutex); + parallel_heap_scan_result_queue_entry *p; + while (isFull()) { var.waiting = true; - wait(); + var.cond.wait (lock); var.waiting = false; } @@ -281,76 +296,416 @@ int parallel_heap_scan_result_queue::enqueue (HEAP_SCAN_ID *hsidp, SCAN_CODE sca { entries[var.end].clear (); } + p = &entries[var.end]; /* copy data from scan_id */ - entries[var.end].valid = true; - entries[var.end].scan_code = scan_code; - COPY_OID (&entries[var.end].curr_oid, &hsidp->curr_oid); - entries[var.end].capture_pred_regu_var_list (hsidp->scan_pred.regu_list); - entries[var.end].capture_rest_regu_var_list (hsidp->rest_regu_list); + p->valid = true; + p->scan_code = scan_code; + COPY_OID (&p->curr_oid, &hsidp->curr_oid); + p->capture_pred_regu_var_list (hsidp->scan_pred.regu_list); + p->capture_rest_regu_var_list (hsidp->rest_regu_list); need_signal = var.waiting; - unlock(); + lock.unlock(); if (need_signal) { - signal(); + var.cond.notify_one(); } return NO_ERROR; } -int parallel_heap_scan_result_queue::dequeue (HEAP_SCAN_ID *hsidp, SCAN_CODE *scan_code) + +int parallel_heap_scan_result_queue::dequeue (PARALLEL_HEAP_SCAN_ID *phsidp, SCAN_CODE *scan_code) { - bool need_signal; + std::unique_lock lock (var.mutex); + parallel_heap_scan_result_queue_entry *p; if (isEmpty()) { var.waiting = true; - wait(); + var.cond.wait (lock); var.waiting = false; } var.start = (var.start + 1) % HP_RESULT_QUEUE_SIZE; /* copy data from queue */ - entries[var.start].valid = true; - entries[var.start].copy_to_pred_regu_var_list (hsidp->scan_pred.regu_list); - entries[var.start].copy_to_rest_regu_var_list (hsidp->rest_regu_list); - COPY_OID (&entries[var.start].curr_oid, &hsidp->curr_oid); - *scan_code = entries[var.start].scan_code; + p = &entries[var.start]; + p->valid = true; + p->copy_to_pred_regu_var_list (phsidp->scan_pred.regu_list); + p->copy_to_rest_regu_var_list (phsidp->rest_regu_list); + COPY_OID (&phsidp->curr_oid, &p->curr_oid); + *scan_code = p->scan_code; + + bool need_signal = var.waiting; + lock.unlock(); - need_signal = var.waiting; - unlock(); if (need_signal) { - signal(); + var.cond.notify_one(); } return NO_ERROR; } -int parallel_heap_scan_result_queue::dequeue_immediate (HEAP_SCAN_ID *hsidp, SCAN_CODE *scan_code) +int parallel_heap_scan_result_queue::dequeue_immediate (PARALLEL_HEAP_SCAN_ID *phsidp, SCAN_CODE *scan_code) { - bool need_signal; - lock(); + std::unique_lock lock (var.mutex); + parallel_heap_scan_result_queue_entry *p; if (isEmpty()) { - unlock(); return FALSE; } + var.start = (var.start + 1) % HP_RESULT_QUEUE_SIZE; /* copy data from queue */ - entries[var.start].valid = true; - entries[var.start].copy_to_pred_regu_var_list (hsidp->scan_pred.regu_list); - entries[var.start].copy_to_rest_regu_var_list (hsidp->rest_regu_list); - COPY_OID (&entries[var.start].curr_oid, &hsidp->curr_oid); - *scan_code = entries[var.start].scan_code; + p = &entries[var.start]; + p->valid = true; + p->copy_to_pred_regu_var_list (phsidp->scan_pred.regu_list); + p->copy_to_rest_regu_var_list (phsidp->rest_regu_list); + COPY_OID (&phsidp->curr_oid, &p->curr_oid); + *scan_code = p->scan_code; + + bool need_signal = var.waiting; + lock.unlock(); - need_signal = var.waiting; - unlock(); if (need_signal) { - signal(); + var.cond.notify_one(); + } + return TRUE; +} + +int parallel_heap_scan_result_queue::dequeue_without_lock (PARALLEL_HEAP_SCAN_ID *phsidp, SCAN_CODE *scan_code) +{ + parallel_heap_scan_result_queue_entry *p; + if (isEmpty()) + { + return FALSE; } + var.start = (var.start + 1) % HP_RESULT_QUEUE_SIZE; + /* copy data from queue */ + p = &entries[var.start]; + p->valid = true; + p->copy_to_pred_regu_var_list (phsidp->scan_pred.regu_list); + p->copy_to_rest_regu_var_list (phsidp->rest_regu_list); + COPY_OID (&phsidp->curr_oid, &p->curr_oid); + *scan_code = p->scan_code; + return TRUE; } +/*************************************************************************************************/ +/* master, context, task */ + +class parallel_heap_scan_context : public cubthread::entry_manager +{ + public: + std::atomic m_tasks_executed; + std::atomic m_tasks_started; + parallel_heap_scan_result_queue *m_result_queue; + int m_has_error; + SCAN_ID *m_scan_id; + int m_orig_tran_index; + REGU_VARIABLE_LIST orig_pred_list; + REGU_VARIABLE_LIST orig_rest_list; + + class locked_vpid + { + public: + VPID vpid; + std::mutex mutex; + } m_locked_vpid; + + parallel_heap_scan_context (SCAN_ID *scan_id, int tran_index, int parallelism); + ~parallel_heap_scan_context(); + void set_regu_vars (REGU_VARIABLE_LIST pred_list, REGU_VARIABLE_LIST rest_list); +}; + +class parallel_heap_scan_task : public cubthread::entry_task +{ + public: + parallel_heap_scan_context *m_context; + parallel_heap_scan_result_queue *m_result_queue; + + parallel_heap_scan_task() = default; + + parallel_heap_scan_task (parallel_heap_scan_context *context) + : m_context (context) + { + } + ~parallel_heap_scan_task() + { + m_context = nullptr; + m_result_queue = nullptr; + } + virtual void execute (cubthread::entry &thread_ref) override; + void set_result_queue (parallel_heap_scan_result_queue *queue) + { + m_result_queue = queue; + } + SCAN_CODE page_next (THREAD_ENTRY *thread_p, HFID *hfid); +}; + +parallel_heap_scan_context::parallel_heap_scan_context (SCAN_ID *scan_id, int tran_index, + int parallelism) +{ + m_scan_id = scan_id; + m_orig_tran_index = tran_index; + VPID_SET_NULL (&m_locked_vpid.vpid); + m_result_queue = new parallel_heap_scan_result_queue[parallelism] {parallel_heap_scan_result_queue()}; + m_tasks_started = 0; + m_tasks_executed = 0; + m_has_error = NO_ERROR; +} + +parallel_heap_scan_context::~parallel_heap_scan_context() +{ + delete[] m_result_queue; +} +void parallel_heap_scan_context::set_regu_vars (REGU_VARIABLE_LIST pred_list, + REGU_VARIABLE_LIST rest_list) +{ + orig_pred_list = pred_list; + orig_rest_list = rest_list; +} +SCAN_CODE parallel_heap_scan_task::page_next (THREAD_ENTRY *thread_p, HFID *hfid) +{ + std::unique_lock lock (m_context->m_locked_vpid.mutex); + SCAN_CODE page_scan_code = heap_page_next (thread_p, NULL, hfid, &m_context->m_locked_vpid.vpid, NULL); + if (page_scan_code == S_END) + { + lock.unlock(); + return S_END; + } + return page_scan_code; +} + +void parallel_heap_scan_task::execute (cubthread::entry &thread_ref) +{ + int tran_index = m_context->m_orig_tran_index; + THREAD_ENTRY *thread_p = &thread_ref; + SCAN_ID *scan_id, *orig_scan_id = m_context->m_scan_id; + PARALLEL_HEAP_SCAN_ID *phsidp = &orig_scan_id->s.phsid; + SCAN_CODE page_scan_code, rec_scan_code; + VPID vpid; + HFID hfid; + HL_HEAPID orig_heap_id = db_change_private_heap (thread_p, 0); + scan_id = (SCAN_ID *) HP_ALLOC (thread_p, sizeof (SCAN_ID)); + HEAP_SCAN_ID *hsidp = &scan_id->s.hsid; + thread_p->tran_index = tran_index; + + scan_open_heap_scan (thread_p, scan_id, orig_scan_id->mvcc_select_lock_needed, orig_scan_id->scan_op_type, + orig_scan_id->fixed, orig_scan_id->grouped, orig_scan_id->single_fetch, orig_scan_id->join_dbval, + orig_scan_id->val_list, orig_scan_id->vd, &phsidp->cls_oid, &phsidp->hfid, + phsidp->scan_pred.regu_list, phsidp->scan_pred.pred_expr, phsidp->rest_regu_list, + phsidp->pred_attrs.num_attrs, phsidp->pred_attrs.attr_ids, phsidp->pred_attrs.attr_cache, + phsidp->rest_attrs.num_attrs, phsidp->rest_attrs.attr_ids, phsidp->rest_attrs.attr_cache, + S_HEAP_SCAN, phsidp->cache_recordinfo, phsidp->recordinfo_regu_list, false); + + hsidp->scan_pred.regu_list = regu_var_list_clone (thread_p, m_context->orig_pred_list); + hsidp->rest_regu_list = regu_var_list_clone (thread_p, m_context->orig_rest_list); + hsidp->pred_attrs.attr_cache = attr_cache_clone (thread_p, phsidp->pred_attrs.attr_cache); + hsidp->rest_attrs.attr_cache = attr_cache_clone (thread_p, phsidp->rest_attrs.attr_cache); + hsidp->scan_pred.pred_expr = (PRED_EXPR *)pred_expr_clone (thread_p, (void *)phsidp->scan_pred.pred_expr, NULL, + PH_PRED_EXPR, hsidp->pred_attrs.attr_cache); + link_attr_cache (thread_p, hsidp->scan_pred.regu_list, phsidp->pred_attrs.attr_cache, hsidp->pred_attrs.attr_cache); + link_attr_cache (thread_p, hsidp->rest_regu_list, phsidp->rest_attrs.attr_cache, hsidp->rest_attrs.attr_cache); + scan_start_scan (thread_p, scan_id); + reset_pred_or_regu_var_list (hsidp->scan_pred.pred_expr, true); + reset_pred_or_regu_var_list (hsidp->scan_pred.regu_list, false); + reset_pred_or_regu_var_list (hsidp->rest_regu_list, false); + /* phsidp->scan_pred.pred_expr, phsidp->pred_attrs.attr_cache phsidp->rest_attrs.attr_cache 를 독립적으로 운용해야함 */ + + hfid = phsidp->hfid; + OID_SET_NULL (&hsidp->curr_oid); + + while (TRUE) + { + page_scan_code = page_next (thread_p, &hfid); + VPID_COPY (&vpid, &m_context->m_locked_vpid.vpid); + if (page_scan_code == S_END) + { + m_result_queue->enqueue (hsidp, page_scan_code); + break; + } + + while (TRUE) + { + rec_scan_code = scan_next_heap_scan_1page_internal (thread_p, scan_id, &vpid); + assert (rec_scan_code == S_SUCCESS || rec_scan_code == S_END); + if (rec_scan_code == S_END) + { + break; + } + else if (rec_scan_code == S_SUCCESS) + { + m_result_queue->enqueue (hsidp, rec_scan_code); + } + } + + } + + scan_end_scan (thread_p, scan_id); + scan_close_scan (thread_p, scan_id); + if (hsidp->caches_inited) + { + heap_attrinfo_end (thread_p, hsidp->pred_attrs.attr_cache); + heap_attrinfo_end (thread_p, hsidp->rest_attrs.attr_cache); + hsidp->caches_inited = false; + } + + regu_var_list_free (thread_p, hsidp->scan_pred.regu_list); + regu_var_list_free (thread_p, hsidp->rest_regu_list); + pred_expr_free (thread_p, hsidp->scan_pred.pred_expr); + attr_cache_free (thread_p, hsidp->pred_attrs.attr_cache); + attr_cache_free (thread_p, hsidp->rest_attrs.attr_cache); + HP_FREE (thread_p, scan_id); + db_change_private_heap (thread_p, orig_heap_id); + m_context->m_tasks_executed++; +} + +parallel_heap_scan_master::parallel_heap_scan_master (int tran_index, SCAN_ID *scan_id, size_t pool_size, + size_t task_max_count, std::size_t core_count) +{ + parallelism = (int)core_count; + m_context = new parallel_heap_scan_context (scan_id, tran_index, parallelism); + m_workpool = thread_get_manager()->create_worker_pool (pool_size, task_max_count, "Parallel heap scan pool", + m_context, parallelism, 1); + m_scan_id = scan_id; + m_is_reset_once = false; + m_is_start_once = false; +} + +parallel_heap_scan_master::~parallel_heap_scan_master() +{ + if (m_workpool != nullptr) + { + thread_get_manager()->destroy_worker_pool (m_workpool); + } +} + +SCAN_CODE parallel_heap_scan_master::get_result (THREAD_ENTRY *thread_p, SCAN_ID *scan_id) +{ + SCAN_CODE scan_code; + int result = FALSE; + int timeout_count = 0; + for (int i = 0; i < parallelism; i++) + { + std::unique_lock lock (m_context->m_result_queue[i].var.mutex, std::try_to_lock); + if (lock.owns_lock()) + { + result = m_context->m_result_queue[i].dequeue_without_lock (&scan_id->s.phsid, &scan_code); + if (result == TRUE) + { + return scan_code; + } + else + { + lock.unlock(); + continue; + } + } + else + { + continue; + } + } + + while (result == FALSE) + { + for (int i=0; i 100) + { + return S_ERROR; + } + std::unique_lock lock (m_context->m_result_queue[i].var.mutex, std::try_to_lock); + if (lock.owns_lock()) + { + result = m_context->m_result_queue[i].dequeue_without_lock (&scan_id->s.phsid, &scan_code); + if (result == TRUE) + { + return scan_code; + } + else + { + lock.unlock(); + continue; + } + } + else + { + thread_sleep (10); + timeout_count++; + } + } + + } + return S_ERROR; +} + +void parallel_heap_scan_master::start (THREAD_ENTRY *thread_p) +{ + //std::unique_ptr task = NULL; + m_context->set_regu_vars (m_scan_id->s.phsid.scan_pred.regu_list, m_scan_id->s.phsid.rest_regu_list); + for (int i = 0; i < parallelism; i++) + { + m_context->m_result_queue[i].init (thread_p, + regu_var_list_len (m_scan_id->s.phsid.scan_pred.regu_list), + regu_var_list_len (m_scan_id->s.phsid.rest_regu_list)); + } +} + +void parallel_heap_scan_master::reset (SCAN_ID *scan_id) +{ + std::unique_ptr task = NULL; + int retired_result_queue_count = 0; + while (m_context->m_tasks_executed < m_context->m_tasks_started) + { + thread_sleep (10); + } + + for (int i = 0; i < parallelism; i++) + { + m_context->m_result_queue[i].clear(); + } + std::unique_lock lock (m_context->m_locked_vpid.mutex); + VPID_SET_NULL (&m_context->m_locked_vpid.vpid); + scan_id->single_fetched = false; + scan_id->null_fetched = false; + scan_id->position = (scan_id->direction == S_FORWARD) ? S_BEFORE : S_AFTER; + OID_SET_NULL (&scan_id->s.hsid.curr_oid); + lock.unlock(); + start_tasks (scan_id); + m_is_start_once = true; +} + +void parallel_heap_scan_master::start_tasks (SCAN_ID *scan_id) +{ + std::unique_ptr task = NULL; + for (int i = 0; i < parallelism; i++) + { + task.reset (new parallel_heap_scan_task (m_context)); + task->set_result_queue (&m_context->m_result_queue[i]); + thread_get_manager()->push_task (m_workpool, task.release()); + m_context->m_tasks_started++; + } +} + +void parallel_heap_scan_master::end() +{ + if (m_context->m_has_error) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_IB_ERROR_ABORT, 0); + } + while (m_context->m_tasks_executed < m_context->m_tasks_started) + { + thread_sleep (10); + } + m_is_start_once = false; + m_is_reset_once = false; +} + +/*************************************************************************************************/ +/* public functions */ static int regu_var_list_len (REGU_VARIABLE_LIST list) { @@ -361,6 +716,7 @@ static int regu_var_list_len (REGU_VARIABLE_LIST list) } return len; } + static REGU_VARIABLE_LIST regu_var_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST src) { REGU_VARIABLE_LIST dest_head = NULL; @@ -375,7 +731,7 @@ static REGU_VARIABLE_LIST regu_var_list_clone (THREAD_ENTRY *thread_p, REGU_VARI while (current) { REGU_VARIABLE_LIST new_node = - (REGU_VARIABLE_LIST) db_private_alloc (thread_p, sizeof (struct regu_variable_list_node)); + (REGU_VARIABLE_LIST) HP_ALLOC (thread_p, sizeof (struct regu_variable_list_node)); if (!new_node) { REGU_VARIABLE_LIST temp = dest_head; @@ -384,7 +740,10 @@ static REGU_VARIABLE_LIST regu_var_list_clone (THREAD_ENTRY *thread_p, REGU_VARI REGU_VARIABLE_LIST next = temp->next; if (temp->value.vfetch_to) { - pr_clear_value (temp->value.vfetch_to); + if (DB_NEED_CLEAR (temp->value.vfetch_to)) + { + pr_clear_value (temp->value.vfetch_to); + } HP_FREE (thread_p, temp->value.vfetch_to); } HP_FREE (thread_p, temp); @@ -394,11 +753,15 @@ static REGU_VARIABLE_LIST regu_var_list_clone (THREAD_ENTRY *thread_p, REGU_VARI } new_node->value = current->value; - new_node->value.vfetch_to = (DB_VALUE *) db_private_alloc (thread_p, sizeof (DB_VALUE)); + new_node->value.vfetch_to = (DB_VALUE *) HP_ALLOC (thread_p, sizeof (DB_VALUE)); /* should we clone value? */ pr_clone_value (current->value.vfetch_to, new_node->value.vfetch_to); - + if (current->value.type == TYPE_ATTR_ID || current->value.type == TYPE_CLASS_ATTR_ID + || current->value.type == TYPE_SHARED_ATTR_ID) + { + new_node->value.value.attr_descr.cache_dbvalp = nullptr; + } new_node->next = NULL; if (dest_tail) @@ -417,6 +780,301 @@ static REGU_VARIABLE_LIST regu_var_list_clone (THREAD_ENTRY *thread_p, REGU_VARI return dest_head; } +void +regu_var_list_free (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST head) +{ + REGU_VARIABLE_LIST current = head; + while (current) + { + REGU_VARIABLE_LIST next = current->next; + + if (current->value.vfetch_to) + { + if (DB_NEED_CLEAR (current->value.vfetch_to)) + { + pr_clear_value (current->value.vfetch_to); + } + HP_FREE (thread_p, current->value.vfetch_to); + } + HP_FREE (thread_p, current); + + current = next; + } +} + +static void * +pred_expr_clone (THREAD_ENTRY *thread_p, void *src, void *dest, enum ph_pred_expr_types type, + heap_cache_attrinfo *attr_info) +{ + void *ret = nullptr; + PRED_EXPR *src_pred_expr; + PRED_EXPR *dest_pred_expr; + PRED *src_pred; + PRED *dest_pred; + EVAL_TERM *src_eval_term; + EVAL_TERM *dest_eval_term; + COMP_EVAL_TERM *src_comp_eval_term; + COMP_EVAL_TERM *dest_comp_eval_term; + ALSM_EVAL_TERM *src_alsm_eval_term; + ALSM_EVAL_TERM *dest_alsm_eval_term; + LIKE_EVAL_TERM *src_like_eval_term; + LIKE_EVAL_TERM *dest_like_eval_term; + RLIKE_EVAL_TERM *src_rlike_eval_term; + RLIKE_EVAL_TERM *dest_rlike_eval_term; + regu_variable_node *src_regu_var; + regu_variable_node *dest_regu_var; + if (!src) + { + return NULL; + } + switch (type) + { + case PH_PRED_EXPR: + src_pred_expr = (PRED_EXPR *) src; + dest_pred_expr = (PRED_EXPR *) HP_ALLOC (thread_p, sizeof (PRED_EXPR)); + *dest_pred_expr = *src_pred_expr; + switch (src_pred_expr->type) + { + case T_PRED: + pred_expr_clone (thread_p, (void *)&src_pred_expr->pe.m_pred, (void *)&dest_pred_expr->pe.m_pred, PH_PRED, attr_info); + break; + case T_EVAL_TERM: + pred_expr_clone (thread_p, (void *)&src_pred_expr->pe.m_eval_term, (void *)&dest_pred_expr->pe.m_eval_term, + PH_EVAL_TERM, attr_info); + break; + case T_NOT_TERM: + dest_pred_expr->pe.m_not_term = (PRED_EXPR *) pred_expr_clone (thread_p, (void *)src_pred_expr->pe.m_not_term, + (void *)dest_pred_expr->pe.m_not_term, PH_PRED_EXPR, attr_info); + break; + default: + assert (false); + break; + } + ret = (void *) dest_pred_expr; + break; + case PH_PRED: + src_pred = (PRED *) src; + dest_pred = (PRED *) dest; + *dest_pred = *src_pred; + dest_pred->lhs = (PRED_EXPR *) pred_expr_clone (thread_p, (void *)src_pred->lhs, (void *)dest_pred->lhs, PH_PRED_EXPR, + attr_info); + dest_pred->rhs = (PRED_EXPR *) pred_expr_clone (thread_p, (void *)src_pred->rhs, (void *)dest_pred->rhs, PH_PRED_EXPR, + attr_info); + break; + case PH_EVAL_TERM: + src_eval_term = (EVAL_TERM *) src; + dest_eval_term = (EVAL_TERM *) dest; + switch (src_eval_term->et_type) + { + case T_COMP_EVAL_TERM: + pred_expr_clone (thread_p, (void *)&src_eval_term->et.et_comp, (void *)&dest_eval_term->et.et_comp, PH_COMP_EVAL_TERM, + attr_info); + break; + case T_ALSM_EVAL_TERM: + pred_expr_clone (thread_p, (void *)&src_eval_term->et.et_alsm, (void *)&dest_eval_term->et.et_alsm, PH_ALSM_EVAL_TERM, + attr_info); + break; + case T_LIKE_EVAL_TERM: + pred_expr_clone (thread_p, (void *)&src_eval_term->et.et_like, (void *)&dest_eval_term->et.et_like, PH_LIKE_EVAL_TERM, + attr_info); + break; + case T_RLIKE_EVAL_TERM: + pred_expr_clone (thread_p, (void *)&src_eval_term->et.et_rlike, (void *)&dest_eval_term->et.et_rlike, + PH_RLIKE_EVAL_TERM, attr_info); + break; + } + break; + case PH_COMP_EVAL_TERM: + src_comp_eval_term = (COMP_EVAL_TERM *) src; + dest_comp_eval_term = (COMP_EVAL_TERM *) dest; + dest_comp_eval_term->lhs = (regu_variable_node *) pred_expr_clone (thread_p, (void *)src_comp_eval_term->lhs, + (void *)dest_comp_eval_term->lhs, PH_REGU_VAR, attr_info); + dest_comp_eval_term->rhs = (regu_variable_node *) pred_expr_clone (thread_p, (void *)src_comp_eval_term->rhs, + (void *)dest_comp_eval_term->rhs, PH_REGU_VAR, attr_info); + break; + case PH_ALSM_EVAL_TERM: + src_alsm_eval_term = (ALSM_EVAL_TERM *) src; + dest_alsm_eval_term = (ALSM_EVAL_TERM *) dest; + dest_alsm_eval_term->elem = (regu_variable_node *) pred_expr_clone (thread_p, (void *)src_alsm_eval_term->elem, + (void *)dest_alsm_eval_term->elem, PH_REGU_VAR, attr_info); + dest_alsm_eval_term->elemset = (regu_variable_node *) pred_expr_clone (thread_p, (void *)src_alsm_eval_term->elemset, + (void *)dest_alsm_eval_term->elemset, PH_REGU_VAR, attr_info); + break; + case PH_LIKE_EVAL_TERM: + src_like_eval_term = (LIKE_EVAL_TERM *) src; + dest_like_eval_term = (LIKE_EVAL_TERM *) dest; + dest_like_eval_term->src = (regu_variable_node *) pred_expr_clone (thread_p, (void *)src_like_eval_term->src, + (void *)dest_like_eval_term->src, PH_REGU_VAR, attr_info); + dest_like_eval_term->pattern = (regu_variable_node *) pred_expr_clone (thread_p, (void *)src_like_eval_term->pattern, + (void *)dest_like_eval_term->pattern, PH_REGU_VAR, attr_info); + dest_like_eval_term->esc_char = (regu_variable_node *) pred_expr_clone (thread_p, (void *)src_like_eval_term->esc_char, + (void *)dest_like_eval_term->esc_char, PH_REGU_VAR, attr_info); + break; + case PH_RLIKE_EVAL_TERM: + src_rlike_eval_term = (RLIKE_EVAL_TERM *) src; + dest_rlike_eval_term = (RLIKE_EVAL_TERM *) dest; + dest_rlike_eval_term->src = (regu_variable_node *) pred_expr_clone (thread_p, (void *)src_rlike_eval_term->src, + (void *)dest_rlike_eval_term->src, PH_REGU_VAR, attr_info); + dest_rlike_eval_term->pattern = (regu_variable_node *) pred_expr_clone (thread_p, (void *)src_rlike_eval_term->pattern, + (void *)dest_rlike_eval_term->pattern, PH_REGU_VAR, attr_info); + dest_rlike_eval_term->case_sensitive = (regu_variable_node *) pred_expr_clone (thread_p, + (void *)src_rlike_eval_term->case_sensitive, (void *)dest_rlike_eval_term->case_sensitive, PH_REGU_VAR, attr_info); + break; + case PH_REGU_VAR: + src_regu_var = (regu_variable_node *) src; + dest_regu_var = (regu_variable_node *) HP_ALLOC (thread_p, sizeof (regu_variable_node)); + *dest_regu_var = *src_regu_var; + if (src_regu_var->vfetch_to) + { + dest_regu_var->vfetch_to = (DB_VALUE *) HP_ALLOC (thread_p, sizeof (DB_VALUE)); + /* should we clone value? */ + pr_clone_value (src_regu_var->vfetch_to, dest_regu_var->vfetch_to); + } + + + if (src_regu_var->type == TYPE_ATTR_ID || src_regu_var->type == TYPE_CLASS_ATTR_ID + || src_regu_var->type == TYPE_SHARED_ATTR_ID) + { + dest_regu_var->value.attr_descr.cache_dbvalp = NULL; + dest_regu_var->value.attr_descr.cache_attrinfo = attr_info; + } + ret = (void *) dest_regu_var; + break; + default: + assert (false); + break; + } + return ret; +} + +static void +pred_expr_free (THREAD_ENTRY *thread_p, PRED_EXPR *src) +{ + if (!src) + { + return; + } + switch (src->type) + { + case T_PRED: + pred_expr_free (thread_p, src->pe.m_pred.lhs); + pred_expr_free (thread_p, src->pe.m_pred.rhs); + break; + case T_EVAL_TERM: + switch (src->pe.m_eval_term.et_type) + { + case T_COMP_EVAL_TERM: + { + COMP_EVAL_TERM *comp_term = &src->pe.m_eval_term.et.et_comp; + HP_FREE (thread_p, comp_term->lhs->vfetch_to); + HP_FREE (thread_p, comp_term->lhs); + HP_FREE (thread_p, comp_term->rhs->vfetch_to); + HP_FREE (thread_p, comp_term->rhs); + } + break; + case T_ALSM_EVAL_TERM: + { + ALSM_EVAL_TERM *alsm_term = &src->pe.m_eval_term.et.et_alsm; + HP_FREE (thread_p, alsm_term->elem->vfetch_to); + HP_FREE (thread_p, alsm_term->elem); + HP_FREE (thread_p, alsm_term->elemset->vfetch_to); + HP_FREE (thread_p, alsm_term->elemset); + } + break; + case T_LIKE_EVAL_TERM: + { + LIKE_EVAL_TERM *like_term = &src->pe.m_eval_term.et.et_like; + HP_FREE (thread_p, like_term->src->vfetch_to); + HP_FREE (thread_p, like_term->src); + HP_FREE (thread_p, like_term->pattern->vfetch_to); + HP_FREE (thread_p, like_term->pattern); + HP_FREE (thread_p, like_term->esc_char->vfetch_to); + HP_FREE (thread_p, like_term->esc_char); + } + break; + case T_RLIKE_EVAL_TERM: + { + RLIKE_EVAL_TERM *rlike_term = &src->pe.m_eval_term.et.et_rlike; + HP_FREE (thread_p, rlike_term->src->vfetch_to); + HP_FREE (thread_p, rlike_term->src); + HP_FREE (thread_p, rlike_term->pattern->vfetch_to); + HP_FREE (thread_p, rlike_term->pattern); + HP_FREE (thread_p, rlike_term->case_sensitive->vfetch_to); + HP_FREE (thread_p, rlike_term->case_sensitive); + } + break; + } + break; + case T_NOT_TERM: + pred_expr_free (thread_p, src->pe.m_not_term); + break; + } + HP_FREE (thread_p, src); +} + +static heap_cache_attrinfo * +attr_cache_clone (THREAD_ENTRY *thread_p, heap_cache_attrinfo *src) +{ + heap_cache_attrinfo *dest = (heap_cache_attrinfo *) HP_ALLOC (thread_p, sizeof (heap_cache_attrinfo)); + *dest = *src; + if (src->num_values > 0) + { + dest->values = (HEAP_ATTRVALUE *) HP_ALLOC (thread_p, sizeof (HEAP_ATTRVALUE) * src->num_values); + for (int i = 0; i < src->num_values; i++) + { + dest->values[i] = src->values[i]; + } + } + + + return dest; +} + +static void +attr_cache_free (THREAD_ENTRY *thread_p, heap_cache_attrinfo *src) +{ + if (!src) + { + return; + } + if (src->num_values > 0) + { + for (int i = 0; i < src->num_values; i++) + { + if (DB_NEED_CLEAR (&src->values[i].dbvalue)) + { + pr_clear_value (&src->values[i].dbvalue); + } + } + + HP_FREE (thread_p, src->values); + } + + HP_FREE (thread_p, src); +} + +static void +link_attr_cache (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST node,heap_cache_attrinfo *old_attr_info, + heap_cache_attrinfo *new_attr_info) +{ + while (node) + { + if (node->value.type == TYPE_ATTR_ID || node->value.type == TYPE_CLASS_ATTR_ID + || node->value.type == TYPE_SHARED_ATTR_ID) + { + if (node->value.value.attr_descr.cache_attrinfo == old_attr_info) + { + node->value.value.attr_descr.cache_attrinfo = new_attr_info; + } + else + { + assert (false); + } + } + node = node->next; + } +} + typedef enum { OBJ_GET_WITHOUT_LOCK = 0, @@ -707,4 +1365,79 @@ scan_next_heap_scan_1page_internal (THREAD_ENTRY *thread_p, SCAN_ID *scan_id, VP return S_SUCCESS; } -} \ No newline at end of file +} + + + +SCAN_CODE +scan_next_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id) +{ + if (!scan_id->s.phsid.master->m_is_start_once) + { + scan_id->s.phsid.master->start_tasks (scan_id); + scan_id->s.phsid.master->m_is_start_once = true; + } + return scan_id->s.phsid.master->get_result (thread_p, scan_id); +} + +int +scan_reset_scan_block_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id) +{ + if (scan_id->s.phsid.master->m_is_reset_once) + { + scan_id->s.phsid.master->reset (scan_id); + //scan_id->s.phsid.master->reset(scan_id); //WHY??????????? + } + else + { + scan_id->s.phsid.master->m_is_reset_once = true; + } + return TRUE; +} + +void +scan_end_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id) +{ + scan_id->s.phsid.master->end(); +} + +void +scan_close_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id) +{ + delete scan_id->s.phsid.master; +} + +int +scan_start_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id) +{ + scan_id->s.phsid.master->start (thread_p); //scan_ptr이라면 여기서 시작하면 안됨 + return TRUE; +} + +int +scan_open_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id, + /* fields of SCAN_ID */ + bool mvcc_select_lock_needed, SCAN_OPERATION_TYPE scan_op_type, int fixed, + int grouped, QPROC_SINGLE_FETCH single_fetch, DB_VALUE *join_dbval, + val_list_node *val_list, VAL_DESCR *vd, + /* fields of HEAP_SCAN_ID */ + OID *cls_oid, HFID *hfid, regu_variable_list_node *regu_list_pred, + PRED_EXPR *pr, regu_variable_list_node *regu_list_rest, int num_attrs_pred, + ATTR_ID *attrids_pred, HEAP_CACHE_ATTRINFO *cache_pred, int num_attrs_rest, + ATTR_ID *attrids_rest, HEAP_CACHE_ATTRINFO *cache_rest, SCAN_TYPE scan_type, + DB_VALUE **cache_recordinfo, regu_variable_list_node *regu_list_recordinfo, + bool is_partition_table) +{ + int ret; + assert (scan_type == S_PARALLEL_HEAP_SCAN); + scan_id->type = S_HEAP_SCAN; + ret = scan_open_heap_scan (thread_p, scan_id, mvcc_select_lock_needed, scan_op_type, fixed, grouped, single_fetch, + join_dbval, + val_list, vd, cls_oid, hfid, regu_list_pred, pr, regu_list_rest, num_attrs_pred, attrids_pred, cache_pred, + num_attrs_rest, attrids_rest, cache_rest, S_HEAP_SCAN, cache_recordinfo, regu_list_recordinfo, is_partition_table); + scan_id->type = S_PARALLEL_HEAP_SCAN; + + scan_id->s.phsid.master = new parallel_heap_scan_master (thread_p->tran_index, scan_id, HP_PARALLELISM, + HP_PARALLELISM, HP_PARALLELISM); + return ret; +} diff --git a/src/query/parallel_heap_scan.hpp b/src/query/parallel_heap_scan.hpp index 056c117b294..c0442f9e194 100644 --- a/src/query/parallel_heap_scan.hpp +++ b/src/query/parallel_heap_scan.hpp @@ -22,8 +22,61 @@ #ifndef _PARALLEL_HEAP_SCAN_H_ #define _PARALLEL_HEAP_SCAN_H_ +#include "dbtype.h" +#include "scan_manager.h" +#include "thread_manager.hpp" #define HP_PARALLELISM 1 #define HP_RESULT_QUEUE_SIZE 11 + +class parallel_heap_scan_context; +class parallel_heap_scan_task; +class parallel_heap_scan_master +{ + public: + + cubthread::entry_workpool *m_workpool; + parallel_heap_scan_context *m_context; + std::atomic m_is_reset_once; + std::atomic m_is_start_once; + SCAN_ID *m_scan_id; + int parallelism; + + parallel_heap_scan_master() = delete; + parallel_heap_scan_master (int tran_index, SCAN_ID *scan_id, size_t pool_size, size_t task_max_count, + std::size_t core_count); + ~parallel_heap_scan_master(); + SCAN_CODE get_result (THREAD_ENTRY *thread_p, SCAN_ID *scan_id); + void start (THREAD_ENTRY *thread_p); + void reset (SCAN_ID *scan_id); + void start_tasks (SCAN_ID *scan_id); + void end(); + + // ... 필요한 메서드들 추가 +}; + +extern SCAN_CODE +scan_next_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id); +extern int +scan_reset_scan_block_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id); +extern void +scan_end_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id); +extern void +scan_close_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id); +extern int +scan_open_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id, + /* fields of SCAN_ID */ + bool mvcc_select_lock_needed, SCAN_OPERATION_TYPE scan_op_type, int fixed, + int grouped, QPROC_SINGLE_FETCH single_fetch, DB_VALUE *join_dbval, + val_list_node *val_list, VAL_DESCR *vd, + /* fields of HEAP_SCAN_ID */ + OID *cls_oid, HFID *hfid, regu_variable_list_node *regu_list_pred, + PRED_EXPR *pr, regu_variable_list_node *regu_list_rest, int num_attrs_pred, + ATTR_ID *attrids_pred, HEAP_CACHE_ATTRINFO *cache_pred, int num_attrs_rest, + ATTR_ID *attrids_rest, HEAP_CACHE_ATTRINFO *cache_rest, SCAN_TYPE scan_type, + DB_VALUE **cache_recordinfo, regu_variable_list_node *regu_list_recordinfo, + bool is_partition_table); +extern int +scan_start_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id); #endif /* _PARALLEL_HEAP_SCAN_H_ */ diff --git a/src/query/query_executor.c b/src/query/query_executor.c index 3e91c069437..a2428616d62 100644 --- a/src/query/query_executor.c +++ b/src/query/query_executor.c @@ -81,7 +81,7 @@ #include "xasl_analytic.hpp" #include "xasl_predicate.hpp" #include "subquery_cache.h" - +#include "parallel_heap_scan.hpp" #include // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" @@ -413,8 +413,7 @@ static int qexec_end_one_iteration (THREAD_ENTRY * thread_p, XASL_NODE * xasl, X QFILE_TUPLE_RECORD * tplrec); static void qexec_failure_line (int line, XASL_STATE * xasl_state); static void qexec_reset_regu_variable (REGU_VARIABLE * var); -static void qexec_reset_regu_variable_list (REGU_VARIABLE_LIST list); -static void qexec_reset_pred_expr (PRED_EXPR * pred); + static int qexec_clear_xasl_head (THREAD_ENTRY * thread_p, XASL_NODE * xasl); static int qexec_clear_arith_list (THREAD_ENTRY * thread_p, XASL_NODE * xasl_p, ARITH_TYPE * list, bool is_final); static int qexec_clear_regu_var (THREAD_ENTRY * thread_p, XASL_NODE * xasl_p, REGU_VARIABLE * regu_var, bool is_final); @@ -1918,6 +1917,7 @@ qexec_clear_access_spec_list (THREAD_ENTRY * thread_p, XASL_NODE * xasl_p, ACCES case S_HEAP_SCAN_RECORD_INFO: case S_CLASS_ATTR_SCAN: case S_HEAP_SAMPLING_SCAN: + case S_PARALLEL_HEAP_SCAN: pg_cnt += qexec_clear_regu_list (thread_p, xasl_p, p->s_id.s.hsid.scan_pred.regu_list, is_final); pg_cnt += qexec_clear_regu_list (thread_p, xasl_p, p->s_id.s.hsid.rest_regu_list, is_final); @@ -9104,6 +9104,12 @@ qexec_open_scan (THREAD_ENTRY * thread_p, ACCESS_SPEC_TYPE * curr_spec, VAL_LIST /* open a sequential heap file scan */ scan_type = S_HEAP_SCAN; indx_info = NULL; +#if defined(SERVER_MODE) + if (!mvcc_select_lock_needed) + { + scan_type = S_PARALLEL_HEAP_SCAN; + } +#endif } else if (curr_spec->access == ACCESS_METHOD_SEQUENTIAL_RECORD_INFO) { @@ -9164,6 +9170,25 @@ qexec_open_scan (THREAD_ENTRY * thread_p, ACCESS_SPEC_TYPE * curr_spec, VAL_LIST goto exit_on_error; } } + else if (scan_type == S_PARALLEL_HEAP_SCAN) + { + error_code = + scan_open_parallel_heap_scan (thread_p, s_id, mvcc_select_lock_needed, scan_op_type, fixed, grouped, + curr_spec->single_fetch, curr_spec->s_dbval, val_list, vd, + &ACCESS_SPEC_CLS_OID (curr_spec), &ACCESS_SPEC_HFID (curr_spec), + curr_spec->s.cls_node.cls_regu_list_pred, curr_spec->where_pred, + curr_spec->s.cls_node.cls_regu_list_rest, + curr_spec->s.cls_node.num_attrs_pred, curr_spec->s.cls_node.attrids_pred, + curr_spec->s.cls_node.cache_pred, curr_spec->s.cls_node.num_attrs_rest, + curr_spec->s.cls_node.attrids_rest, curr_spec->s.cls_node.cache_rest, + scan_type, curr_spec->s.cls_node.cache_reserved, + curr_spec->s.cls_node.cls_regu_list_reserved, false); + if (error_code != NO_ERROR) + { + ASSERT_ERROR (); + goto exit_on_error; + } + } else if (scan_type == S_HEAP_PAGE_SCAN) { error_code = scan_open_heap_page_scan (thread_p, s_id, val_list, vd, &ACCESS_SPEC_CLS_OID (curr_spec), @@ -10164,6 +10189,19 @@ qexec_reset_regu_variable (REGU_VARIABLE * var) } } +void +reset_pred_or_regu_var_list (void * object, bool is_pred) +{ + if(is_pred) + { + qexec_reset_pred_expr((PRED_EXPR*)object); + } + else + { + qexec_reset_regu_variable_list((REGU_VARIABLE_LIST)object); + } +} + /* * qexec_prune_spec () - perform partition pruning on an access spec * return : error code or NO_ERROR diff --git a/src/query/query_executor.h b/src/query/query_executor.h index 8344f566fa5..0074e6a22fb 100644 --- a/src/query/query_executor.h +++ b/src/query/query_executor.h @@ -101,4 +101,6 @@ extern int qexec_insert_tuple_into_list (THREAD_ENTRY * thread_p, qfile_list_id valptr_list_node * outptr_list, val_descr * vd, qfile_tuple_record * tplrec); extern void qexec_replace_prior_regu_vars_prior_expr (THREAD_ENTRY * thread_p, regu_variable_node * regu, xasl_node * xasl, xasl_node * connect_by_ptr); +extern void +reset_pred_or_regu_var_list (void * object, bool is_pred); #endif /* _QUERY_EXECUTOR_H_ */ diff --git a/src/query/scan_manager.c b/src/query/scan_manager.c index 51400b0fb22..7da63c1f9bf 100644 --- a/src/query/scan_manager.c +++ b/src/query/scan_manager.c @@ -51,6 +51,7 @@ #include "xasl.h" #include "query_hash_scan.h" #include "statistics.h" +#include "parallel_heap_scan.hpp" // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" @@ -4158,7 +4159,9 @@ scan_start_scan (THREAD_ENTRY * thread_p, SCAN_ID * scan_id) hsidp->caches_inited = true; } break; - + case S_PARALLEL_HEAP_SCAN: + scan_start_parallel_heap_scan (thread_p, scan_id); + break; case S_HEAP_PAGE_SCAN: VPID_SET_NULL (&scan_id->s.hpsid.curr_vpid); break; @@ -4403,6 +4406,10 @@ scan_reset_scan_block (THREAD_ENTRY * thread_p, SCAN_ID * s_id) } break; + case S_PARALLEL_HEAP_SCAN: + scan_reset_scan_block_parallel_heap_scan (thread_p, s_id); + break; + case S_INDX_SCAN: if (s_id->grouped) { @@ -4535,6 +4542,7 @@ scan_next_scan_block (THREAD_ENTRY * thread_p, SCAN_ID * s_id) case S_HEAP_SCAN_RECORD_INFO: case S_HEAP_PAGE_SCAN: case S_HEAP_SAMPLING_SCAN: + case S_PARALLEL_HEAP_SCAN: if (s_id->grouped) { /* grouped, fixed scan */ @@ -4719,6 +4727,10 @@ scan_end_scan (THREAD_ENTRY * thread_p, SCAN_ID * scan_id) } break; + case S_PARALLEL_HEAP_SCAN: + scan_end_parallel_heap_scan (thread_p, scan_id); + break; + case S_CLASS_ATTR_SCAN: /* do not free attr_cache here. xs_clear_access_spec_list() will free attr_caches. */ break; @@ -4811,6 +4823,10 @@ scan_close_scan (THREAD_ENTRY * thread_p, SCAN_ID * scan_id) case S_HEAP_SAMPLING_SCAN: break; + case S_PARALLEL_HEAP_SCAN: + scan_close_parallel_heap_scan (thread_p, scan_id); + break; + case S_INDX_SCAN: isidp = &scan_id->s.isid; if (isidp->key_vals) @@ -5110,6 +5126,9 @@ scan_next_scan_local (THREAD_ENTRY * thread_p, SCAN_ID * scan_id) case S_HEAP_SAMPLING_SCAN: status = scan_next_heap_scan (thread_p, scan_id); break; + case S_PARALLEL_HEAP_SCAN: + status = scan_next_parallel_heap_scan (thread_p, scan_id); + break; case S_HEAP_PAGE_SCAN: status = scan_next_heap_page_scan (thread_p, scan_id); diff --git a/src/query/scan_manager.h b/src/query/scan_manager.h index a5e930600dc..9260a75254b 100644 --- a/src/query/scan_manager.h +++ b/src/query/scan_manager.h @@ -76,6 +76,7 @@ using PRED_EXPR = cubxasl::pred_expr; typedef enum { S_HEAP_SCAN = 1, + S_PARALLEL_HEAP_SCAN, S_CLASS_ATTR_SCAN, S_INDX_SCAN, S_LIST_SCAN, @@ -120,6 +121,28 @@ struct heap_scan_id sampling_info sampling; /* for sampling statistics */ }; /* Regular Heap File Scan Identifier */ +class parallel_heap_scan_master; /* forward declaration */ +typedef struct parallel_heap_scan_id PARALLEL_HEAP_SCAN_ID; +struct parallel_heap_scan_id +{ + OID curr_oid; /* current object identifier */ + OID cls_oid; /* class object identifier */ + HFID hfid; /* heap file identifier */ + HEAP_SCANCACHE scan_cache; /* heap file scan_cache */ + HEAP_SCANRANGE scan_range; /* heap file scan range */ + SCAN_PRED scan_pred; /* scan predicates(filters) */ + SCAN_ATTRS pred_attrs; /* attr info from predicates */ + regu_variable_list_node *rest_regu_list; /* regulator variable list */ + SCAN_ATTRS rest_attrs; /* attr info from other than preds */ + bool caches_inited; /* are the caches initialized?? */ + bool scancache_inited; + bool scanrange_inited; + DB_VALUE **cache_recordinfo; /* cache for record information */ + regu_variable_list_node *recordinfo_regu_list; /* regulator variable list for record info */ + sampling_info sampling; /* for sampling statistics */ + parallel_heap_scan_master *master; +}; /* Heap PARALLEL Scan Identifier */ + typedef struct heap_page_scan_id HEAP_PAGE_SCAN_ID; struct heap_page_scan_id { @@ -365,6 +388,7 @@ struct scan_id_struct { LLIST_SCAN_ID llsid; /* List File Scan Identifier */ HEAP_SCAN_ID hsid; /* Regular Heap File Scan Identifier */ + PARALLEL_HEAP_SCAN_ID phsid; /* Parallel Heap File Scan Identifier */ HEAP_PAGE_SCAN_ID hpsid; /* Scan heap pages without going through records */ INDX_SCAN_ID isid; /* Indexed Heap File Scan Identifier */ INDEX_NODE_SCAN_ID insid; /* Scan b-tree nodes */ diff --git a/src/storage/heap_file.c b/src/storage/heap_file.c index 0afd46641b3..e3e54481f62 100644 --- a/src/storage/heap_file.c +++ b/src/storage/heap_file.c @@ -8190,6 +8190,190 @@ heap_next_internal (THREAD_ENTRY * thread_p, const HFID * hfid, OID * class_oid, return scan; } +SCAN_CODE +heap_next_1page (THREAD_ENTRY * thread_p, const HFID * hfid, const VPID * vpid, OID * class_oid, OID * next_oid, + RECDES * recdes, HEAP_SCANCACHE * scan_cache, int ispeeking) +{ + VPID *vpidptr_incache; + INT16 type = REC_UNKNOWN; + OID oid; + RECDES forward_recdes; + SCAN_CODE scan = S_ERROR; + bool is_null_recdata; + + if (!OID_ISNULL (&scan_cache->node.class_oid)) + { + class_oid = &scan_cache->node.class_oid; + } + + if (OID_ISNULL (next_oid)) + { + /* Retrieve the first object of the page */ + oid.volid = vpid->volid; + oid.pageid = vpid->pageid; + oid.slotid = 0; /* i.e., will get slot 1 */ + } + else + { + oid = *next_oid; + } + + is_null_recdata = (recdes->data == NULL); + + /* Start looking for next object */ + while (true) + { + /* Start looking for next object in current page. If we reach the end of this page without finding a new object, + * fetch next page and continue looking there. If no objects are found, end scanning */ + + while (true) + { + + /* + * Fetch the page where the object of OID is stored. Use previous + * scan page whenever possible, otherwise, deallocate the page. + */ + if (scan_cache->page_watcher.pgptr != NULL) + { + vpidptr_incache = pgbuf_get_vpid_ptr (scan_cache->page_watcher.pgptr); + if (!VPID_EQ (vpid, vpidptr_incache)) + { + pgbuf_ordered_unfix (thread_p, &scan_cache->page_watcher); + } + } + + if (scan_cache->page_watcher.pgptr == NULL) + { + scan_cache->page_watcher.pgptr = + heap_scan_pb_lock_and_fetch (thread_p, vpid, OLD_PAGE, S_LOCK, scan_cache, + &scan_cache->page_watcher); + + if (scan_cache->page_watcher.pgptr == NULL) + { + if (er_errid () == ER_PB_BAD_PAGEID) + { + er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HEAP_UNKNOWN_OBJECT, 3, oid.volid, oid.pageid, + oid.slotid); + } + + /* something went wrong, return */ + assert (scan_cache->page_watcher.pgptr == NULL); + return S_ERROR; + } + } + + { + /* Find the next object. Skip relocated records (i.e., new_home records). This records must be accessed + * through the relocation record (i.e., the object). */ + + while (true) + { + scan = spage_next_record (scan_cache->page_watcher.pgptr, &oid.slotid, &forward_recdes, PEEK); + + if (scan != S_SUCCESS) + { + /* stop */ + break; + } + + if (oid.slotid == HEAP_HEADER_AND_CHAIN_SLOTID) + { + /* skip the header */ + continue; + } + type = spage_get_record_type (scan_cache->page_watcher.pgptr, oid.slotid); + if (type == REC_NEWHOME || type == REC_ASSIGN_ADDRESS || type == REC_UNKNOWN) + { + /* skip */ + continue; + } + + break; + } + } + + if (scan != S_SUCCESS) + { + if (scan == S_END) + { + /* must be last slot of page, end scanning */ + OID_SET_NULL (next_oid); + pgbuf_ordered_unfix (thread_p, &scan_cache->page_watcher); + return scan; + } + else + { + /* Error, stop scanning */ + pgbuf_ordered_unfix (thread_p, &scan_cache->page_watcher); + return scan; + } + } + else + { + /* found a new object */ + break; + } + } + + { + int cache_last_fix_page_save = scan_cache->cache_last_fix_page; + + scan_cache->cache_last_fix_page = true; + + scan = + heap_scan_get_visible_version (thread_p, &oid, class_oid, recdes, &forward_recdes, scan_cache, ispeeking, + NULL_CHN); + scan_cache->cache_last_fix_page = cache_last_fix_page_save; + } + + + if (scan == S_SUCCESS) + { + /* + * Make sure that the found object is an instance of the desired + * class. If it isn't then continue looking. + */ + if (class_oid == NULL || OID_ISNULL (class_oid) || !OID_IS_ROOTOID (&oid)) + { + /* stop */ + *next_oid = oid; + break; + } + else + { + /* continue looking */ + if (is_null_recdata) + { + /* reset recdes->data before getting next record */ + recdes->data = NULL; + } + continue; + } + } + else if (scan == S_SNAPSHOT_NOT_SATISFIED || scan == S_DOESNT_EXIST) + { + /* the record does not satisfies snapshot or was deleted - continue */ + if (is_null_recdata) + { + /* reset recdes->data before getting next record */ + recdes->data = NULL; + } + continue; + } + + /* scan was not successful, stop scanning */ + break; + } + + if (scan_cache->page_watcher.pgptr != NULL && scan_cache->cache_last_fix_page == false) + { + pgbuf_ordered_unfix (thread_p, &scan_cache->page_watcher); + } + + return scan; +} + + /* * heap_first () - Retrieve or peek first object of heap * return: SCAN_CODE (Either of S_SUCCESS, S_DOESNT_FIT, S_END, S_ERROR) diff --git a/src/storage/heap_file.h b/src/storage/heap_file.h index ff5e86d8c19..e2407f98a4f 100644 --- a/src/storage/heap_file.h +++ b/src/storage/heap_file.h @@ -426,6 +426,8 @@ extern SCAN_CODE heap_next_record_info (THREAD_ENTRY * thread_p, const HFID * hf DB_VALUE ** cache_recordinfo); extern SCAN_CODE heap_prev (THREAD_ENTRY * thread_p, const HFID * hfid, OID * class_oid, OID * prev_oid, RECDES * recdes, HEAP_SCANCACHE * scan_cache, int ispeeking); +extern SCAN_CODE heap_next_1page (THREAD_ENTRY * thread_p, const HFID * hfid, const VPID * vpid, OID * class_oid, + OID * next_oid, RECDES * recdes, HEAP_SCANCACHE * scan_cache, int ispeeking); extern SCAN_CODE heap_prev_record_info (THREAD_ENTRY * thread_p, const HFID * hfid, OID * class_oid, OID * next_oid, RECDES * recdes, HEAP_SCANCACHE * scan_cache, int ispeeking, DB_VALUE ** cache_recordinfo); From 0252fe391309f594f0c6aa04a2b22fe59c87b403 Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Fri, 13 Dec 2024 16:33:36 +0900 Subject: [PATCH 04/20] db_class (change to private heap and notifying) --- src/query/parallel_heap_scan.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/query/parallel_heap_scan.cpp b/src/query/parallel_heap_scan.cpp index 64593f95966..28df8a0658a 100644 --- a/src/query/parallel_heap_scan.cpp +++ b/src/query/parallel_heap_scan.cpp @@ -183,8 +183,21 @@ void parallel_heap_scan_result_queue_entry::init (THREAD_ENTRY *thread_p, int n_ } void parallel_heap_scan_result_queue_entry::clear () { - db_value_clear_array (&pred_val_array); - db_value_clear_array (&rest_val_array); + int i; + for (i = 0; i < pred_val_array.size; i++) + { + if (DB_NEED_CLEAR (&pred_val_array.vals[i])) + { + pr_clear_value (&pred_val_array.vals[i]); + } + } + for (i = 0; i < rest_val_array.size; i++) + { + if (DB_NEED_CLEAR (&rest_val_array.vals[i])) + { + pr_clear_value (&rest_val_array.vals[i]); + } + } scan_code = S_END; valid = false; curr_oid = {0,0,0}; @@ -627,7 +640,13 @@ SCAN_CODE parallel_heap_scan_master::get_result (THREAD_ENTRY *thread_p, SCAN_ID } else { + bool need_signal = m_context->m_result_queue[i].var.waiting; lock.unlock(); + + if (need_signal) + { + m_context->m_result_queue[i].var.cond.notify_one(); + } continue; } } @@ -1383,10 +1402,13 @@ scan_next_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id) int scan_reset_scan_block_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id) { + HL_HEAPID orig_heap_id; if (scan_id->s.phsid.master->m_is_reset_once) { + orig_heap_id = db_change_private_heap (thread_p, 0); scan_id->s.phsid.master->reset (scan_id); //scan_id->s.phsid.master->reset(scan_id); //WHY??????????? + db_change_private_heap (thread_p, orig_heap_id); } else { From 03d8fffe396cc571dac96a9f9e97015a101759f5 Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Fri, 13 Dec 2024 16:39:40 +0900 Subject: [PATCH 05/20] code style --- src/query/query_executor.c | 20 ++++++++++---------- src/query/query_executor.h | 3 +-- src/query/scan_manager.h | 2 +- src/storage/heap_file.c | 3 +-- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/query/query_executor.c b/src/query/query_executor.c index 4d1267d0f06..516b847295b 100644 --- a/src/query/query_executor.c +++ b/src/query/query_executor.c @@ -10207,17 +10207,17 @@ qexec_reset_regu_variable (REGU_VARIABLE * var) } } -void -reset_pred_or_regu_var_list (void * object, bool is_pred) +void +reset_pred_or_regu_var_list (void *object, bool is_pred) { - if(is_pred) - { - qexec_reset_pred_expr((PRED_EXPR*)object); - } - else - { - qexec_reset_regu_variable_list((REGU_VARIABLE_LIST)object); - } + if (is_pred) + { + qexec_reset_pred_expr ((PRED_EXPR *) object); + } + else + { + qexec_reset_regu_variable_list ((REGU_VARIABLE_LIST) object); + } } /* diff --git a/src/query/query_executor.h b/src/query/query_executor.h index 0074e6a22fb..45e22e6d6d3 100644 --- a/src/query/query_executor.h +++ b/src/query/query_executor.h @@ -101,6 +101,5 @@ extern int qexec_insert_tuple_into_list (THREAD_ENTRY * thread_p, qfile_list_id valptr_list_node * outptr_list, val_descr * vd, qfile_tuple_record * tplrec); extern void qexec_replace_prior_regu_vars_prior_expr (THREAD_ENTRY * thread_p, regu_variable_node * regu, xasl_node * xasl, xasl_node * connect_by_ptr); -extern void -reset_pred_or_regu_var_list (void * object, bool is_pred); +extern void reset_pred_or_regu_var_list (void *object, bool is_pred); #endif /* _QUERY_EXECUTOR_H_ */ diff --git a/src/query/scan_manager.h b/src/query/scan_manager.h index 86aa4d948d7..964bbadeea7 100644 --- a/src/query/scan_manager.h +++ b/src/query/scan_manager.h @@ -120,7 +120,7 @@ struct heap_scan_id sampling_info sampling; /* for sampling statistics */ }; /* Regular Heap File Scan Identifier */ -class parallel_heap_scan_master; /* forward declaration */ +class parallel_heap_scan_master; /* forward declaration */ typedef struct parallel_heap_scan_id PARALLEL_HEAP_SCAN_ID; struct parallel_heap_scan_id { diff --git a/src/storage/heap_file.c b/src/storage/heap_file.c index e3e54481f62..2f6c5c5598e 100644 --- a/src/storage/heap_file.c +++ b/src/storage/heap_file.c @@ -8245,8 +8245,7 @@ heap_next_1page (THREAD_ENTRY * thread_p, const HFID * hfid, const VPID * vpid, if (scan_cache->page_watcher.pgptr == NULL) { scan_cache->page_watcher.pgptr = - heap_scan_pb_lock_and_fetch (thread_p, vpid, OLD_PAGE, S_LOCK, scan_cache, - &scan_cache->page_watcher); + heap_scan_pb_lock_and_fetch (thread_p, vpid, OLD_PAGE, S_LOCK, scan_cache, &scan_cache->page_watcher); if (scan_cache->page_watcher.pgptr == NULL) { From 084da103768c67a3359d707285b1f1b2c71ada8c Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Fri, 13 Dec 2024 17:07:24 +0900 Subject: [PATCH 06/20] only for user table --- src/query/query_executor.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/query/query_executor.c b/src/query/query_executor.c index 516b847295b..da3883e13bd 100644 --- a/src/query/query_executor.c +++ b/src/query/query_executor.c @@ -9121,7 +9121,10 @@ qexec_open_scan (THREAD_ENTRY * thread_p, ACCESS_SPEC_TYPE * curr_spec, VAL_LIST #if defined(SERVER_MODE) if (!mvcc_select_lock_needed) { - scan_type = S_PARALLEL_HEAP_SCAN; + if (curr_spec->s.cls_node.hfid.hpgid > (1 << 12)) /* Only for User table */ + { + scan_type = S_PARALLEL_HEAP_SCAN; + } } #endif } From 9594c90cfc3a1a304e4f6b7d67ed7297f98570b0 Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Mon, 16 Dec 2024 17:49:48 +0900 Subject: [PATCH 07/20] parallel_heap_scan with multiple threads --- src/query/parallel_heap_scan.cpp | 142 ++++++++++++++++++++++--------- src/query/query_executor.c | 2 +- 2 files changed, 102 insertions(+), 42 deletions(-) diff --git a/src/query/parallel_heap_scan.cpp b/src/query/parallel_heap_scan.cpp index 28df8a0658a..9f446b72b37 100644 --- a/src/query/parallel_heap_scan.cpp +++ b/src/query/parallel_heap_scan.cpp @@ -224,6 +224,7 @@ class parallel_heap_scan_result_queue std::mutex mutex; std::condition_variable cond; }; + std::atomic is_scan_ended; parallel_heap_scan_result_queue_variable var; void init (THREAD_ENTRY *thread_p, int n_pred, int n_rest); @@ -248,6 +249,7 @@ parallel_heap_scan_result_queue::parallel_heap_scan_result_queue() { var.start = var.end = 0; var.waiting = false; + is_scan_ended = false; } void parallel_heap_scan_result_queue::init (THREAD_ENTRY *thread_p, int n_pred, int n_rest) @@ -260,6 +262,7 @@ void parallel_heap_scan_result_queue::init (THREAD_ENTRY *thread_p, int n_pred, std::unique_lock (var.mutex); var.start = var.end = 0; var.waiting = false; + is_scan_ended = false; } void parallel_heap_scan_result_queue::clear () @@ -274,6 +277,7 @@ void parallel_heap_scan_result_queue::clear () } var.start = var.end = 0; var.waiting = false; + is_scan_ended = false; } bool parallel_heap_scan_result_queue::isFull () @@ -412,16 +416,17 @@ class parallel_heap_scan_context : public cubthread::entry_manager std::atomic m_tasks_executed; std::atomic m_tasks_started; parallel_heap_scan_result_queue *m_result_queue; + std::atomic scan_ended_queue_count; int m_has_error; SCAN_ID *m_scan_id; int m_orig_tran_index; REGU_VARIABLE_LIST orig_pred_list; REGU_VARIABLE_LIST orig_rest_list; - class locked_vpid { public: VPID vpid; + bool is_ended; std::mutex mutex; } m_locked_vpid; @@ -452,7 +457,7 @@ class parallel_heap_scan_task : public cubthread::entry_task { m_result_queue = queue; } - SCAN_CODE page_next (THREAD_ENTRY *thread_p, HFID *hfid); + SCAN_CODE page_next (THREAD_ENTRY *thread_p, HFID *hfid, VPID *vpid); }; parallel_heap_scan_context::parallel_heap_scan_context (SCAN_ID *scan_id, int tran_index, @@ -461,10 +466,12 @@ parallel_heap_scan_context::parallel_heap_scan_context (SCAN_ID *scan_id, int tr m_scan_id = scan_id; m_orig_tran_index = tran_index; VPID_SET_NULL (&m_locked_vpid.vpid); + m_locked_vpid.is_ended = false; m_result_queue = new parallel_heap_scan_result_queue[parallelism] {parallel_heap_scan_result_queue()}; m_tasks_started = 0; m_tasks_executed = 0; m_has_error = NO_ERROR; + scan_ended_queue_count = 0; } parallel_heap_scan_context::~parallel_heap_scan_context() @@ -479,21 +486,30 @@ void parallel_heap_scan_context::set_regu_vars (REGU_VARIABLE_LIST pred_list, orig_rest_list = rest_list; } -SCAN_CODE parallel_heap_scan_task::page_next (THREAD_ENTRY *thread_p, HFID *hfid) +SCAN_CODE parallel_heap_scan_task::page_next (THREAD_ENTRY *thread_p, HFID *hfid, VPID *vpid) { std::unique_lock lock (m_context->m_locked_vpid.mutex); - SCAN_CODE page_scan_code = heap_page_next (thread_p, NULL, hfid, &m_context->m_locked_vpid.vpid, NULL); - if (page_scan_code == S_END) + if (m_context->m_locked_vpid.is_ended) { - lock.unlock(); return S_END; } - return page_scan_code; + else + { + SCAN_CODE page_scan_code = heap_page_next (thread_p, NULL, hfid, &m_context->m_locked_vpid.vpid, NULL); + VPID_COPY (vpid, &m_context->m_locked_vpid.vpid); + if (page_scan_code == S_END) + { + m_context->m_locked_vpid.is_ended = true; + return S_END; + } + return page_scan_code; + } } void parallel_heap_scan_task::execute (cubthread::entry &thread_ref) { int tran_index = m_context->m_orig_tran_index; + int ret = NO_ERROR; THREAD_ENTRY *thread_p = &thread_ref; SCAN_ID *scan_id, *orig_scan_id = m_context->m_scan_id; PARALLEL_HEAP_SCAN_ID *phsidp = &orig_scan_id->s.phsid; @@ -521,7 +537,8 @@ void parallel_heap_scan_task::execute (cubthread::entry &thread_ref) PH_PRED_EXPR, hsidp->pred_attrs.attr_cache); link_attr_cache (thread_p, hsidp->scan_pred.regu_list, phsidp->pred_attrs.attr_cache, hsidp->pred_attrs.attr_cache); link_attr_cache (thread_p, hsidp->rest_regu_list, phsidp->rest_attrs.attr_cache, hsidp->rest_attrs.attr_cache); - scan_start_scan (thread_p, scan_id); + hsidp->caches_inited = false; + ret = scan_start_scan (thread_p, scan_id); reset_pred_or_regu_var_list (hsidp->scan_pred.pred_expr, true); reset_pred_or_regu_var_list (hsidp->scan_pred.regu_list, false); reset_pred_or_regu_var_list (hsidp->rest_regu_list, false); @@ -532,8 +549,8 @@ void parallel_heap_scan_task::execute (cubthread::entry &thread_ref) while (TRUE) { - page_scan_code = page_next (thread_p, &hfid); - VPID_COPY (&vpid, &m_context->m_locked_vpid.vpid); + page_scan_code = page_next (thread_p, &hfid, &vpid); + if (page_scan_code == S_END) { m_result_queue->enqueue (hsidp, page_scan_code); @@ -600,63 +617,103 @@ SCAN_CODE parallel_heap_scan_master::get_result (THREAD_ENTRY *thread_p, SCAN_ID SCAN_CODE scan_code; int result = FALSE; int timeout_count = 0; + if (m_context->scan_ended_queue_count == parallelism) + { + return S_END; + } + for (int i = 0; i < parallelism; i++) { - std::unique_lock lock (m_context->m_result_queue[i].var.mutex, std::try_to_lock); - if (lock.owns_lock()) + if (!m_context->m_result_queue[i].is_scan_ended) { - result = m_context->m_result_queue[i].dequeue_without_lock (&scan_id->s.phsid, &scan_code); - if (result == TRUE) + std::unique_lock lock (m_context->m_result_queue[i].var.mutex, std::try_to_lock); + if (lock.owns_lock()) { - return scan_code; + result = m_context->m_result_queue[i].dequeue_without_lock (&scan_id->s.phsid, &scan_code); + if (result == TRUE) + { + if (scan_code == S_END) + { + lock.unlock(); + m_context->scan_ended_queue_count++; + m_context->m_result_queue[i].is_scan_ended = true; + result = FALSE; + continue; + } + return scan_code; + } + else + { + lock.unlock(); + continue; + } } else { - lock.unlock(); continue; } } - else - { - continue; - } + + } + + if (m_context->scan_ended_queue_count == parallelism) + { + return S_END; } while (result == FALSE) { for (int i=0; i 100) - { - return S_ERROR; - } - std::unique_lock lock (m_context->m_result_queue[i].var.mutex, std::try_to_lock); - if (lock.owns_lock()) + if (!m_context->m_result_queue[i].is_scan_ended) { - result = m_context->m_result_queue[i].dequeue_without_lock (&scan_id->s.phsid, &scan_code); - if (result == TRUE) + if (timeout_count > 100) { - return scan_code; + return S_ERROR; } - else + std::unique_lock lock (m_context->m_result_queue[i].var.mutex, std::try_to_lock); + if (lock.owns_lock()) { - bool need_signal = m_context->m_result_queue[i].var.waiting; - lock.unlock(); - - if (need_signal) + result = m_context->m_result_queue[i].dequeue_without_lock (&scan_id->s.phsid, &scan_code); + if (result == TRUE) { - m_context->m_result_queue[i].var.cond.notify_one(); + if (scan_code == S_END) + { + lock.unlock(); + m_context->scan_ended_queue_count++; + m_context->m_result_queue[i].is_scan_ended = true; + result = FALSE; + continue; + } + return scan_code; } - continue; + else + { + bool need_signal = m_context->m_result_queue[i].var.waiting; + lock.unlock(); + + if (need_signal) + { + m_context->m_result_queue[i].var.cond.notify_one(); + } + continue; + } + } + else + { + thread_sleep (10); + timeout_count++; } } else { - thread_sleep (10); - timeout_count++; + continue; } } - + if (m_context->scan_ended_queue_count == parallelism) + { + return S_END; + } } return S_ERROR; } @@ -665,6 +722,7 @@ void parallel_heap_scan_master::start (THREAD_ENTRY *thread_p) { //std::unique_ptr task = NULL; m_context->set_regu_vars (m_scan_id->s.phsid.scan_pred.regu_list, m_scan_id->s.phsid.rest_regu_list); + m_context->scan_ended_queue_count = 0; for (int i = 0; i < parallelism; i++) { m_context->m_result_queue[i].init (thread_p, @@ -676,7 +734,6 @@ void parallel_heap_scan_master::start (THREAD_ENTRY *thread_p) void parallel_heap_scan_master::reset (SCAN_ID *scan_id) { std::unique_ptr task = NULL; - int retired_result_queue_count = 0; while (m_context->m_tasks_executed < m_context->m_tasks_started) { thread_sleep (10); @@ -686,8 +743,10 @@ void parallel_heap_scan_master::reset (SCAN_ID *scan_id) { m_context->m_result_queue[i].clear(); } + m_context->scan_ended_queue_count = 0; std::unique_lock lock (m_context->m_locked_vpid.mutex); VPID_SET_NULL (&m_context->m_locked_vpid.vpid); + m_context->m_locked_vpid.is_ended = false; scan_id->single_fetched = false; scan_id->null_fetched = false; scan_id->position = (scan_id->direction == S_FORWARD) ? S_BEFORE : S_AFTER; @@ -1155,7 +1214,8 @@ scan_next_heap_scan_1page_internal (THREAD_ENTRY *thread_p, SCAN_ID *scan_id, VP { COPY_OID (&retry_oid, &hsidp->curr_oid); object_get_status = OBJ_GET_WITHOUT_LOCK; - + assert (hsidp->pred_attrs.attr_cache->last_classrepr != NULL); + assert (hsidp->rest_attrs.attr_cache->last_classrepr != NULL); restart_scan_oid: /* get next object */ diff --git a/src/query/query_executor.c b/src/query/query_executor.c index da3883e13bd..aa5004bd54f 100644 --- a/src/query/query_executor.c +++ b/src/query/query_executor.c @@ -9121,7 +9121,7 @@ qexec_open_scan (THREAD_ENTRY * thread_p, ACCESS_SPEC_TYPE * curr_spec, VAL_LIST #if defined(SERVER_MODE) if (!mvcc_select_lock_needed) { - if (curr_spec->s.cls_node.hfid.hpgid > (1 << 12)) /* Only for User table */ + if (!oid_is_cached_class_oid (&curr_spec->s.cls_node.cls_oid)) /* Only for User table */ { scan_type = S_PARALLEL_HEAP_SCAN; } From 4dbc4a84a8bd94e7475a94574cdca33bf0146b67 Mon Sep 17 00:00:00 2001 From: Daehyun Kim <18080546+vimkim@users.noreply.github.com> Date: Sat, 14 Dec 2024 03:32:22 +0900 Subject: [PATCH 08/20] [CBRD-25356] rename att_name in db_serial to attr_name (#5346) http://jira.cubrid.org/browse/CBRD-25356 * rename att_name in db_serial to attr_name for consistency with other catalogs * minor: fix comments for consistency for the update. This edit was suggested during the team meeting. * fix: att_name in emit_class_alter_serial query * fix att_name in pt_make_field_extra... for consistency * revert(class_object): not related att_name in classobj_constr... * refactor(macro): SERIAL_ATTR_ATT_NAME to ATTR_NAME (nit) * style(storage_common): fix additional space after rename * ATT -> ATTR for authenticate_owner after rebase --- src/executables/unload_schema.c | 8 ++++---- src/object/authenticate_owner.cpp | 2 +- src/object/schema_system_catalog_install.cpp | 2 +- src/parser/parser_support.c | 6 +++--- src/query/execute_statement.c | 4 ++-- src/query/serial.c | 6 +++--- src/storage/storage_common.h | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/executables/unload_schema.c b/src/executables/unload_schema.c index 03673a28eae..ed22451a2d8 100644 --- a/src/executables/unload_schema.c +++ b/src/executables/unload_schema.c @@ -700,12 +700,12 @@ export_serial (extract_context & ctxt, print_output & output_ctx) const char *query_all = "select [unique_name], [name], [owner].[name], " "[current_val], " "[increment_val], " "[max_val], " "[min_val], " "[cyclic], " "[started], " "[cached_num], " "[comment] " - "from [db_serial] where [class_name] is null and [att_name] is null"; + "from [db_serial] where [class_name] is null and [attr_name] is null"; const char *query_user = "select [unique_name], [name], [owner].[name], " "[current_val], " "[increment_val], " "[max_val], " "[min_val], " "[cyclic], " "[started], " "[cached_num], " "[comment] " - "from [db_serial] where [class_name] is null and [att_name] is null and owner.name='%s'"; + "from [db_serial] where [class_name] is null and [attr_name] is null and owner.name='%s'"; if (ctxt.is_dba_user == false && ctxt.is_dba_group_member == false) { @@ -907,12 +907,12 @@ emit_class_alter_serial (extract_context & ctxt, print_output & output_ctx) const char *query_all = "select [unique_name], [name], [owner].[name], [current_val], [increment_val], [max_val], [min_val], " "[cyclic], [started], [cached_num], [class_name], [comment] " - "from [db_serial] where [class_name] is not null and [att_name] is not null"; + "from [db_serial] where [class_name] is not null and [attr_name] is not null"; const char *query_user = "select [unique_name], [name], [owner].[name], [current_val], [increment_val], [max_val], [min_val], " "[cyclic], [started], [cached_num], [class_name], [comment] " - "from [db_serial] where [class_name] is not null and [att_name] is not null and owner.name='%s'"; + "from [db_serial] where [class_name] is not null and [attr_name] is not null and owner.name='%s'"; if (ctxt.is_dba_user == false && ctxt.is_dba_group_member == false) { diff --git a/src/object/authenticate_owner.cpp b/src/object/authenticate_owner.cpp index 365720ee8f3..a152cab152b 100644 --- a/src/object/authenticate_owner.cpp +++ b/src/object/authenticate_owner.cpp @@ -125,7 +125,7 @@ au_change_serial_owner (MOP serial_mop, MOP owner_mop, bool by_class_owner_chang if (!by_class_owner_change) { /* It can be checked as one of unique_name, class_name, and att_name. */ - error = obj_get (serial_mop, SERIAL_ATTR_ATT_NAME, &value); + error = obj_get (serial_mop, SERIAL_ATTR_ATTR_NAME, &value); if (error != NO_ERROR) { ASSERT_ERROR (); diff --git a/src/object/schema_system_catalog_install.cpp b/src/object/schema_system_catalog_install.cpp index 8f4220b2a52..73916ad1b22 100644 --- a/src/object/schema_system_catalog_install.cpp +++ b/src/object/schema_system_catalog_install.cpp @@ -968,7 +968,7 @@ namespace cubschema } }, {"class_name", "string"}, - {"att_name", "string"}, + {"attr_name", "string"}, {attribute_kind::CLASS_METHOD, "change_serial_owner", "au_change_serial_owner_method"}, { "cached_num", "integer", [] (DB_VALUE* val) diff --git a/src/parser/parser_support.c b/src/parser/parser_support.c index eb6aaf6fb9d..b990e55aceb 100644 --- a/src/parser/parser_support.c +++ b/src/parser/parser_support.c @@ -5975,7 +5975,7 @@ pt_make_collation_expr_node (PARSER_CONTEXT * parser) * * IF( (SELECT count(*) * FROM db_serial S - * WHERE S.att_name = A.attr_name AND + * WHERE S.attr_name = A.attr_name AND * S.class_name = C.class_name * ) >= 1 , * 'auto_increment', @@ -6004,8 +6004,8 @@ pt_make_field_extra_expr_node (PARSER_CONTEXT * parser) from_item = pt_add_table_name_to_from_list (parser, query, "db_serial", "S", DB_AUTH_NONE); - /* S.att_name = A.attr_name */ - where_item1 = pt_make_pred_with_identifiers (parser, PT_EQ, "S.att_name", "A.attr_name"); + /* S.attr_name = A.attr_name */ + where_item1 = pt_make_pred_with_identifiers (parser, PT_EQ, "S.attr_name", "A.attr_name"); /* S.class_name = C.class_name */ where_item2 = pt_make_pred_with_identifiers (parser, PT_EQ, "S.class_name", "C.class_name"); diff --git a/src/query/execute_statement.c b/src/query/execute_statement.c index e533f0d00be..0bb255af332 100644 --- a/src/query/execute_statement.c +++ b/src/query/execute_statement.c @@ -807,7 +807,7 @@ do_create_serial_internal (MOP * serial_object, const char *serial_name, DB_VALU if (att_name) { db_make_string (&value, att_name); - error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_ATT_NAME, &value); + error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_ATTR_NAME, &value); pr_clear_value (&value); if (error != NO_ERROR) { @@ -948,7 +948,7 @@ do_update_auto_increment_serial_on_rename (MOP serial_obj, const char *class_nam /* att name */ db_make_string (&value, att_name); - error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_ATT_NAME, &value); + error = dbt_put_internal (obj_tmpl, SERIAL_ATTR_ATTR_NAME, &value); pr_clear_value (&value); if (error != NO_ERROR) { diff --git a/src/query/serial.c b/src/query/serial.c index e14709abcde..404cba80cc5 100644 --- a/src/query/serial.c +++ b/src/query/serial.c @@ -65,7 +65,7 @@ typedef enum SERIAL_ATTR_CYCLIC_INDEX, SERIAL_ATTR_STARTED_INDEX, SERIAL_ATTR_CLASS_NAME_INDEX, - SERIAL_ATTR_ATT_NAME_INDEX, + SERIAL_ATTR_ATTR_NAME_INDEX, SERIAL_ATTR_CACHED_NUM_INDEX, SERIAL_ATTR_MAX_INDEX } SR_ATTRIBUTES; @@ -1303,9 +1303,9 @@ serial_load_attribute_info_of_db_serial (THREAD_ENTRY * thread_p) { serial_Attrs_id[SERIAL_ATTR_CLASS_NAME_INDEX] = i; } - else if (strcmp (attr_name_p, SERIAL_ATTR_ATT_NAME) == 0) + else if (strcmp (attr_name_p, SERIAL_ATTR_ATTR_NAME) == 0) { - serial_Attrs_id[SERIAL_ATTR_ATT_NAME_INDEX] = i; + serial_Attrs_id[SERIAL_ATTR_ATTR_NAME_INDEX] = i; } else if (strcmp (attr_name_p, SERIAL_ATTR_CACHED_NUM) == 0) { diff --git a/src/storage/storage_common.h b/src/storage/storage_common.h index f8546d49e68..f624dfbc1a9 100644 --- a/src/storage/storage_common.h +++ b/src/storage/storage_common.h @@ -1100,7 +1100,7 @@ typedef enum #define SERIAL_ATTR_CYCLIC "cyclic" #define SERIAL_ATTR_STARTED "started" #define SERIAL_ATTR_CLASS_NAME "class_name" -#define SERIAL_ATTR_ATT_NAME "att_name" +#define SERIAL_ATTR_ATTR_NAME "attr_name" #define SERIAL_ATTR_CACHED_NUM "cached_num" #define SERIAL_ATTR_COMMENT "comment" From 743310209cd5dda61d65362577c25b50c1b2e881 Mon Sep 17 00:00:00 2001 From: Kisoo Han Date: Mon, 16 Dec 2024 08:58:14 +0900 Subject: [PATCH 09/20] [CBRD-25706] change external lib URLs of lz4, re2 and win flex/bison (#5699) change external lib URLs for lz4, re2 and win flex/bison --- 3rdparty/CMakeLists.txt | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 52e81a13b03..3ec5cf7d256 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -24,6 +24,9 @@ set(WITH_RAPIDJSON_URL "https://github.com/CUBRID/3rdparty/raw/develop/rapidjson set(WITH_LIBOPENSSL_URL "https://github.com/CUBRID/3rdparty/raw/develop/openssl/openssl-1.1.1f.tar.gz") # openssl library sources URL set(WITH_LIBUNIXODBC_URL "https://github.com/CUBRID/3rdparty/raw/develop/unixODBC/unixODBC-2.3.9.tar.gz") # unixODBC library sources URL set(WITH_LIBTBB_URL "https://github.com/CUBRID/3rdparty/raw/develop/tbb/v2021.11.0.tar.gz") # intel oneTBB library sources URL +set(WITH_RE2_URL "https://github.com/CUBRID/3rdparty/raw/develop/re2/2022-06-01.tar.gz") # RE2 +set(WITH_LZ4_URL "https://github.com/CUBRID/3rdparty/raw/develop/lz4/v1.9.2.tar.gz") # LZ4 +set(WIN_FLEX_BISON_URL "https://github.com/CUBRID/3rdparty/raw/develop/win_flex_bison/win_flex_bison-2.5.22.zip") # Windows # URL_HASH is a hash value used to verify the integrity of a file downloaded from a specified URL. # It is optional but highly recommended to set this value. If not set, the file will be downloaded @@ -47,6 +50,9 @@ set(WITH_RAPIDJSON_URL_HASH "SHA256=bf7ced29704a1e696fbccf2a2b4ea068e7774fa37f6d set(WITH_LIBOPENSSL_URL_HASH "SHA256=186c6bfe6ecfba7a5b48c47f8a1673d0f3b0e5ba2e25602dd23b629975da3f35") # openssl library sources URL set(WITH_LIBUNIXODBC_URL_HASH "SHA256=52833eac3d681c8b0c9a5a65f2ebd745b3a964f208fc748f977e44015a31b207") # unixODBC library sources URL set(WITH_LIBTBB_URL_HASH "SHA256=782ce0cab62df9ea125cdea253a50534862b563f1d85d4cda7ad4e77550ac363") # intel oneTBB library sources URL +set(WITH_LIBTBB_URL_HASH "SHA256=782ce0cab62df9ea125cdea253a50534862b563f1d85d4cda7ad4e77550ac363") # intel oneTBB library sources URL +set(WITH_RE2_URL_HASH "SHA256=f89c61410a072e5cbcf8c27e3a778da7d6fd2f2b5b1445cd4f4508bee946ab0f") +set(WITH_LZ4_URL_HASH "SHA256=658ba6191fa44c92280d4aa2c271b0f4fbc0e34d249578dd05e50e76d0e5efcc") # options for external libraries (BUNDLED, EXTERAL or SYSTEM) @@ -66,6 +72,7 @@ set(WITH_LIBEDIT "${WITH_EXTERNAL_PREFIX}" CACHE STRING "Build with editlin set(WITH_LIBOPENSSL "${WITH_EXTERNAL_PREFIX}" CACHE STRING "Build with openssl library (default: EXTERNAL)") set(WITH_LIBUNIXODBC "${WITH_EXTERNAL_PREFIX}" CACHE STRING "Build with unixODBC library (default: EXTERNAL)") set(WITH_RE2 "${WITH_EXTERNAL_PREFIX}" CACHE STRING "Build with re2 library (default: EXTERNAL)") +set(WITH_LZ4 "${WITH_EXTERNAL_PREFIX}" CACHE STRING "Build with lz4 library (default: EXTERNAL)") set(WITH_LIBTBB "${WITH_EXTERNAL_PREFIX}" CACHE STRING "Build with TBB library (default: EXTERNAL)") message(STATUS "Build with flex and bison library: ${WITH_LIBFLEXBISON}") @@ -75,6 +82,7 @@ message(STATUS "Build with editline library: ${WITH_LIBEDIT}") message(STATUS "Build with openssl library: ${WITH_LIBOPENSSL}") message(STATUS "Build with unixODBC library: ${WITH_LIBUNIXODBC}") message(STATUS "Build with RE2 library: ${WITH_RE2}") +message(STATUS "Build with LZ4 library: ${WITH_LZ4}") message(STATUS "Build with TBB library: ${WITH_LIBTBB}") macro(ADD_BY_PRODUCTS_VARIABLE prefix_dependee) @@ -114,10 +122,8 @@ endif(WIN32) if(WITH_LIBFLEXBISON STREQUAL "EXTERNAL") if(WIN32) # bison and flex for Windows - set(WIN_FLEX_BISON_VERSION "2.5.22") - set(WIN_FLEX_BISON_URL "https://github.com/lexxmark/winflexbison/releases/download/v${WIN_FLEX_BISON_VERSION}/win_flex_bison-${WIN_FLEX_BISON_VERSION}.zip") set(WIN_FLEX_BISON_FILENAME "${WINDOWS_EXTERNAL_DIR}/Download/win_flex_bison.zip") - file(DOWNLOAD ${WIN_FLEX_BISON_URL} ${WIN_FLEX_BISON_FILENAME}) + file(DOWNLOAD ${WIN_FLEX_BISON_URL} ${WIN_FLEX_BISON_FILENAME} INACTIVITY_TIMEOUT 600) set(WIN_FLEX_BISON_INSTALL_DIR "${WINDOWS_EXTERNAL_DIR}/Install/win_flex_bison") file(MAKE_DIRECTORY ${WIN_FLEX_BISON_INSTALL_DIR}) @@ -326,11 +332,14 @@ else() set(LZ4_LIBS ${3RDPARTY_LIBS_DIR}/Source/lz4/lib/liblz4.a) ADD_BY_PRODUCTS_VARIABLE ("LZ4" ${LZ4_LIBS}) externalproject_add(${LZ4_TARGET} - GIT_REPOSITORY https://github.com/lz4/lz4 - GIT_TAG fdf2ef5 # https://github.com/lz4/lz4/releases/tag/v1.9.2 + URL ${WITH_LZ4_URL} + URL_HASH ${WITH_LZ4_URL_HASH} + TIMEOUT 600 + LOG_BUILD TRUE + DOWNLOAD_NO_PROGRESS 1 CONFIGURE_COMMAND "" # no configure BUILD_IN_SOURCE true # lz4 Makefile is designed to run locally - BUILD_COMMAND make CFLAGS="-fPIC" # to allow static linking in shared library + BUILD_COMMAND make CFLAGS=-fPIC # to allow static linking in shared library INSTALL_COMMAND "" # suppress install "${LZ4_BYPRODUCTS}" ) @@ -457,11 +466,14 @@ if(WITH_RE2 STREQUAL "EXTERNAL") set(RE2_LIBS ${3RDPARTY_LIBS_DIR}/Source/re2/obj/libre2.a) ADD_BY_PRODUCTS_VARIABLE ("RE2" ${RE2_LIBS}) externalproject_add(${RE2_TARGET} - GIT_REPOSITORY https://github.com/google/re2 - GIT_TAG 5723bb8 # https://github.com/google/re2/releases/tag/2022-06-01 + URL ${WITH_RE2_URL} + URL_HASH ${WITH_RE2_URL_HASH} + TIMEOUT 600 + LOG_BUILD TRUE + DOWNLOAD_NO_PROGRESS 1 CONFIGURE_COMMAND "" # no configure BUILD_IN_SOURCE true # re2 Makefile is designed to run locally - BUILD_COMMAND make CFLAGS="-fPIC" CXXFLAGS="-fPIC" # to allow static linking in shared library + BUILD_COMMAND make CFLAGS=-fPIC CXXFLAGS=-fPIC # to allow static linking in shared library INSTALL_COMMAND "" "${RE2_BYPRODUCTS}" ) From 3f4b13b45794a0c289967510642fc96a15391aaa Mon Sep 17 00:00:00 2001 From: airnet73 <61675061+airnet73@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:47:56 +0900 Subject: [PATCH 10/20] [CBRD-25737] When unloading serial and trigger as dba user, schema name is missing (#5705) http://jira.cubrid.org/browse/CBRD-25737 In unloaddb, extract serial and trigger by adding schema. --- src/executables/unload_schema.c | 32 ++++++++++++++++-------------- src/object/trigger_description.cpp | 31 +++++++++++++++++++---------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/executables/unload_schema.c b/src/executables/unload_schema.c index ed22451a2d8..9731814afeb 100644 --- a/src/executables/unload_schema.c +++ b/src/executables/unload_schema.c @@ -692,6 +692,9 @@ export_serial (extract_context & ctxt, print_output & output_ctx) size_t uppercase_user_size = 0; size_t query_size = 0; char *query = NULL; + char owner_name[DB_MAX_IDENTIFIER_LENGTH] = { '\0' }; + char *serial_name = NULL; + char output_owner[DB_MAX_USER_LENGTH + 4] = { '\0' }; /* * You must check SERIAL_VALUE_INDEX enum defined on the top of this file @@ -827,23 +830,28 @@ export_serial (extract_context & ctxt, print_output & output_ctx) } } - output_ctx ("\ncreate serial %s%s%s\n", PRINT_IDENTIFIER (db_get_string (&values[SERIAL_NAME]))); - output_ctx ("\t start with %s\n", numeric_db_value_print (&values[SERIAL_CURRENT_VAL], str_buf)); - output_ctx ("\t increment by %s\n", numeric_db_value_print (&values[SERIAL_INCREMENT_VAL], str_buf)); - output_ctx ("\t minvalue %s\n", numeric_db_value_print (&values[SERIAL_MIN_VAL], str_buf)); - output_ctx ("\t maxvalue %s\n", numeric_db_value_print (&values[SERIAL_MAX_VAL], str_buf)); - output_ctx ("\t %scycle\n", (db_get_int (&values[SERIAL_CYCLIC]) == 0 ? "no" : "")); + SPLIT_USER_SPECIFIED_NAME (db_get_string (&values[SERIAL_UNIQUE_NAME]), owner_name, serial_name); + PRINT_OWNER_NAME (owner_name, (ctxt.is_dba_user || ctxt.is_dba_group_member), output_owner, + sizeof (output_owner)); + + output_ctx ("\nCREATE SERIAL %s%s%s%s\n", output_owner, + PRINT_IDENTIFIER (db_get_string (&values[SERIAL_NAME]))); + output_ctx ("\t START WITH %s\n", numeric_db_value_print (&values[SERIAL_CURRENT_VAL], str_buf)); + output_ctx ("\t INCREMENT BY %s\n", numeric_db_value_print (&values[SERIAL_INCREMENT_VAL], str_buf)); + output_ctx ("\t MINVALUE %s\n", numeric_db_value_print (&values[SERIAL_MIN_VAL], str_buf)); + output_ctx ("\t MAXVALUE %s\n", numeric_db_value_print (&values[SERIAL_MAX_VAL], str_buf)); + output_ctx ("\t %sCYCLE\n", (db_get_int (&values[SERIAL_CYCLIC]) == 0 ? "no" : "")); if (db_get_int (&values[SERIAL_CACHED_NUM]) <= 1) { - output_ctx ("\t nocache\n"); + output_ctx ("\t NOCACHE\n"); } else { - output_ctx ("\t cache %d\n", db_get_int (&values[SERIAL_CACHED_NUM])); + output_ctx ("\t CACHE %d\n", db_get_int (&values[SERIAL_CACHED_NUM])); } if (DB_IS_NULL (&values[SERIAL_COMMENT]) == false) { - output_ctx ("\t comment "); + output_ctx ("\t COMMENT "); desc_value_print (output_ctx, &values[SERIAL_COMMENT]); } output_ctx (";\n"); @@ -853,12 +861,6 @@ export_serial (extract_context & ctxt, print_output & output_ctx) output_ctx ("SELECT %s%s%s.NEXT_VALUE;\n", PRINT_IDENTIFIER (db_get_string (&values[SERIAL_NAME]))); } - if (ctxt.is_dba_user || ctxt.is_dba_group_member) - { - output_ctx ("call [change_serial_owner] ('%s', '%s') on class [db_serial];\n", - db_get_string (&values[SERIAL_NAME]), db_get_string (&values[SERIAL_OWNER_NAME])); - } - db_value_clear (&diff_value); db_value_clear (&answer_value); for (i = 0; i < SERIAL_VALUE_INDEX_MAX; i++) diff --git a/src/object/trigger_description.cpp b/src/object/trigger_description.cpp index b651181597d..86930e73606 100644 --- a/src/object/trigger_description.cpp +++ b/src/object/trigger_description.cpp @@ -256,9 +256,27 @@ tr_dump_trigger (extract_context &ctxt, print_output &output_ctx, DB_OBJECT *tri } else if (trigger->status != TR_STATUS_INVALID) { + if (trigger->class_mop != NULL) + { + name = db_get_class_name (trigger->class_mop); + if (sm_qualifier_name (name, owner_name, DB_MAX_USER_LENGTH) == NULL) + { + ASSERT_ERROR_AND_SET (error); + return error; + } + class_name = sm_remove_qualifier_name (name); + } + /* automatically filter out invalid triggers */ output_ctx ("CREATE TRIGGER "); - output_ctx ("[%s]\n", sm_remove_qualifier_name (trigger->name)); + if (ctxt.is_dba_user || ctxt.is_dba_group_member) + { + output_ctx ("[%s].[%s]\n", owner_name, sm_remove_qualifier_name (trigger->name)); + } + else + { + output_ctx ("[%s]\n", sm_remove_qualifier_name (trigger->name)); + } output_ctx (" STATUS %s\n", tr_status_as_string (trigger->status)); output_ctx (" PRIORITY %f\n", trigger->priority); @@ -277,13 +295,6 @@ tr_dump_trigger (extract_context &ctxt, print_output &output_ctx, DB_OBJECT *tri if (trigger->class_mop != NULL) { - name = db_get_class_name (trigger->class_mop); - if (sm_qualifier_name (name, owner_name, DB_MAX_USER_LENGTH) == NULL) - { - ASSERT_ERROR_AND_SET (error); - return error; - } - class_name = sm_remove_qualifier_name (name); output_ctx (" ON "); if (ctxt.is_dba_user || ctxt.is_dba_group_member) { @@ -339,7 +350,7 @@ tr_dump_trigger (extract_context &ctxt, print_output &output_ctx, DB_OBJECT *tri help_print_describe_comment (output_ctx, trigger->comment); } - output_ctx (";\n"); + output_ctx (";\n\n"); } AU_ENABLE (save); @@ -423,8 +434,6 @@ tr_dump_selective_triggers (extract_context &ctxt, print_output &output_ctx, DB_ if (trigger->status != TR_STATUS_INVALID) { tr_dump_trigger (ctxt, output_ctx, trigger_object); - output_ctx ("call [change_trigger_owner]('%s'," " '%s') on class [db_root];\n\n", - sm_remove_qualifier_name (trigger->name), get_user_name (trigger->owner)); } } else if (is_system_class < 0) From fd79f93cdd60b0781431a47e7c1ecba0e8991772 Mon Sep 17 00:00:00 2001 From: airnet73 <61675061+airnet73@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:14:39 +0900 Subject: [PATCH 11/20] [APIS-1010] Update JDBC version to 11.3.0 (#5715) http://jira.cubrid.org/browse/APIS-1010 Update JDBC version to 11.3.0 --- cubrid-jdbc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cubrid-jdbc b/cubrid-jdbc index 198918ce4c1..be76d9bb893 160000 --- a/cubrid-jdbc +++ b/cubrid-jdbc @@ -1 +1 @@ -Subproject commit 198918ce4c11c1f2a821c9e019d83c97c633aa4b +Subproject commit be76d9bb893475986f632b89a885f15ea3480eca From ebd4154e58bb5feb4f15cb705fb31457cbd242a0 Mon Sep 17 00:00:00 2001 From: Yeunjun Lee Date: Mon, 16 Dec 2024 19:22:38 +0900 Subject: [PATCH 12/20] [CBRD-25651] Improve Error Message Logging for HA Failover / Failback (#5660) http://jira.cubrid.org/browse/CBRD-25651 --- src/connection/server_support.c | 11 +++ src/executables/master_heartbeat.c | 108 +++++++++++++++++++++++++---- 2 files changed, 106 insertions(+), 13 deletions(-) diff --git a/src/connection/server_support.c b/src/connection/server_support.c index 3255f503f33..33808518cf7 100644 --- a/src/connection/server_support.c +++ b/src/connection/server_support.c @@ -776,6 +776,7 @@ css_process_get_eof_request (SOCKET master_fd) { #if !defined(WINDOWS) LOG_LSA *eof_lsa; + static LOG_LSA prev_eof_lsa = LSA_INITIALIZER; OR_ALIGNED_BUF (OR_LOG_LSA_ALIGNED_SIZE) a_reply; char *reply; THREAD_ENTRY *thread_p; @@ -792,6 +793,16 @@ css_process_get_eof_request (SOCKET master_fd) LOG_CS_EXIT (thread_p); + if (LSA_EQ (&prev_eof_lsa, eof_lsa)) + { + er_log_debug (ARG_FILE_LINE, "Disk failure has been occurred: prev_eof_lsa(%lld, %d), eof_lsa(%lld, %d)\n", + LSA_AS_ARGS (&prev_eof_lsa), LSA_AS_ARGS (eof_lsa)); + } + else + { + LSA_COPY (&prev_eof_lsa, eof_lsa); + } + css_send_heartbeat_request (css_Master_conn, SERVER_GET_EOF); css_send_heartbeat_data (css_Master_conn, reply, OR_ALIGNED_BUF_SIZE (a_reply)); #endif diff --git a/src/executables/master_heartbeat.c b/src/executables/master_heartbeat.c index f45f6b75493..5a137fbdf99 100644 --- a/src/executables/master_heartbeat.c +++ b/src/executables/master_heartbeat.c @@ -252,6 +252,8 @@ static char hb_Nolog_event_msg[LINE_MAX] = ""; static HB_DEACTIVATE_INFO hb_Deactivate_info = { NULL, 0, false }; static bool hb_Is_activated = true; +static bool hb_Is_master_node_isolated = false; +static char hb_Master_host_name[CUB_MAXHOSTNAMELEN]; /* cluster jobs */ static HB_JOB_FUNC hb_cluster_jobs[] = { @@ -328,6 +330,13 @@ static HB_JOB_FUNC hb_resource_jobs[] = { " Error Logging: disabled\n" #define HA_ADMIN_INFO_NOLOG_EVENT_FORMAT_STRING \ " %s\n" + +#define HA_FAILBACK_DIAG_STRING "[Failback] [Diagnosis]" +#define HA_FAILBACK_SUCCESS_STRING "[Failback] [Success]" +#define HA_FAILBACK_CANCEL_STRING "[Failback] [Cancelled]" +#define HA_FAILOVER_DIAG_STRING "[Failover] [Diagnosis]" +#define HA_FAILOVER_SUCCESS_STRING "[Failover] [Success]" +#define HA_FAILOVER_CANCEL_STRING "[Failover] [Cancelled]" /* * linked list */ @@ -836,6 +845,11 @@ hb_cluster_job_calc_score (HB_JOB_ARG * arg) clst_arg->ping_check_count = 0; clst_arg->retries = 0; + snprintf (hb_info_str, HB_INFO_STR_MAX, + "%s The master node has failed to receive heartbeat messages from all other slave nodes, resulting in a network partition", + HA_FAILBACK_DIAG_STRING); + MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); + error = hb_cluster_job_queue (HB_CJOB_CHECK_PING, job_arg, HB_JOB_TIMER_IMMEDIATELY); assert (error == NO_ERROR); } @@ -854,8 +868,9 @@ hb_cluster_job_calc_score (HB_JOB_ARG * arg) && (hb_Cluster->master && hb_Cluster->myself && hb_Cluster->myself->state == HB_NSTATE_MASTER && hb_Cluster->master->priority != hb_Cluster->myself->priority)) { - MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, - "More than one master detected and failback will be initiated"); + snprintf (hb_info_str, HB_INFO_STR_MAX, "%s Multiple master nodes (%s, %s) are detected", HA_FAILBACK_DIAG_STRING, + hb_Cluster->myself->host_name, hb_Cluster->master->host_name); + MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); hb_help_sprint_nodes_info (hb_info_str, HB_INFO_STR_MAX); MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); @@ -894,6 +909,21 @@ hb_cluster_job_calc_score (HB_JOB_ARG * arg) hb_Cluster->state = HB_NSTATE_TO_BE_MASTER; hb_cluster_request_heartbeat_to_all (); + if (hb_Is_master_node_isolated) + { + snprintf (hb_info_str, HB_INFO_STR_MAX, + "%s The current node has failed to receive heartbeat messages from the master node (%s)", + HA_FAILOVER_DIAG_STRING, hb_Master_host_name); + MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); + } + else if (hb_Master_host_name[0] != '\0') + { + snprintf (hb_info_str, HB_INFO_STR_MAX, + "%s The master node (%s) has lost its role due to server process problem, such as disk failure", + HA_FAILOVER_DIAG_STRING, hb_Master_host_name); + MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); + } + pthread_mutex_unlock (&hb_Cluster->lock); job_arg = (HB_JOB_ARG *) malloc (sizeof (HB_JOB_ARG)); @@ -968,6 +998,7 @@ hb_cluster_job_check_ping (HB_JOB_ARG * arg) unsigned int failover_wait_time; HB_CLUSTER_JOB_ARG *clst_arg = (arg) ? &(arg->cluster_job_arg) : NULL; HB_PING_HOST_ENTRY *ping_host; + char hb_info_str[HB_INFO_STR_MAX]; ENTER_FUNC (); @@ -1076,9 +1107,30 @@ hb_cluster_job_check_ping (HB_JOB_ARG * arg) ping_check_cancel: /* if this node is a master, then failback is cancelled */ - if (hb_Cluster->state != HB_NSTATE_MASTER) + if (hb_Cluster->state == HB_NSTATE_MASTER) + { + if (ping_try_count == 0) + { + snprintf (hb_info_str, HB_INFO_STR_MAX, + "%s No hosts are registered in ha_ping_hosts, or all registered hosts are invalid, making it impossible to determine the network partition", + HA_FAILBACK_CANCEL_STRING); + MASTER_ER_SET (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); + } + else + { + assert (ping_success); + snprintf (hb_info_str, HB_INFO_STR_MAX, + "%s Ping check succeeded for the hosts registered in ha_ping_hosts, determining that it is not a network partition", + HA_FAILBACK_CANCEL_STRING); + MASTER_ER_SET (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); + } + } + else { - MASTER_ER_SET (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, "Failover cancelled by ping check"); + snprintf (hb_info_str, HB_INFO_STR_MAX, + "%s Ping check has been failed to all hosts registered in ha_ping_hosts, indicating a network partition", + HA_FAILOVER_CANCEL_STRING); + MASTER_ER_SET (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); hb_Cluster->state = HB_NSTATE_SLAVE; } hb_cluster_request_heartbeat_to_all (); @@ -1122,7 +1174,9 @@ hb_cluster_job_failover (HB_JOB_ARG * arg) if (hb_Cluster->master && hb_Cluster->myself && hb_Cluster->master->priority == hb_Cluster->myself->priority) { - MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, "Failover completed"); + snprintf (hb_info_str, HB_INFO_STR_MAX, "%s Current node has been successfully promoted to master", + HA_FAILOVER_SUCCESS_STRING); + MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); hb_Cluster->state = HB_NSTATE_MASTER; hb_Resource->state = HB_NSTATE_MASTER; @@ -1131,7 +1185,10 @@ hb_cluster_job_failover (HB_JOB_ARG * arg) } else { - MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, "Failover cancelled"); + snprintf (hb_info_str, HB_INFO_STR_MAX, + "%s New master has been found. Failover for current node has been cancelled", + HA_FAILOVER_CANCEL_STRING); + MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); hb_Cluster->state = HB_NSTATE_SLAVE; } @@ -1252,6 +1309,10 @@ hb_cluster_job_demote (HB_JOB_ARG * arg) hb_Cluster->hide_to_demote = false; + snprintf (hb_info_str, HB_INFO_STR_MAX, "%s Current node has been successfully demoted to slave", + HA_FAILBACK_SUCCESS_STRING); + MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); + pthread_mutex_unlock (&hb_Cluster->lock); if (arg) @@ -1305,8 +1366,9 @@ hb_cluster_job_failback (HB_JOB_ARG * arg) hb_cluster_request_heartbeat_to_all (); - MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, - "This master will become a slave and cub_server will be restarted"); + snprintf (hb_info_str, HB_INFO_STR_MAX, "%s Current node has been successfully demoted to slave", + HA_FAILBACK_SUCCESS_STRING); + MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); hb_help_sprint_nodes_info (hb_info_str, HB_INFO_STR_MAX); MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_NODE_EVENT, 1, hb_info_str); @@ -1498,6 +1560,8 @@ hb_cluster_calc_score (void) HB_NODE_ENTRY *node; struct timeval now; + hb_Is_master_node_isolated = false; + if (hb_Cluster == NULL) { MASTER_ER_LOG_DEBUG (ARG_FILE_LINE, "hb_Cluster is null. \n"); @@ -1518,6 +1582,13 @@ hb_cluster_calc_score (void) node->last_recv_hbtime) > prm_get_integer_value (PRM_ID_HA_CALC_SCORE_INTERVAL_IN_MSECS))) { + if (hb_Cluster->myself != node && node->state == HB_NSTATE_MASTER) + { + // Current master node is isolated. Save master node's host name to hb_Master_host_name. It is used for error message at failover event. + hb_Is_master_node_isolated = true; + snprintf (hb_Master_host_name, strlen (node->host_name), node->host_name); + } + node->heartbeat_gap = 0; node->last_recv_hbtime.tv_sec = 0; node->last_recv_hbtime.tv_usec = 0; @@ -1793,7 +1864,9 @@ hb_cluster_receive_heartbeat (char *buffer, int len, struct sockaddr_in *from, s { if (node->state == HB_NSTATE_MASTER && node->state != hb_state) { + // Current master node has been demoted. Save master node's host name to hb_Master_host_name. It is used for error message at failover event. is_state_changed = true; + snprintf (hb_Master_host_name, strlen (node->host_name), node->host_name); } node->state = hb_state; @@ -3524,6 +3597,9 @@ hb_resource_job_confirm_start (HB_JOB_ARG * arg) } /* shutdown working server processes to change its role to slave */ + snprintf (hb_info_str, HB_INFO_STR_MAX, "%s The master node failed to restart the server process", + HA_FAILBACK_DIAG_STRING); + MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_PROCESS_EVENT, 1, hb_info_str); error = hb_resource_job_queue (HB_RJOB_DEMOTE_START_SHUTDOWN, NULL, HB_JOB_TIMER_IMMEDIATELY); assert (error == NO_ERROR); @@ -4017,6 +4093,7 @@ hb_cleanup_conn_and_start_process (CSS_CONN_ENTRY * conn, SOCKET sfd) HB_PROC_ENTRY *proc; HB_JOB_ARG *job_arg; HB_RESOURCE_JOB_ARG *proc_arg; + char hb_info_str[HB_INFO_STR_MAX]; css_remove_entry_by_conn (conn, &css_Master_socket_anchor); @@ -4078,11 +4155,11 @@ hb_cleanup_conn_and_start_process (CSS_CONN_ENTRY * conn, SOCKET sfd) hb_Resource->state = HB_NSTATE_SLAVE; snprintf (error_string, LINE_MAX, "(args:%s)", proc->args); - MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_PROCESS_EVENT, 2, - "Process failure repeated within a short period of time. " "The current node will be demoted", - error_string); + snprintf (hb_info_str, HB_INFO_STR_MAX, + "%s Server process failure repeated within a short period of time. The current node will be demoted", + HA_FAILBACK_DIAG_STRING); + MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_PROCESS_EVENT, 1, hb_info_str); - /* shutdown working server processes to change its role to slave */ error = hb_resource_job_queue (HB_RJOB_DEMOTE_START_SHUTDOWN, NULL, HB_JOB_TIMER_IMMEDIATELY); assert (error == NO_ERROR); } @@ -4741,6 +4818,7 @@ hb_thread_check_disk_failure (void *arg) int rv, error; int interval; INT64 remaining_time_msecs = 0; + char hb_info_str[HB_INFO_STR_MAX]; /* *INDENT-OFF* */ cuberr::context er_context (true); /* *INDENT-ON* */ @@ -4764,6 +4842,11 @@ hb_thread_check_disk_failure (void *arg) { if (hb_resource_check_server_log_grow () == false) { + snprintf (hb_info_str, HB_INFO_STR_MAX, + "%s The master node has lost its role due to server process problem, such as disk failure", + HA_FAILOVER_DIAG_STRING); + MASTER_ER_SET (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_HB_PROCESS_EVENT, 1, hb_info_str); + /* be silent to avoid blocking write operation on disk */ hb_disable_er_log (HB_NOLOG_DEMOTE_ON_DISK_FAIL, NULL); hb_Resource->state = HB_NSTATE_SLAVE; @@ -4775,7 +4858,6 @@ hb_thread_check_disk_failure (void *arg) syslog (LOG_ALERT, "[CUBRID] %s () at %s:%d", __func__, __FILE__, __LINE__); #endif /* !WINDOWS */ - error = hb_resource_job_queue (HB_RJOB_DEMOTE_START_SHUTDOWN, NULL, HB_JOB_TIMER_IMMEDIATELY); assert (error == NO_ERROR); From cd398f709a6190e931276580dae20d7fea463c13 Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Tue, 17 Dec 2024 13:56:22 +0900 Subject: [PATCH 13/20] shouldn't have to alloc attrinfo->values, its allocated in start_scan --- src/query/parallel_heap_scan.cpp | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/query/parallel_heap_scan.cpp b/src/query/parallel_heap_scan.cpp index 9f446b72b37..b89e07cb755 100644 --- a/src/query/parallel_heap_scan.cpp +++ b/src/query/parallel_heap_scan.cpp @@ -1095,16 +1095,6 @@ attr_cache_clone (THREAD_ENTRY *thread_p, heap_cache_attrinfo *src) { heap_cache_attrinfo *dest = (heap_cache_attrinfo *) HP_ALLOC (thread_p, sizeof (heap_cache_attrinfo)); *dest = *src; - if (src->num_values > 0) - { - dest->values = (HEAP_ATTRVALUE *) HP_ALLOC (thread_p, sizeof (HEAP_ATTRVALUE) * src->num_values); - for (int i = 0; i < src->num_values; i++) - { - dest->values[i] = src->values[i]; - } - } - - return dest; } @@ -1115,19 +1105,6 @@ attr_cache_free (THREAD_ENTRY *thread_p, heap_cache_attrinfo *src) { return; } - if (src->num_values > 0) - { - for (int i = 0; i < src->num_values; i++) - { - if (DB_NEED_CLEAR (&src->values[i].dbvalue)) - { - pr_clear_value (&src->values[i].dbvalue); - } - } - - HP_FREE (thread_p, src->values); - } - HP_FREE (thread_p, src); } @@ -1214,8 +1191,6 @@ scan_next_heap_scan_1page_internal (THREAD_ENTRY *thread_p, SCAN_ID *scan_id, VP { COPY_OID (&retry_oid, &hsidp->curr_oid); object_get_status = OBJ_GET_WITHOUT_LOCK; - assert (hsidp->pred_attrs.attr_cache->last_classrepr != NULL); - assert (hsidp->rest_attrs.attr_cache->last_classrepr != NULL); restart_scan_oid: /* get next object */ From da6f8281a8298d4722ed4704101659ef6148658b Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Wed, 18 Dec 2024 13:23:09 +0900 Subject: [PATCH 14/20] add flag for not parallel heap scan --- src/parser/xasl_generation.c | 7 + src/query/parallel_heap_scan.cpp | 712 ++++++++++++++++++++++++++----- src/query/query_executor.c | 2 +- 3 files changed, 622 insertions(+), 99 deletions(-) diff --git a/src/parser/xasl_generation.c b/src/parser/xasl_generation.c index 1b6d8964e43..13fd5620b69 100644 --- a/src/parser/xasl_generation.c +++ b/src/parser/xasl_generation.c @@ -12204,6 +12204,7 @@ pt_to_class_spec_list (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * where_ OUTPTR_LIST *output_val_list = NULL; REGU_VARIABLE_LIST regu_var_list = NULL; DB_VALUE **db_values_array_p = NULL; + bool is_parallel_heap_scan_callable = true; assert (parser != NULL); @@ -12259,10 +12260,12 @@ pt_to_class_spec_list (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * where_ if (PT_IS_VALUE_QUERY (spec)) { scan_type = TARGET_REGUVAL_LIST; + is_parallel_heap_scan_callable = false; } else if (spec->info.spec.meta_class == PT_META_CLASS) { scan_type = TARGET_CLASS_ATTR; + is_parallel_heap_scan_callable = false; } else { @@ -12569,6 +12572,10 @@ pt_to_class_spec_list (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * where_ { access->flags = (ACCESS_SPEC_FLAG) (access->flags | ACCESS_SPEC_FLAG_FOR_UPDATE); } + if(!is_parallel_heap_scan_callable) + { + access->flags = (ACCESS_SPEC_FLAG) (access->flags | ACCESS_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN); + } access->next = access_list; access_list = access; diff --git a/src/query/parallel_heap_scan.cpp b/src/query/parallel_heap_scan.cpp index b89e07cb755..37f98ffbf98 100644 --- a/src/query/parallel_heap_scan.cpp +++ b/src/query/parallel_heap_scan.cpp @@ -68,8 +68,6 @@ enum ph_pred_expr_types }; static int regu_var_list_len (REGU_VARIABLE_LIST list); -static REGU_VARIABLE_LIST regu_var_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST list); -static void regu_var_list_free (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST head); static void * pred_expr_clone (THREAD_ENTRY *thread_p, void *src, void *dest, enum ph_pred_expr_types type, heap_cache_attrinfo *attr_info); @@ -80,6 +78,20 @@ static void link_attr_cache (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST node,hea heap_cache_attrinfo *new_attr_info); static SCAN_CODE scan_next_heap_scan_1page_internal (THREAD_ENTRY *thread_p, SCAN_ID *scan_id, VPID *curr_vpid); +static void arith_list_free (THREAD_ENTRY *thread_p, ARITH_TYPE *src); +static void regu_list_free (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST src); +static void regu_val_list_free (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *src); +static void regu_var_free (THREAD_ENTRY *thread_p, REGU_VARIABLE *src, bool free_self); +static int regu_list_clear (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST list); +static int regu_var_clear (THREAD_ENTRY *thread_p, REGU_VARIABLE *regu_var); +static int pred_clear (THREAD_ENTRY *thread_p, PRED_EXPR *pred); +static int arith_list_clear (THREAD_ENTRY *thread_p, ARITH_TYPE *list); +static void pos_desc_clear (THREAD_ENTRY *thread_p, QFILE_TUPLE_VALUE_POSITION *pos_desc); +static int regu_val_list_clear (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *list); +ARITH_TYPE *arith_list_clone (THREAD_ENTRY *thread_p, ARITH_TYPE *src); +REGU_VARIABLE *regu_var_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE *src); +REGU_VARIABLE_LIST regu_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST src); +REGU_VALUE_LIST *regu_val_list_clone (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *src); /*************************************************************************************************/ /* parallel_heap_scan_result_queue_entry */ @@ -99,11 +111,37 @@ class parallel_heap_scan_result_queue_entry void init (THREAD_ENTRY *thread_p, int n_pred_val, int n_rest_val); void clear (); + ~parallel_heap_scan_result_queue_entry(); + parallel_heap_scan_result_queue_entry(); + private: void capture_regu_var_list (REGU_VARIABLE_LIST list, DB_VALUE_ARRAY *dbvalue_array); void copy_to_regu_var_list (DB_VALUE_ARRAY *dbvalue_array, REGU_VARIABLE_LIST list); }; +parallel_heap_scan_result_queue_entry::parallel_heap_scan_result_queue_entry() +{ + pred_val_array.size = 0; + pred_val_array.vals = NULL; + rest_val_array.size = 0; + rest_val_array.vals = NULL; + valid = false; + scan_code = S_END; + curr_oid = {0,0,0}; +} + +parallel_heap_scan_result_queue_entry::~parallel_heap_scan_result_queue_entry() +{ + if (pred_val_array.size > 0) + { + HP_FREE (NULL, pred_val_array.vals); + } + if (rest_val_array.size > 0) + { + HP_FREE (NULL, rest_val_array.vals); + } +} + void parallel_heap_scan_result_queue_entry::capture_regu_var_list (REGU_VARIABLE_LIST list, DB_VALUE_ARRAY *dbvalue_array) { @@ -126,10 +164,7 @@ void parallel_heap_scan_result_queue_entry::copy_to_regu_var_list (DB_VALUE_ARRA assert (iter); if (!DB_IS_NULL (iter->value.vfetch_to)) { - if (DB_NEED_CLEAR (iter->value.vfetch_to)) - { - pr_clear_value (iter->value.vfetch_to); - } + pr_clear_value (iter->value.vfetch_to); } db_value_clone (&dbvalue_array->vals[i], iter->value.vfetch_to); iter = iter->next; @@ -186,17 +221,11 @@ void parallel_heap_scan_result_queue_entry::clear () int i; for (i = 0; i < pred_val_array.size; i++) { - if (DB_NEED_CLEAR (&pred_val_array.vals[i])) - { - pr_clear_value (&pred_val_array.vals[i]); - } + pr_clear_value (&pred_val_array.vals[i]); } for (i = 0; i < rest_val_array.size; i++) { - if (DB_NEED_CLEAR (&rest_val_array.vals[i])) - { - pr_clear_value (&rest_val_array.vals[i]); - } + pr_clear_value (&rest_val_array.vals[i]); } scan_code = S_END; valid = false; @@ -204,7 +233,6 @@ void parallel_heap_scan_result_queue_entry::clear () } /*************************************************************************************************/ - /* parallel_heap_scan_result_queue */ class parallel_heap_scan_result_queue { @@ -529,8 +557,8 @@ void parallel_heap_scan_task::execute (cubthread::entry &thread_ref) phsidp->rest_attrs.num_attrs, phsidp->rest_attrs.attr_ids, phsidp->rest_attrs.attr_cache, S_HEAP_SCAN, phsidp->cache_recordinfo, phsidp->recordinfo_regu_list, false); - hsidp->scan_pred.regu_list = regu_var_list_clone (thread_p, m_context->orig_pred_list); - hsidp->rest_regu_list = regu_var_list_clone (thread_p, m_context->orig_rest_list); + hsidp->scan_pred.regu_list = regu_list_clone (thread_p, m_context->orig_pred_list); + hsidp->rest_regu_list = regu_list_clone (thread_p, m_context->orig_rest_list); hsidp->pred_attrs.attr_cache = attr_cache_clone (thread_p, phsidp->pred_attrs.attr_cache); hsidp->rest_attrs.attr_cache = attr_cache_clone (thread_p, phsidp->rest_attrs.attr_cache); hsidp->scan_pred.pred_expr = (PRED_EXPR *)pred_expr_clone (thread_p, (void *)phsidp->scan_pred.pred_expr, NULL, @@ -581,9 +609,12 @@ void parallel_heap_scan_task::execute (cubthread::entry &thread_ref) heap_attrinfo_end (thread_p, hsidp->rest_attrs.attr_cache); hsidp->caches_inited = false; } + pred_clear (thread_p, hsidp->scan_pred.pred_expr); + regu_list_clear (thread_p, hsidp->scan_pred.regu_list); + regu_list_clear (thread_p, hsidp->rest_regu_list); - regu_var_list_free (thread_p, hsidp->scan_pred.regu_list); - regu_var_list_free (thread_p, hsidp->rest_regu_list); + regu_list_free (thread_p, hsidp->scan_pred.regu_list); + regu_list_free (thread_p, hsidp->rest_regu_list); pred_expr_free (thread_p, hsidp->scan_pred.pred_expr); attr_cache_free (thread_p, hsidp->pred_attrs.attr_cache); attr_cache_free (thread_p, hsidp->rest_attrs.attr_cache); @@ -610,6 +641,7 @@ parallel_heap_scan_master::~parallel_heap_scan_master() { thread_get_manager()->destroy_worker_pool (m_workpool); } + delete m_context; } SCAN_CODE parallel_heap_scan_master::get_result (THREAD_ENTRY *thread_p, SCAN_ID *scan_id) @@ -795,89 +827,402 @@ static int regu_var_list_len (REGU_VARIABLE_LIST list) return len; } -static REGU_VARIABLE_LIST regu_var_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST src) +int pred_clear (THREAD_ENTRY *thread_p, PRED_EXPR *pr) { - REGU_VARIABLE_LIST dest_head = NULL; - REGU_VARIABLE_LIST dest_tail = NULL; + int pg_cnt; + PRED_EXPR *expr; - REGU_VARIABLE_LIST current = src; - if (!src) + pg_cnt = 0; + + if (pr == NULL) { - return NULL; + return pg_cnt; } - while (current) + switch (pr->type) { - REGU_VARIABLE_LIST new_node = - (REGU_VARIABLE_LIST) HP_ALLOC (thread_p, sizeof (struct regu_variable_list_node)); - if (!new_node) + case T_PRED: + pg_cnt += pred_clear (thread_p, pr->pe.m_pred.lhs); + for (expr = pr->pe.m_pred.rhs; expr && expr->type == T_PRED; expr = expr->pe.m_pred.rhs) + { + pg_cnt += pred_clear (thread_p, expr->pe.m_pred.lhs); + } + pg_cnt += pred_clear (thread_p, expr); + break; + case T_EVAL_TERM: + switch (pr->pe.m_eval_term.et_type) + { + case T_COMP_EVAL_TERM: + { + COMP_EVAL_TERM *et_comp = &pr->pe.m_eval_term.et.et_comp; + + pg_cnt += regu_var_clear (thread_p, et_comp->lhs); + pg_cnt += regu_var_clear (thread_p, et_comp->rhs); + } + break; + case T_ALSM_EVAL_TERM: + { + ALSM_EVAL_TERM *et_alsm = &pr->pe.m_eval_term.et.et_alsm; + + pg_cnt += regu_var_clear (thread_p, et_alsm->elem); + pg_cnt += regu_var_clear (thread_p, et_alsm->elemset); + } + break; + case T_LIKE_EVAL_TERM: + { + LIKE_EVAL_TERM *et_like = &pr->pe.m_eval_term.et.et_like; + + pg_cnt += regu_var_clear (thread_p, et_like->src); + pg_cnt += regu_var_clear (thread_p, et_like->pattern); + pg_cnt += regu_var_clear (thread_p, et_like->esc_char); + } + break; + case T_RLIKE_EVAL_TERM: { - REGU_VARIABLE_LIST temp = dest_head; - while (temp) + RLIKE_EVAL_TERM *et_rlike = &pr->pe.m_eval_term.et.et_rlike; + + pg_cnt += regu_var_clear (thread_p, et_rlike->src); + pg_cnt += regu_var_clear (thread_p, et_rlike->pattern); + pg_cnt += regu_var_clear (thread_p, et_rlike->case_sensitive); + + /* free memory of compiled regex */ + if (et_rlike->compiled_regex) { - REGU_VARIABLE_LIST next = temp->next; - if (temp->value.vfetch_to) + delete et_rlike->compiled_regex; + et_rlike->compiled_regex = NULL; + } + } + break; + } + break; + case T_NOT_TERM: + pg_cnt += pred_clear (thread_p, pr->pe.m_not_term); + break; + } + + return pg_cnt; +} + +int arith_list_clear (THREAD_ENTRY *thread_p, ARITH_TYPE *list) +{ + int pg_cnt = 0; + + if (list == NULL) + { + return NO_ERROR; + } + + /* restore the original domain, in order to avoid coerce when the XASL clones will be used again */ + list->domain = list->original_domain; + pr_clear_value (list->value); + pg_cnt += regu_var_clear (thread_p, list->leftptr); + pg_cnt += regu_var_clear (thread_p, list->rightptr); + pg_cnt += regu_var_clear (thread_p, list->thirdptr); + pg_cnt += pred_clear (thread_p, list->pred); + + if (list->rand_seed != NULL) + { + free_and_init (list->rand_seed); + } + + return pg_cnt; +} + +void pos_desc_clear (THREAD_ENTRY *thread_p, QFILE_TUPLE_VALUE_POSITION *pos_desc) +{ + pos_desc->dom = pos_desc->original_domain; +} + +int regu_list_clear (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST list) +{ + REGU_VARIABLE_LIST p; + int pg_cnt; + + pg_cnt = 0; + for (p = list; p; p = p->next) + { + pg_cnt += regu_var_clear (thread_p, &p->value); + } + + return pg_cnt; +} + +int regu_val_list_clear (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *list) +{ + REGU_VALUE_ITEM *list_node; + int pg_cnt = 0; + for (list_node = list->regu_list; list_node; list_node = list_node->next) + { + pg_cnt += regu_var_clear (thread_p, list_node->value); + } + return pg_cnt; +} + +int regu_var_clear (THREAD_ENTRY *thread_p, REGU_VARIABLE *regu_var) +{ + int pg_cnt; + + pg_cnt = 0; + if (!regu_var) + { + return pg_cnt; + } + + /* restore the original domain, in order to avoid coerce when the XASL clones will be used again */ + regu_var->domain = regu_var->original_domain; + + switch (regu_var->type) + { + case TYPE_ATTR_ID: /* fetch object attribute value */ + case TYPE_SHARED_ATTR_ID: + case TYPE_CLASS_ATTR_ID: + regu_var->value.attr_descr.cache_dbvalp = NULL; + break; + case TYPE_CONSTANT: + //(void) pr_clear_value (regu_var->value.dbvalptr); + break; + case TYPE_INARITH: + case TYPE_OUTARITH: + pg_cnt += arith_list_clear (thread_p, regu_var->value.arithptr); + break; + case TYPE_SP: + pr_clear_value (regu_var->value.sp_ptr->value); + pg_cnt += regu_list_clear (thread_p, regu_var->value.sp_ptr->args); + + delete regu_var->value.sp_ptr->sig; + regu_var->value.sp_ptr->sig = nullptr; + + break; + case TYPE_FUNC: + pr_clear_value (regu_var->value.funcp->value); + pg_cnt += regu_list_clear (thread_p, regu_var->value.funcp->operand); + if (regu_var->value.funcp->tmp_obj != NULL) + { + switch (regu_var->value.funcp->ftype) + { + case F_REGEXP_COUNT: + case F_REGEXP_INSTR: + case F_REGEXP_LIKE: + case F_REGEXP_REPLACE: + case F_REGEXP_SUBSTR: + { + if (regu_var->value.funcp->tmp_obj->compiled_regex) { - if (DB_NEED_CLEAR (temp->value.vfetch_to)) - { - pr_clear_value (temp->value.vfetch_to); - } - HP_FREE (thread_p, temp->value.vfetch_to); + delete regu_var->value.funcp->tmp_obj->compiled_regex; + regu_var->value.funcp->tmp_obj->compiled_regex = NULL; } - HP_FREE (thread_p, temp); - temp = next; } - return NULL; + break; + default: + // any member of union func_tmp_obj may have been erased + assert (false); + break; + } + + delete regu_var->value.funcp->tmp_obj; + regu_var->value.funcp->tmp_obj = NULL; } - new_node->value = current->value; - new_node->value.vfetch_to = (DB_VALUE *) HP_ALLOC (thread_p, sizeof (DB_VALUE)); + break; + case TYPE_REGUVAL_LIST: + pg_cnt += regu_val_list_clear (thread_p, regu_var->value.reguval_list); + break; + case TYPE_DBVAL: + (void) pr_clear_value (®u_var->value.dbval); + break; + case TYPE_REGU_VAR_LIST: + pg_cnt += regu_list_clear (thread_p, regu_var->value.regu_var_list); + break; + case TYPE_POSITION: + pos_desc_clear (thread_p, ®u_var->value.pos_descr); + break; + default: + break; + } - /* should we clone value? */ - pr_clone_value (current->value.vfetch_to, new_node->value.vfetch_to); - if (current->value.type == TYPE_ATTR_ID || current->value.type == TYPE_CLASS_ATTR_ID - || current->value.type == TYPE_SHARED_ATTR_ID) + if (regu_var->vfetch_to != NULL) + { + pr_clear_value (regu_var->vfetch_to); + } + + return pg_cnt; +} + +ARITH_TYPE *arith_list_clone (THREAD_ENTRY *thread_p, ARITH_TYPE *src) +{ + if (!src) + { + return NULL; + } + + ARITH_TYPE *dest = (ARITH_TYPE *) HP_ALLOC (thread_p, sizeof (ARITH_TYPE)); + if (dest == NULL) + { + return NULL; + } + + *dest = *src; + + dest->value = (DB_VALUE *) HP_ALLOC (thread_p, sizeof (DB_VALUE)); + if (dest->value == NULL) + { + HP_FREE (thread_p, dest); + return NULL; + } + pr_clone_value (src->value, dest->value); + + dest->leftptr = regu_var_clone (thread_p, src->leftptr); + dest->rightptr = regu_var_clone (thread_p, src->rightptr); + dest->thirdptr = regu_var_clone (thread_p, src->thirdptr); + + if (src->rand_seed) + { + dest->rand_seed = (struct drand48_data *) HP_ALLOC (thread_p, sizeof (struct drand48_data)); + if (dest->rand_seed) { - new_node->value.value.attr_descr.cache_dbvalp = nullptr; + *dest->rand_seed = *src->rand_seed; } - new_node->next = NULL; + } + + return dest; - if (dest_tail) +} + +REGU_VARIABLE_LIST regu_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST src) +{ + if (!src) + { + return NULL; + } + + REGU_VARIABLE_LIST head = NULL; + REGU_VARIABLE_LIST tail = NULL; + REGU_VARIABLE_LIST curr_src = src; + + while (curr_src) + { + REGU_VARIABLE_LIST curr_dest = (REGU_VARIABLE_LIST) HP_ALLOC (thread_p, sizeof (regu_variable_list_node)); + curr_dest->next = NULL; + REGU_VARIABLE *cloned = regu_var_clone (thread_p, &curr_src->value); + if (cloned != NULL) { - dest_tail->next = new_node; + curr_dest->value = *cloned; + HP_FREE (thread_p, cloned); + } + + if (!head) + { + head = curr_dest; + tail = curr_dest; } else { - dest_head = new_node; + tail->next = curr_dest; + tail = curr_dest; } - dest_tail = new_node; - current = current->next; + curr_src = curr_src->next; } - return dest_head; + return head; } -void -regu_var_list_free (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST head) +REGU_VALUE_LIST *regu_val_list_clone (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *src) { - REGU_VARIABLE_LIST current = head; - while (current) + if (!src) + { + return NULL; + } + + REGU_VALUE_LIST *dest = (REGU_VALUE_LIST *) HP_ALLOC (thread_p, sizeof (REGU_VALUE_LIST)); + *dest = *src; + dest->regu_list = NULL; + dest->current_value = NULL; + + if (src->count > 0) { - REGU_VARIABLE_LIST next = current->next; + REGU_VALUE_ITEM *curr_src = src->regu_list; + REGU_VALUE_ITEM *curr_dest = NULL; + REGU_VALUE_ITEM *prev_dest = NULL; - if (current->value.vfetch_to) + for (int i = 0; i < src->count; i++) { - if (DB_NEED_CLEAR (current->value.vfetch_to)) + curr_dest = (REGU_VALUE_ITEM *) HP_ALLOC (thread_p, sizeof (REGU_VALUE_ITEM)); + curr_dest->value = regu_var_clone (thread_p, curr_src->value); + curr_dest->next = NULL; + + if (prev_dest == NULL) + { + dest->regu_list = curr_dest; + } + else { - pr_clear_value (current->value.vfetch_to); + prev_dest->next = curr_dest; } - HP_FREE (thread_p, current->value.vfetch_to); + prev_dest = curr_dest; + curr_src = curr_src->next; } - HP_FREE (thread_p, current); + } + + return dest; +} - current = next; +REGU_VARIABLE *regu_var_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE *src) +{ + REGU_VARIABLE *dest; + if (!src) + { + return NULL; + } + dest = (REGU_VARIABLE *) HP_ALLOC (thread_p, sizeof (REGU_VARIABLE)); + + + *dest = *src; + + switch (src->type) + { + case TYPE_ATTR_ID: /* fetch object attribute value */ + case TYPE_SHARED_ATTR_ID: + case TYPE_CLASS_ATTR_ID: + dest->value.attr_descr.cache_dbvalp = NULL; + break; + case TYPE_CONSTANT: + dest->value.dbvalptr = src->value.dbvalptr; + break; + case TYPE_INARITH: + case TYPE_OUTARITH: + dest->value.arithptr = arith_list_clone (thread_p, src->value.arithptr); + break; + case TYPE_SP: + dest->value.sp_ptr->value = (DB_VALUE *) HP_ALLOC (thread_p, sizeof (DB_VALUE)); + pr_clone_value (src->value.sp_ptr->value, dest->value.sp_ptr->value); + dest->value.sp_ptr->args = regu_list_clone (thread_p, src->value.sp_ptr->args); + break; + case TYPE_FUNC: + dest->value.funcp->value = (DB_VALUE *) HP_ALLOC (thread_p, sizeof (DB_VALUE)); + pr_clone_value (src->value.funcp->value, dest->value.funcp->value); + dest->value.funcp->operand = regu_list_clone (thread_p, src->value.funcp->operand); + break; + case TYPE_DBVAL: + pr_clone_value (&src->value.dbval, &dest->value.dbval); + break; + case TYPE_REGUVAL_LIST: + dest->value.reguval_list = regu_val_list_clone (thread_p, src->value.reguval_list); + break; + case TYPE_REGU_VAR_LIST: + dest->value.regu_var_list = regu_list_clone (thread_p, src->value.regu_var_list); + break; + default: + break; + } + + if (src->vfetch_to != NULL) + { + dest->vfetch_to = (DB_VALUE *) HP_ALLOC (thread_p, sizeof (DB_VALUE)); + pr_clone_value (src->vfetch_to, dest->vfetch_to); } + + return dest; } static void * @@ -1000,18 +1345,9 @@ pred_expr_clone (THREAD_ENTRY *thread_p, void *src, void *dest, enum ph_pred_exp break; case PH_REGU_VAR: src_regu_var = (regu_variable_node *) src; - dest_regu_var = (regu_variable_node *) HP_ALLOC (thread_p, sizeof (regu_variable_node)); - *dest_regu_var = *src_regu_var; - if (src_regu_var->vfetch_to) - { - dest_regu_var->vfetch_to = (DB_VALUE *) HP_ALLOC (thread_p, sizeof (DB_VALUE)); - /* should we clone value? */ - pr_clone_value (src_regu_var->vfetch_to, dest_regu_var->vfetch_to); - } - - - if (src_regu_var->type == TYPE_ATTR_ID || src_regu_var->type == TYPE_CLASS_ATTR_ID - || src_regu_var->type == TYPE_SHARED_ATTR_ID) + dest_regu_var = regu_var_clone (thread_p, src_regu_var); + if (dest_regu_var->type == TYPE_ATTR_ID || dest_regu_var->type == TYPE_SHARED_ATTR_ID + || dest_regu_var->type == TYPE_CLASS_ATTR_ID) { dest_regu_var->value.attr_descr.cache_dbvalp = NULL; dest_regu_var->value.attr_descr.cache_attrinfo = attr_info; @@ -1025,6 +1361,113 @@ pred_expr_clone (THREAD_ENTRY *thread_p, void *src, void *dest, enum ph_pred_exp return ret; } +static void +arith_list_free (THREAD_ENTRY *thread_p, ARITH_TYPE *src) +{ + if (!src) + { + return; + } + + if (src->value) + { + pr_clear_value (src->value); + HP_FREE (thread_p, src->value); + } + + regu_var_free (thread_p, src->leftptr, true); + regu_var_free (thread_p, src->rightptr, true); + regu_var_free (thread_p, src->thirdptr, true); + + if (src->rand_seed) + { + HP_FREE (thread_p, src->rand_seed); + } + + HP_FREE (thread_p, src); +} + +static void +regu_list_free (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST src) +{ + if (!src) + { + return; + } + + REGU_VARIABLE_LIST curr = src; + REGU_VARIABLE_LIST next; + + while (curr) + { + next = curr->next; + regu_var_free (thread_p, &curr->value, false); + HP_FREE (thread_p, curr); + curr = next; + } +} + +static void +regu_val_list_free (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *src) +{ + if (!src) + { + return; + } + + REGU_VALUE_ITEM *curr = src->regu_list; + REGU_VALUE_ITEM *next; + + while (curr) + { + next = curr->next; + regu_var_free (thread_p, curr->value, true); + HP_FREE (thread_p, curr); + curr = next; + } + + HP_FREE (thread_p, src); +} + +static void +regu_var_free (THREAD_ENTRY *thread_p, REGU_VARIABLE *src, bool free_self) +{ + if (!src) + { + return; + } + + switch (src->type) + { + case TYPE_CONSTANT: + pr_clear_value (src->value.dbvalptr); + break; + case TYPE_INARITH: + case TYPE_OUTARITH: + arith_list_free (thread_p, src->value.arithptr); + break; + case TYPE_REGUVAL_LIST: + regu_val_list_free (thread_p, src->value.reguval_list); + break; + case TYPE_REGU_VAR_LIST: + regu_list_free (thread_p, src->value.regu_var_list); + break; + default: + break; + } + + if (src->vfetch_to) + { + pr_clear_value (src->vfetch_to); + HP_FREE (thread_p, src->vfetch_to); + } + if (free_self) + { + HP_FREE (thread_p, src); + } +} + + static void pred_expr_free (THREAD_ENTRY *thread_p, PRED_EXPR *src) { @@ -1044,41 +1487,111 @@ pred_expr_free (THREAD_ENTRY *thread_p, PRED_EXPR *src) case T_COMP_EVAL_TERM: { COMP_EVAL_TERM *comp_term = &src->pe.m_eval_term.et.et_comp; - HP_FREE (thread_p, comp_term->lhs->vfetch_to); - HP_FREE (thread_p, comp_term->lhs); - HP_FREE (thread_p, comp_term->rhs->vfetch_to); - HP_FREE (thread_p, comp_term->rhs); + if (comp_term->lhs) + { + if (comp_term->lhs->vfetch_to) + { + pr_clear_value (comp_term->lhs->vfetch_to); + HP_FREE (thread_p, comp_term->lhs->vfetch_to); + } + HP_FREE (thread_p, comp_term->lhs); + } + if (comp_term->rhs) + { + if (comp_term->rhs->vfetch_to) + { + pr_clear_value (comp_term->rhs->vfetch_to); + HP_FREE (thread_p, comp_term->rhs->vfetch_to); + } + HP_FREE (thread_p, comp_term->rhs); + } } break; case T_ALSM_EVAL_TERM: { ALSM_EVAL_TERM *alsm_term = &src->pe.m_eval_term.et.et_alsm; - HP_FREE (thread_p, alsm_term->elem->vfetch_to); - HP_FREE (thread_p, alsm_term->elem); - HP_FREE (thread_p, alsm_term->elemset->vfetch_to); - HP_FREE (thread_p, alsm_term->elemset); + if (alsm_term->elem) + { + if (alsm_term->elem->vfetch_to) + { + pr_clear_value (alsm_term->elem->vfetch_to); + HP_FREE (thread_p, alsm_term->elem->vfetch_to); + } + HP_FREE (thread_p, alsm_term->elem); + } + if (alsm_term->elemset) + { + if (alsm_term->elemset->vfetch_to) + { + pr_clear_value (alsm_term->elemset->vfetch_to); + HP_FREE (thread_p, alsm_term->elemset->vfetch_to); + } + HP_FREE (thread_p, alsm_term->elemset); + } } break; case T_LIKE_EVAL_TERM: { LIKE_EVAL_TERM *like_term = &src->pe.m_eval_term.et.et_like; - HP_FREE (thread_p, like_term->src->vfetch_to); - HP_FREE (thread_p, like_term->src); - HP_FREE (thread_p, like_term->pattern->vfetch_to); - HP_FREE (thread_p, like_term->pattern); - HP_FREE (thread_p, like_term->esc_char->vfetch_to); - HP_FREE (thread_p, like_term->esc_char); + if (like_term->src) + { + if (like_term->src->vfetch_to) + { + pr_clear_value (like_term->src->vfetch_to); + HP_FREE (thread_p, like_term->src->vfetch_to); + } + HP_FREE (thread_p, like_term->src); + } + if (like_term->pattern) + { + if (like_term->pattern->vfetch_to) + { + pr_clear_value (like_term->pattern->vfetch_to); + HP_FREE (thread_p, like_term->pattern->vfetch_to); + } + HP_FREE (thread_p, like_term->pattern); + } + if (like_term->esc_char) + { + if (like_term->esc_char->vfetch_to) + { + pr_clear_value (like_term->esc_char->vfetch_to); + HP_FREE (thread_p, like_term->esc_char->vfetch_to); + } + HP_FREE (thread_p, like_term->esc_char); + } } break; case T_RLIKE_EVAL_TERM: { RLIKE_EVAL_TERM *rlike_term = &src->pe.m_eval_term.et.et_rlike; - HP_FREE (thread_p, rlike_term->src->vfetch_to); - HP_FREE (thread_p, rlike_term->src); - HP_FREE (thread_p, rlike_term->pattern->vfetch_to); - HP_FREE (thread_p, rlike_term->pattern); - HP_FREE (thread_p, rlike_term->case_sensitive->vfetch_to); - HP_FREE (thread_p, rlike_term->case_sensitive); + if (rlike_term->src) + { + if (rlike_term->src->vfetch_to) + { + pr_clear_value (rlike_term->src->vfetch_to); + HP_FREE (thread_p, rlike_term->src->vfetch_to); + } + HP_FREE (thread_p, rlike_term->src); + } + if (rlike_term->pattern) + { + if (rlike_term->pattern->vfetch_to) + { + pr_clear_value (rlike_term->pattern->vfetch_to); + HP_FREE (thread_p, rlike_term->pattern->vfetch_to); + } + HP_FREE (thread_p, rlike_term->pattern); + } + if (rlike_term->case_sensitive) + { + if (rlike_term->case_sensitive->vfetch_to) + { + pr_clear_value (rlike_term->case_sensitive->vfetch_to); + HP_FREE (thread_p, rlike_term->case_sensitive->vfetch_to); + } + HP_FREE (thread_p, rlike_term->case_sensitive); + } } break; } @@ -1461,7 +1974,10 @@ scan_end_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id) void scan_close_parallel_heap_scan (THREAD_ENTRY *thread_p, SCAN_ID *scan_id) { + HL_HEAPID orig_heap_id; + orig_heap_id = db_change_private_heap (thread_p, 0); delete scan_id->s.phsid.master; + db_change_private_heap (thread_p, orig_heap_id); } int diff --git a/src/query/query_executor.c b/src/query/query_executor.c index aa5004bd54f..13124e14589 100644 --- a/src/query/query_executor.c +++ b/src/query/query_executor.c @@ -9121,7 +9121,7 @@ qexec_open_scan (THREAD_ENTRY * thread_p, ACCESS_SPEC_TYPE * curr_spec, VAL_LIST #if defined(SERVER_MODE) if (!mvcc_select_lock_needed) { - if (!oid_is_cached_class_oid (&curr_spec->s.cls_node.cls_oid)) /* Only for User table */ + if (!oid_is_cached_class_oid (&curr_spec->s.cls_node.cls_oid) && (curr_spec->flags & ACCESS_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN)) /* Only for User table */ { scan_type = S_PARALLEL_HEAP_SCAN; } From e8d0ef66e4f2dc9b4ce161fbe093aeedd74db676 Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Wed, 18 Dec 2024 13:23:25 +0900 Subject: [PATCH 15/20] add flag for not parallel heap scan --- src/query/xasl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/query/xasl.h b/src/query/xasl.h index 4a70a2471fe..61c9f8330bf 100644 --- a/src/query/xasl.h +++ b/src/query/xasl.h @@ -832,7 +832,8 @@ typedef enum typedef enum { ACCESS_SPEC_FLAG_NONE = 0, - ACCESS_SPEC_FLAG_FOR_UPDATE = 0x01 /* used with FOR UPDATE clause. The spec that will be locked. */ + ACCESS_SPEC_FLAG_FOR_UPDATE = 0x01, /* used with FOR UPDATE clause. The spec that will be locked. */ + ACCESS_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN = 0x02 /* used with parallel heap scan. */ } ACCESS_SPEC_FLAG; struct cls_spec_node From 6f5566a568d3e09789ed326b85f4d2d3d8c7d573 Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Wed, 18 Dec 2024 13:25:55 +0900 Subject: [PATCH 16/20] codestyle --- src/parser/xasl_generation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/xasl_generation.c b/src/parser/xasl_generation.c index 13fd5620b69..4066391656c 100644 --- a/src/parser/xasl_generation.c +++ b/src/parser/xasl_generation.c @@ -12572,7 +12572,7 @@ pt_to_class_spec_list (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * where_ { access->flags = (ACCESS_SPEC_FLAG) (access->flags | ACCESS_SPEC_FLAG_FOR_UPDATE); } - if(!is_parallel_heap_scan_callable) + if (!is_parallel_heap_scan_callable) { access->flags = (ACCESS_SPEC_FLAG) (access->flags | ACCESS_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN); } From c7dd41efdae456226747f6381f3a5db63fda79e2 Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Wed, 18 Dec 2024 16:12:31 +0900 Subject: [PATCH 17/20] parallel 2 --- src/query/parallel_heap_scan.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/query/parallel_heap_scan.hpp b/src/query/parallel_heap_scan.hpp index c0442f9e194..e296996a94d 100644 --- a/src/query/parallel_heap_scan.hpp +++ b/src/query/parallel_heap_scan.hpp @@ -26,7 +26,7 @@ #include "scan_manager.h" #include "thread_manager.hpp" -#define HP_PARALLELISM 1 +#define HP_PARALLELISM 2 #define HP_RESULT_QUEUE_SIZE 11 From 35295884d87a624281e021f25824c32237a6fa97 Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Mon, 23 Dec 2024 19:36:35 +0900 Subject: [PATCH 18/20] dptr and scan_proc, disable and some fixes about flags --- src/parser/parse_tree.h | 3 +- src/parser/xasl_generation.c | 16 +++++++- src/query/parallel_heap_scan.cpp | 70 ++++++++++++++++++++------------ src/query/query_executor.c | 2 +- 4 files changed, 62 insertions(+), 29 deletions(-) diff --git a/src/parser/parse_tree.h b/src/parser/parse_tree.h index bdc1e739ce0..45950dfd3a8 100644 --- a/src/parser/parse_tree.h +++ b/src/parser/parse_tree.h @@ -1741,7 +1741,8 @@ typedef enum PT_SPEC_FLAG_MVCC_ASSIGN_REEV = 0x800, /* the spec is used in UPDATE assignment reevaluation */ PT_SPEC_FLAG_DOESNT_HAVE_UNIQUE = 0x1000, /* the spec was checked and does not have any uniques */ PT_SPEC_FLAG_SAMPLING_SCAN = 0x2000, /* spec for sampling scan */ - PT_SPEC_FLAG_REFERENCED_AT_ODKU = 0x4000 /* spec for odku assignment */ + PT_SPEC_FLAG_REFERENCED_AT_ODKU = 0x4000, /* spec for odku assignment */ + PT_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN = 0x8000 /* spec for not for parallel heap scan */ } PT_SPEC_FLAG; typedef enum diff --git a/src/parser/xasl_generation.c b/src/parser/xasl_generation.c index 4066391656c..36479df7bb6 100644 --- a/src/parser/xasl_generation.c +++ b/src/parser/xasl_generation.c @@ -9982,6 +9982,19 @@ pt_attribute_to_regu (PARSER_CONTEXT * parser, PT_NODE * attr) /* The attribute is correlated variable. Find it in an enclosing scope(s). Note that this subquery has * also just been determined to be a correlated subquery. */ REGU_VARIABLE_SET_FLAG (regu, REGU_VARIABLE_CORRELATED); + + for (table_info = symbols->table_info; table_info != NULL; table_info = table_info->next) + { + if (table_info->class_spec) + { + table_info->class_spec->info.spec.flag = + (PT_SPEC_FLAG) (table_info->class_spec->info.spec. + flag | PT_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN); + } + } + + table_info = NULL; + if (symbols->stack == NULL) { if (!pt_has_error (parser)) @@ -12572,7 +12585,7 @@ pt_to_class_spec_list (PARSER_CONTEXT * parser, PT_NODE * spec, PT_NODE * where_ { access->flags = (ACCESS_SPEC_FLAG) (access->flags | ACCESS_SPEC_FLAG_FOR_UPDATE); } - if (!is_parallel_heap_scan_callable) + if (!is_parallel_heap_scan_callable || (spec->info.spec.flag & PT_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN)) { access->flags = (ACCESS_SPEC_FLAG) (access->flags | ACCESS_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN); } @@ -14286,6 +14299,7 @@ ptqo_to_scan_proc (PARSER_CONTEXT * parser, QO_PLAN * plan, XASL_NODE * xasl, PT if (spec != NULL) { + spec->info.spec.flag = (PT_SPEC_FLAG) (spec->info.spec.flag | PT_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN); xasl->spec_list = pt_to_spec_list (parser, spec, where_key_part, where_part, plan, info, NULL, where_hash_part); if (xasl->spec_list == NULL) { diff --git a/src/query/parallel_heap_scan.cpp b/src/query/parallel_heap_scan.cpp index 37f98ffbf98..786f10039d8 100644 --- a/src/query/parallel_heap_scan.cpp +++ b/src/query/parallel_heap_scan.cpp @@ -74,8 +74,11 @@ pred_expr_clone (THREAD_ENTRY *thread_p, void *src, void *dest, enum ph_pred_exp static void pred_expr_free (THREAD_ENTRY *thread_p, PRED_EXPR *src); static heap_cache_attrinfo *attr_cache_clone (THREAD_ENTRY *thread_p, heap_cache_attrinfo *src); static void attr_cache_free (THREAD_ENTRY *thread_p, heap_cache_attrinfo *src); -static void link_attr_cache (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST node,heap_cache_attrinfo *old_attr_info, +static void link_attr_cache (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST node, heap_cache_attrinfo *old_attr_info, heap_cache_attrinfo *new_attr_info); +static void link_attr_cache_for_regu_var (THREAD_ENTRY *thread_p, REGU_VARIABLE *regu_var, + heap_cache_attrinfo *old_attr_info, + heap_cache_attrinfo *new_attr_info); static SCAN_CODE scan_next_heap_scan_1page_internal (THREAD_ENTRY *thread_p, SCAN_ID *scan_id, VPID *curr_vpid); static void arith_list_free (THREAD_ENTRY *thread_p, ARITH_TYPE *src); @@ -88,10 +91,10 @@ static int pred_clear (THREAD_ENTRY *thread_p, PRED_EXPR *pred); static int arith_list_clear (THREAD_ENTRY *thread_p, ARITH_TYPE *list); static void pos_desc_clear (THREAD_ENTRY *thread_p, QFILE_TUPLE_VALUE_POSITION *pos_desc); static int regu_val_list_clear (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *list); -ARITH_TYPE *arith_list_clone (THREAD_ENTRY *thread_p, ARITH_TYPE *src); -REGU_VARIABLE *regu_var_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE *src); -REGU_VARIABLE_LIST regu_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST src); -REGU_VALUE_LIST *regu_val_list_clone (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *src); +ARITH_TYPE *arith_list_clone (THREAD_ENTRY *thread_p, ARITH_TYPE *src, heap_cache_attrinfo *new_attr_info); +REGU_VARIABLE *regu_var_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE *src, heap_cache_attrinfo *new_attr_info); +REGU_VARIABLE_LIST regu_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST src, heap_cache_attrinfo *new_attr_info); +REGU_VALUE_LIST *regu_val_list_clone (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *, heap_cache_attrinfo *new_attr_info); /*************************************************************************************************/ /* parallel_heap_scan_result_queue_entry */ @@ -556,15 +559,12 @@ void parallel_heap_scan_task::execute (cubthread::entry &thread_ref) phsidp->pred_attrs.num_attrs, phsidp->pred_attrs.attr_ids, phsidp->pred_attrs.attr_cache, phsidp->rest_attrs.num_attrs, phsidp->rest_attrs.attr_ids, phsidp->rest_attrs.attr_cache, S_HEAP_SCAN, phsidp->cache_recordinfo, phsidp->recordinfo_regu_list, false); - - hsidp->scan_pred.regu_list = regu_list_clone (thread_p, m_context->orig_pred_list); - hsidp->rest_regu_list = regu_list_clone (thread_p, m_context->orig_rest_list); hsidp->pred_attrs.attr_cache = attr_cache_clone (thread_p, phsidp->pred_attrs.attr_cache); hsidp->rest_attrs.attr_cache = attr_cache_clone (thread_p, phsidp->rest_attrs.attr_cache); + hsidp->scan_pred.regu_list = regu_list_clone (thread_p, m_context->orig_pred_list, hsidp->pred_attrs.attr_cache); + hsidp->rest_regu_list = regu_list_clone (thread_p, m_context->orig_rest_list, hsidp->rest_attrs.attr_cache); hsidp->scan_pred.pred_expr = (PRED_EXPR *)pred_expr_clone (thread_p, (void *)phsidp->scan_pred.pred_expr, NULL, PH_PRED_EXPR, hsidp->pred_attrs.attr_cache); - link_attr_cache (thread_p, hsidp->scan_pred.regu_list, phsidp->pred_attrs.attr_cache, hsidp->pred_attrs.attr_cache); - link_attr_cache (thread_p, hsidp->rest_regu_list, phsidp->rest_attrs.attr_cache, hsidp->rest_attrs.attr_cache); hsidp->caches_inited = false; ret = scan_start_scan (thread_p, scan_id); reset_pred_or_regu_var_list (hsidp->scan_pred.pred_expr, true); @@ -1048,7 +1048,7 @@ int regu_var_clear (THREAD_ENTRY *thread_p, REGU_VARIABLE *regu_var) return pg_cnt; } -ARITH_TYPE *arith_list_clone (THREAD_ENTRY *thread_p, ARITH_TYPE *src) +ARITH_TYPE *arith_list_clone (THREAD_ENTRY *thread_p, ARITH_TYPE *src, heap_cache_attrinfo *new_attr_info) { if (!src) { @@ -1071,9 +1071,9 @@ ARITH_TYPE *arith_list_clone (THREAD_ENTRY *thread_p, ARITH_TYPE *src) } pr_clone_value (src->value, dest->value); - dest->leftptr = regu_var_clone (thread_p, src->leftptr); - dest->rightptr = regu_var_clone (thread_p, src->rightptr); - dest->thirdptr = regu_var_clone (thread_p, src->thirdptr); + dest->leftptr = regu_var_clone (thread_p, src->leftptr, new_attr_info); + dest->rightptr = regu_var_clone (thread_p, src->rightptr, new_attr_info); + dest->thirdptr = regu_var_clone (thread_p, src->thirdptr, new_attr_info); if (src->rand_seed) { @@ -1088,7 +1088,7 @@ ARITH_TYPE *arith_list_clone (THREAD_ENTRY *thread_p, ARITH_TYPE *src) } -REGU_VARIABLE_LIST regu_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST src) +REGU_VARIABLE_LIST regu_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST src, heap_cache_attrinfo *new_attr_info) { if (!src) { @@ -1103,7 +1103,7 @@ REGU_VARIABLE_LIST regu_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST s { REGU_VARIABLE_LIST curr_dest = (REGU_VARIABLE_LIST) HP_ALLOC (thread_p, sizeof (regu_variable_list_node)); curr_dest->next = NULL; - REGU_VARIABLE *cloned = regu_var_clone (thread_p, &curr_src->value); + REGU_VARIABLE *cloned = regu_var_clone (thread_p, &curr_src->value, new_attr_info); if (cloned != NULL) { curr_dest->value = *cloned; @@ -1127,7 +1127,7 @@ REGU_VARIABLE_LIST regu_list_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST s return head; } -REGU_VALUE_LIST *regu_val_list_clone (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *src) +REGU_VALUE_LIST *regu_val_list_clone (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *src, heap_cache_attrinfo *new_attr_info) { if (!src) { @@ -1148,7 +1148,7 @@ REGU_VALUE_LIST *regu_val_list_clone (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *s for (int i = 0; i < src->count; i++) { curr_dest = (REGU_VALUE_ITEM *) HP_ALLOC (thread_p, sizeof (REGU_VALUE_ITEM)); - curr_dest->value = regu_var_clone (thread_p, curr_src->value); + curr_dest->value = regu_var_clone (thread_p, curr_src->value, new_attr_info); curr_dest->next = NULL; if (prev_dest == NULL) @@ -1167,7 +1167,7 @@ REGU_VALUE_LIST *regu_val_list_clone (THREAD_ENTRY *thread_p, REGU_VALUE_LIST *s return dest; } -REGU_VARIABLE *regu_var_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE *src) +REGU_VARIABLE *regu_var_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE *src, heap_cache_attrinfo *new_attr_info) { REGU_VARIABLE *dest; if (!src) @@ -1185,32 +1185,33 @@ REGU_VARIABLE *regu_var_clone (THREAD_ENTRY *thread_p, REGU_VARIABLE *src) case TYPE_SHARED_ATTR_ID: case TYPE_CLASS_ATTR_ID: dest->value.attr_descr.cache_dbvalp = NULL; + dest->value.attr_descr.cache_attrinfo = new_attr_info; break; case TYPE_CONSTANT: dest->value.dbvalptr = src->value.dbvalptr; break; case TYPE_INARITH: case TYPE_OUTARITH: - dest->value.arithptr = arith_list_clone (thread_p, src->value.arithptr); + dest->value.arithptr = arith_list_clone (thread_p, src->value.arithptr, new_attr_info); break; case TYPE_SP: dest->value.sp_ptr->value = (DB_VALUE *) HP_ALLOC (thread_p, sizeof (DB_VALUE)); pr_clone_value (src->value.sp_ptr->value, dest->value.sp_ptr->value); - dest->value.sp_ptr->args = regu_list_clone (thread_p, src->value.sp_ptr->args); + dest->value.sp_ptr->args = regu_list_clone (thread_p, src->value.sp_ptr->args, new_attr_info); break; case TYPE_FUNC: dest->value.funcp->value = (DB_VALUE *) HP_ALLOC (thread_p, sizeof (DB_VALUE)); pr_clone_value (src->value.funcp->value, dest->value.funcp->value); - dest->value.funcp->operand = regu_list_clone (thread_p, src->value.funcp->operand); + dest->value.funcp->operand = regu_list_clone (thread_p, src->value.funcp->operand, new_attr_info); break; case TYPE_DBVAL: pr_clone_value (&src->value.dbval, &dest->value.dbval); break; case TYPE_REGUVAL_LIST: - dest->value.reguval_list = regu_val_list_clone (thread_p, src->value.reguval_list); + dest->value.reguval_list = regu_val_list_clone (thread_p, src->value.reguval_list, new_attr_info); break; case TYPE_REGU_VAR_LIST: - dest->value.regu_var_list = regu_list_clone (thread_p, src->value.regu_var_list); + dest->value.regu_var_list = regu_list_clone (thread_p, src->value.regu_var_list, new_attr_info); break; default: break; @@ -1345,12 +1346,11 @@ pred_expr_clone (THREAD_ENTRY *thread_p, void *src, void *dest, enum ph_pred_exp break; case PH_REGU_VAR: src_regu_var = (regu_variable_node *) src; - dest_regu_var = regu_var_clone (thread_p, src_regu_var); + dest_regu_var = regu_var_clone (thread_p, src_regu_var, attr_info); if (dest_regu_var->type == TYPE_ATTR_ID || dest_regu_var->type == TYPE_SHARED_ATTR_ID || dest_regu_var->type == TYPE_CLASS_ATTR_ID) { dest_regu_var->value.attr_descr.cache_dbvalp = NULL; - dest_regu_var->value.attr_descr.cache_attrinfo = attr_info; } ret = (void *) dest_regu_var; break; @@ -1643,6 +1643,24 @@ link_attr_cache (THREAD_ENTRY *thread_p, REGU_VARIABLE_LIST node,heap_cache_attr } } +static void link_attr_cache_for_regu_var (THREAD_ENTRY *thread_p, REGU_VARIABLE *node, + heap_cache_attrinfo *old_attr_info, + heap_cache_attrinfo *new_attr_info) +{ + if (node->type == TYPE_ATTR_ID || node->type == TYPE_CLASS_ATTR_ID + || node->type == TYPE_SHARED_ATTR_ID) + { + if (node->value.attr_descr.cache_attrinfo == old_attr_info) + { + node->value.attr_descr.cache_attrinfo = new_attr_info; + } + else + { + assert (false); + } + } +} + typedef enum { OBJ_GET_WITHOUT_LOCK = 0, diff --git a/src/query/query_executor.c b/src/query/query_executor.c index 13124e14589..e89e3c146be 100644 --- a/src/query/query_executor.c +++ b/src/query/query_executor.c @@ -9121,7 +9121,7 @@ qexec_open_scan (THREAD_ENTRY * thread_p, ACCESS_SPEC_TYPE * curr_spec, VAL_LIST #if defined(SERVER_MODE) if (!mvcc_select_lock_needed) { - if (!oid_is_cached_class_oid (&curr_spec->s.cls_node.cls_oid) && (curr_spec->flags & ACCESS_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN)) /* Only for User table */ + if (!oid_is_cached_class_oid (&curr_spec->s.cls_node.cls_oid) && !(curr_spec->flags & ACCESS_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN)) /* Only for User table */ { scan_type = S_PARALLEL_HEAP_SCAN; } From c034519f080af780168df823e7a3a2a238fcfd20 Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Mon, 23 Dec 2024 19:40:15 +0900 Subject: [PATCH 19/20] code style --- src/parser/xasl_generation.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser/xasl_generation.c b/src/parser/xasl_generation.c index 36479df7bb6..9c252624772 100644 --- a/src/parser/xasl_generation.c +++ b/src/parser/xasl_generation.c @@ -9988,8 +9988,8 @@ pt_attribute_to_regu (PARSER_CONTEXT * parser, PT_NODE * attr) if (table_info->class_spec) { table_info->class_spec->info.spec.flag = - (PT_SPEC_FLAG) (table_info->class_spec->info.spec. - flag | PT_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN); + (PT_SPEC_FLAG) (table_info->class_spec->info. + spec.flag | PT_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN); } } From 55d4601ef0383ae47a16f76ad3aace39da11c58e Mon Sep 17 00:00:00 2001 From: xmilex-git Date: Mon, 23 Dec 2024 19:43:32 +0900 Subject: [PATCH 20/20] code style --- src/parser/xasl_generation.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser/xasl_generation.c b/src/parser/xasl_generation.c index 9c252624772..04189d31c73 100644 --- a/src/parser/xasl_generation.c +++ b/src/parser/xasl_generation.c @@ -9985,11 +9985,11 @@ pt_attribute_to_regu (PARSER_CONTEXT * parser, PT_NODE * attr) for (table_info = symbols->table_info; table_info != NULL; table_info = table_info->next) { + PT_SPEC_FLAG flag = table_info->class_spec->info.spec.flag; if (table_info->class_spec) { table_info->class_spec->info.spec.flag = - (PT_SPEC_FLAG) (table_info->class_spec->info. - spec.flag | PT_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN); + (PT_SPEC_FLAG) (flag | PT_SPEC_FLAG_NOT_FOR_PARALLEL_HEAP_SCAN); } }