From c70b28b19f49b28e4c7035c9664890ebcbc7f01e Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 7 Sep 2023 16:47:34 +0800 Subject: [PATCH 001/118] Update binaryheap.h --- src/include/lib/binaryheap.h | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/include/lib/binaryheap.h b/src/include/lib/binaryheap.h index 12d97fce8..699b42f6d 100644 --- a/src/include/lib/binaryheap.h +++ b/src/include/lib/binaryheap.h @@ -43,24 +43,27 @@ typedef int (*binaryheap_comparator)(Datum a, Datum b, void* arg); * bh_nodes variable-length array of "space" nodes */ typedef struct binaryheap { - int bh_size; - int bh_space; + int bh_size; /* number of nodes currently in heap */ + int bh_space; /* current size of bh_nodes array */ bool bh_has_heap_property; /* debugging cross-check */ - binaryheap_comparator bh_compare; - void* bh_arg; - Datum bh_nodes[FLEXIBLE_ARRAY_MEMBER]; + binaryheap_comparator bh_compare; /* comparison function */ + void* bh_arg; /* extra argument for comparison function */ + Datum bh_nodes[FLEXIBLE_ARRAY_MEMBER]; /* VARIABLE LENGTH ARRAY */ } binaryheap; -extern binaryheap* binaryheap_allocate(int capacity, binaryheap_comparator compare, void* arg); -extern void binaryheap_reset(binaryheap* heap); -extern void binaryheap_free(binaryheap* heap); +extern binaryheap* binaryheap_allocate(int capacity, binaryheap_comparator compare, void* arg); /* allocates memory */ +extern void binaryheap_reset(binaryheap* heap); /* reset heap, but not free memory*/ +extern void binaryheap_free(binaryheap* heap); /* frees memory */ extern void binaryheap_add_unordered(binaryheap* heap, Datum d); -extern void binaryheap_build(binaryheap* heap); -extern void binaryheap_add(binaryheap* heap, Datum d); -extern Datum binaryheap_first(binaryheap* heap); -extern Datum binaryheap_remove_first(binaryheap* heap); -extern void binaryheap_replace_first(binaryheap* heap, Datum d); +/* add element to heap ,but may violate heap property */ -#define binaryheap_empty(h) ((h)->bh_size == 0) +extern void binaryheap_build(binaryheap* heap); /* builds heap property */ +extern void binaryheap_add(binaryheap* heap, Datum d); /*add element to heap*/ + +extern Datum binaryheap_first(binaryheap* heap); /* returns first element */ +extern Datum binaryheap_remove_first(binaryheap* heap); /* removes first element */ +extern void binaryheap_replace_first(binaryheap* heap, Datum d); /* replaces first element */ + +#define binaryheap_empty(h) ((h)->bh_size == 0) /* judge whether heap is empty*/ #endif /* BINARYHEAP_H */ -- 2.34.1 From f12abf70f9377c392c3ea3e7dbf490e112c8479b Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 7 Sep 2023 17:21:21 +0800 Subject: [PATCH 002/118] Update dllist.h --- src/include/lib/dllist.h | 72 ++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/include/lib/dllist.h b/src/include/lib/dllist.h index 0c9850442..729466ae1 100644 --- a/src/include/lib/dllist.h +++ b/src/include/lib/dllist.h @@ -45,6 +45,7 @@ struct Dllist; struct Dlelem; +// Dlelem is a node in a doubly linked list. typedef struct Dlelem { struct Dlelem* dle_next; /* next element */ struct Dlelem* dle_prev; /* previous element */ @@ -53,63 +54,62 @@ typedef struct Dlelem { } Dlelem; typedef struct Dllist { - Dlelem *dll_head; - Dlelem *dll_tail; - uint64 dll_len; + Dlelem* dll_head; /* head of list */ + Dlelem* dll_tail; /* tail of list */ + uint64 dll_len; /* number of elements in list */ } Dllist; class DllistWithLock : public BaseObject { -public: - DllistWithLock(); - ~DllistWithLock(); - void Remove(Dlelem* e) - { + public: + DllistWithLock(); // constructor + ~DllistWithLock(); // destructor + void Remove(Dlelem* e) { (void)RemoveConfirm(e); } - bool RemoveConfirm(Dlelem* e); - void AddHead(Dlelem* e); - void AddTail(Dlelem* e); - Dlelem* RemoveHead(); - Dlelem* RemoveHeadNoLock(); - Dlelem* RemoveTail(); - bool IsEmpty(); - Dlelem* GetHead(); - void GetLock(); - void ReleaseLock(); + bool RemoveConfirm(Dlelem* e); // remove element from list, return true if removed + void AddHead(Dlelem* e); // add element to head of list + void AddTail(Dlelem* e); // add element to tail of list + Dlelem* RemoveHead(); // remove element from head of list + Dlelem* RemoveHeadNoLock(); // remove element from head of list without lock + Dlelem* RemoveTail(); // remove element from tail of list + bool IsEmpty(); // is the list empty? + Dlelem* GetHead(); // get the head of the list + void GetLock(); // get the lock + void ReleaseLock(); // release the lock - inline uint64 GetLength() - { + inline uint64 GetLength() { // get the length of the list return m_list.dll_len; } -private: - slock_t m_lock; - Dllist m_list; + private: + slock_t m_lock; // lock for the list + Dllist m_list; // the list }; extern Dllist* DLNewList(void); /* allocate and initialize a list header */ extern void DLInitList(Dllist* list); /* init a header alloced by caller */ extern void DLFreeList(Dllist* list); /* free up a list and all the nodes in * it */ -extern Dlelem* DLNewElem(void* val); -extern void DLInitElem(Dlelem* e, void* val); -extern void DLFreeElem(Dlelem* e); +extern Dlelem* DLNewElem(void* val); /* allocate a new list element */ +extern void DLInitElem(Dlelem* e, void* val); /* initialize caller-allocated node */ +extern void DLFreeElem(Dlelem* e); /* free a list element */ extern void DLRemove(Dlelem* e); /* removes node from list */ -extern void DLAddHead(Dllist* list, Dlelem* node); -extern void DLAddTail(Dllist* list, Dlelem* node); +extern void DLAddHead(Dllist* list, Dlelem* node); /* add node to head of list */ +extern void DLAddTail(Dllist* list, Dlelem* node); /* add node to tail of list */ extern Dlelem* DLRemHead(Dllist* list); /* remove and return the head */ -extern Dlelem* DLRemTail(Dllist* list); +extern Dlelem* DLRemTail(Dllist* list); /* remove and return the tail */ extern void DLMoveToFront(Dlelem* e); /* move node to front of its list */ extern uint64 DLListLength(Dllist* list); /* These are macros for speed */ -#define DLGetHead(list) ((list)->dll_head) -#define DLGetTail(list) ((list)->dll_tail) -#define DLIsNIL(list) ((list)->dll_head == NULL) -#define DLGetSucc(elem) ((elem)->dle_next) -#define DLGetPred(elem) ((elem)->dle_prev) -#define DLGetListHdr(elem) ((elem)->dle_list) +#define DLGetHead(list) ((list)->dll_head) /* get the head of the list */ +#define DLGetTail(list) ((list)->dll_tail) /* get the tail of the list */ +#define DLIsNIL(list) ((list)->dll_head == NULL) /* is the list empty? */ +#define DLGetSucc(elem) ((elem)->dle_next) /* get the successor */ +#define DLGetPred(elem) ((elem)->dle_prev) /* get the predecessor */ +#define DLGetListHdr(elem) ((elem)->dle_list) /* get the list header */ -#define DLE_VAL(elem) ((elem)->dle_val) +#define DLE_VAL(elem) ((elem)->dle_val) /* get the value of the * element */ #endif /* DLLIST_H */ + -- 2.34.1 From a8e2cf0915e693dfa603a1634291b0481b5e3640 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Sat, 9 Sep 2023 18:36:23 +0800 Subject: [PATCH 003/118] Update dllist.cpp --- src/common/backend/lib/dllist.cpp | 325 ++++++++++++++---------------- 1 file changed, 150 insertions(+), 175 deletions(-) diff --git a/src/common/backend/lib/dllist.cpp b/src/common/backend/lib/dllist.cpp index 79cc63a23..c537c3c54 100644 --- a/src/common/backend/lib/dllist.cpp +++ b/src/common/backend/lib/dllist.cpp @@ -13,317 +13,292 @@ * * ------------------------------------------------------------------------- */ -#include "postgres.h" +#include "postgres.h" #include "knl/knl_variable.h" #include "lib/dllist.h" #include "miscadmin.h" -Dllist* DLNewList(void) -{ - Dllist* l = NULL; +Dllist* DLNewList(void) { + Dllist* l = NULL; // list pointer - l = (Dllist*)palloc(sizeof(Dllist)); + l = (Dllist*)palloc(sizeof(Dllist)); // allocate memory - l->dll_head = NULL; - l->dll_tail = NULL; - l->dll_len = 0; + l->dll_head = NULL; // init head pointer + l->dll_tail = NULL; // init tail pointer + l->dll_len = 0; // init length return l; } -void DLInitList(Dllist* list) -{ - list->dll_head = NULL; - list->dll_tail = NULL; - list->dll_len = 0; +void DLInitList(Dllist* list) { + list->dll_head = NULL; // init head pointer + list->dll_tail = NULL; // init tail pointer + list->dll_len = 0; // init length } /* * free up a list and all the nodes in it --- but *not* whatever the nodes * might point to! */ -void DLFreeList(Dllist* list) -{ - Dlelem* curr = NULL; +void DLFreeList(Dllist* list) { + Dlelem* curr = NULL; // current pointer - while ((curr = DLRemHead(list)) != NULL) + while ((curr = DLRemHead(list)) != NULL) // remove head from list pfree(curr); - pfree(list); + pfree(list); // free list } -Dlelem* DLNewElem(void* val) -{ - Dlelem* e = NULL; +Dlelem* DLNewElem(void* val) { + Dlelem* e = NULL; // element pointer - e = (Dlelem*)palloc(sizeof(Dlelem)); + e = (Dlelem*)palloc(sizeof(Dlelem)); // allocate memory - e->dle_next = NULL; - e->dle_prev = NULL; - e->dle_val = val; - e->dle_list = NULL; + e->dle_next = NULL; // init next pointer + e->dle_prev = NULL; // init prev pointer + e->dle_val = val; // init value + e->dle_list = NULL; // init list return e; } -void DLInitElem(Dlelem* e, void* val) -{ - e->dle_next = NULL; - e->dle_prev = NULL; - e->dle_val = val; - e->dle_list = NULL; +void DLInitElem(Dlelem* e, void* val) { + e->dle_next = NULL; // init next pointer + e->dle_prev = NULL; // init prev pointer + e->dle_val = val; // init value + e->dle_list = NULL; // init list } -void DLFreeElem(Dlelem* e) -{ - pfree(e); +void DLFreeElem(Dlelem* e) { + pfree(e); // free element } -void DLRemove(Dlelem* e) -{ - Dllist* l = e->dle_list; +void DLRemove(Dlelem* e) { + Dllist* l = e->dle_list; // list pointer - if (e->dle_prev) + if (e->dle_prev) // if e has prev element e->dle_prev->dle_next = e->dle_next; else { /* must be the head element */ Assert(e == l->dll_head); - l->dll_head = e->dle_next; + l->dll_head = e->dle_next; // set head pointer } if (e->dle_next) e->dle_next->dle_prev = e->dle_prev; else { /* must be the tail element */ Assert(e == l->dll_tail); - l->dll_tail = e->dle_prev; + l->dll_tail = e->dle_prev; // set tail pointer } if (l != NULL) { - l->dll_len--; + l->dll_len--; // decrease length } - e->dle_next = NULL; + e->dle_next = NULL; // reset pointer e->dle_prev = NULL; e->dle_list = NULL; } -void DLAddHead(Dllist* l, Dlelem* e) -{ - e->dle_list = l; +void DLAddHead(Dllist* l, Dlelem* e) { + e->dle_list = l; // set list pointer - if (l->dll_head) - l->dll_head->dle_prev = e; - e->dle_next = l->dll_head; - e->dle_prev = NULL; - l->dll_head = e; + if (l->dll_head) // if list is not empty + l->dll_head->dle_prev = e; // set prev pointer + e->dle_next = l->dll_head; // set next pointer + e->dle_prev = NULL; // set prev pointer + l->dll_head = e; // set head pointer if (l->dll_tail == NULL) /* if this is first element added */ - l->dll_tail = e; - l->dll_len++; + l->dll_tail = e; // set tail pointer + l->dll_len++; // increase length } -void DLAddTail(Dllist* l, Dlelem* e) -{ - e->dle_list = l; +void DLAddTail(Dllist* l, Dlelem* e) { + e->dle_list = l; // set list pointer - if (l->dll_tail) - l->dll_tail->dle_next = e; - e->dle_prev = l->dll_tail; - e->dle_next = NULL; - l->dll_tail = e; + if (l->dll_tail) // if list is not empty + l->dll_tail->dle_next = e; // set next pointer + e->dle_prev = l->dll_tail; // set prev pointer + e->dle_next = NULL; // set next pointer + l->dll_tail = e; // set tail pointer if (l->dll_head == NULL) /* if this is first element added */ l->dll_head = e; - l->dll_len++; + l->dll_len++; // increase length } -Dlelem* DLRemHead(Dllist* l) -{ +Dlelem* DLRemHead(Dllist* l) { /* remove and return the head */ Dlelem* result = l->dll_head; - if (result == NULL) + if (result == NULL) /* if list is empty */ return result; - if (result->dle_next) - result->dle_next->dle_prev = NULL; + if (result->dle_next) // if head has next element + result->dle_next->dle_prev = NULL; // set prev pointer - l->dll_head = result->dle_next; + l->dll_head = result->dle_next; // set head pointer if (result == l->dll_tail) /* if the head is also the tail */ l->dll_tail = NULL; - l->dll_len--; - result->dle_next = NULL; + l->dll_len--; // decrease length + result->dle_next = NULL; // reset pointer result->dle_list = NULL; return result; } -Dlelem* DLRemTail(Dllist* l) -{ +Dlelem* DLRemTail(Dllist* l) { /* remove and return the tail */ Dlelem* result = l->dll_tail; - if (result == NULL) + if (result == NULL) /* if list is empty */ return result; - if (result->dle_prev) - result->dle_prev->dle_next = NULL; + if (result->dle_prev) // if tail has prev element + result->dle_prev->dle_next = NULL; // set the previous poninter's next pointer - l->dll_tail = result->dle_prev; + l->dll_tail = result->dle_prev; // set tail pointer if (result == l->dll_head) /* if the tail is also the head */ - l->dll_head = NULL; + l->dll_head = NULL; // set head pointer - l->dll_len--; - result->dle_prev = NULL; + l->dll_len--; // decrease length + result->dle_prev = NULL; // reset pointer result->dle_list = NULL; return result; } /* Same as DLRemove followed by DLAddHead, but faster */ -void DLMoveToFront(Dlelem* e) -{ - Dllist* l = e->dle_list; +void DLMoveToFront(Dlelem* e) { + Dllist* l = e->dle_list; // list pointer if (l->dll_head == e) return; /* Fast path if already at front */ Assert(e->dle_prev != NULL); /* since it's not the head */ - e->dle_prev->dle_next = e->dle_next; + e->dle_prev->dle_next = e->dle_next; // set next pointer - if (e->dle_next) - e->dle_next->dle_prev = e->dle_prev; + if (e->dle_next) // if e has next element + e->dle_next->dle_prev = e->dle_prev; // set prev pointer else { /* must be the tail element */ Assert(e == l->dll_tail); - l->dll_tail = e->dle_prev; + l->dll_tail = e->dle_prev; // set tail pointer } - l->dll_head->dle_prev = e; - e->dle_next = l->dll_head; - e->dle_prev = NULL; - l->dll_head = e; + l->dll_head->dle_prev = e; // set prev pointer + e->dle_next = l->dll_head; // set next pointer + e->dle_prev = NULL; // set prev pointer + l->dll_head = e; // set head pointer /* We need not check dll_tail, since there must have been > 1 entry */ } /* * double-linked list length */ -uint64 DLListLength(Dllist* list) -{ - Dlelem* cur = list->dll_head; - uint64 length = 0; +uint64 DLListLength(Dllist* list) { + Dlelem* cur = list->dll_head; // current pointer + uint64 length = 0; // init length - while (cur != NULL) { - length++; - cur = cur->dle_next; + while (cur != NULL) { // traverse list + length++; // increase length + cur = cur->dle_next; // get next pointer } - Assert(length == list->dll_len); - return length; + Assert(length == list->dll_len); // check length + return length; // return length } -DllistWithLock::DllistWithLock() -{ - DLInitList(&m_list); - SpinLockInit(&m_lock); +DllistWithLock::DllistWithLock() { + DLInitList(&m_list); // init list + SpinLockInit(&m_lock); // init lock } -DllistWithLock::~DllistWithLock() -{ - SpinLockFree(&m_lock); +DllistWithLock::~DllistWithLock() { + SpinLockFree(&m_lock); // free lock } -bool DllistWithLock::RemoveConfirm(Dlelem* e) -{ - bool found = false; - START_CRIT_SECTION(); - SpinLockAcquire(&(m_lock)); - if (e->dle_list == &m_list) { +bool DllistWithLock::RemoveConfirm(Dlelem* e) { + bool found = false; // found flag + START_CRIT_SECTION(); // start critical section,avoid interrupt + SpinLockAcquire(&(m_lock)); // get lock + if (e->dle_list == &m_list) { // if e is in list found = true; - DLRemove(e); + DLRemove(e); // remove e from list } - SpinLockRelease(&(m_lock)); - END_CRIT_SECTION(); - return found; + SpinLockRelease(&(m_lock)); // release lock + END_CRIT_SECTION(); // end critical section + return found; // return found flag } -void DllistWithLock::AddHead(Dlelem* e) -{ - START_CRIT_SECTION(); - SpinLockAcquire(&(m_lock)); - if (e->dle_list == NULL) { - DLAddHead(&m_list, e); +void DllistWithLock::AddHead(Dlelem* e) { + START_CRIT_SECTION(); // start critical section + SpinLockAcquire(&(m_lock)); // get lock + if (e->dle_list == NULL) { // if e is not in list + DLAddHead(&m_list, e); // add e to list } - SpinLockRelease(&(m_lock)); - END_CRIT_SECTION(); + SpinLockRelease(&(m_lock)); // release lock + END_CRIT_SECTION(); // end critical section } -void DllistWithLock::AddTail(Dlelem* e) -{ - START_CRIT_SECTION(); - SpinLockAcquire(&(m_lock)); - if (e->dle_list == NULL) { - DLAddTail(&m_list, e); +void DllistWithLock::AddTail(Dlelem* e) { + START_CRIT_SECTION(); // start critical section + SpinLockAcquire(&(m_lock)); // get lock + if (e->dle_list == NULL) { // if e is not in list + DLAddTail(&m_list, e); // add e to list } - SpinLockRelease(&(m_lock)); - END_CRIT_SECTION(); + SpinLockRelease(&(m_lock)); // release lock + END_CRIT_SECTION(); // end critical section } -Dlelem* DllistWithLock::RemoveHead() -{ - Dlelem* head = NULL; - START_CRIT_SECTION(); - SpinLockAcquire(&(m_lock)); - head = DLRemHead(&m_list); - SpinLockRelease(&(m_lock)); - END_CRIT_SECTION(); - return head; +Dlelem* DllistWithLock::RemoveHead() { + Dlelem* head = NULL; // head pointer + START_CRIT_SECTION(); // start critical section + SpinLockAcquire(&(m_lock)); // get lock + head = DLRemHead(&m_list); // remove head from list + SpinLockRelease(&(m_lock)); // release lock + END_CRIT_SECTION(); // end critical section + return head; // return head pointer } -Dlelem* DllistWithLock::RemoveTail() -{ - Dlelem* head = NULL; - START_CRIT_SECTION(); - SpinLockAcquire(&(m_lock)); - head = DLRemTail(&m_list); - SpinLockRelease(&(m_lock)); - END_CRIT_SECTION(); - return head; +Dlelem* DllistWithLock::RemoveTail() { + Dlelem* head = NULL; // head pointer + START_CRIT_SECTION(); // start critical section + SpinLockAcquire(&(m_lock)); // get lock + head = DLRemTail(&m_list); // remove tail from list + SpinLockRelease(&(m_lock)); // release lock + END_CRIT_SECTION(); // end critical section + return head; // return head pointer } -bool DllistWithLock::IsEmpty() -{ - START_CRIT_SECTION(); - SpinLockAcquire(&(m_lock)); - bool ret = DLIsNIL(&m_list); - SpinLockRelease(&(m_lock)); - END_CRIT_SECTION(); - return ret; +bool DllistWithLock::IsEmpty() { + START_CRIT_SECTION(); // start critical section + SpinLockAcquire(&(m_lock)); // get lock + bool ret = DLIsNIL(&m_list); // judge whether list is empty + SpinLockRelease(&(m_lock)); // release lock + END_CRIT_SECTION(); // end critical section + return ret; // return result } -Dlelem* DllistWithLock::GetHead() -{ - Dlelem* head = NULL; - head = m_list.dll_head; - return head; +Dlelem* DllistWithLock::GetHead() { + Dlelem* head = NULL; // head pointer + head = m_list.dll_head; // get head pointer + return head; // return head pointer } -void DllistWithLock::GetLock() -{ - START_CRIT_SECTION(); - SpinLockAcquire(&(m_lock)); +void DllistWithLock::GetLock() { + START_CRIT_SECTION(); // start critical section + SpinLockAcquire(&(m_lock)); // get lock } -Dlelem* DllistWithLock::RemoveHeadNoLock() -{ - Dlelem* head = DLRemHead(&m_list); - return head; +Dlelem* DllistWithLock::RemoveHeadNoLock() { + Dlelem* head = DLRemHead(&m_list); // remove head from list + return head; // return head pointer } -void DllistWithLock::ReleaseLock() -{ - SpinLockRelease(&(m_lock)); - END_CRIT_SECTION(); +void DllistWithLock::ReleaseLock() { + SpinLockRelease(&(m_lock)); // release lock + END_CRIT_SECTION(); // end critical section } -- 2.34.1 From 915b2800cdd5d8f6cc06295114e365cf44f90ab2 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sat, 16 Sep 2023 23:53:20 +0800 Subject: [PATCH 004/118] Update archive_am.h --- src/include/access/archive/archive_am.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/include/access/archive/archive_am.h b/src/include/access/archive/archive_am.h index 8f349d77f..f291adaec 100644 --- a/src/include/access/archive/archive_am.h +++ b/src/include/access/archive/archive_am.h @@ -34,12 +34,18 @@ /* in archive/archive_am.cpp */ ArchiveConfig *getArchiveConfig(); +/*Return to the basic configuration of the Archive table.*/ size_t ArchiveRead(const char* fileName, int offset, char *buffer, int length, ArchiveConfig *archive_config = NULL); +/*Read the contents of the Archive table*/ int ArchiveWrite(const char* fileName, const char *buffer, const int bufferLength, ArchiveConfig *archive_config = NULL); +/*Write content into the Archive table.*/ + int ArchiveDelete(const char* fileName, ArchiveConfig *archive_config = NULL); +/*Delete content into the Archive table.*/ List* ArchiveList(const char* prefix, ArchiveConfig *archive_config = NULL, bool reportError = true, bool shortenConnTime = false); +/*List all tables in the Archive*/ bool ArchiveFileExist(const char* file_path, ArchiveConfig *archive_config); - +/*Judge whether the file exists.*/ #endif /* ARCHIVE_AM_H */ -- 2.34.1 From 605b5b00f0236fa5e6fbe337997df034ef50afd8 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sat, 16 Sep 2023 23:59:44 +0800 Subject: [PATCH 005/118] Update nas_am.h --- src/include/access/archive/nas_am.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/include/access/archive/nas_am.h b/src/include/access/archive/nas_am.h index 88887239e..10f77c1b8 100644 --- a/src/include/access/archive/nas_am.h +++ b/src/include/access/archive/nas_am.h @@ -23,6 +23,11 @@ * --------------------------------------------------------------------------------------- */ +/* +Network Attached Storage (NAS), the name of a special data storage technology, +can be directly connected to the computer network, +providing centralized data access services for heterogeneous network users*/ + #ifndef NAS_AM_H #define NAS_AM_H -- 2.34.1 From 379ed252f350de1fa1543b219da9fd8e8db247d7 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 00:01:58 +0800 Subject: [PATCH 006/118] Update nas_am.h --- src/include/access/archive/nas_am.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/include/access/archive/nas_am.h b/src/include/access/archive/nas_am.h index 10f77c1b8..27f429aeb 100644 --- a/src/include/access/archive/nas_am.h +++ b/src/include/access/archive/nas_am.h @@ -36,9 +36,13 @@ providing centralized data access services for heterogeneous network users*/ #include "replication/slot.h" size_t NasRead(const char* fileName, int offset, char *buffer, int length, ArchiveConfig *nas_config = NULL); +/*read file*/ int NasWrite(const char* fileName, const char *buffer, const int bufferLength, ArchiveConfig *nas_config = NULL); +/*write file*/ int NasDelete(const char* fileName, ArchiveConfig *nas_config = NULL); +/*delete file*/ List* NasList(const char* prefix, ArchiveConfig *nas_config = NULL); +/*list all file*/ bool checkNASFileExist(const char* file_path, ArchiveConfig *nas_config); - +/*judge whether exist */ #endif /* NAS_AM_H */ -- 2.34.1 From e91972e82f6545a3d43cf1cbd4b1765f1f63693e Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 00:14:16 +0800 Subject: [PATCH 007/118] Update carbondata_index_reader.h --- src/include/access/dfs/carbondata_index_reader.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/dfs/carbondata_index_reader.h b/src/include/access/dfs/carbondata_index_reader.h index 8f18546b1..2e08238be 100644 --- a/src/include/access/dfs/carbondata_index_reader.h +++ b/src/include/access/dfs/carbondata_index_reader.h @@ -21,6 +21,12 @@ * ------------------------------------------------------------------------- */ +/* +CarbonData is a new Apache Hadoop local file format, which uses +advanced columnar storage, indexing, compression and coding technologies to improve the calculation efficiency, +help to speed up the data query beyond PB, and can be used for faster interactive query. +At the same time, CarbonData is also a high-performance analysis engine that integrates data sources with Spark.*/ + #ifndef CARBONDATA_INDEX_READER_H_ #define CARBONDATA_INDEX_READER_H_ -- 2.34.1 From f0c4025a52a2975c0b0efbf19bc1951992a884e4 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 00:20:55 +0800 Subject: [PATCH 008/118] Update dfs_stream.h --- src/include/access/dfs/dfs_stream.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/include/access/dfs/dfs_stream.h b/src/include/access/dfs/dfs_stream.h index cf2f5d046..d465cd020 100644 --- a/src/include/access/dfs/dfs_stream.h +++ b/src/include/access/dfs/dfs_stream.h @@ -31,6 +31,10 @@ #include "dfs_config.h" // for DFS_UNIQUE_PTR +/* +Get input stream +*/ + namespace dfs { class GSInputStream { -- 2.34.1 From 4f76c8b27a56d32a7e59131fa812213d2bfb2e1b Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 00:28:34 +0800 Subject: [PATCH 009/118] Update batch_redo.h --- src/include/access/extreme_rto/batch_redo.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/include/access/extreme_rto/batch_redo.h b/src/include/access/extreme_rto/batch_redo.h index 5d8cbfedc..79c9af60f 100644 --- a/src/include/access/extreme_rto/batch_redo.h +++ b/src/include/access/extreme_rto/batch_redo.h @@ -26,6 +26,8 @@ #ifndef BATCH_REDO_H #define BATCH_REDO_H +/*This header file is used for replay after the failure of multi-batch database.*/ + #include "c.h" #include "storage/buf/block.h" #include "storage/smgr/relfilenode.h" @@ -64,6 +66,7 @@ typedef struct redoitemhashentry { XLogRecParseState *tail; int redoItemNum; } RedoItemHashEntry; +/*Provide operations for multiple threads*/ extern void PRPrintRedoItemHashTab(HTAB *redoItemHash); extern HTAB *PRRedoItemHashInitialize(MemoryContext context); -- 2.34.1 From 01dd50c00786c9f897493b702e9c6393e3dd56f8 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 00:37:39 +0800 Subject: [PATCH 010/118] Update spsc_blocking_queue.h --- .../access/extreme_rto/spsc_blocking_queue.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/include/access/extreme_rto/spsc_blocking_queue.h b/src/include/access/extreme_rto/spsc_blocking_queue.h index a2238a70a..74c1ff89d 100644 --- a/src/include/access/extreme_rto/spsc_blocking_queue.h +++ b/src/include/access/extreme_rto/spsc_blocking_queue.h @@ -23,6 +23,15 @@ * --------------------------------------------------------------------------------------- */ +/* +Lock-free SPSC queue proposed by Lamport. In his paper [paper], it is proved that the locks +in the single producer and single consumer (SPSC) first-in-first-out queue can be removed in a computer +that obeys the sequential consistency memory model, thus a lock-free queue is obtained, and the implementation +of the concurrent lock-in first-out (CLF) queue is given for the first time. By removing the lock in the queue, producers +and consumers can access the queue concurrently, thus improving the concurrent execution degree of the system. +*/ + + #ifndef EXTREME_RTO_SPSC_BLOCKING_QUEUE_H #define EXTREME_RTO_SPSC_BLOCKING_QUEUE_H @@ -44,10 +53,11 @@ struct SPSCBlockingQueue { CallBackFunc callBackFunc; void *buffer[1]; /* Queue buffer, the actual size is capacity. */ }; - +/* +Basic operation of SPSC queue*/ + SPSCBlockingQueue *SPSCBlockingQueueCreate(uint32 capacity, CallBackFunc func = NULL); void SPSCBlockingQueueDestroy(SPSCBlockingQueue *queue); - bool SPSCBlockingQueuePut(SPSCBlockingQueue *queue, void *element); void *SPSCBlockingQueueTake(SPSCBlockingQueue *queue); bool SPSCBlockingQueueIsEmpty(SPSCBlockingQueue *queue); -- 2.34.1 From c1cda703b1d1a5876303a55d300ea65d6b89a37c Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 00:50:55 +0800 Subject: [PATCH 011/118] Update obs_am.h --- src/include/access/obs/obs_am.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/obs/obs_am.h b/src/include/access/obs/obs_am.h index fc1aaec7b..2ed9be000 100755 --- a/src/include/access/obs/obs_am.h +++ b/src/include/access/obs/obs_am.h @@ -22,6 +22,12 @@ * * --------------------------------------------------------------------------------------- */ + +/* +Object Storage Service (OSS) is a massive, safe, low-cost and highly reliable cloud storage +service, which is suitable for storing any type of files. Flexible expansion of capacity and processing capacity, +multiple storage types to choose from, and comprehensive optimization of storage costs.*/ + #ifndef OBS_AM_H #define OBS_AM_H -- 2.34.1 From ccb26b21526f38eeac7c77c532d2836c4f5f8e97 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 04:42:48 +0800 Subject: [PATCH 012/118] Update knl_uundotype.h --- src/include/access/ustore/undo/knl_uundotype.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/include/access/ustore/undo/knl_uundotype.h b/src/include/access/ustore/undo/knl_uundotype.h index 22140747d..bf50bd7d7 100644 --- a/src/include/access/ustore/undo/knl_uundotype.h +++ b/src/include/access/ustore/undo/knl_uundotype.h @@ -22,6 +22,13 @@ #include "catalog/pg_tablespace.h" #include "storage/buf/bufpage.h" +/* +Undo log records the value of some data before it is modified, +which can be used for rollback; when the transaction fails; +Redo log records the modified value of a data block, which +can be used to recover the data updated by a successful +transaction that has not been written to the data file.*/ + /* The type used to identify an undo log and position within it. */ typedef uint64 UndoRecPtr; -- 2.34.1 From 73189d9112f84b57c6fd311123be3d9e45559016 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 05:06:52 +0800 Subject: [PATCH 013/118] Update clog.h --- src/include/access/clog.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/clog.h b/src/include/access/clog.h index ec8a27b42..670c854f1 100644 --- a/src/include/access/clog.h +++ b/src/include/access/clog.h @@ -27,6 +27,12 @@ * and page numbers in TruncateCLOG (see CLOGPagePrecedes). */ +/* + Because of compression, the storage on the disk is greatly reduced, and the compression ratio can reach 2-4 times. + Some blocks in the data are stored, and the max and min values of the block data are recorded, and block skipping query can be performed during query. +When querying, instead of loading all disk data into memory, columns are selected to load the required data according to the offset in the recorded skiplist, reducing IO. +*/ + /* We need two bits per xact, so four xacts fit in a byte */ #define CLOG_BITS_PER_XACT 2 #define CLOG_XACTS_PER_BYTE 4 -- 2.34.1 From 94ef8aa0e387dc492d6d15d53e702513b9bbfcb0 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 05:07:19 +0800 Subject: [PATCH 014/118] Update clog.h --- src/include/access/clog.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/include/access/clog.h b/src/include/access/clog.h index 670c854f1..45cf028f2 100644 --- a/src/include/access/clog.h +++ b/src/include/access/clog.h @@ -29,8 +29,10 @@ /* Because of compression, the storage on the disk is greatly reduced, and the compression ratio can reach 2-4 times. - Some blocks in the data are stored, and the max and min values of the block data are recorded, and block skipping query can be performed during query. -When querying, instead of loading all disk data into memory, columns are selected to load the required data according to the offset in the recorded skiplist, reducing IO. + Some blocks in the data are stored, and the max and min values of the + block data are recorded, and block skipping query can be performed during query. +When querying, instead of loading all disk data into memory, columns are selected to load the +required data according to the offset in the recorded skiplist, reducing IO. */ /* We need two bits per xact, so four xacts fit in a byte */ -- 2.34.1 From 5514a55bfa614c8fb0f7c5a6b8f40039ad582e9e Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 05:12:34 +0800 Subject: [PATCH 015/118] Update cstore_psort.h --- src/include/access/cstore_psort.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/access/cstore_psort.h b/src/include/access/cstore_psort.h index ea8778b60..dad7252e8 100644 --- a/src/include/access/cstore_psort.h +++ b/src/include/access/cstore_psort.h @@ -43,6 +43,7 @@ extern THR_LOCAL int psort_work_mem; #define InvalidBathCursor (-1) #define BathCursorIsValid(_c) ((_c) > InvalidBathCursor) +/*Sort each row of data by attributes.*/ class CStorePSort : public BaseObject { public: CStorePSort(Relation rel, AttrNumber *sortKeys, int keyNum, int type, MemInfoArg *m_memInfo = NULL); -- 2.34.1 From 22d9b9fe98a557274e8bb62dadd9c9cc84be4066 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 05:17:35 +0800 Subject: [PATCH 016/118] Update cstore_delta.h --- src/include/access/cstore_delta.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/include/access/cstore_delta.h b/src/include/access/cstore_delta.h index 0d0800e46..3cb9f53ee 100644 --- a/src/include/access/cstore_delta.h +++ b/src/include/access/cstore_delta.h @@ -23,6 +23,11 @@ * --------------------------------------------------------------------------------------- */ +/* +Delta table: the row storage table attached to the column +storage table is used to improve the query +performance and reduce the consumption of cu +space when inserting small quantities of data.*/ #ifndef CSTORE_DELTA_H #define CSTORE_DELTA_H -- 2.34.1 From 928b0c8fbbdb7bf491ec088c16b36462064e003c Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 05:21:03 +0800 Subject: [PATCH 017/118] Update cstore_psort.h --- src/include/access/cstore_psort.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/access/cstore_psort.h b/src/include/access/cstore_psort.h index dad7252e8..f9bd04037 100644 --- a/src/include/access/cstore_psort.h +++ b/src/include/access/cstore_psort.h @@ -43,7 +43,7 @@ extern THR_LOCAL int psort_work_mem; #define InvalidBathCursor (-1) #define BathCursorIsValid(_c) ((_c) > InvalidBathCursor) -/*Sort each row of data by attributes.*/ +/*psort table*/ class CStorePSort : public BaseObject { public: CStorePSort(Relation rel, AttrNumber *sortKeys, int keyNum, int type, MemInfoArg *m_memInfo = NULL); -- 2.34.1 From 70773c8f53acbf7c5b1be91524fa7090bc6fb386 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 05:22:25 +0800 Subject: [PATCH 018/118] Update cstoreskey.h --- src/include/access/cstoreskey.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/include/access/cstoreskey.h b/src/include/access/cstoreskey.h index 0d746add2..8b78a30b6 100644 --- a/src/include/access/cstoreskey.h +++ b/src/include/access/cstoreskey.h @@ -22,6 +22,17 @@ * * --------------------------------------------------------------------------------------- */ + +/* +A technique of listing. This technology can realize the filter filtering of base table scanning quickly through +min/max sparse index. Partial Cluster Key can specify multiple columns, but it is generally not recommended to +exceed 2 columns. Simply put, it is orderly storage according to clusterkey. Selection principle of Partial Cluster +Key: constrained by simple expressions in the base table. This constraint is generally in the form of col op const, +where col is the column name, op is the operator =, >, > =, < =, <, and const is a constant value. Try to use columns +in simple expressions with high selectivity (filtering out more data). Try to put the constraint col with low selectivity in +front of the Partial Cluster Key. Try to put the column of enumeration type in front of the Partial Cluster Key. +*/ + #ifndef CSTORESKEY_H #define CSTORESKEY_H -- 2.34.1 From 541ddd61a6afe0efa31ccbdebc6688bdeb7484f6 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 05:25:06 +0800 Subject: [PATCH 019/118] Update cbtree.h --- src/include/access/cbtree.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/include/access/cbtree.h b/src/include/access/cbtree.h index 9c35b967c..2d4ac1359 100644 --- a/src/include/access/cbtree.h +++ b/src/include/access/cbtree.h @@ -23,6 +23,9 @@ * --------------------------------------------------------------------------------------- */ +/*--btree index B-tree index is basically similar to line storage, but the difference +is that line storage uses ctid and column storage uses cuid(n)+ offset.*/ + #ifndef CTREE_H #define CTREE_H -- 2.34.1 From 81f221828d1689c4c63a036cfa96c389613c29af Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 05:39:41 +0800 Subject: [PATCH 020/118] Update gin.h --- src/include/access/gin.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/include/access/gin.h b/src/include/access/gin.h index 2fe76b1e0..ab9f21295 100644 --- a/src/include/access/gin.h +++ b/src/include/access/gin.h @@ -7,6 +7,17 @@ * src/include/access/gin.h * -------------------------------------------------------------------------- */ + +/* +GIN(Generalized Inverted Index) is an index structure that stores a set of key, posting list), +where the key is a key value and the posting list is a group of locations where the keys have +appeared. For example, in ('‘hello', '14:2 23:4 2 23:4'), it means that hello has appeared in the +ancestors of 14:2 and 23: 4. In PG, these positions are actually the tid (line number, including +data block ID(32bit) and item point(16 bit)) of tuples. +For each attribute in the table, it may be parsed into multiple key values when establishing +the corresponding gin index, so the tid of the same tuple may appear in the posting list of multiple keys. +*/ + #ifndef GIN_H #define GIN_H -- 2.34.1 From 800ed82ca3d8e165f1c216ebc71d73e7991449f5 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 05:44:42 +0800 Subject: [PATCH 021/118] Update gist.h --- src/include/access/gist.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/include/access/gist.h b/src/include/access/gist.h index 2db2f6388..82febe14e 100644 --- a/src/include/access/gist.h +++ b/src/include/access/gist.h @@ -14,6 +14,18 @@ * * ------------------------------------------------------------------------- */ + +/* +Gist(Generalized Search Tree), that is, universal search tree. Like btree, it is also a balanced search tree. +Different from btree, btree index is often used for operations such as greater than, less than and equal to, +but in real life, many data are not suitable for this scenario, such as geographic data, images and so on. +If we want to query whether there is a certain point in a certain place, that is, to judge the "inclusion" of +geographical location, then we can use the gist index. Because the gist index allows you to define rules to +distribute any type of data into a balanced tree, and allows you to define a method to use this representation +for some operators to access. For example, for spatial data, GiST index can use R-tree to support relative position +operators (left, right, inclusive, etc.), while for tree graph, R-tree can support intersection or inclusion operators. +*/ + #ifndef GIST_H #define GIST_H -- 2.34.1 From 4c7cc4c269c5e0b47f50997482003b07bfcec404 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 05:54:01 +0800 Subject: [PATCH 022/118] Update tupdesc.h --- src/include/access/tupdesc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index fbbdc8b2a..a12d3f726 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.h @@ -26,6 +26,7 @@ /* * Total number of different Table Access Method types. + Describe basic information */ const int NUM_TABLE_AM = 2; -- 2.34.1 From 7a55bdb7cc48060999a84f711131ac63e8c7b25e Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 05:59:29 +0800 Subject: [PATCH 023/118] Update tupconvert.h --- src/include/access/tupconvert.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/include/access/tupconvert.h b/src/include/access/tupconvert.h index 3064d8710..011cee296 100644 --- a/src/include/access/tupconvert.h +++ b/src/include/access/tupconvert.h @@ -16,6 +16,8 @@ #include "access/htup.h" +/*Conversion of tuple types to other types.*/ + typedef struct TupleConversionMap { TupleDesc indesc; /* tupdesc for source rowtype */ TupleDesc outdesc; /* tupdesc for result rowtype */ -- 2.34.1 From 49c1d030a9076eab0fe4b5836dd81b3695c27e20 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 07:01:46 +0800 Subject: [PATCH 024/118] Update hypopg_index.cpp --- src/gausskernel/dbmind/kernel/hypopg_index.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index 62fad5d84..ed6315bc5 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -17,6 +17,21 @@ * * ------------------------------------------------------------------------- */ + + +/* +In PG database, if you check whether an index contributes to one or more queries, +HypoPG can play a key role. It is an extension of postgresql, which allows you to create +virtual indexes and observe whether the optimizer is used. Therefore, you can provide methods +for which queries need to be optimized and which indexes you want to try. So for the average user, +how to better judge whether indexing is effective or not? Virtual index is a very useful thing, with no +side effects. It is just a virtual index. After establishing a virtual index, you can check the COST estimate +after adding the index through EXPLAIN to judge whether the cost will be reduced. In addition, the hypothetica +l index HypoPG will create is not stored in any directory, but in the connection private memory. Therefore, it +will not inflate any tables, nor will it affect any concurrent connections. Because it is assumed that indexes +don't really exist, HypoPG ensures that they will only be used with a simple EXPLAIN statement (no ANALYZE option). + +*/ #include #include #include "postgres.h" -- 2.34.1 From 0f06c8238c2b47728842c6a78957e66fa19ad750 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 07:04:21 +0800 Subject: [PATCH 025/118] Update hypopg_index.cpp --- src/gausskernel/dbmind/kernel/hypopg_index.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index ed6315bc5..f01508dfb 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -31,6 +31,8 @@ l index HypoPG will create is not stored in any directory, but in the connection will not inflate any tables, nor will it affect any concurrent connections. Because it is assumed that indexes don't really exist, HypoPG ensures that they will only be used with a simple EXPLAIN statement (no ANALYZE option). +Virtual index does not occupy space, and can be used to evaluate the performance of sql query conveniently, +which helps us to understand the effect of query optimization. */ #include #include -- 2.34.1 From 95d9400d77d7bf053706141bd5a9197c6775cdc1 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 18:28:53 +0800 Subject: [PATCH 026/118] Update hypopg_index.cpp --- .../dbmind/kernel/hypopg_index.cpp | 122 +++++++++++++++++- 1 file changed, 116 insertions(+), 6 deletions(-) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index f01508dfb..71b58f431 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -40,7 +40,7 @@ which helps us to understand the effect of query optimization. #include "fmgr.h" #include "funcapi.h" #include "miscadmin.h" -#include "access/gist.h" +#include "access/gist.h" /*Storage index*/ #include "access/nbtree.h" #include "access/reloptions.h" #include "access/spgist.h" @@ -111,6 +111,13 @@ static void hypo_injectHypotheticalIndex(PlannerInfo *root, Oid relationObjectId static List *get_table_indexes(Oid oid); static List *get_index_attrnum(Oid oid); +/* +Parameter: None, +return value: None. +Judge whether the virtual index of the instance exists. +If it does not exist, initialize the virtual index with +AllocSetContextCreate () function and mark it as unexplained. +*/ void InitHypopg() { // init memory context @@ -122,14 +129,22 @@ void InitHypopg() } /* - * This function is used for setting prev_utility_hook to rewrite - * standard_ProcessUtility by extension. +Set_hypopg_prehook function: +Parameter: ProcessUtility_hook_type func, +return value: none. +Function: Set prev_utility_hook, rewrite standard_ProcessUtility, +and control the execution of specific activities in the database +by using the hook mechanism of the database. + */ void set_hypopg_prehook(ProcessUtility_hook_type func) { prev_utility_hook = func; } +/* +Full hook mechanism to control all kinds of activities of the database.*/ + void hypopg_register_hook() { // register hooks @@ -150,6 +165,16 @@ void hypopg_register_hook() * Wrapper around GetNewRelFileNode * Return a new OID for an hypothetical index. */ + +/* +Hypo_getNewOid function: +Parameter: oid +Return value: oid +Open the relationship that we want a new OID, +now close the relationship and release the lock, +open pg_class to get a new OID, request a new relfilenode, +close pg_class and unlock it immediately.*/ + static Oid hypo_getNewOid(Oid relid) { Relation pg_class; @@ -194,6 +219,15 @@ void hypo_utility_hook(Node *parsetree, const char *queryString, ParamListInfo p } } +/* +Hypo_index_match_table function: + +Formal parameter: hypoIndex *entry Oid relid + +Return value: bool + +Judge whether the virtual index and the object identifier (OID) match. +*/ static bool hypo_index_match_table(hypoIndex *entry, Oid relid) { /* Hypothetical index on the exact same relation, use it. */ @@ -227,6 +261,15 @@ static bool hypo_query_walker(Node *parsetree) } /* Reset the isExplain flag after each query */ + +/*Hypo_executorEnd_hook function + +Parameter: QueryDesc *queryDesc + +Return value: None + +Reset the isExplain flag after each query.*/ + static void hypo_executorEnd_hook(QueryDesc *queryDesc) { isExplain = false; @@ -237,6 +280,19 @@ static void hypo_executorEnd_hook(QueryDesc *queryDesc) standard_ExecutorEnd(queryDesc); } } + +/*Get_table_indexes function: + +Parameter: oid + +Back to: list + +Query the list corresponding to the object identifier + +First open the specified heap to get the list of + +the specified heap, then close the heap to return to the list.*/ + List *get_table_indexes(Oid oid) { Relation rel = heap_open(oid, NoLock); @@ -246,6 +302,15 @@ List *get_table_indexes(Oid oid) } /* Return the names of all the columns involved in the index. */ + +/*Get_index_attrnum function: + +Parameter: index_oid + +Back to: list + +Returns the names of all columns.*/ + List *get_index_attrnum(Oid index_oid) { HeapTuple index_tup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid)); @@ -444,7 +509,16 @@ static hypoIndex *hypo_newIndex(Oid relid, char *accessMethod, int nkeycolumns, return entry; } -/* Add an hypoIndex to hypo_index_list */ +/* + +Hypo_addIndex function: + +Formal parameter: *entry + +Return: None + +Add a virtual index to the virtual index table.*/ + static void hypo_addIndex(hypoIndex *entry) { MemoryContext oldcontext; @@ -461,6 +535,12 @@ static void hypo_addIndex(hypoIndex *entry) } /* +Hypo_index_reset function: + +Formal parameter: none + +Return: None + * Remove cleanly all hypothetical indexes by calling hypo_index_remove() on * each entry. hypo_index_remove() function pfree all allocated memory */ @@ -899,7 +979,13 @@ static bool hypo_index_remove(Oid indexid) return false; } -/* pfree all allocated memory for within an hypoIndex and the entry itself. */ +/* +Hypo_index_pfree function: + +Formal parameter: entry + +Return: None +pfree all allocated memory for within an hypoIndex and the entry itself. */ static void hypo_index_pfree(hypoIndex *entry) { /* pfree all memory that has been allocated */ @@ -1183,6 +1269,13 @@ Datum hypopg_display_index(PG_FUNCTION_ARGS) } /* +Hypopg_create_index function: + +Parameter: (PG_FUNCTION_ARGS) + +Return: (Datum) + + * SQL wrapper to create an hypothetical index with his parsetree */ Datum hypopg_create_index(PG_FUNCTION_ARGS) @@ -1261,6 +1354,14 @@ Datum hypopg_create_index(PG_FUNCTION_ARGS) } /* + +Hypopg_drop_index function: + +Parameter: (PG_FUNCTION_ARGS) + +Return: (Datum) + +Delete the specified index * SQL wrapper to drop an hypothetical index. */ Datum hypopg_drop_index(PG_FUNCTION_ARGS) @@ -1270,6 +1371,8 @@ Datum hypopg_drop_index(PG_FUNCTION_ARGS) PG_RETURN_BOOL(hypo_index_remove(indexid)); } + + /* * SQL Wrapper around the hypothetical index size estimation */ @@ -1489,7 +1592,14 @@ static void hypo_estimate_index(hypoIndex *entry, RelOptInfo *rel) } /* - * Estimate a single index's column of an hypothetical index. + * + Hypo_estimate_index_colsize function: + +Parameter: (hypoIndex *entry, int col) + +Return: (int) + +Estimate the index column size of a virtual index. */ static int hypo_estimate_index_colsize(hypoIndex *entry, int col) { -- 2.34.1 From 705c19c73d17dd1155e5bbf37da4248f4562d8dd Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Sun, 17 Sep 2023 23:00:02 +0800 Subject: [PATCH 027/118] Update hypopg_index.cpp --- .../dbmind/kernel/hypopg_index.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index 71b58f431..015d2ff28 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -127,6 +127,12 @@ void InitHypopg() } isExplain = false; } +/* +SQLAllocConnect() allocates a connection handle and associated resources within the +environment that is identified by the input environment handle. Call SQLGetInfo() with +fInfoType set to SQL_ACTIVE_CONNECTIONS to query the number of connections that +can be allocated at any one time. SQLAllocEnv() must be called before calling this function.*/ + /* Set_hypopg_prehook function: @@ -185,7 +191,18 @@ static Oid hypo_getNewOid(Oid relid) /* Open the relation on which we want a new OID */ relation = heap_open(relid, AccessShareLock); - + +/*In PostgreSQL, AccessShareLock is a lock type used to +control concurrent access to database objects. It is a read +lock that allows multiple transactions to read from the same +object at the same time, but it prevents concurrent transactions +from acquiring conflicting locks, such as write locks or exclusive locks. +When a transaction obtains AccessShareLock on an object, other +transactions can also obtain AccessShareLock on the same object. +This means that multiple transactions can read objects at the same +time without interfering with each other.*/ + + reltablespace = relation->rd_rel->reltablespace; relpersistence = relation->rd_rel->relpersistence; @@ -300,6 +317,7 @@ List *get_table_indexes(Oid oid) heap_close(rel, NoLock); return indexes; } +/*Read-only here will not cause deadlock, so use NoLock lock.*/ /* Return the names of all the columns involved in the index. */ -- 2.34.1 From 8269dc065f113ab430ae1f7970499136fa025a74 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Mon, 18 Sep 2023 10:06:53 +0800 Subject: [PATCH 028/118] Update hypopg_index.cpp --- src/gausskernel/dbmind/kernel/hypopg_index.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index 015d2ff28..7b8fc459b 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -610,7 +610,7 @@ static void hypo_process_attr(IndexStmt *node, hypoIndex *volatile entry, String int attn; attn = 0; - foreach (lc, node->indexParams) { + foreach (lc, node->indexParams) { /*Traverse all nodes*/ IndexElem *attribute = (IndexElem *)lfirst(lc); Oid atttype = InvalidOid; Oid opclass; @@ -805,7 +805,7 @@ static const hypoIndex *hypo_index_store_parsetree(IndexStmt *node, const char * if (nkeycolumns > INDEX_MAX_KEYS) { elog(ERROR, "hypopg: cannot use more thant %d columns in an index", INDEX_MAX_KEYS); } - + //Show basic attributes initStringInfo(&indexRelationName); appendStringInfoString(&indexRelationName, node->accessMethod); appendStringInfoString(&indexRelationName, "_"); @@ -876,7 +876,7 @@ static const hypoIndex *hypo_index_store_parsetree(IndexStmt *node, const char * pull_varattnos((Node *)entry->indexprs, 1, &indexattrs); pull_varattnos((Node *)entry->indpred, 1, &indexattrs); - for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++) { + for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++) { //I is a negative number if (i != ObjectIdAttributeNumber && bms_is_member(i - FirstLowInvalidHeapAttributeNumber, indexattrs)) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("hypopg: index creation on system columns is not supported"))); -- 2.34.1 From c5547abf8e90e47868332898278bbffd6dae87a9 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Mon, 18 Sep 2023 13:55:51 +0800 Subject: [PATCH 029/118] Update index_advisor.cpp --- .../dbmind/kernel/index_advisor.cpp | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/gausskernel/dbmind/kernel/index_advisor.cpp b/src/gausskernel/dbmind/kernel/index_advisor.cpp index 125ec911e..e4e47c1d3 100644 --- a/src/gausskernel/dbmind/kernel/index_advisor.cpp +++ b/src/gausskernel/dbmind/kernel/index_advisor.cpp @@ -24,6 +24,25 @@ * ------------------------------------------------------------------------- */ +/*Single index recommendation: it is suitable for the case of large data in the table, +and it will not be recommended if the data is too small. + +When there is only one query condition in where, a single index is recommended; +if only id is in where, only id is recommended as the index; When there are multiple query conditions in where, +multiple indexes are recommended. For example, if id and name are used as conditions in where, they are recommended +as joint indexes together. However, if id and person_id exist +at the same time, id is recommended by default(the reason is unknown at present). + +When there are conditions such as order by and group by besides the where statement in the query, +all the attributes in where, order by and group by are recommended as joint indexes. + +When using like fuzzy query or precise query, the attribute is not indexed, and = attribute must be recommended for indexing. + +When there are too many conditions in the query and there are more than three attributes, it is still recommended that the joint +attributes are more than three, which will lead to too many recommended indexes, which is debatable. It is best to recommend +the attributes in the index to be less than three. However, this may need to be learned through DRL to determine which attributes +in a query to choose to build an index.*/ + #include "postgres.h" #include "access/tableam.h" @@ -58,6 +77,7 @@ #define MAX_SAMPLE_ROWS 10000 /* sampling range for executing a query */ #define CARDINALITY_THRESHOLD 30 /* the threshold of index selection */ +/*Some structures used for queries*/ #define RelAttrName(__tupdesc, __attridx) (NameStr((__tupdesc)->attrs[(__attridx)]->attname)) #define IsSameRel(_schema1, _table1, _schema2, _table2) \ ((!_schema1 || !_schema2 || strcasecmp(_schema1, _schema2) == 0) && strcasecmp(_table1, _table2) == 0) @@ -241,17 +261,7 @@ Datum gs_index_advise(PG_FUNCTION_ARGS) } /* - * suggest_index - * Parse the given query and return the suggested indexes. The suggested - * index consists of table names and column names. - * - * The main steps are summarized as follows: - * 1. Get parse tree; - * 2. Find and parse SelectStmt structures; - * 3. Parse 'from' and 'where' clause, and add candidate indexes for tables; - * 4. Determine the driver table; - * 5. Parse 'group' and 'order' clause and add candidate indexes for tables; - * 6. Add candidate indexes for drived tables according to the 'join' conditions. + */ SuggestedIndex *suggest_index(const char *query_string, _out_ int *len) { -- 2.34.1 From 42b6cbb50174b4174d3954f353b7cd2fe7aa821a Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Mon, 18 Sep 2023 13:56:30 +0800 Subject: [PATCH 030/118] Update index_advisor.cpp --- .../dbmind/kernel/index_advisor.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/gausskernel/dbmind/kernel/index_advisor.cpp b/src/gausskernel/dbmind/kernel/index_advisor.cpp index e4e47c1d3..c211f50c2 100644 --- a/src/gausskernel/dbmind/kernel/index_advisor.cpp +++ b/src/gausskernel/dbmind/kernel/index_advisor.cpp @@ -261,7 +261,26 @@ Datum gs_index_advise(PG_FUNCTION_ARGS) } /* +Suggest_index function: +Parameter: (constchar * query _ string, _ out _ int * len) + +Return value: SuggestedIndex + +Function: Parse the given query and return the suggested index. This proposed index consists of table names and column names. +The main steps are summarized as follows: + +1. Obtain a parse tree; + +2. Find and parse the structure of SelectStmt; + +3. Parse the "from" and "where" clauses and add candidate indexes to the table. + +4. Determine the driver table; + +5. Analyze the "group" and "order" clauses and add candidate indexes to the table; + +6. Add a candidate index for the driver table according to the "Join" condition. */ SuggestedIndex *suggest_index(const char *query_string, _out_ int *len) { -- 2.34.1 From 4387e8852a05a10bb607c2d4857a0c8ea88855d1 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Mon, 18 Sep 2023 14:35:37 +0800 Subject: [PATCH 031/118] Update index_advisor.cpp --- .../dbmind/kernel/index_advisor.cpp | 71 ++++++++++++++++++- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/src/gausskernel/dbmind/kernel/index_advisor.cpp b/src/gausskernel/dbmind/kernel/index_advisor.cpp index c211f50c2..0a3def97e 100644 --- a/src/gausskernel/dbmind/kernel/index_advisor.cpp +++ b/src/gausskernel/dbmind/kernel/index_advisor.cpp @@ -485,6 +485,14 @@ void get_join_condition_from_plan(Node* node, List* rtable) } } +/*/*Add_index function: + +Parameter: (table cell * table, char * index _ name) + +Return value: None. + +Function: Add nodes to the table.*/ + void add_index(TableCell *table, char *index_name) { IndexCell *index = (IndexCell *)palloc0(sizeof(*index)); @@ -521,6 +529,8 @@ void add_index(TableCell *table, char *index_name) } } + + void get_order_condition_from_plan(Node* node) { Sort *sortopt = (Sort *)node; @@ -564,6 +574,14 @@ void get_order_condition_from_plan(Node* node) } } +/*Free_global_resource function + +Formal parameter: none + +Return value: None + +Role: release global resources.*/ + void free_global_resource() { list_free(g_drived_tables); @@ -577,7 +595,14 @@ void free_global_resource() g_driver_table = NULL; } -/* Search the oid of all indexes created on the table through the oid of the table, +/* +Get_table_indexes function: + +Parameter: oid + +Back to: list + +Search the oid of all indexes created on the table through the oid of the table, * and return the index oid list. */ List *get_table_indexes(Oid oid) @@ -650,7 +675,11 @@ List *get_index_attname(Oid index_oid) return attnames; } -// Execute an SQL statement and return its result. +/* +Execute_ Stmt function: +Formal parameters: (const char * query_string, bool need_result) +Return: StmtResult +Execute an SQL statement and return the result.*/ StmtResult *execute_stmt(const char *query_string, bool need_result) { int16 format = 0; @@ -757,7 +786,14 @@ void shutdown(DestReceiver *self) { /* nothing */ } -/* Release resources */ +/* +Destroy function: + +Parameter: (DestReceiver *self) + +Return: None + +The function frees all allocated memory.Release resources */ void destroy(DestReceiver *self) { StmtResult *result = (StmtResult *)self; @@ -772,6 +808,15 @@ void destroy(DestReceiver *self) } /* + +Find_select_stmt function: + +Parameter: (Node *parsetree) + +Return: None + +Recursively search the SelectStmt structure in the parse tree. + * find_select_stmt * Recursively search for SelectStmt structures within a parse tree. * @@ -927,6 +972,12 @@ void get_partition_index_type(IndexPrint *suggested_index, TableCell *table) } /* +Generate_ Index_ Print function: +Formal parameters: (TableCell * table, char * index_print) +Return: IndexPrint* +Generate Index Printing + + * generat_index_print * Generate index type, normal table is '' by default * partition table is divided into local and global. @@ -972,6 +1023,15 @@ IndexPrint *generat_index_print(TableCell *table, char *index_print) return suggested_index; } + +/*Find_table function: + +Parameter: (TableCell *table) + +Return: TableCell* + +Find index table*/ + TableCell *find_table(TableCell *table) { ListCell *item = NULL; @@ -1528,6 +1588,11 @@ uint4 calculate_field_cardinality(char *schema_name, char *table_name, const cha return cardinality; } +/*Split_ Field_ List function: +Formal parameters: (List * fields, char * * schema_name_ptr, char * * table_name_ptr, char * * col_name_ptr) +Return: None +Split the specified area index table*/ + void split_field_list(List *fields, char **schema_name_ptr, char **table_name_ptr, char **col_name_ptr) { if (fields == NULL) { -- 2.34.1 From 1fbc036907cfbb58e0eb7997bbd1c64da9c68080 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Mon, 18 Sep 2023 20:20:37 +0800 Subject: [PATCH 032/118] Update hyperparameter_validation.cpp --- .../executor/hyperparameter_validation.cpp | 140 +++++++++++++++++- 1 file changed, 137 insertions(+), 3 deletions(-) diff --git a/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp b/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp index e91ac8990..f5a966fe4 100644 --- a/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp @@ -28,6 +28,8 @@ #include "nodes/plannodes.h" #include "db4ai/db4ai_api.h" +//Used to add, delete, check and modify the value of the superparameter. + /////////////////////////////////////////////////////////////////////////////// @@ -37,13 +39,22 @@ is_supervised \ } - +/*Function: get_ Hyperparameter_ Definitions +Parameter: (AlgorithmML algorithm, int32_t * result_size) +Return: HyperparameterDefinition* +Enter the algorithm and number of result digits to return the definition of hyperparameters for this model.*/ + const HyperparameterDefinition* get_hyperparameter_definitions(AlgorithmML algorithm, int32_t *result_size) { AlgorithmAPI* api = get_algorithm_api(algorithm); return api->get_hyperparameters_definitions(api, result_size); } + /*Function: get_ Algorithm_ Configuration +Parameter: AlgorithmML algorithm +Return: AlgorithmConfiguration* +Determine if the algorithm exists.*/ + AlgorithmConfiguration *get_algorithm_configuration(AlgorithmML algorithm) { switch (algorithm) { @@ -55,6 +66,16 @@ AlgorithmConfiguration *get_algorithm_configuration(AlgorithmML algorithm) return NULL; } +/* +Function: find_hyperparameter_definition + +Parameter:(const HyperparameterDefinition definitions[], + int32_t definitions_size, + const char *hyperparameter_name) + +Return:HyperparameterDefinition * +Enter the model name and return the model definition. +*/ const HyperparameterDefinition *find_hyperparameter_definition(const HyperparameterDefinition definitions[], int32_t definitions_size, const char *hyperparameter_name) @@ -68,6 +89,14 @@ const HyperparameterDefinition *find_hyperparameter_definition(const Hyperparame } // Set the value of a hyperparameter structure +/* +Function: set_ Hyperparameter_ Datum +Parameter: (Hyperparameter * hyperp, Oid type, Datum value) +Return: None +Set the hyperparameter type and value, which is called by the system. +An exception is thrown if there is no super parameter. +*/ + static void set_hyperparameter_datum(Hyperparameter *hyperp, Oid type, Datum value) { if (type == ANYENUMOID) { // Outside of hyperparameter module, treat them as strings @@ -80,6 +109,14 @@ static void set_hyperparameter_datum(Hyperparameter *hyperp, Oid type, Datum val } } +/* +Function: add_model_hyperparameter +Parameter: (List *hyperparameters, MemoryContext memcxt, const char *name, Oid type, + Datum value) +Return: List * +Adding hyperparameters to the model +*/ + static List *add_model_hyperparameter(List *hyperparameters, MemoryContext memcxt, const char *name, Oid type, Datum value) { @@ -93,7 +130,14 @@ static List *add_model_hyperparameter(List *hyperparameters, MemoryContext memcx return hyperparameters; } - +/* +Function: update_model_hyperparameter +Parameter: (MemoryContext memcxt, List *hyperparameters, const char *name, Oid type, Datum value) +Return:None +update hyperparameters to the model +*/ + + void update_model_hyperparameter(MemoryContext memcxt, List *hyperparameters, const char *name, Oid type, Datum value) { MemoryContext old_context = MemoryContextSwitchTo(memcxt); @@ -108,12 +152,20 @@ void update_model_hyperparameter(MemoryContext memcxt, List *hyperparameters, co MemoryContextSwitchTo(old_context); } - +/* inline change bool to str*/ inline const char *bool_to_str(bool value) { return value ? "TRUE" : "FALSE"; } +/*Function: ereport_ Hyperparameter + +Formal parameters: (int level, const char * name, Datum value, Oid type) + +Return value: None + +Display model hyperparameters*/ + static void ereport_hyperparameter(int level, const char *name, Datum value, Oid type) { switch (type) { @@ -214,6 +266,15 @@ static Datum get_hyperparameter(const HyperparameterDefinition *definition, void // Set hyperparameter in hyperparameter struct to the givne value in the datum. Definition is used for metadata +/*Function: set_ Hyperparameter + +Formal parameters: (const HyperparameterDefinition * definition, Datum value, void * hyperparameter_struct) + +Return value: None + +Modify model hyperparameter values*/ + + static void set_hyperparameter(const HyperparameterDefinition *definition, Datum value, void *hyperparameter_struct) { switch (definition->type) { @@ -259,6 +320,17 @@ static void set_hyperparameter(const HyperparameterDefinition *definition, Datum } } + + /* + Function: validate_ Hyperparameter_ String + +Formal parameters: (const char * name, const char * value, const char * valid_values [], + +Int32_ T valid_ Values_ Size) + +Return value: None + +Given the hyperparameter name, modify the model hyperparameter value.*/ static void validate_hyperparameter_string(const char *name, const char *value, const char *valid_values[], int32_t valid_values_size) { @@ -284,6 +356,11 @@ static void validate_hyperparameter_string(const char *name, const char *value, } } + /*Function: validate_ Hyperparameter +Formal parameters: (Datum value, Oid type, const HyperparameterValidation * validation, const char * name) +Return value: None +Make the modified hyperparameter values effective.*/ + static void validate_hyperparameter(Datum value, Oid type, const HyperparameterValidation *validation, const char *name) { switch (type) { @@ -354,6 +431,16 @@ static void validate_hyperparameter(Datum value, Oid type, const HyperparameterV } } + /*Function: extract_ Value_ From_ Variable_ Set_ Stmt +Parameter: (VariableSetStmt * stmt) +Return value: Value +Obtain modified values using preprocessing.*/ + /*STMT is a C API provided by MySQL, + which is used to execute Prepared statements. + Compared with the direct execution of SQL, the + preprocessing statement has higher running + efficiency and better security.*/ + static Value *extract_value_from_variable_set_stmt(VariableSetStmt *stmt) { if (list_length(stmt->args) > 1) { @@ -370,6 +457,14 @@ static Value *extract_value_from_variable_set_stmt(VariableSetStmt *stmt) return value; } + +/*Function: value_ To_ Datum + +Formal parameters: (Value * value, Oid expected_type, const char * name) + +Return value: Datum + +Modify the hyperparameter value to Datum type.*/ static Datum value_to_datum(Value *value, Oid expected_type, const char *name) { Datum result = (Datum)0; @@ -457,6 +552,10 @@ static Datum value_to_datum(Value *value, Oid expected_type, const char *name) return result; } + /*Function: extract_ Datum_ From_ Variable_ Set_ Stmt +Formal parameters: (VariableSetStmt * stmt, const HyperparameterDefinition * definition) +Return value: Datum +Use preprocessing to obtain and modify Datum.*/ Datum extract_datum_from_variable_set_stmt(VariableSetStmt *stmt, const HyperparameterDefinition *definition) { Datum selected_value = (Datum)0; @@ -470,6 +569,16 @@ Datum extract_datum_from_variable_set_stmt(VariableSetStmt *stmt, const Hyperpar return selected_value; } + + /*Function: configure_ Hyperparameters_ VSET + +Formal parameters: (const HyperparameterDefinition definitions [], int32_t definitions_size, + +List * hyperparameters, void * configuration) + +Return value: Datum + +Initialize hyperparameter configuration using set.*/ void configure_hyperparameters_vset(const HyperparameterDefinition definitions[], int32_t definitions_size, List *hyperparameters, void *configuration) { @@ -543,6 +652,16 @@ void configure_hyperparameters(const HyperparameterDefinition definitions[], int } } + + /*Function: prepare_ Model_ Hyperparameters + +Formal parameters: (const HyperparameterDefinition * definitions, int32_t definitions_size, + +Void * hyperparameter_ Struct, MemoryContext memcxt) + +Return value: List* + +Prepare model hyperparameters.*/ List *prepare_model_hyperparameters(const HyperparameterDefinition *definitions, int32_t definitions_size, void *hyperparameter_struct, MemoryContext memcxt) { @@ -555,6 +674,17 @@ List *prepare_model_hyperparameters(const HyperparameterDefinition *definitions, return hyperparameters; } + /*Function: init_ Hyperparameters_ With_ Defaults + +Formal parameters: (const HyperparameterDefinition definitions [], int32_t definitions_size, + +Void * hyperparameter_ Struct + +Return value: None + +Initialize hyperparameters + +*/ void init_hyperparameters_with_defaults(const HyperparameterDefinition definitions[], int32_t definitions_size, void *hyperparameter_struct) { @@ -563,6 +693,10 @@ void init_hyperparameters_with_defaults(const HyperparameterDefinition definitio } } + /*Function: print_ Hyperparameters +Formal parameters: (int level, List * hyperparameters) +Return value: None +Output all hyperparameter attributes*/ void print_hyperparameters(int level, List *hyperparameters) { foreach_cell(it, hyperparameters) { -- 2.34.1 From e970fb92dc55e6f24d6c5a2ac0d2096402c70360 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Mon, 18 Sep 2023 20:37:46 +0800 Subject: [PATCH 033/118] Update hyperparameter_validation.cpp --- .../db4ai/executor/hyperparameter_validation.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp b/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp index f5a966fe4..f439d4874 100644 --- a/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp @@ -21,6 +21,16 @@ * --------------------------------------------------------------------------------------- */ +/*In the direction of DB4AI, the database can avoid the problem of data handling +when users perform AI calculation by integrating AI capabilities. Different from other +DB4AI frameworks, the native framework of openGauss open source is to complete +the AI calculation in the database by adding AI operators.*/ + +/*In the context of machine learning, superparameters are parameters whose values are +set before the learning process begins, rather than parameter data obtained through training. +Usually, it is necessary to optimize the hyperparameters and choose a set of optimal hyperparameters +for the learning machine to improve the learning performance and effect.*/ + #include "db4ai/hyperparameter_validation.h" #include "db4ai/aifuncs.h" @@ -456,8 +466,9 @@ static Value *extract_value_from_variable_set_stmt(VariableSetStmt *stmt) } return value; } - - + /*Datum' is one of the data types used in C language functions + in PostgreSQL, which can represent any value in valid SQL types. + */ /*Function: value_ To_ Datum Formal parameters: (Value * value, Oid expected_type, const char * name) -- 2.34.1 From 8f4aea4f0b3a31cec05dcd6b347d65c489e11098 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Tue, 19 Sep 2023 14:15:32 +0800 Subject: [PATCH 034/118] Update hyperparameter_validation.cpp --- .../dbmind/db4ai/executor/hyperparameter_validation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp b/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp index f439d4874..9612a74bf 100644 --- a/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp @@ -39,7 +39,7 @@ for the learning machine to improve the learning performance and effect.*/ #include "db4ai/db4ai_api.h" //Used to add, delete, check and modify the value of the superparameter. - +// /////////////////////////////////////////////////////////////////////////////// -- 2.34.1 From 41d9fcfd26afb8f2be0fc7278b6b31a2216ce422 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Tue, 19 Sep 2023 14:23:25 +0800 Subject: [PATCH 035/118] Update matrix.cpp --- src/gausskernel/dbmind/db4ai/executor/matrix.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/matrix.cpp b/src/gausskernel/dbmind/db4ai/executor/matrix.cpp index 60144d1af..cd2b6baac 100644 --- a/src/gausskernel/dbmind/db4ai/executor/matrix.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/matrix.cpp @@ -21,6 +21,14 @@ * --------------------------------------------------------------------------------------- */ +/*Matrix refers to a set of complex numbers or real numbers arranged in a rectangular array in mathematics. +It originated from the square matrix composed of coefficients and constants of equations. It was first proposed +by the 19th century British mathematician Kelly. It is a common tool in advanced algebra, and its operation is +an important problem in the field of numerical analysis. Decomposition of a matrix into a combination of simple +matrices can simplify the operation of the matrix in theory and practical application. + +For a matrix, at least the following operations should be included: addition, multiplication, transposition, eigenvalue +calculation, and for a square matrix, determinant calculation is also required.*/ #include "db4ai/matrix.h" #define MATRIX_LIMITED_OUTPUT 30 -- 2.34.1 From 3900e88c53f491027cb612dfaacedc8ee7a27623 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Tue, 19 Sep 2023 14:28:37 +0800 Subject: [PATCH 036/118] Update matrix.cpp --- .../dbmind/db4ai/executor/matrix.cpp | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/src/gausskernel/dbmind/db4ai/executor/matrix.cpp b/src/gausskernel/dbmind/db4ai/executor/matrix.cpp index cd2b6baac..2da1b4267 100644 --- a/src/gausskernel/dbmind/db4ai/executor/matrix.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/matrix.cpp @@ -33,6 +33,11 @@ calculation, and for a square matrix, determinant calculation is also required.* #define MATRIX_LIMITED_OUTPUT 30 + +/*Function: void matrix_ Init_ Random_ Gaussian +Formal parameters: (Matrix * matrix, int rows, int columns, float8 mu, float8 sigma, int seed) +Return: None +Production random Gaussian matrix*/ // using Box-Muller implementation void matrix_init_random_gaussian(Matrix *matrix, int rows, int columns, float8 mu, float8 sigma, int seed) { @@ -60,12 +65,20 @@ void matrix_init_random_gaussian(Matrix *matrix, int rows, int columns, float8 m } } +/*Function: matrix_ Init_ Kernel_ Gaussian +Formal parameters: (int features, int components, float8 gamma, int seed, Matrix * weights, Matrix * offsets) +Return: None +Initialize a matrix using a specified number*/ void matrix_init_kernel_gaussian(int features, int components, float8 gamma, int seed, Matrix *weights, Matrix *offsets) { matrix_init_random_gaussian(weights, features, components, 0.0, sqrt(2.0 * gamma), seed); matrix_init_random_uniform(offsets, components, 1, 0.0, 2.0 * M_PI, seed+1); } +/*Function: matrix_ Transform_ Kernel_ Gaussian +Formal parameters: (const Matrix * input, const Matrix * weights, const Matrix * offsets, Matrix * output) +Return: None +Matrix transpose*/ void matrix_transform_kernel_gaussian(const Matrix *input, const Matrix *weights, const Matrix *offsets, Matrix *output) { int components = weights->columns; @@ -91,6 +104,10 @@ void matrix_transform_kernel_gaussian(const Matrix *input, const Matrix *weights matrix_mult_scalar(output, sqrt(2.0 / components)); } +/*Function: matrix_ Init_ Random_ Uniform +Formal parameters: (Matrix * matrix, int rows, int columns, float8 min, float8 max, int seed) +Return: None +Initializing a matrix using random floating-point numbers*/ void matrix_init_random_uniform(Matrix *matrix, int rows, int columns, float8 min, float8 max, int seed) { Assert(min < max); @@ -109,7 +126,10 @@ void matrix_init_random_uniform(Matrix *matrix, int rows, int columns, float8 mi *pd++ = min + range * u; } } - +/*Function: matrix_ Init_ Random_ Bernoulli +Formal parameters: (Matrix * matrix, int rows, int columns, float8 p, float8 min, float8 max, int seed) +Return: None +Generate Random Bernoulli Matrix*/ void matrix_init_random_bernoulli(Matrix *matrix, int rows, int columns, float8 p, float8 min, float8 max, int seed) { matrix_init(matrix, rows, columns); @@ -126,6 +146,11 @@ void matrix_init_random_bernoulli(Matrix *matrix, int rows, int columns, float8 } } +/*Function: matrix_ Init_ Kernel_ Polynomial +Formal parameters: (int features, int components, int degree, float8 coef0, int seed, Matrix * weights, +Matrix * coefs) +Return: int* +Initialize a polynomial matrix using a specified number*/ int *matrix_init_kernel_polynomial(int features, int components, int degree, float8 coef0, int seed, Matrix *weights, Matrix *coefs) { @@ -160,6 +185,11 @@ int *matrix_init_kernel_polynomial(int features, int components, int degree, flo return pcomponents; } +/*Function: matrix_ Transform_ Kernel_ Polynomial +Formal parameters: (const Matrix * input, int ncomponents, int * components, const Matrix * weights, +Const Matrix * coefficients, Matrix * output) +Return: None +Polynomial matrix transpose*/ void matrix_transform_kernel_polynomial(const Matrix *input, int ncomponents, int *components, const Matrix *weights, const Matrix *coefficients, Matrix *output) { @@ -185,6 +215,10 @@ void matrix_transform_kernel_polynomial(const Matrix *input, int ncomponents, in matrix_mult_scalar(output, sqrt(1.0 / output->rows)); } +/*Function: matrix_ Mult +Formal parameters: (const Matrix * matrix1, const Matrix * matrix2, Matrix * result) +Return value: None +matrix multiplication*/ void matrix_mult(const Matrix *matrix1, const Matrix *matrix2, Matrix *result) { Assert(matrix1 != nullptr); @@ -213,6 +247,10 @@ void matrix_mult(const Matrix *matrix1, const Matrix *matrix2, Matrix *result) } } +/*Function: matrix_ Print +Formal parameters: (const Matrix * matrix, StringInfo buf, bool full) +Return value: None +Print Matrix*/ void matrix_print(const Matrix *matrix, StringInfo buf, bool full) { Assert(matrix != nullptr); @@ -253,6 +291,24 @@ void matrix_print(const Matrix *matrix, StringInfo buf, bool full) appendStringInfoChar(buf, ']'); } +/*Function: elog_ Matrix +Formal parameters: (int level, const char * msg, const matrix * matrix) +Return value: None +Matrix error*/ +/*elog is an old mode that can be equivalent to the ereport mode. +You can see that it provides level and the error level is the same, +but it does not provide errcode. As mentioned earlier, the default +errcode is provided based on the severity level. Then the message +is passed through an auxiliary function errmsg_ Internal() goes to +show it, and the process is different from the errmsg in ereport mentioned +earlier. errmsg() is set according to regional settings, such as it can be +translated into the language of the corresponding country, such as Chinese. +In fact, errmsg_ Internal() is a language that is not limited by translation and +can automatically print out the original language. +Why should we keep this old pattern? Because it is concise enough, when +there are some internal errors, such as internal errors in the PG kernel, these +errors are not actually displayed to the user and are not of interest to the user. +This concise mode can be used for printing, which is very convenient and has been preserved.*/ void elog_matrix(int elevel, const char *msg, const Matrix *matrix) { if (is_errmodule_enable(elevel, MOD_DB4AI)) { -- 2.34.1 From dfc44d4a4267f0ba7761ed6b01fe0790da96d894 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Tue, 19 Sep 2023 16:15:59 +0800 Subject: [PATCH 037/118] Update distance_functions.cpp --- .../dbmind/db4ai/executor/distance_functions.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp b/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp index af759c590..bac87b97b 100644 --- a/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp @@ -37,6 +37,13 @@ IDENTIFICATION #endif +/*Euclidean distance: the distance between two points, +that is, the distance we usually calculate. +Manhattan distance: the sum of absolute +wheelbase of two points in the standard coordinate system. +Chebyshev distance: the maximum value of the +numerical difference of each coordinate.*/ + /* * L1 distance (Manhattan) * We sum using cascaded summation @@ -44,6 +51,10 @@ IDENTIFICATION * are not available or for the the case that the dimension is not a multiple * of the width of the registers */ + +/*Vectorization refers to using an array instead of a scalar +to manipulate each element in the array.*/ + static force_inline double l1_non_vectorized(double const * p, double const * q, uint32_t const dimension) { double term = 0.; -- 2.34.1 From 2a46b8bdd8713ac1d0be749627290a939b130394 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Tue, 19 Sep 2023 19:13:46 +0800 Subject: [PATCH 038/118] Update distance_functions.cpp --- .../db4ai/executor/distance_functions.cpp | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp b/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp index bac87b97b..bdc536107 100644 --- a/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp @@ -55,6 +55,10 @@ numerical difference of each coordinate.*/ /*Vectorization refers to using an array instead of a scalar to manipulate each element in the array.*/ +/*Function: l1_ Non_ Vectorized +Formal parameters: (double const * p, double const * q, uint32_t const dimension) +Return value: double +Calculate Manhattan distance without vectorization processing*/ static force_inline double l1_non_vectorized(double const * p, double const * q, uint32_t const dimension) { double term = 0.; @@ -84,6 +88,11 @@ static force_inline double l1_non_vectorized(double const * p, double const * q, * This version is vectorized using SSE or NEON and is used in case only 128-bit * vectorized instructions are available */ + +/*Function: l1_ 128 +Formal parameters: (double const * p, double const * q, uint32_t const dimension) +Return value: double +Calculate Manhattan distance without vectorization processing*/ static double l1_128(double const * p, double const * q, uint32_t const dimension) { if (unlikely(dimension == 0)) @@ -190,6 +199,11 @@ static double l1_128(double const * p, double const * q, uint32_t const dimensio * are not available or for the the case that the dimension is not a multiple * of the width of the registers */ + +/*Function: l2_ Squared_ Non_ Vectorized +Formal parameters: (double const * p, double const * q, uint32_t const dimension) +Return value: double +Calculating Euclidean Distance Without Vectorization*/ static force_inline double l2_squared_non_vectorized(double const * p, double const * q, uint32_t const dimension) { double subtraction = 0.; @@ -223,6 +237,11 @@ static force_inline double l2_squared_non_vectorized(double const * p, double co * This version is vectorized using SSE or NEON and is used in case only 128-bit * vectorized instructions are available */ + +/*Function: l2_ Squared_128 +Formal parameters: (double const * p, double const * q, uint32_t const dimension) +Return value: double +Vectorization processing for calculating Euclidean distance*/ static double l2_squared_128(double const * p, double const * q, uint32_t const dimension) { if (unlikely(dimension == 0)) @@ -318,6 +337,12 @@ static double l2_squared_128(double const * p, double const * q, uint32_t const #endif +/* +Function: linf_ Non_ Vectorized +Formal parameters: (double const * p, double const * q, uint32_t const dimension) +Return value: double +Calculating Chebyshev Distance through Non Vectorization Processing +*/ /* * L infinity distance (Chebyshev) * This version is unvectorized and is used in case vectorized instructions @@ -347,6 +372,13 @@ static force_inline double linf_non_vectorized(double const * p, double const * } #if (defined(__x86_64__) && defined(__SSE3__)) || (defined(__aarch64__) && defined(__ARM_NEON)) +/* +Function: linf_ one hundred and twenty-eight +Formal parameters: (double const * p, double const * q, uint32_t const dimension) +Return value: double +Vectorization processing for calculating Chebyshev distance +*/ + /* * L infinity distance (Chebyshev) * This version is vectorized using SSE or NEON and is used in case only 128-bit @@ -431,6 +463,11 @@ static double linf_128(double const * p, double const * q, uint32_t const dimens #endif +/*Function: l1 +Formal parameters: (double const * p, double const * q, uint32_t const dimension) +Return value: double +Automatic vectorization processing for calculating Manhattan distance*/ + /* * L1 distance (Manhattan) * This is the main function. It will be automatically vectorized @@ -457,6 +494,11 @@ double l1(double const * p, double const * q, uint32_t const dimension) * This is the main function. It will be automatically vectorized * if possible */ + +/*Function: l2_ Squared +Formal parameters: (double const * p, double const * q, uint32_t const dimension) +Return value: double +Automatic vectorization processing for calculating Euclidean distance*/ double l2_squared(double const * p, double const * q, uint32_t const dimension) { if (unlikely(dimension == 0)) @@ -478,6 +520,11 @@ double l2_squared(double const * p, double const * q, uint32_t const dimension) * This is the main function. It will be automatically vectorized * if possible */ + +/*Function: l2_ Squared +Formal parameters: (double const * p, double const * q, uint32_t const dimension) +Return value: double +Automatic vectorization processing for calculating Euclidean distance*/ double l2(double const * p, double const * q, uint32_t const dimension) { if (unlikely(dimension == 0)) @@ -499,6 +546,12 @@ double l2(double const * p, double const * q, uint32_t const dimension) * This is the main function. It will be automatically vectorized * if possible */ + +/*Function: linf +Parameter: (double const * p, double const * q, uint32 _ t const dimension) +Return value: double + +Calculation of Chebyshev distance by automatic vectorization processing*/ double linf(double const * p, double const * q, uint32_t const dimension) { if (unlikely(dimension == 0)) -- 2.34.1 From 93ace67b068a8965f30b9f71b4f6b0618464cf39 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Wed, 20 Sep 2023 11:35:26 +0800 Subject: [PATCH 039/118] Update direct.cpp --- .../dbmind/db4ai/executor/direct.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/direct.cpp b/src/gausskernel/dbmind/db4ai/executor/direct.cpp index d893a16e0..edaf254df 100644 --- a/src/gausskernel/dbmind/db4ai/executor/direct.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/direct.cpp @@ -21,6 +21,25 @@ * --------------------------------------------------------------------------------------- */ +/*In artificial intelligence, it is not so easy to accurately and easily identify and output the image/voice +we expect to output in the face of a large number of data/materials input by users. Therefore, the algorithm +is particularly important. The algorithm is what we call a model. + +Of course, in addition to the core recognition engine, the content of the algorithm also includes various +configuration parameters, such as bit rate, sampling rate, timbre, tone, pitch, audio, cadence, dialect, noise +and other messy parameters. In a mature recognition engine, the core content generally does not change +frequently. In order to achieve the goal of "successful recognition", we can only adjust the configuration +parameters. For different inputs, we will configure different parameter values, and finally take a group of +parameter values with balanced parties and high recognition rate in the result statistics. This group of +parameter values is the result we get after training. This is the training process, also called model training. + +So: +Model = algorithm +Training = the process of finding out the optimal configuration parameters by using big data to +achieve the goal of high recognition rate. +Results = Determine the parameter configuration and achieve high recognition rate. +*/ + #include "db4ai/db4ai_api.h" Model *model_fit(const char *name, AlgorithmML algorithm, const Hyperparameter *hyperparameters, int nhyperp, -- 2.34.1 From 04af05a85908d80bd6094301a19dfd4d036a0f85 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Wed, 20 Sep 2023 11:42:24 +0800 Subject: [PATCH 040/118] Update direct.cpp --- .../dbmind/db4ai/executor/direct.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/gausskernel/dbmind/db4ai/executor/direct.cpp b/src/gausskernel/dbmind/db4ai/executor/direct.cpp index edaf254df..417602135 100644 --- a/src/gausskernel/dbmind/db4ai/executor/direct.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/direct.cpp @@ -42,6 +42,12 @@ Results = Determine the parameter configuration and achieve high recognition rat #include "db4ai/db4ai_api.h" +/*Function: model_ Fit +Formal parameters: (const char * name, AlgorithmML algorithm, const Hyperparameter * hyperparameters, int nhyperp, +Oid * typid, bool * typbyval, int16 * typlen, int ncolumns, callback_ Ml_ Fetch fetch, +Callback_ Ml_ Rescan rescan, void * callback_ Data) +Return value: Model* +model training*/ Model *model_fit(const char *name, AlgorithmML algorithm, const Hyperparameter *hyperparameters, int nhyperp, Oid *typid, bool *typbyval, int16 *typlen, int ncolumns, callback_ml_fetch fetch, callback_ml_rescan rescan, void *callback_data) @@ -119,6 +125,10 @@ ModelPredictor model_prepare_predict(const Model* model) pred->predictor = pred->palgo->prepare_predict(pred->palgo, &model->data, model->return_type); return (ModelPredictor)pred; } +/*Function: model_ Predict +Formal parameters: (ModelPredictor predictor, Datum * values, bool * isnull, Oid * typid, int num_columns) +Return value: Datum +model prediction*/ Datum model_predict(ModelPredictor predictor, Datum *values, bool *isnull, Oid *typid, int num_columns) { @@ -126,11 +136,18 @@ Datum model_predict(ModelPredictor predictor, Datum *values, bool *isnull, Oid * return pred->palgo->predict(pred->palgo, pred->predictor, values, isnull, typid, num_columns); } +/*Function: model_ Store +Parameter: (const Model * model) +Return value: None +Model Storage*/ void model_store(const Model *model) { store_model(model); } - +/*Function: model_ Load +Formal parameter: (const char * modelname) +Return value: Model* +Model loading*/ const Model *model_load(const char *model_name) { return get_model(model_name, false); -- 2.34.1 From f455fe3ac14d601c2ec52a02eaf33431f3850614 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Wed, 20 Sep 2023 17:20:39 +0800 Subject: [PATCH 041/118] Update kmeans.cpp --- .../dbmind/db4ai/executor/kmeans/kmeans.cpp | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp b/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp index 0b8933966..5946c1880 100644 --- a/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp @@ -42,6 +42,12 @@ IDENTIFICATION /* * parameters that affect k-means (hyper-parameters) */ + +/*KMeans is one of the top ten algorithms in data mining. +In data mining practice, we often apply KMeans to various +scenarios, because it is simple in principle, easy to implement +and suitable for various data mining scenarios.*/ + typedef struct HyperparametersKMeans { ModelHyperparameters mhp; // place-holder SeedingFunction seeding = KMEANS_RANDOM_SEED; @@ -314,6 +320,14 @@ static bool deal_sample(bool const sample, std::mt19937_64 *prng, GSPoint *batch return false; } +/*Function: compute_cost_and_weights +Parameters: (list const * centroids, GS point const * points, uint32 _ tdimension, +uint32_t const num_slots, double *cost) +Return value: bool +Given a set of centroids (as a PG list) and a set of points, this function +calculates the cost of the centroid set and their weights +(the number of points assigned to each centroid).*/ + /* * given a set of centroids (as a PG list) and a set of points, this function computes * the cost of the set of centroids as well as their weights (number of points assigned @@ -366,6 +380,12 @@ force_inline static void release_batch(GSPoint *batch, uint32_t const num_slots) * using a sum that provides higher precision (we could provide much higher precision at the cost * of allocating yet another array to keep correction terms for every dimension */ +/*Function: aggregate_ Point +Formal parameters: (double * centroid_aggregation, double const * new_point, +Uint32_ T const dimension) +Return value: None +Given the moving average of the centroid and new points, this will add new points to the set*/ + force_inline static void aggregate_point(double *centroid_aggregation, double const *new_point, uint32_t const dimension) { @@ -380,6 +400,12 @@ force_inline static void aggregate_point(double *centroid_aggregation, double co * we assume that all slots in the batch are non-null (guaranteed by the upper call) * also, that the next set of centroids has been reset previous to the very first call */ + +/*Function: update_ Centroids +Formal parameters: (KMeansStateDescription * description, GSPoint * slots, uint32_t const num_slots, +Uint32_ T const idx_ Current_ Centroids, uint32_ T const idx_ Next_ Centroids) +Return value: None +Update centroid*/ static void update_centroids(KMeansStateDescription *description, GSPoint *slots, uint32_t const num_slots, uint32_t const idx_current_centroids, uint32_t const idx_next_centroids) { @@ -450,6 +476,13 @@ static void update_centroids(KMeansStateDescription *description, GSPoint *slots /* * updates the minimum bounding box to contain the new given point */ +/*Function: update_ Centroids +Formal parameters: (double * const bbox_min, double * const bbox_max, double const * point, +Uint32_ T const dimension) +Return value: None +Update the minimum bounding box to include the new given point*/ + + force_inline static void update_bbox(double *const bbox_min, double *const bbox_max, double const *point, uint32_t const dimension) { @@ -743,6 +776,11 @@ static List *one_data_pass(TrainModelState *pstate, KMeansStateDescription *stat /* * this sets the weights of a set of candidates to 1 (every point is the centroid of itself) */ +/*Function: reset_ Weights +Formal parameters: (List const * centroids) +Return value: None +Initialize weights (each point has a centroid of 1)*/ + void reset_weights(List const *centroids) { ListCell const *current_centroid_cell = centroids ? centroids->head : nullptr; @@ -983,6 +1021,12 @@ void reset_centroids(KMeansStateDescription *description, uint32_t const idx_cen * this produces the centroid by dividing the aggregate by the amount of points it got assigned * we assumed that population > 0 */ + +/*Function: finish_ Centroid +Formal parameters: (double * centroid_aggregation, +uint32_t const dimension, double const population) +Return value: None +Generate centroid*/ force_inline void finish_centroid(double *centroid_aggregation, uint32_t const dimension, double const population) { double local_correction = 0.; @@ -992,6 +1036,11 @@ force_inline void finish_centroid(double *centroid_aggregation, uint32_t const d } } +/*Function: merge_ Centroids +Parameter: (KMeansStateDescription * description, uint32_t const idx_current_centroids, +Uint32_ T const idx_ Next_ Centroids) +Return value: None +Merge centroids*/ void merge_centroids(KMeansStateDescription *description, uint32_t const idx_current_centroids, uint32_t const idx_next_centroids) { -- 2.34.1 From 09c55212e684cffd9a996939d926724a00f134a1 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Wed, 20 Sep 2023 18:16:23 +0800 Subject: [PATCH 042/118] Update kmeans.cpp --- .../dbmind/db4ai/executor/kmeans/kmeans.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp b/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp index 5946c1880..eaec8d697 100644 --- a/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp @@ -48,6 +48,12 @@ In data mining practice, we often apply KMeans to various scenarios, because it is simple in principle, easy to implement and suitable for various data mining scenarios.*/ +/*The basic steps are as follows: +1. Select k objects from the data as the initial clustering centers. +2. Calculate the distance from each cluster object to the cluster center. +3. Calculate each cluster center again. +4. Calculate termination conditions*/ + typedef struct HyperparametersKMeans { ModelHyperparameters mhp; // place-holder SeedingFunction seeding = KMEANS_RANDOM_SEED; @@ -231,6 +237,11 @@ static bool copy_slot_coordinates_to_array(GSPoint *coordinates, ModelTuple cons * given a set of centroids (as a PG list) and a point, this function compute the distance to the closest * centroid */ + +/*Function: closest_ Centroid +Formal parameters: (List const * centroids, GSPoint const * point, uint32_t const dimension, double * distance) +Return value: bool +Given a set of centroids (as PG list) and a point, this function calculates the distance to the nearest point*/ static bool closest_centroid(List const *centroids, GSPoint const *point, uint32_t const dimension, double *distance) { ListCell const *current_centroid_cell = centroids ? centroids->head : nullptr; @@ -1465,6 +1476,11 @@ void kmeans_create_model(KMeansState *kmeans_state, Model *model) * 2) execute a seeding method (random++ or kmeans||) (at least one data pass but not more than 10), * 3) run Lloyd's algorithm (at least one data pass) */ +/*Function: kmeans_ Run +Formal parameters: (AlgorithmAPI * self, TrainModelState * pstate, Model * * models) +Return value: None +Run kmeans until convergence.*/ + static void kmeans_run(AlgorithmAPI *self, TrainModelState *pstate, Model **models) { /* -- 2.34.1 From 7576ca6e073f742ef795663992c940bbb6f51bcb Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Wed, 20 Sep 2023 20:53:51 +0800 Subject: [PATCH 043/118] Update xgboost.cpp --- .../dbmind/db4ai/executor/xgboost/xgboost.cpp | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/xgboost/xgboost.cpp b/src/gausskernel/dbmind/db4ai/executor/xgboost/xgboost.cpp index 803a0cea4..562592d2e 100644 --- a/src/gausskernel/dbmind/db4ai/executor/xgboost/xgboost.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/xgboost/xgboost.cpp @@ -40,6 +40,20 @@ double total_exec_time = 0.0; struct timespec exec_start_time, exec_end_time; +/*XGBoost provides gradient lifting tree (also called GBDT, GBM), which +can solve many data science problems quickly and accurately. The same +code can run in major distributed environments (Apache Hadoop, Apache +Spark, Apache Flink). System optimization: parallel computing: supporting +parallel computing. Tree pruning: use greedy algorithm to choose the best +splitting point and then start pruning. Hardware optimization: effective use +of hardware resources. Algorithm addition: regularization: preventing over-fitting. +Sparse consciousness: automatically "learn" the best missing value according to +the training loss and deal with different types of sparse patterns in the data more +effectively. Weighted quantile sketch: Using the distributed weighted quantile sketch +algorithm, the optimal split point in the weighted data set can be found effectively. +Cross-validation: Each iteration has a built-in cross-validation method.*/ + + #define XGBOOST_LIB_NAME "libxgboost.so" typedef const int (*XGBoosterSetParam_Sym)(BoosterHandle handle, const char *name, const char *value); @@ -430,6 +444,10 @@ void setup_xg_chunk(xg_data_t &xg_data) /* * this function initializes the algorithm */ +/*Function: xgboost_ Create +Parameter: (AlgorithmAPI * self, const TrainModel * pnode) +Return value: TrainModelState* +Create xgboost*/ static TrainModelState *xgboost_create(AlgorithmAPI *self, const TrainModel *pnode) { if (pnode->configurations != 1) @@ -449,6 +467,11 @@ static TrainModelState *xgboost_create(AlgorithmAPI *self, const TrainModel *pno * chunk. * ---------------------------------------------------------------- */ +/*Function: trainXG +Formal parameters: (AlgorithmAPI * alg, const HyperparamsXGBoost * xg_hyp, xg_data_t * chunk, const int n_tuples, +Bool first_ Call=true) +Return value: None +Training xgboost*/ void trainXG(AlgorithmAPI *alg, const HyperparamsXGBoost *xg_hyp, xg_data_t *chunk, const int n_tuples, bool first_call = true) { @@ -714,6 +737,10 @@ ModelPredictor xgboost_predict_prepare(AlgorithmAPI *, SerializedModel const *mo return reinterpret_cast(xgboostm); } +/*Function: xgboost_ Predict +Formal parameters: (AlgorithmAPI * self, TrainModelState * pstate, Model * * models) +Return value: Datum +Using xgboost for prediction*/ Datum xgboost_predict(AlgorithmAPI *, ModelPredictor model, Datum *values, bool *isnull, Oid *types, int ncolumns) { @@ -752,6 +779,12 @@ Datum xgboost_predict(AlgorithmAPI *, ModelPredictor model, Datum *values, bool /* * used in EXPLAIN MODEL */ + +/*Function: xgboost_ Explain +Parameter: (AlgorithmAPI * self, SerializedModel const * model, Oid return_type) +Return value: List +Explain xgboost*/ + List *xgboost_explain(AlgorithmAPI *self, SerializedModel const *model, Oid return_type) { if (unlikely(!model)) -- 2.34.1 From 3a54c744591b27a4953e6aea78960f7135d1706b Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Thu, 21 Sep 2023 13:05:39 +0800 Subject: [PATCH 044/118] Update pca.cpp --- src/gausskernel/dbmind/db4ai/executor/gd/pca.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/gd/pca.cpp b/src/gausskernel/dbmind/db4ai/executor/gd/pca.cpp index 7abbe9171..6d2ba0d47 100644 --- a/src/gausskernel/dbmind/db4ai/executor/gd/pca.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/gd/pca.cpp @@ -22,6 +22,14 @@ * --------------------------------------------------------------------------------------- */ +/*Principal component analysis is a mathematical transformation method, +which transforms a given set of related variables into another set of unrelated +variables through linear transformation, and these new variables are arranged +in the order of decreasing variance. In mathematical transformation, the total +variance of variables is kept constant, so that the first variable has the largest +variance, which is called first principal component, and the second variable has +the second largest variance and is not related to the first variable, which is called +the second principal component. By analogy, I variables have I principal components.*/ #include "db4ai/gd.h" #include "db4ai/db4ai_cpu.h" #include "db4ai/fp_ops.h" -- 2.34.1 From 6b0ccf6f62e18fbbe7e54260280dea79394340ec Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Thu, 21 Sep 2023 13:06:30 +0800 Subject: [PATCH 045/118] Update svm.cpp --- src/gausskernel/dbmind/db4ai/executor/gd/svm.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/gd/svm.cpp b/src/gausskernel/dbmind/db4ai/executor/gd/svm.cpp index cbf7014be..c748c9af7 100644 --- a/src/gausskernel/dbmind/db4ai/executor/gd/svm.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/gd/svm.cpp @@ -23,6 +23,10 @@ #include "db4ai/gd.h" #include "db4ai/kernel.h" +/*Support vector machine (SVM), because of its English name, is generally referred to as SVM. Generally speaking, +it is a two-class classification model. Its basic model is defined as a linear classifier with the largest interval in the +feature space, and its learning strategy is to maximize the interval, which can eventually be transformed into the +solution of a convex quadratic programming problem.*/ static void svmc_gradients(GradientsConfig *cfg) { -- 2.34.1 From 5a196e809687c1643049aab7b575e6fc6a91a7f1 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Thu, 21 Sep 2023 13:07:13 +0800 Subject: [PATCH 046/118] Update gd.cpp --- src/gausskernel/dbmind/db4ai/executor/gd/gd.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/gd/gd.cpp b/src/gausskernel/dbmind/db4ai/executor/gd/gd.cpp index 293221fa7..1920be902 100644 --- a/src/gausskernel/dbmind/db4ai/executor/gd/gd.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/gd/gd.cpp @@ -22,6 +22,12 @@ * --------------------------------------------------------------------------------------- */ +/*Gradient Descent is a commonly used optimization algorithm, which is used to solve +the minimum value of the objective function. It is an iterative algorithm. In each iteration, +the gradient (or approximate gradient) of the objective function is calculated, and then the +parameters are updated along the negative gradient direction until the minimum value that +meets the conditions is reached.*/ + #include "postgres.h" #include "executor/executor.h" #include "utils/builtins.h" -- 2.34.1 From 5bc56fc02fee5b638e26444afa2ceb02e1dbf2ea Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Thu, 21 Sep 2023 13:07:57 +0800 Subject: [PATCH 047/118] Update linregr.cpp --- src/gausskernel/dbmind/db4ai/executor/gd/linregr.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/gd/linregr.cpp b/src/gausskernel/dbmind/db4ai/executor/gd/linregr.cpp index 96e9f1ed3..c208bab2a 100644 --- a/src/gausskernel/dbmind/db4ai/executor/gd/linregr.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/gd/linregr.cpp @@ -21,6 +21,15 @@ * --------------------------------------------------------------------------------------- */ +/*Linear regression is a regression analysis that uses the least square function called linear +regression equation to model the relationship between one or more independent variables and dependent +variables. Its expression form is y = w'x+e, where e is the normal distribution with the average value of 0. +In regression analysis, only one independent variable and one dependent variable are included, and the +relationship between them can be approximately expressed by a straight line. This regression analysis is +called unary linear regression analysis. If regression analysis includes two or more independent variables, +and there is a linear relationship between dependent variables and independent variables, it is called +multivariate linear regression analysis.*/ + #include "db4ai/gd.h" static void linear_reg_gradients(GradientsConfig *cfg) -- 2.34.1 From 23f16eba7c5a315e5e77cf1f8710ffaa7a19c119 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Thu, 21 Sep 2023 13:08:32 +0800 Subject: [PATCH 048/118] Update logregr.cpp --- src/gausskernel/dbmind/db4ai/executor/gd/logregr.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/gd/logregr.cpp b/src/gausskernel/dbmind/db4ai/executor/gd/logregr.cpp index e27db493f..908e15273 100644 --- a/src/gausskernel/dbmind/db4ai/executor/gd/logregr.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/gd/logregr.cpp @@ -21,6 +21,10 @@ * --------------------------------------------------------------------------------------- */ +/*Logistic regression, also known as logistic regression analysis, is mainly used in epidemiology. +The common situation is to explore the risk factors of a disease and predict the probability +of a disease according to the risk factors.*/ + #include "db4ai/gd.h" static void logreg_gradients(GradientsConfig *cfg) -- 2.34.1 From e807068a8f42fd0cf75a82fcd0d3b5461f3728db Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Fri, 22 Sep 2023 18:36:26 +0800 Subject: [PATCH 049/118] Update blockchain.cpp --- .../security/gs_ledger/blockchain.cpp | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/gausskernel/security/gs_ledger/blockchain.cpp b/src/gausskernel/security/gs_ledger/blockchain.cpp index 23c0d946f..98310ffa7 100644 --- a/src/gausskernel/security/gs_ledger/blockchain.cpp +++ b/src/gausskernel/security/gs_ledger/blockchain.cpp @@ -30,6 +30,32 @@ #include "libpq/md5.h" #include "gs_ledger/blockchain.h" #include "utils/snapmgr.h" +/*Blockchain was first used in the Bitcoin project to provide a distributed accounting +platform for the operation of Bitcoin. With the development of blockchain technology, +the definition of blockchain is that a blockchain is a distributed database, which maintains +a continuously growing data record chain and can prevent data from being tampered with. +It consists of data structure blocks, which hold proprietary data in the initial blockchain +implementation, and the data and programs are saved in some recent implementations, +and each block holds some personal transaction data and block execution results. Each +block contains a timestamp and information of the previous block. Blockchain is a +decentralized recording technology. In other words, any node participating in the system +may not belong to the same organization and need not trust each other; Blockchain +data is maintained by all node functions, and each participating node can copy and +obtain a complete copy of the record. + +The basic concepts of blockchain are: +Transaction: that is, an operation that changes the account book status once, such as adding a record. + +Block: It records the transactions and status results in a period of time, +which is a consensus on the current account book status. + +Chain: It is composed of blocks connected in series according to +the sequence of occurrence, and it is a log record of the whole state change. + +If the blockchain is regarded as a state machine, each transaction is an attempt to change the state, +and the block generated by each consensus is the result that +the parameter confirms the state change caused by all the transactions in the block. +*/ /* * gen_global_hash -- generate globalhash of gchain @@ -41,6 +67,11 @@ * * Note: globalhash is generated by operate info and previous globalhash using md5. */ + +/*Function name: gen_ Global_ Hash +Formal parameters: (hash32_t * hash_buffer, const char * info_string, bool exist, const hash32_t * prev_hash) +Return value: bool +Generate global hash for gchain*/ bool gen_global_hash(hash32_t *hash_buffer, const char *info_string, bool exist, const hash32_t *prev_hash) { errno_t rc = EOK; @@ -87,6 +118,11 @@ bool gen_global_hash(hash32_t *hash_buffer, const char *info_string, bool exist, * cmd_text: the command query which modified user table. * rel_hash: rel_hash of current block. */ +/*Function name: set_ Gchain_ Comb_ String +Formal parameters (const char * dbname, const char * username, +Const char * nsp_ Name, const char * rel_ Name, const char * cmd_ Text, uint64 rel_ Hash) +Return value: char* +Set combo block information*/ char *set_gchain_comb_string(const char *db_name, const char *user_name, const char *nsp_name, const char *rel_name, const char *cmd_text, uint64 rel_hash) { @@ -113,6 +149,10 @@ char *set_gchain_comb_string(const char *db_name, const char *user_name, * into gchain cache for next block. Thus, previous global hash is * come from cache directly. */ +/*Function name: ledger_ Gchain_ Append +Formal parameters: (Oid relid, const char * query_string, uint64 cn_hash) +Return value: void +Record the block to gchain.*/ void ledger_gchain_append(Oid relid, const char *query_string, uint64 cn_hash) { Datum current_time; @@ -173,6 +213,10 @@ void ledger_gchain_append(Oid relid, const char *query_string, uint64 cn_hash) * operation: command operation. * hash: the hash that prepare to append. */ +/*Function name: ledger_ Output_ Append_ Hash +Formal parameters: (char * resp_tag, CmdType operation, uint64 hash) +Return value: void +Append relhash to the response tag.*/ static void ledger_output_append_hash(char *resp_tag, CmdType operation, uint64 hash) { Assert(resp_tag != NULL); @@ -202,6 +246,10 @@ static void ledger_output_append_hash(char *resp_tag, CmdType operation, uint64 * use es_modifiedRowHash to receive all DN relhash and accumulate them * as cn_relhash for insertion. */ +/*Function name: ledger_ ExecutorEnd +Formal parameter: (QueryDesc * query_desc) +Return value: void +Record the end block to gchain.*/ static void ledger_ExecutorEnd(QueryDesc *query_desc) { uint64 hashsum; @@ -302,6 +350,10 @@ void opfusion_ledger_ExecutorEnd(FusionType fusiontype, Oid relid, const char *q /* * ledger_hook_init -- install of gchain block record hook. */ +/*Function name: ledger_ Hook_ Init +Formal parameter: void +Return value: void +The gchain block records the installation of hooks.*/ void ledger_hook_init(void) { t_thrd.security_ledger_cxt.prev_ExecutorEnd = (void *)ExecutorEnd_hook; @@ -311,6 +363,10 @@ void ledger_hook_init(void) /* * ledger_hook_fini -- uninstall of gchain block record hook. */ +/*Function name: ledger_ Hook_ Init +Formal parameter: void +Return value: void +The gchain block records the installation of hooks.*/ void ledger_hook_fini(void) { ExecutorEnd_hook = (ExecutorEnd_hook_type)t_thrd.security_ledger_cxt.prev_ExecutorEnd; -- 2.34.1 From 5d826c856b93e93c06d9c8e2c66bebbcf340874f Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Fri, 22 Sep 2023 21:43:20 +0800 Subject: [PATCH 050/118] Update iprange.cpp --- src/gausskernel/security/iprange/iprange.cpp | 46 ++++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/gausskernel/security/iprange/iprange.cpp b/src/gausskernel/security/iprange/iprange.cpp index ca7b66ef9..c40d1e376 100644 --- a/src/gausskernel/security/iprange/iprange.cpp +++ b/src/gausskernel/security/iprange/iprange.cpp @@ -22,6 +22,11 @@ * * --------------------------------------------------------------------------------------- */ +/*IP address, called Internet protocol address, is a way to address a host on the Internet. +It is a unified address format provided by IP protocol. Common IP addresses can be divided +into IPv4 and IPv6. It assigns a logical address to every network and every host on the Internet +to shield the difference of physical addresses.*/ + #include #include #include @@ -134,6 +139,11 @@ void IPRange::net_ipv6_to_host_order(IPV6 *ip, const struct sockaddr_in6 *sa) co ip->ip_32.d = ntohl(tmp_ip.ip_32.a); } +/*Function name: net_ Ipv4_ To_ Host_ Order +Formal parameters: (IPV6 * ip, const construct in_addr * addr) +Return value: None +Convert IPv4 addresses to host addresses*/ + void IPRange::net_ipv4_to_host_order(IPV6 *ip, const struct in_addr *addr) const { ip->ip_32.a = ntohl(addr->s_addr); @@ -141,6 +151,10 @@ void IPRange::net_ipv4_to_host_order(IPV6 *ip, const struct in_addr *addr) const ip->ip_32.c = ip->ip_32.d = 0; } +/*Function name: str_ To_ IP +Formal parameters: (const char * ip_str, IPV6 * ip) +Return value: bool +Convert string to IP address*/ bool IPRange::str_to_ip(const char* ip_str, IPV6 *ip) { struct in_addr addr; @@ -160,7 +174,10 @@ bool IPRange::str_to_ip(const char* ip_str, IPV6 *ip) } return true; } - +/*Function name: mask_ Range +Formal parameter: (Range * range, unsigned short cidr) +Return value: bool +Calculate Mask*/ bool IPRange::mask_range(Range *range, unsigned short cidr) { if (IPRANGE_IS_IPV4(range->from)) { /* ipv4 */ @@ -211,6 +228,10 @@ bool IPRange::mask_range(Range *range, unsigned short cidr) * parse the ip with mask into range sturst , format is as below: * x.x.x.x|x, ptr is the postion of "|" */ +/*Function name: parse_ Mask +Formal parameters: (const char * range, size_t range_len, const char * ptr, Range * new_range) +Return value: bool +Resolve mask.*/ bool IPRange::parse_mask(const char* range, size_t range_len, const char *ptr, Range *new_range) { if (range_len > 100) { @@ -250,6 +271,10 @@ bool IPRange::parse_mask(const char* range, size_t range_len, const char *ptr, R return true; } +/*Function name: parse_ Single +Formal parameters: (const char * range, size_t range_len, Range * new_range) +Return value: bool +Resolve a single IP.*/ bool IPRange::parse_single(const char* range, size_t range_len, Range *new_range) { if (range_len > 100) { @@ -479,14 +504,20 @@ bool IPRange::add_range(Range *new_range) m_ranges.swap(new_ranges); return true; } - +/*Function name: is_ Range_ Valid +Formal parameter: (const std:: string range) +Return value: bool +Determine if the IP type is empty*/ bool IPRange::is_range_valid(const std::string range) { IPRange tmp; Range new_range; return tmp.parse_range(range.c_str(), range.size(), &new_range); } - +/*Function name: add_ Range +Formal parameter: (Range * new_range) +Return value: void +Increase range IP*/ bool IPRange::add_range(const char* range, size_t range_len) { Range new_range; @@ -496,7 +527,10 @@ bool IPRange::add_range(const char* range, size_t range_len) } return add_range(&new_range); } - +/*Function name: remove_ Range +Formal parameters: (const char * range, size_t range_len) +Return value: bool +Delete Scope IP*/ bool IPRange::remove_range(const char *range, size_t range_len) { Ranges_t new_ranges; @@ -530,6 +564,10 @@ std::string IPRange::ip_to_str(const IPV6 *ip) const return std::string(ip_str); } +/*Function name: binary_ Search +Formal parameter: (const IPV6 ip) +Return value: bool +Binary search IP*/ bool IPRange::binary_search(const IPV6 ip) const { /* do a binary search */ -- 2.34.1 From 19ece33f534f6662f32a7323955d6b3a5aa549f3 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Mon, 25 Sep 2023 19:48:24 +0800 Subject: [PATCH 051/118] Update db4ai_common.cpp --- .../runtime/executor/db4ai_common.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/gausskernel/runtime/executor/db4ai_common.cpp b/src/gausskernel/runtime/executor/db4ai_common.cpp index 4b1baca96..f4d679fbe 100644 --- a/src/gausskernel/runtime/executor/db4ai_common.cpp +++ b/src/gausskernel/runtime/executor/db4ai_common.cpp @@ -21,6 +21,22 @@ * * --------------------------------------------------------------------------------------- */ +/*This code is a part of a C language function library, including +some functions for dealing with time and data type conversion. +The time_diff function is used to calculate the difference between +the times represented by two timespec structures. +The interval_to_sec and interval_to_msec functions convert a +numerical value representing a time interval into seconds and milliseconds. +The float8_get_Datum function converts a value of float8 type into +a corresponding datum value according to the input data type. +The Datum_get_float8 function converts a datum value into a +corresponding float8 value according to the input data type. +The Datum_get_int function converts a datum value into a +corresponding value of type int32 according to the input data type. +The string_to_Datum function converts a string into a datum value of the specified data type. +The check_hyper_bounds function is used to check the boundary condition of the superparameter. +These functions can be used in data type conversion, +time difference calculation and boundary check of superparameters in database systems.*/ #include "db4ai/db4ai_common.h" -- 2.34.1 From b074601139785a2c943c762a601b6961513f849e Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Mon, 25 Sep 2023 20:15:26 +0800 Subject: [PATCH 052/118] Update execAmi.cpp --- src/gausskernel/runtime/executor/execAmi.cpp | 79 ++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/gausskernel/runtime/executor/execAmi.cpp b/src/gausskernel/runtime/executor/execAmi.cpp index 9d4f45526..1016648af 100755 --- a/src/gausskernel/runtime/executor/execAmi.cpp +++ b/src/gausskernel/runtime/executor/execAmi.cpp @@ -73,6 +73,39 @@ static bool index_supports_backward_scan(Oid indexid); * Note that if the plan node has parameters that have changed value, * the output might be different from last time. */ +/*The ExecReScanByType' function performs +different rescan operations according to the type of plan node, such as: +-For the ResultState, perform the result rescan operation. +-For the modified table node (ModifyTableState) and the distributed +DistInsertSelectState, perform the modified table rescan operation. +-For the merge AppendState, perform the merge append rescan operation. +-For a RecursiveUnionState, perform a recursive union rescan operation. +-For the node with the initial operation, perform the rescan operation with the initial operation. +-For BitmapAndState and BitmapOrState, perform bitoperation rescan operation. +-For a sequential scan node (SeqScanState), perform a sequential scan rescan operation. +-For index scan node (IndexScanState), index scan only node (indexscan state), bit index scan node +(BitmapIndexScanState) and bit heap scan node (BitmapHeapScanState), perform corresponding scan rescan operations. +-For tid scan nodes, SubqueryScanState, FunctionScanState, ValuesScanState, CteScanState, Worksheet +scanning node (workbench scanning state), external scanning node (foreign scanning state), extensible +planning node (extensible planning state), etc., and perform corresponding rescan operations according to specific node types. +-Rescan the partition PartIteratorState. +-In PGXC environment, rescan the remote query for the RemoteQueryState. +-Rescan the nested loop connection node. +-Rescan the MergeJoinState. +-rescan the hash connection node (HashJoinState). +-Rescan the materialized state. +-Rescan the SortState. +-Rescan the grouped nodes. +-rescan the aggregation node (AggState) and the window aggregation node (WindowAggState). +-rescan the UniqueState. +-rescan the HashState. +-Rescan the set operation node (SetOpState). +-Rescan the lock result of the lock node that locks the row node. +-Rescan the restriction result of the restriction node. +Rescan the vectorization conversion result of the vectorization conversion node. + +The implementation of these rescan operations varies according to the type of specific planning nodes, +and they will re-read the data and generate new output results for use in the next execution.*/ void ExecReScanByType(PlanState* node) { /* If collecting timing stats, update them */ @@ -260,6 +293,18 @@ void ExecReScanByType(PlanState* node) } } +/*This code is the source code of an executor access method, which is used to perform rescan operation in the executor. + +Rescan refers to rescan the executed plan node in order to regenerate the output results. In the executor, +the plan node refers to each step in the query plan, such as scanning tables, filtering data and aggregating data. +The function ExecReScan in the code is the main function to +perform rescan in the actuator. It takes a plan node as a parameter and does the following: + +1. If performance statistics are being collected, update the statistics. +2. If the parameters of the plan node change, update the parameter information. +3. Close any SRF(Server-Side Function) in the plan node. +4. Stop rescanning if Stub execution is needed. +5. Call the ExecReScanByType' function to perform the corresponding rescan operation according to the type of the plan node.*/ /* * ExecReScan * Reset a plan node so that its output can be re-scanned. @@ -343,6 +388,40 @@ void ExecReScan(PlanState* node) node->chgParam = NULL; } } +/*This code defines the functions and auxiliary functions related to the execution plan. + +The function ExecMarkPos' is used to save the scanning position and mark the status of the execution +plan as saved. According to the passed-in PlanState object, the function will call the corresponding +function to save the scanning position according to its type. + +The function ExecRestrPos' is used to restore the +scanning position and perform the corresponding +restoration operation. According to the passed-in PlanState object, this function will call the +corresponding function to restore the scanning position according to its type. + +The function ExecSupportsMarkRestore' is used +to check whether the execution plan supports marking +and recovery operations. According to the passed-in Path object, +the function will return the corresponding result according to its type. + +The function ExecSupportsBackwardScan is used to check +whether the execution plan supports reverse scanning. +According to the passed-in Plan object, the function will return +the corresponding result according to its type. + +The function `target _ list _ supports _ backward _ scan` is used to check whether +the target list supports reverse scanning. +It determines whether to support reverse scanning by checking +whether each expression in the target list returns a collection type. + +The function `index _ supports _ backward _ scan` is used to check +whether the index supports reverse scanning. +It determines whether to support reverse scanning by checking +whether the access method of the index supports reverse scanning. + +The function ExecMaterializesOutput' is used to check whether the execution plan automatically +materialization the output. Depending on the type of execution +plan passed in, this function will return the corresponding results.*/ /* * ExecMarkPos -- 2.34.1 From 7758348b68b7bfb87867f489a1a446f384a260e8 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Tue, 26 Sep 2023 14:08:17 +0800 Subject: [PATCH 053/118] Update execClusterResize.cpp --- .../runtime/executor/execClusterResize.cpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/gausskernel/runtime/executor/execClusterResize.cpp b/src/gausskernel/runtime/executor/execClusterResize.cpp index 4eb0444a5..131453e0b 100644 --- a/src/gausskernel/runtime/executor/execClusterResize.cpp +++ b/src/gausskernel/runtime/executor/execClusterResize.cpp @@ -69,6 +69,31 @@ static inline bool redis_offset_retrive_function(const char* funcname, Oid retty ((nargs) == 4 && (rettype) == TIDOID && (argstype)[0] == TEXTOID && (argstype)[1] == NAMEOID && \ (argstype)[2] == INT4OID && (argstype)[3] == INT4OID)) +/*The function of this code is to implement some functions related to Redis. Specifically includes the following aspects: +1. Some macros are defined to specify some constants. +2. Some inline functions are declared to judge whether a function is a corresponding Redis function. +3. Some functions are implemented, including recording deleted tuples, judging whether the relationship is in cluster +redistribution, checking whether the table is a deletion operation table, and judging whether the process is in the process of cluster redistribution. +The function RecordDeletedTuple is used to record the tupleid of a given tuple into the `pg _ delete _ delta` table. As follows: + +-parameters: +-`Relid`: OID of the target relationship of the update/delete operation. +-`bucket id`: ID of the bucket where the target tuple is located. +-`tupleid': the tupleid to be recorded. +-`deldelta_rel: the corresponding `pg _ delete _ delta` relationship. + +The function RelationInClusterResizing' is used to determine whether the relationship is in the operation of cluster resizing. + +The function `relationinclusteresinggreadonly` is used to determine whether the relationship is in a read-only cluster resizing operation. + +The function `relationinclusteresizingendachup' is used to determine whether the relationship is in an operation (write error) before the end of cluster resizing. + +The function CheckRangeVarInRedistribution' is used to check whether the relationship is in redistribution through the relationship variable. + +The function RelationIsDeleteDeltaTable is used to determine whether the given table name is a delete_delta table. + +The function `clusterSizingProgress' is used to determine whether the cluster resizing process is in progress.*/ + static inline bool redis_tupleid_retrive_function(const char* funcname, Oid rettype, const Oid* argstype, int nargs) { -- 2.34.1 From 1a882a9ee6f0c745107ec9eb3cee46aba4cc6cdf Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Tue, 26 Sep 2023 14:28:35 +0800 Subject: [PATCH 054/118] Update execCurrent.cpp --- .../runtime/executor/execCurrent.cpp | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/src/gausskernel/runtime/executor/execCurrent.cpp b/src/gausskernel/runtime/executor/execCurrent.cpp index 9e49bdc14..2e3770e07 100644 --- a/src/gausskernel/runtime/executor/execCurrent.cpp +++ b/src/gausskernel/runtime/executor/execCurrent.cpp @@ -47,6 +47,63 @@ static ScanState* search_plan_tree(PlanState *node, Oid table_oid); * legal situation in inheritance cases). Raises error if cursor is not a * valid updatable scan of the specified table. */ +/*The segment code defines a function named execCurrentOf, which is used to execute the CURRENT OF expression in SQL query. +The CURRENT OF expression is a part of SQL/PSM (Persistent Storage Module), +which is used to implement sensitive operations on a cursor. +The function execCurrentOf receives five parameters: + +1. cexpr: a pointer to the CurrentOfExpr structure, which contains the information of the CURRENT OF expression. +2. econtext: a pointer to ExprContext structure, which contains the context information of expression execution. +3. Relationship: A pointer to the relationship structure, which represents a relationship (i.e. a table) in the database. +4. current_tid: a pointer to the ItemPointer structure, which represents the current transaction ID. +5. partitionOfCursor_tid: A pointer to the RelationPtr structure, which represents the partition of the cursor. + +The function first obtains the name of the cursor according to cexpr, and +then finds the corresponding Portal according to the name. +If a valid Portal cannot be found, an error is reported. Then, the function checks +the query description (query_desc) corresponding to the Portal. +An error is also reported if the query description does not exist +or the status of the query description is invalid. + +Then, the function decides which strategy to execute according to the row marks in the query description. +If there is a line mark, use FOR UPDATE/SHARE; Otherwise, use a FOR-UPDATE method. + +It defines a variable named `erm` with an initial value of NULL. Then it traverses ` query _ desc-> estate-> es _ row marks`, +which is a list of all the rowmarks in the cursor query. During traversal, it +checks whether each row tag needs a row share lock, and if not, it ignores the row tag. + +For the row tag that needs a row sharing lock, the code checks whether the table associated with the row tag is +the target table (that is, the OID returned by the RelationGetRelid' of `thiserm-> relation' is equal to table_oid'). +If it is, and there is already a row tag associated with the target table, it will report an error because +the cursor cannot have more than one FOR UPDATE/SHARE reference to the same table. + +After the traversal is completed, if the row tag associated with the target table is not found, it will report an error, +because the cursor must have a FOR UPDATE/SHARE reference to the target table. + +Next, the code checks whether the cursor currently has a result row. +If not, it will report an error, because in the SQL specification, this is wrong. + +Finally, if there is a valid TID (transaction ID) of the current scan, it will set' current_tid' and check whether +the relationship is partitioned. If the relationship is partitioned, it will set `partition of cursor _ tid' to NULL. +Then return true, indicating that the related TID has been found. If a valid TID is not found, it will return false, +indicating that this table has not generated the current row of the cursor, and other inherited +sub-tables may have generated the current row of the cursor. + +Some variables are defined, including a pointer named scanstate', a boolean variable` lisnull', +an Oid variable` tuple_tableoid' and an ItemPointer variable` tuple_tid'. + +Then, it searches the search_plan_tree by calling the `search _ plan _ tree` function to find the scan node +associated with the given table OID. If the scan node is not found, +or the scan node is overwritten by the aggregation operation, it will report an error. + +Next, the code checks whether the cursor currently has a result row. If not, +it will report an error, because in the SQL specification, this is wrong. + +Then, if the current scan tuple in the scan state is NULL, it will return false. + +Finally, the code uses the slot_getattr function to get the table OID and transaction ID of +the tuple and check whether they are valid. If the relationship is partitioned, it will also check +whether the table OID is the same as the parent table OID of the partition.*/ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relation, ItemPointer current_tid, RelationPtr partitionOfCursor_tid) { @@ -208,6 +265,22 @@ bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Relation relatio * * Fetch the string value of a param, verifying it is of type REFCURSOR. */ +/*This code defines a function `fetch _ cursor _ param _ value`, which is used to get the specified +parameter value, especially when the parameter is of the reference cursor type. + +The input parameters of the function include a pointer to an ExprContext structure and an integer paramId. +The ExprContext' structure contains the execution context of the expression, which may contain +some parameter information. ParamId' is the ID of the parameter to get. + +The function first checks whether there is parameter information and whether the parameter ID is within the valid range. +Then, it locates the specific parameter and checks its type. If the parameter type is dynamic (that is, its type identifier is invalid) +and there is a parameter obtaining function, it will call this function to obtain the value of the parameter. + +If the parameter type is valid and not null, the function will check further. If the parameter type is not a reference refcursor, +it will report an error because the function only deals with this type. If the parameter type is a reference cursor, +the function will convert its value to a C string and return this string. + +If the value of the parameter is not found during the execution of the function, it will report an error and return NULL.*/ static char *fetch_cursor_param_value(ExprContext *econtext, int paramId) { ParamListInfo paramInfo = econtext->ecxt_param_list_info; @@ -243,6 +316,40 @@ static char *fetch_cursor_param_value(ExprContext *econtext, int paramId) * Search through a PlanState tree for a scan node on the specified table. * Return NULL if not found or multiple candidates. */ +/*t searches the PlanState tree for scan nodes on the specified table. +In PostgreSQL, the PlanState tree is a data structure representing the query execution plan. +The function `search _ plan _ tree` receives two parameters: a pointer` node of PlanState and +a ` table _ Oid` of oid type. The function starts searching from the given node +and finds the scanning node that matches the OID of the specified table. +In the code, use the switch statement to judge the type of the node. For each scan node type that can be processed +(for example, sequential scan, index scan, index only scan, bitmap heap scan and TID scan), the code checks whether the ID +of the current relationship (that is, the scanned table) matches the given table OID. +If there is a match, the function returns a pointer to the scan node. + +For the `t _ remotequerystate` node, the code will return the scanning status of the node. +For the `t _ extensibleplanstate' node, the code will check whether the ID of the current relationship matches +the given table OID, and return the scanning status at the time of matching. + +For the `t _ appendstate` node, the code will iterate through all the attached plans and recursively call the `search _ plan _ tree` function. +If multiple matching scan nodes are found in the attached schedule, the function will return NULL. + +-`T_AppendState' and `t _ mergeappendState': Both node types represent a method of combining multiple subquery results into one result. +The code will traverse each subquery and recursively call the `search _ plan _ tree` function for each subquery. +If a matching scanning node is found, and no matching node has been found before, the matching node is assigned to result. +If multiple matching nodes are found, the function will return NULL. +-`t _ resultstate`, `t _ limitstate`, `t _ partiteratorstate`, and `t _ materialstate` (only exists in PGXC): These node types can be +traversed directly because they always return the current line of their input. +-`T_SubqueryScanState: This node type represents the scanning of the subquery, +and the code will return the scanning node in the subquery. +-Default: If the node is not of any of the above types, +the code will assume that it cannot traverse through the node, so it will return NULL. + +The main purpose of this function is to find the scanning node corresponding to a specific table in the query execution plan. +This is very useful for understanding and tracking query execution, especially +when it is necessary to understand and debug query performance problems. + +Generally speaking, this function is used to find the scan node corresponding to the specified table in the query execution plan.*/ + #ifdef PGXC ScanState* search_plan_tree(PlanState* node, Oid table_oid) #else -- 2.34.1 From 76815dc009ac2e848d3ecdce07dcfdaa3490ed3c Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Tue, 26 Sep 2023 14:48:12 +0800 Subject: [PATCH 055/118] Update execGrouping.cpp --- .../runtime/executor/execGrouping.cpp | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/src/gausskernel/runtime/executor/execGrouping.cpp b/src/gausskernel/runtime/executor/execGrouping.cpp index 505986cfe..9dbd0d050 100644 --- a/src/gausskernel/runtime/executor/execGrouping.cpp +++ b/src/gausskernel/runtime/executor/execGrouping.cpp @@ -48,6 +48,25 @@ static int TupleHashTableMatch(const void* key1, const void* key2, Size keysize) * * NB: evalContext is reset each time! */ +/*The main purpose of this code is to compare whether two Tuple are equal. +In database, tuple is a basic data structure, which is used to store a series of related values. +The function execTuplesMatch receives two TupleTableSlot pointers (slot1 and slot2), +which point to the tuple to be compared, as well as the number of columns (numCols), +the matching column index (matchColIdx), the equation functions (eqfunctions) and an evalContext. + +It first switches to a temporary memory context (evalContext), and then loops through each column, +starting with the last column (the least important sort key). This is because the last column +is most likely to be different when processing sorted input. + +For each column, it gets the property values in two tuples and checks whether they are empty. +If one is empty and the other is not, they are not equal, and the function sets the result to false +and jumps out of the loop. If both of them are empty, they are regarded as equal and continue the next cycle. + +If both attributes are not empty, then a specific type of equality function will be used to compare whether +they are equal. If not, the function sets the result to false and jumps out of the loop. + +Finally, the function switches back to the old memory context and returns the result. If all columns match, +the function will return true, otherwise it will return false.*/ bool execTuplesMatch(TupleTableSlot* slot1, TupleTableSlot* slot2, int numCols, AttrNumber* matchColIdx, FmgrInfo* eqfunctions, MemoryContext evalContext) { @@ -166,6 +185,26 @@ bool execTuplesUnequal(TupleTableSlot* slot1, TupleTableSlot* slot2, int numCols * * The result is a palloc'd array. */ +/*The main purpose of this code is to generate an array of function information for +each pair of equality operators for subsequent tuple comparison. + +The function execTuplesMatchPrepare takes the number of columns (numCols) and +the array of equality eqOperators (`eq operators`) as parameters. + +First, it uses `p palloc to allocate memory for the function information array, +and the length of the array is the number of columns. + +Then, it enters a loop, and each iteration in the loop corresponds to a column. +For each column, it gets the equality operator (` eq _ opr`) and the corresponding +function (` eq _ function`). This is done by calling the get_opcode function. + +Next, it uses the fmgr_info function to fill the corresponding position +of the function information array. + +Finally, the function returns the generated function information array. + +This function is usually called before performing tuple matching to +prepare the required function information.*/ FmgrInfo* execTuplesMatchPrepare(int numCols, Oid* eqOperators) { FmgrInfo* eqFunctions = (FmgrInfo*)palloc(numCols * sizeof(FmgrInfo)); @@ -192,6 +231,26 @@ FmgrInfo* execTuplesMatchPrepare(int numCols, Oid* eqOperators) * * Note: we expect that the given operators are not cross-type comparisons. */ +/*The purpose of this code is to prepare equality function and hash function for tuple hash table. + +The' executtupleshahprep' function receives four parameters: number of columns ('numCols'), +equality operator array ('eqOperators'), equality function array ('eqFunctions') and hash function array ('hashFunctions'). + +First, the function allocates memory for the array of equality functions and hash functions. + +Then, it enters a loop, and each iteration in the loop corresponds to a column. For each column, +it gets the equality operator (` eq _ opr`) and the corresponding function (` eq _ function`). This is done by calling the get_opcode function. + +Next, it tries to get the hash function of the equality operator. If the hash function cannot be found, +it will report an error and call the `ereport' function, which will send the error information to the error handling system of PostgreSQL. + +Then, it asserts that the left and right hash functions are the same, which +means that it does not support cross-type cases. + +Finally, it uses the fmgr_info function to fill the corresponding positions +of the array of equality functions and hash functions. + +This function is usually called before performing tuple hashing to prepare the required function information.*/ void execTuplesHashPrepare(int numCols, Oid* eqOperators, FmgrInfo** eqFunctions, FmgrInfo** hashFunctions) { int i; @@ -248,6 +307,29 @@ void execTuplesHashPrepare(int numCols, Oid* eqOperators, FmgrInfo** eqFunctions * Note that keyColIdx, eqfunctions, and hashfunctions must be allocated in * storage that will live as long as the hashtable does. */ +/*The main purpose of this code is to create a TupleHashTable, which is a data structure for storing tuples, +which is the basic data structure for storing a series of related values in the database. + +The function' BuildTupleHashTable' receives a series of parameters, including the number of columns ('numCols'), +key column index ('keyColIdx'), equation function ('eqfunctions'), hash function ('hashfunctions'), number of buckets ('nbuckets'), entrysize ('entrysize'). + +First, the function checks whether the number of buckets and the entry size are valid. Then, +it limits the request for the initial table size according to the working memory. + +Then, it allocates memory in the table context to store TupleHashTableData. + +Then, it sets various fields, including column number, key column index, hash function, +equality function, table context, temporary context, entry size, etc. + +Then, it clears the memory of the hash_ctl structure and sets its various fields, including key size, +entry size, hash function, matching function and hash context. + +Finally, it creates a hashtable using the hash_create function and stores it in the hashtab' field of `hashtable'. + +Function returns the created ` hashtable'. + +This function is usually called when creating a tuple hash when executing a database query, +and is used to prepare the required data structure.*/ TupleHashTable BuildTupleHashTable(int numCols, AttrNumber* keyColIdx, FmgrInfo* eqfunctions, FmgrInfo* hashfunctions, long nbuckets, Size entrysize, MemoryContext tablecxt, MemoryContext tempcxt, int workMem) { @@ -309,6 +391,21 @@ TupleHashTable BuildTupleHashTable(int numCols, AttrNumber* keyColIdx, FmgrInfo* * hash table if it is new * */ +/*The main purpose of this code is to find the TupleTableSlot in the TupleHashTable and insert it as needed. +TupleHashTable is a data structure used to store tuples, which are the basic data structures used to store a series of related values in the database. + +The function LookupTupleHashEntry receives four parameters: a TupleHashTable(`hashtable), a TupleTableSlot pointer (`slot`), +a Boolean pointer (isnew) and a Boolean value (isinserthashtbl). + +The function first checks whether it is the first time to pass, and if it is, it will clone +the input time slot to make the table time slot. + +Then, the function switches to the temporary context, sets the hash and the data needed +by the matching function, and saves the current tuple hash table. + +Next, it searches the hash table. If' isinserthashtbl' is true, it will search the hash table and return the found entry +if it is found; If it is not found and' isnew' is not NULL, set' isnew' to true, indicating a new entry. If' isinserthashtbl' is false, +it will only search the hash table, and if it is found, it will return the found entry; If it is not found, it will create a new table.*/ TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot* slot, bool* isnew, bool isinserthashtbl) { TupleHashEntry entry; @@ -510,6 +607,21 @@ static uint32 TupleHashTableHash(const void* key, Size keysize) * Also, the caller must select an appropriate memory context for running * the compare functions. (dynahash.c doesn't change CurrentMemoryContext.) */ +/*This code is used to process a part of tuple hash table, which is a data +structure used to store and retrieve tuple data in PostgreSQL. + +The function TupleHashTableMatch' is a comparison function, which is used to compare +whether two tuples are equal. This function is designed to be used with dynahash.c library, +which is a general hash table library and can be used to store and retrieve data. + +The function receives three parameters: key1, key2 and keysize. Key1' and' key2' are pointers +to two tuples to be compared, and' keysize' is the size of tuples. + +Within the function, firstly, ` key1' and ` key2' are converted into tuples, and then the tuples are stored +in the table slots and input slots of the hash table by using the ` ExecStoreMinimalTuple' function. + +Finally, compare whether two tuples are equal by using the execTuplesMatch function. +If two tuples are equal, the function returns 0, otherwise it returns 1.*/ static int TupleHashTableMatch(const void* key1, const void* key2, Size keysize) { MinimalTuple tuple1 = ((const TupleHashEntryData*)key1)->firstTuple; -- 2.34.1 From f0a0f5fcc59909cc7317b91f718a3e53796a8458 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Tue, 26 Sep 2023 15:27:02 +0800 Subject: [PATCH 056/118] Update execJunk.cpp --- src/gausskernel/runtime/executor/execJunk.cpp | 98 ++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/src/gausskernel/runtime/executor/execJunk.cpp b/src/gausskernel/runtime/executor/execJunk.cpp index 96adc29e0..db33535a8 100644 --- a/src/gausskernel/runtime/executor/execJunk.cpp +++ b/src/gausskernel/runtime/executor/execJunk.cpp @@ -60,6 +60,30 @@ * of whether to include room for an OID or not. * An optional resultSlot can be passed as well. */ +/*This function is used to initialize a JunkFilter structure, +which is mainly used to deal with' junk' data in SQL query results. , +Function definition: JunkFilter * executinitjunkfilter +(list * targetlist, boolhasoid, tupletableslot * slot, tablemtype tam) +is a function whose return value is a pointer of junkfilter type. ", +Variable initialization: some variables are initialized inside the +function, including a JunkFilter pointer, a TupleDesc cleaning +tuple type, an int cleaning length, an AttrNumber pointer array, +and a ListCell pointer. +Calculate the clean tuple type: use the ExecCleanTypeFromTL +function to calculate the clean tuple type based on the target list, +whether it has OID, and the type of table access method. +Set or create a tuple table slot: if the passed slot is not empty, +then use the passed slot; Otherwise, create a new slot. +Calculating the mapping between the original tuple and the clean tuple: +calculating the mapping between the attributes of the original tuple and +the attributes of the clean tuple. This mapping is an array whose length is +equal to the number of attributes of the clean tuple. For each attribute of +the clean tuple, if the corresponding original tuple attribute is not' garbage', +the attribute number is stored in the mapping array. +Create and initialize JunkFilter structure: Finally, create a new JunkFilter structure, +and store the data (target list, clean tuple type, mapping, result slot) obtained +by the above calculation in this structure. Then take the pointer of this +structure as the return value of the function.*/ JunkFilter* ExecInitJunkFilter(List* targetList, bool hasoid, TupleTableSlot* slot, TableAmType tam) { JunkFilter* junkfilter = NULL; @@ -131,6 +155,26 @@ JunkFilter* ExecInitJunkFilter(List* targetList, bool hasoid, TupleTableSlot* sl * deleted columns. It is assumed that the caller has checked that the * non-deleted columns match up with the non-junk columns of the targetlist. */ +/*The segment code defines a function named ExecInitJunkFilterConversion, +which is used to initialize a JunkFilter structure, mainly used to deal with' junk' data in SQL query results. + +The function receives three parameters: a targetList, a clean tuple type and a tuple table slot. + +Inside the function, some variables are initialized, including a JunkFilter pointer, +a clean length, a clean mapping array, a ListCell pointer and an integer variable. + +Next, the function checks whether the incoming slot is empty. +If it is not empty, the incoming slot is used, otherwise, a new slot is created. + +Then, the function calculates the mapping between the original tuple and the clean tuple. +This mapping is an array whose length is equal to the number of attributes of the clean tuple. +For each attribute of the clean tuple, if the corresponding original tuple attribute is not' garbage', +the attribute number is stored in the mapping array. If an attribute of the clean tuple is deleted, a +0 will be stored in the corresponding position in the mapping array, indicating that a NULL value is needed in the output tuple. + +Finally, the function creates a new JunkFilter structure, and stores the data (target list, clean tuple type, +mapping, result slot) obtained from the above calculation into this structure. Then take the +pointer of this structure as the return value of the function.*/ JunkFilter* ExecInitJunkFilterConversion(List* targetList, TupleDesc cleanTupType, TupleTableSlot* slot) { JunkFilter* junkfilter = NULL; @@ -208,6 +252,17 @@ AttrNumber ExecFindJunkAttribute(JunkFilter* junkfilter, const char* attrName) * Locate the specified junk attribute in the junk filter's targetlist. * Returns NIL if not found. */ +/*This function is called' ExecFindJunkPrimaryKeys', and it receives a parameter named' targetList', +which is a pointer to the list type. The main goal of the function is to traverse the' targetlist' +and find and return all the' garbage' attributes named' xc_primary_key'. + +A list named' jk_primary_keys' is initialized inside the function to store the found properties that meet the conditions. +Then, use the foreach loop to traverse' targetlist'. In each loop, it first gets a pointer to the current element and casts +the element to the' TargetEntry' type. Then, check whether the element is a' garbage' attribute and its name is' xc_primary_key'. +If the condition is met, then add the expression of this attribute to the' jk_primary_keys' list. + +Finally, the function returns the' jk_primary_keys' list. +This list contains all the' junk' attributes named' xc_primary_key' found in' targetlist'.*/ List* ExecFindJunkPrimaryKeys(List* targetlist) { List* jk_primary_keys = NIL; @@ -231,6 +286,29 @@ List* ExecFindJunkPrimaryKeys(List* targetlist) * Find a junk attribute given a subplan's targetlist (not necessarily * part of a JunkFilter). */ +/*This code has three functions, namely' ExecFindJunkAttributeInTlist',' +ExecGetJunkAttribute' and' ExecFilterJunk'. The following is an explanation of each function: + +1. `ExecFindUnkattributeinlist': This function receives a targetlist and an attribute name as parameters, +and then looks for the matching attribute name in the target list. If a matching attribute is found, +and the attribute is marked as' junk' (that is,' resjunk' is true), the number of the attribute ('resno') is returned. +If no matching attribute is found, or the attribute is not marked as' junk', an invalid attribute number ('InvalidAttrNumber') is returned. +2. `ExecGetJunkatAttribute`: This function receives a tuple table slot, an attribute number (attno) +and a pointer to a Boolean value (isNull) as parameters. It uses the `tableam _ tslot _ getattr` function +to get the value of the specified attribute number and the isNull flag from the slot. The function also does +some assertion checking to ensure that the attribute number passed in is greater than 0 and the slot is not empty. +3.'ExecFilterJunk': It is used to filter the "junk" attribute in OpenGauss database. +It receives two parameters: a JunkFilter structure pointer and a TupleTableSlot structure pointer. +The main work of this function can be roughly divided into the following steps: +1. Extract all the values of the old tuple (that is, the input TupleTableSlot) and store them in old_values and old_isnull. +2. Get the required information from JunkFilter structure, including clean tuple type, cleanLength and cleanMap. +3. Prepare to build a new virtual tuple (namely resultSlot). +4. Traverse every element in the clean map, and if the value of the map is 0, set it to NULL; +in the corresponding position in the new tuple; Otherwise, the corresponding value is obtained from the old tuple and copied to the new tuple. +5. Finally, return the virtual TupleTableSlot that stores the new tuple. +In this way, this function realizes the function of transforming from tuple containing "garbage" attribute to a tuple without "garbage" attribute. +These functions may be related to database query optimization, especially when dealing with a large number of data, +by identifying and filtering out' junk' attributes (that is, unnecessary attributes), the efficiency and performance of the query can be improved.*/ AttrNumber ExecFindJunkAttributeInTlist(List* targetlist, const char* attrName) { ListCell* t = NULL; @@ -364,7 +442,25 @@ VectorBatch* BatchExecFilterJunk(_in_ JunkFilter* junkfilter, __inout VectorBatc // return batch; } - +/*"ExecSetjunkFilteDescriptor function": +"Function": "This function is mainly used to set the tupleDescriptor of the resultSlot +of JunkFilter. It receives two parameters: a JunkFilter structure pointer and a TupleDesc structure. +It copies the attribute type ID in the input tuple descriptor to the corresponding attribute in +the tuple descriptor of the result slot by traversing the cleanMap. " , +"parameters": +"junkfilter": "A pointer to JunkFilter structure, which contains information needed for filtering operation, +such as cleaning tuple type and cleaning mapping." , +"tupdesc": "A pointer to a TupleDesc structure that describes the properties of a tuple." +"BatchCheckNodeIdentifier function": +"Function": "This function is mainly used to check whether the value of the' xc_node_id' +column in a VectorBatch is the same as the identifier of the current node. If not, the function +will report an error. The function first checks whether' xc_node_id' is a valid attribute number, +and then obtains the values of the' xc_node_id' column, and checks whether they are the same +as the identifier of the current node one by one. " , +"parameters": +"junkfilter": "A pointer to JunkFilter structure, which contains information needed +for filtering operation, such as cleaning tuple type and cleaning mapping." , +"batch": "A pointer to the VectorBatch structure, which contains the data to be filtered."*/ void ExecSetjunkFilteDescriptor(JunkFilter* junkfilter, TupleDesc tupdesc) { TupleDesc resultslotTupType; -- 2.34.1 From 74fa63df6e355ed1ff525d248e9438e1471cf3c4 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Tue, 26 Sep 2023 16:11:37 +0800 Subject: [PATCH 057/118] Update execMain.cpp --- src/gausskernel/runtime/executor/execMain.cpp | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/src/gausskernel/runtime/executor/execMain.cpp b/src/gausskernel/runtime/executor/execMain.cpp index cf58f8fdd..780766e92 100755 --- a/src/gausskernel/runtime/executor/execMain.cpp +++ b/src/gausskernel/runtime/executor/execMain.cpp @@ -435,6 +435,39 @@ void standard_ExecutorStart(QueryDesc *queryDesc, int eflags) * * ---------------------------------------------------------------- */ + /*This code is written in C++ and seems to be extracted from a + database management system (maybe PostgreSQL). + +The ExecutorRun function is the main routine of the executor module. +It receives the query descriptor from the traffic police and executes the query plan. + +This function first performs some initialization operations, and then +calls the exec_explain_plan function, probably to explain the query plan. + +Then, if the workload manager is enabled, and the resource tracking +level is set to RESOURCE_TRACK_OPERATOR, +and the query descriptor is not empty, and the plan +statement in the query descriptor is a flow plan, +and resources need to be tracked, then some additional variables are set. + +Then, it checks whether operation history statistics +can be performed, and if so, it calls the ExplainNodeFinish function. + +Next, it checks whether there is an ExecutorRun_hook, and calls it if there is; +Otherwise, call the standard_ExecutorRun function. + +Then, if it is a PGXC coordinator or a single node, and the query operation is insert, +delete, update or merge, the report_iud_time function is called. + +Next, if resources need to be tracked, and there are query descriptors and tracking operations, +the PlanAnalyzerOperator function is called to analyze the query plan problem. +If a problem is found, it is stored in the system view gs_wlm_session_history. + +Finally, print the query duration and call the instr_stmt_report_query_plan function. +If operation history statistics can be performed, set can_record_to_table to true, +and call the ExplainNodeFinish function again. If it is a PGXC coordinator and the +global instrument is not empty, delete the global instrument and set the thread instrument to NULL. +Finally, the old statement name is restored and the execution level is reduced by 1.*/ void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, long count) { /* sql active feature, opeartor history statistics */ @@ -655,6 +688,19 @@ void standard_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, long co * * ---------------------------------------------------------------- */ + /*"ExecutorFinish function": "This function is a calling hook. It first checks whether there is an ExecutorFinish_hook' + and calls it if there is one; Otherwise, call the standard_ExecutorFinish function. " , +"standard_ExecutorFinish function": +"Function": "This is the standard end routine of the actuator module." , +"step": +"Perform a health check to make sure that the query descriptor and status exist and are not in an interpretation mode." , +"Switch to the memory context of each query." , +"If the total time is set, start the instrument node." , +"Run the ModifyTable node to finish." , +"Executes a queued AFTER trigger unless told to skip the trigger." , +"If the total time is set, stop the instrument node." , +"Switch back to the old memory context." , +"Mark the status as completed."*/ void ExecutorFinish(QueryDesc *queryDesc) { if (ExecutorFinish_hook) { @@ -733,7 +779,28 @@ int ExecGetPlanNodeid(void) } return key; } +/*This is a function called standard_ExecutorEnd', +which releases the resources used by the executor during the query. +The following is the function explanation of the function: + +1. Define some variables, including an execution state pointer ` estate', a memory context +` old_context', an instrument time ` starttime' and a totaltime ` totaltime'. +2. Set the start time by calling `instr _ time _ set _ current (start time)'. +3. Do some health checks to ensure that' queryDesc' and' estate' are not empty. +4. If `memory _ context _ checking` is defined, all memory contexts are checked at the start of the executor. +5. Check whether ExecutorFinish has been called, unless it is in interpretation-only mode. +This is because before version 9.1, the caller may forget to call it. +6. Switch to the memory context of each query to run' ExecEndPlan'. +7. Release our snapshot. +8. If LLVM compilation is enabled and it is not currently running in the function manager, +code generation thread disassembly is performed. +9. Switch to the old context before destroying it. +10. If `memory _ context _ checking` is defined, the memory context of each query is checked before FreeExecutorState'. +11. Release the execution state and the memory context of each query, which should release all the contents allocated by the executor. +12. Reset the fields in the query descriptor that no longer point to anything. + +The main purpose of this code is to clean up and release resources after the query execution.*/ void standard_ExecutorEnd(QueryDesc *queryDesc) { EState *estate = NULL; @@ -826,6 +893,20 @@ void standard_ExecutorEnd(QueryDesc *queryDesc) * to the start. * ---------------------------------------------------------------- */ +/*This is a function called ExecutorRewind', which is used to rescan the query plan without executing it. + +The following is the functional explanation of the code: + +1. Define two variables, an execution estate pointer `establishment` and a memory context `old _ context`. +2. Do some health checks to ensure that' queryDesc' and' estate' are not empty. +3. Check whether the query operation is CMD_SELECT by assertion, +because it may be meaningless to rescan and update the query. +4. Switch to the memory context of each query to run ExecReScan. +5. Rescan the query plan without executing it. +6. Switch back to the old memory context. + +This function may be used to reload or rescan the query plan under certain circumstances without actually executing it. +This may be useful when you need to refresh the query plan or reload the data.*/ void ExecutorRewind(QueryDesc *queryDesc) { EState *estate = NULL; @@ -910,6 +991,22 @@ bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation) * ExecCheckRTEPerms * Check access permissions for a single RTE. */ +/*The function ` ExecCheckRTPerms' is used to check whether each table in a query +(listed in ` rangeTable') meets certain permission requirements. + +The main logic of the code is as follows: + +1. Define a' foreach' loop to traverse each element in' rangeTable'. +2. For each element, it first checks whether this element is a time series table (RTE_RELATION), +if so, it skips the check, if not, it continues to check the permissions. +3. The function `ExecCheckrtePerms (RTE) ` is called to check the permissions of the current element (table). +4. If the permission check fails, the function will report an error (if `ereport _ on _ violation` is `true`) and then return `false`. +5. If ExecutorCheckPerms_hook is defined, call this function and assign the result to `result`. +6. After all the operations are completed, the function returns result. + +It should be noted that some parts of this function may be compiled according to whether +`enable _ multiple _ nodes` is defined, which is a common technique of preprocessor to include +or exclude specific code segments in different compilation environments.*/ static bool ExecCheckRTEPerms(RangeTblEntry *rte) { AclMode requiredPerms; @@ -1067,6 +1164,29 @@ static bool ExecCheckRTEPerms(RangeTblEntry *rte) * Check INSERT or UPDATE access permissions for a single RTE (these * are processed uniformly). */ +/*The function ExecCheckRTEPermsModified' in this code is the process of performing permission check. + +Function parameters: + +-`relOid': the object identifier representing the relationship to be operated on. +-`userid: the user ID of the operation. +-`modifiedCols: Represents the bitmap of the modified column. +-`requiredPerms: required permission type. + +Code logic: + +-If' modifiedCols' is empty, it means that the query has not explicitly updated any columns, +so if the user has permission on any column of the relationship, the query is allowed. +This is to deal with possible marginal situations in' SELECT FOR UPDATE' and' UPDATE'. +-If' modifiedCols' is not empty, traverse each modified column. In the process of traversal, +firstly, the index of the next modified column is obtained by the function of `bms _ next _ member', +and then the attribute number attno' is obtained by adding the offset `firstlowinvalidheapattributenumber' to the index. +-If' attno' equals' InvalidAttrNumber', it means that the whole line is referenced, +which is not allowed here, so an error is reported and an exception is thrown. +-If' attno' is not equal to' InvalidAttrNumber', use the' pg_attribute_aclcheck' function +to check the user's permissions on the current attribute. If the permission check fails, it returns `false`. + +If the function can successfully handle the permission check of all columns, then it finally returns ` true'.*/ static bool ExecCheckRTEPermsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols, AclMode requiredPerms) { int col = -1; @@ -1097,6 +1217,20 @@ static bool ExecCheckRTEPermsModified(Oid relOid, Oid userid, Bitmapset *modifie return true; } +/*The main function of this code is to check whether a transaction is read-only. Specifically, +this function traverses all table references in the SQL query, and then rejects those queries that attempt to write on non-temporary tables. + +Every part of the code has specific checks: + +1. Traverse all table references in the query (` foreach (l, plannedstmt->rtable) `). +2. for each table reference, check its type (rte->rtekind! = RTE_RELATION`)。 If it is not a relationship (that is, it is not a table), then skip it. +3. check the required permissions (`rte-> requiredperms & (~ ACL _ select) `). If you only need to select the permission, then skip it. +4. Check whether this table is in the temporary namespace (`istempnamespace (get _ rel _ namespace (rte-> Relid)) `). If so, then skip it. +5. Check the persistence of this table (` get _ rel _ persistence (rte-> Relid) = = rel persistence _ global _ temp`). If it is a global temporary table, then skip it. +6. For a specific Greenplum database, if it is a roach standby cluster in maintenance mode and is accessing the node relationship, then skip it. +7. If all the above checks pass, then call the PreventCommandIfReadOnly' function to stop the execution of this query. + +Generally speaking, the purpose of this function is to protect the consistency of the database by preventing write operations in read-only transactions.*/ /* * Check that the query does not imply any writes to non-temp tables. * -- 2.34.1 From dfb3849780396cf01b5ced7c2f6c67fb58e41d73 Mon Sep 17 00:00:00 2001 From: bjyb <1091839467@qq.com> Date: Tue, 26 Sep 2023 19:37:29 +0800 Subject: [PATCH 058/118] Update execProcnode.cpp --- .../runtime/executor/execProcnode.cpp | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/gausskernel/runtime/executor/execProcnode.cpp b/src/gausskernel/runtime/executor/execProcnode.cpp index fd1cf1372..a27336c22 100755 --- a/src/gausskernel/runtime/executor/execProcnode.cpp +++ b/src/gausskernel/runtime/executor/execProcnode.cpp @@ -175,6 +175,23 @@ * initilaization work like open scanrel, instead allow NodeInit work to continue on its * lefttree/righttree */ +/*The function is called ` NeedStubExecution', and its input parameter is a pointer to type ` Plan'. +The main function of this function is to judge whether a plan node needs pile execution. +The following is a detailed explanation of each part of the function: + +-` # ifndef enable _ multiple _ nodes`: This is a preprocessor instruction to check whether the +macro definition `enable _ multiple _ nodes` exists. If it does not exist, the function directly returns false. +-`if (exec _ in _ recursive _ mode (plan) )`: This judgment statement checks whether the plan node is +in recursive mode. If so, the function returns false. +-`if (NeedExecute(plan) )`: This judgment statement calls the `NeedExecute' function to judge +whether this plan step needs to be executed on the current data node. If necessary, the function returns false. +-`switch (nodeTag(plan) )`: This judgment statement is processed differently according to the type +of plan node. For most types of planning nodes, it returns ` false', but for certain node types +(such as T_ModifyTable, T_VecModifyTable, T_Scan, etc.), it returns ` true'. If `enable _ multiple _ nodes` is defined, it will also handle the T_TsStoreScan type. + +Therefore, in a word, this function mainly judges whether a given plan node needs to be executed, +and it is influenced by many conditions, including whether some macros are defined, +the state of the plan node, and the type of the plan node.*/ bool NeedStubExecution(Plan* plan) { #ifndef ENABLE_MULTIPLE_NODES @@ -219,6 +236,21 @@ bool NeedStubExecution(Plan* plan) /* * not need execute active sql if the datanode don't run in multi-nodegroup. */ +/*1. `Needexecutivesql (plan * plan)' function: judge whether the current plan node needs to be executed. +If the current node is neither a PGXC coordinator nor a single node and does not need to be executed, then return false;; Otherwise return true. +2. `seqscannodestub (seqscanstate * seq _ scan) ` function: judge whether the sequential scanning node is a pile. +If the scan description is NULL, then it is a pile and returns true;; Otherwise return false. +3. `idxscannodestub (indexscanstate * index _ scan) ` function: judge whether the index scanning node is a stub. +If the scan description is NULL, then it is a pile and returns true;; Otherwise return false. +4. `idxonlyscannodestub (indexonlyscanstate * index _ only _ scan) ` function: judge whether the index-only +scanning node is a pile. If the scan description is NULL, then it is a pile and returns true;; Otherwise return false. +5. `bmidxonlyscannodestub (bitmapindexscanstate * BM _ index _ scan) ` function: judge whether the +bitmap index scanning node is a pile. If the scan description is NULL, then it is a pile and returns true;; Otherwise return false. +6. `bmheapscannodestub (bitmapheapstate * BM _ heap _ scan) ` function: judge whether the bitmap heap +scanning node is a pile. If the scan description is NULL, then it is a pile and returns true;; Otherwise return false. + +Each of these functions checks whether certain types of database operations (such as sequential scanning, +index scanning, etc.) need to be performed on the current data node. If not, then the operation is a "stub", that is, it is a placeholder and does not actually perform any work.*/ static bool NeedExecuteActiveSql(Plan* plan) { if ((!IS_PGXC_COORDINATOR) && (!IS_SINGLE_NODE) && false == NeedExecute(plan)) { @@ -252,7 +284,16 @@ static inline bool BmHeapScanNodeIsStub(BitmapHeapScanState* bm_heap_scan) { return bm_heap_scan->ss.ss_currentScanDesc == NULL; } +/*The function is called ExecInitNodeByType, and it has three parameters: plan * node, estate * estate, +int eflags. This function calls the corresponding initialization function by judging the type of the incoming Plan node. +This code is a part of a database management system (such as PostgreSQL) to handle the execution of the query plan +. Each query will be parsed and transformed into a plan, and then the plan will guide the execution of the query. + +In the code, each case corresponds to a plan node type, such as T_SeqScan corresponding to sequential scanning +and T_IndexScan corresponding to index scanning. Each case will pass the node, estate and eflags to the corresponding +initialization function, and return the initialized PlanState. This is a kind of polymorphism, +which enables us to call the corresponding function according to the node type.*/ PlanState* ExecInitNodeByType(Plan* node, EState* estate, int eflags) { switch (nodeTag(node)) { @@ -405,7 +446,24 @@ PlanState* ExecInitNodeByType(Plan* node, EState* estate, int eflags) return NULL; /* keep compiler quiet */ } } +/* +The function ExecInitNodeSubPlan accepts three parameters: a Plan node, an execution state and a result PlanState. +Its main purpose is to initialize sub-plans and execute them if certain conditions are met. +The following is a detailed explanation of the code: +A sub_ps variable is defined, which is a list used to store the initialized sub-plan status. +Traverse each element in the node->initPlan list. Node->initPlan is a list containing subplans. +In each iteration, take the current sub-plan out of the list and check whether it is empty. If empty, the current iteration is skipped. +Make sure that the sub-plan taken out is indeed of SubPlan type. +This part of the code performs different processing according to whether the macro ENABLE_MULTIPLE_NODES is defined. +If this macro is defined, then if the current node is PGXC coordinator, or estate->es_subplan_ids is empty, or the ID of the +current node is equal to the ID of the subplan, the subplan will be executed. If the macro is not defined, the sub-plan +will be executed if the current node is the top consumer of the stream, or if the estate->es_subplan_ids is empty, +or if the ID of the current node is equal to the ID of the sub-plan. +If the above conditions are met, the ExecInitSubPlan function is called to initialize the subplan, +and the returned subplan status is stored in the sub_ps list. +Finally, assign the sub_ps list to the result->initPlan, that is, the status of the result plan. +Generally speaking, the main task of this function is to initialize and execute the subplans in the query plan.*/ void ExecInitNodeSubPlan(Plan* node, EState* estate, PlanState* result) { List* sub_ps = NIL; @@ -1002,6 +1060,27 @@ ExecProcFuncType g_execProcFuncTable[] = { * Execute the given node to return a(nother) tuple. * ---------------------------------------------------------------- */ +/*The function ExecProcNode accepts a pointer node of type PlanState and returns a pointer of type TupleTableSlot'. + +The following is a detailed explanation of the code: + +1. A pointer' result' to the type' TupleTableSlot' is defined and initialized to NULL. This pointer will be used to store the return value of the function. +2. `CHECK_FOR_INTERRUPTS () ` is a macro used to check whether there is an interrupt signal. If so, it will stop the current operation and handle the interrupt. +3. `MemoryContext old_context; Defines a variable' old_context' of type' MemoryContext', which will be used to save the current memory context. +4.' # ifdef ENABLE_MULTIPLE_NODES' is a preprocessor instruction. +If' enable _ multiple _ nodes' is defined, the next code will be compiled and executed. +This code checks whether there is an early stop signal, and if there is, the function returns NULL. +5. `MemoryContextSwitchTo(node->nodeContext); Switch the memory context to the memory context of the node. +6. If the parameters of the node have changed, call ExecReScan(node)' for rescan. +7. If the node has an instrument (for performance analysis), call `instr start node (node-> instrument)' to start the timing of the instrument. +8. In the case of multi-nodes, if the nodes need stubs, call ExecProcNodeStub(node)' to execute stub nodes. +Otherwise, the node is processed by looking up the ` g _ execprocfunctional` function table and executing the corresponding function. +9. If the node has instruments, call ExecProcNodeInstr(node, result)' to record the implementation of the node. +10. Switch back to the old memory context. +11. Increment the row counter of the node. +12. Return the result pointer. + +The purpose of this code is to perform the corresponding operation according to the type of node and return the result. It is one of the core parts of database query execution.*/ TupleTableSlot* ExecProcNode(PlanState* node) { TupleTableSlot* result = NULL; @@ -1062,6 +1141,38 @@ TupleTableSlot* ExecProcNode(PlanState* node) * function must provide its own instrumentation support. * ---------------------------------------------------------------- */ +/*This code is a part of a database management system (such as PostgreSQL) and is used to handle the execution of the query plan. +Each query will be parsed and transformed into a plan, and then the plan will guide the execution of the query. + +The function MultiExecProcNode accepts a pointer `node` of type +PlanState and returns a pointer to type `node`. + +The following is a detailed explanation of the code: + +1. A pointer result to the type Node is defined and initialized to NULL. +This pointer will be used to store the return value of the function. +2. `MemoryContext old_context; Defines a variable' old_context' of type' MemoryContext', +which will be used to save the current memory context. +3. `CHECK_FOR_INTERRUPTS(); ` is a macro used to check whether there is an interrupt signal. +If so, it will stop the current operation and handle the interrupt. +4. `MemoryContextSwitchTo(node->nodeContext); +Switch the memory context to the memory context of the node. +5. If the parameters of the node have changed, call ExecReScan(node)' for rescan. +6. The `switch (node tag (node)) ` statement performs +corresponding operations according to the type of node: +-If the node type is `t _ hashstate`, call `multiexecshash ((hashstate *) node) `. +-If the node type is `t _ bitmapindexscanState', call `multiexecbitmapindexscan ((bitmapindexscanState *) node) `. +-If the node type is `t _ bitmapandstate`, call `multiexecbitmapand ((bitmapandstate *) node) `. +-If the node type is `t _ bitmaporstate`, call `multiexecbitmapor ((bitmaporstate *) node) `. +-If the node type is not any of the above, an error is reported with the error code `errcode _ unrecognized _ node _ type` +and ERRCODE_UNRECOGNIZED_NODE_TYPE is displayed. +7. If the node has an instrument (used for performance analysis), +set the memory information of the node as the memory information of the instrument. +8. Switch back to the old memory context. +9. Return the result pointer. + +The purpose of this code is to perform the corresponding operation according to the type of node and return the result. +It is one of the core parts of database query execution.*/ Node* MultiExecProcNode(PlanState* node) { Node* result = NULL; -- 2.34.1 From 819accf25a4606fb1fbd2cd78809aea635420b2a Mon Sep 17 00:00:00 2001 From: Wang17 Date: Thu, 5 Oct 2023 16:03:00 +0800 Subject: [PATCH 059/118] Update cmake_package_mini.sh --- build/script/cmake_package_mini.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build/script/cmake_package_mini.sh b/build/script/cmake_package_mini.sh index fb2380e7d..ba48b6d4c 100644 --- a/build/script/cmake_package_mini.sh +++ b/build/script/cmake_package_mini.sh @@ -1,6 +1,7 @@ #!/bin/bash ####################################################################### # Copyright (c): 2020-2021, Huawei Tech. Co., Ltd. + # descript: Compile and pack MPPDB # Return 0 means OK. # Return 1 means failed. -- 2.34.1 From cbc2e94653a5a2ab2459af1204417f3821685d91 Mon Sep 17 00:00:00 2001 From: Wang17 Date: Thu, 5 Oct 2023 16:09:00 +0800 Subject: [PATCH 060/118] Update alarm_log.cpp --- src/lib/alarm/alarm_log.cpp | 123 +++++++++++++++++++++++++++++------- 1 file changed, 100 insertions(+), 23 deletions(-) diff --git a/src/lib/alarm/alarm_log.cpp b/src/lib/alarm/alarm_log.cpp index ad80bebbb..0dca25923 100644 --- a/src/lib/alarm/alarm_log.cpp +++ b/src/lib/alarm/alarm_log.cpp @@ -1,3 +1,10 @@ +/*** + * @Author: 王贤义 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:10:31 + */ + + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * @@ -21,6 +28,8 @@ * * ------------------------------------------------------------------------- */ + + #include #include #include @@ -78,20 +87,30 @@ static FILE* logfile_open(const char* filename, const char* mode) FILE* fh = NULL; mode_t oumask; - // Note we do not let Log_file_mode disable IWUSR, since we certainly want to be able to write the files ourselves. + // Set the file permission mask to allow read, write, and execute permissions for the owner (user) + // while preserving the permissions for the group and others. oumask = umask((mode_t)((~(mode_t)(S_IRUSR | S_IWUSR | S_IXUSR)) & (S_IRWXU | S_IRWXG | S_IRWXO))); + + // Open the file with the specified filename and mode. fh = fopen(filename, mode); + + // Restore the original file permission mask. (void)umask(oumask); + + // If the file was successfully opened, set the buffering mode to line-buffered. if (fh != NULL) { setvbuf(fh, NULL, LBF_MODE, 0); #ifdef WIN32 - /* use CRLF line endings on Windows */ + // On Windows, use CRLF line endings. _setmode(_fileno(fh), _O_TEXT); #endif } else { + // If the file could not be opened, log an error message. AlarmLog(ALM_LOG, "could not open log file \"%s\"\n", filename); } + + // Return the file handle. return fh; } @@ -103,32 +122,52 @@ static void create_new_alarm_log_file(const char* sys_log_path) char log_temp_name[MAXPGPATH] = {0}; errno_t rc; + // Initialize the systm struct and log_create_time buffer rc = memset_s(&systm, sizeof(systm), 0, sizeof(systm)); securec_check_c(rc, "\0", "\0"); - /* create new log file */ + + // Clear the system_alarm_log buffer rc = memset_s(system_alarm_log, MAXPGPATH, 0, MAXPGPATH); securec_check_c(rc, "\0", "\0"); + // Get the current time current_time = time(NULL); + + // Convert the current time to a formatted string if (localtime_r(¤t_time, &systm) != NULL) { (void)strftime(log_create_time, LOG_MAX_TIMELEN, "-%Y-%m-%d_%H%M%S", &systm); } else { + // Print an error message if getting the local time failed AlarmLog(ALM_LOG, "get localtime_r failed\n"); } + // Create the temporary log file name rc = snprintf_s( log_temp_name, MAXPGPATH, MAXPGPATH - 1, "%s%s%s", SYSTEM_ALARM_LOG, log_create_time, CURLOGFILEMARK); securec_check_ss_c(rc, "\0", "\0"); + + // Create the full path of the new log file rc = snprintf_s(system_alarm_log, MAXPGPATH, MAXPGPATH - 1, "%s/%s", sys_log_path, log_temp_name); securec_check_ss_c(rc, "\0", "\0"); + + // Clear the system_alarm_log_name buffer rc = memset_s(system_alarm_log_name, MAXPGPATH, 0, MAXPGPATH); securec_check_c(rc, "\0", "\0"); + + // Copy the temporary log file name to system_alarm_log_name rc = strncpy_s(system_alarm_log_name, MAXPGPATH, log_temp_name, strlen(log_temp_name)); securec_check_c(rc, "\0", "\0"); + // Open the new log file in "append" mode alarmLogFile = logfile_open(system_alarm_log, "a"); } +/** + * Renames the current alarm log file without the "CURLOGFILEMARK" suffix. + * + * @param sys_log_path The system log path. + * @return True if the log file was successfully renamed, false otherwise. + */ static bool rename_alarm_log_file(const char* sys_log_path) { int len_log_old_name, len_suffix_name, len_log_new_name; @@ -137,25 +176,30 @@ static bool rename_alarm_log_file(const char* sys_log_path) errno_t rc; int ret; - /* renamed the current file without Mark */ + /* Get the lengths of the old log file name, the suffix name, and the new log file name */ len_log_old_name = strlen(system_alarm_log_name); len_suffix_name = strlen(CURLOGFILEMARK); len_log_new_name = len_log_old_name - len_suffix_name; + /* Copy the old log file name to logFileBuff */ rc = strncpy_s(logFileBuff, MAXPGPATH, system_alarm_log_name, len_log_new_name); securec_check_c(rc, "\0", "\0"); + + /* Append the ".log" suffix to logFileBuff */ rc = strncat_s(logFileBuff, MAXPGPATH, ".log", strlen(".log")); securec_check_c(rc, "\0", "\0"); + /* Create the full path of the new log file */ rc = snprintf_s(log_new_name, MAXPGPATH, MAXPGPATH - 1, "%s/%s", sys_log_path, logFileBuff); securec_check_ss_c(rc, "\0", "\0"); - /* close the current file */ + /* Close the current log file */ if (alarmLogFile != NULL) { fclose(alarmLogFile); alarmLogFile = NULL; } + /* Rename the current log file to the new log file name */ ret = rename(system_alarm_log, log_new_name); if (ret != 0) { AlarmLog(ALM_LOG, "ERROR: %s: rename log file %s failed! \n", system_alarm_log, system_alarm_log); @@ -164,19 +208,28 @@ static bool rename_alarm_log_file(const char* sys_log_path) return true; } -/* write alarm info to alarm log file */ + +/** + * Writes the given buffer to the alarm log file. + * + * @param buffer The buffer containing the data to be written. + */ static void write_log_file(const char* buffer) { int rc; (void)pthread_rwlock_wrlock(&alarm_log_write_lock); + // Check if the alarm log file is not open if (alarmLogFile == NULL) { + // If the current log file is "/dev/null", create a new system alarm log if (strncmp(system_alarm_log, "/dev/null", strlen("/dev/null")) == 0) { create_system_alarm_log(sys_alarm_log_path); } + // Open the alarm log file in "append" mode alarmLogFile = logfile_open(system_alarm_log, "a"); } + // Write the buffer to the alarm log file if (alarmLogFile != NULL) { int count = strlen(buffer); @@ -205,20 +258,25 @@ void create_system_alarm_log(const char* sys_log_path) char* name_ptr = NULL; errno_t rc; + // Check if the sys_alarm_log_path is empty if (strlen(sys_alarm_log_path) == 0) { + // Copy the sys_log_path to sys_alarm_log_path rc = strncpy_s(sys_alarm_log_path, MAX_PATH_LEN, sys_log_path, strlen(sys_log_path)); securec_check_c(rc, "\0", "\0"); } + // Open the directory specified by sys_log_path if ((dir = opendir(sys_log_path)) == NULL) { + // Print an error message if opendir fails AlarmLog(ALM_LOG, "opendir %s failed! \n", sys_log_path); rc = strncpy_s(system_alarm_log, MAXPGPATH, "/dev/null", strlen("/dev/null")); securec_check_ss_c(rc, "\0", "\0"); return; } + // Iterate through the directory entries while ((de = readdir(dir)) != NULL) { - /* exist current log file */ + // Check if the current log file exists if (strstr(de->d_name, SYSTEM_ALARM_LOG) != NULL) { name_ptr = strstr(de->d_name, CURLOGFILEMARK); if (name_ptr != NULL) { @@ -230,13 +288,20 @@ void create_system_alarm_log(const char* sys_log_path) } } } + + // If the current log file exists if (is_exist) { + // Clear the system_alarm_log_name and system_alarm_log buffers rc = memset_s(system_alarm_log_name, MAXPGPATH, 0, MAXPGPATH); securec_check_c(rc, "\0", "\0"); rc = memset_s(system_alarm_log, MAXPGPATH, 0, MAXPGPATH); securec_check_c(rc, "\0", "\0"); + + // Construct the new log file path rc = snprintf_s(system_alarm_log, MAXPGPATH, MAXPGPATH - 1, "%s/%s", sys_log_path, de->d_name); securec_check_ss_c(rc, "\0", "\0"); + + // Copy the log file name to system_alarm_log_name rc = strncpy_s(system_alarm_log_name, MAXPGPATH, de->d_name, strlen(de->d_name)); securec_check_c(rc, "\0", "\0"); } else { @@ -248,49 +313,69 @@ void create_system_alarm_log(const char* sys_log_path) void clean_system_alarm_log(const char* file_name, const char* sys_log_path) { + // Assert that file_name is not NULL Assert(file_name != NULL); unsigned long filesize = 0; struct stat statbuff; int ret; + // Initialize statbuff with zeros errno_t rc = memset_s(&statbuff, sizeof(statbuff), 0, sizeof(statbuff)); securec_check_c(rc, "\0", "\0"); + // Get the file status using stat ret = stat(file_name, &statbuff); + + // Check if stat failed or if the file_name is "/dev/null" if (ret != 0 || (strncmp(file_name, "/dev/null", strlen("/dev/null")) == 0)) { + // Print an error message and return if there is an error with stat or if the file_name is "/dev/null" AlarmLog(ALM_LOG, "ERROR: stat system alarm log %s error.ret=%d\n", file_name, ret); return; } else { + // Get the file size from the statbuff filesize = statbuff.st_size; } + + // Check if the file size is greater than MAX_SYSTEM_ALARM_LOG_SIZE if (filesize > MAX_SYSTEM_ALARM_LOG_SIZE) { + // Acquire a write lock on alarm_log_write_lock (void)pthread_rwlock_wrlock(&alarm_log_write_lock); - /* renamed the current file without Mark */ + + // Rename the current file without the Mark if (rename_alarm_log_file(sys_log_path)) { - /* create new log file */ + // Create a new log file create_new_alarm_log_file(sys_log_path); } + + // Release the write lock on alarm_log_write_lock (void)pthread_rwlock_unlock(&alarm_log_write_lock); } + return; } void write_alarm(Alarm* alarmItem, const char* alarmName, const char* alarmLevel, AlarmType type, AlarmAdditionalParam* additionalParam) { + // Declare variables char command[COMMAND_SIZE]; char reportInfo[REPORT_MSG_SIZE]; errno_t rcs = 0; + // Check if system_alarm_log is empty, if so, return if (strlen(system_alarm_log) == 0) return; + // Initialize command and reportInfo buffers with zeros errno_t rc = memset_s(command, COMMAND_SIZE, 0, COMMAND_SIZE); securec_check_c(rc, "\0", "\0"); rc = memset_s(reportInfo, REPORT_MSG_SIZE, 0, REPORT_MSG_SIZE); securec_check_c(rc, "\0", "\0"); + + // Check the type of the alarm if (type == ALM_AT_Fault || type == ALM_AT_Event) { + // Construct the reportInfo string for fault or event alarms rcs = snprintf_s(reportInfo, REPORT_MSG_SIZE, REPORT_MSG_SIZE - 1, @@ -307,20 +392,8 @@ void write_alarm(Alarm* alarmItem, const char* alarmName, const char* alarmLevel alarmLevel, g_alarm_scope, additionalParam->hostName, - (strlen(additionalParam->instanceName) != 0) ? additionalParam->instanceName : additionalParam->clusterName, - "firing", - additionalParam->additionInfo, - "ADAC", - alarmItem->startTimeStamp, - 0); - } else if (type == ALM_AT_Resume) { - rcs = snprintf_s(reportInfo, - REPORT_MSG_SIZE, - REPORT_MSG_SIZE - 1, - "{" SYSQUOTE "id" SYSQUOTE SYSCOLON SYSQUOTE "%016ld" SYSQUOTE SYSCOMMA SYSQUOTE - "name" SYSQUOTE SYSCOLON SYSQUOTE "%s" SYSQUOTE SYSCOMMA SYSQUOTE "level" SYSQUOTE SYSCOLON SYSQUOTE - "%s" SYSQUOTE SYSCOMMA SYSQUOTE "scope" SYSQUOTE SYSCOLON "%s" SYSCOMMA SYSQUOTE - "source_tag" SYSQUOTE SYSCOLON SYSQUOTE "%s-%s" SYSQUOTE SYSCOMMA SYSQUOTE + (strlen(additionalParam->instanceName) != 0) ? additionalParam->instanceName : additionalParam->cluster + "ame" SYSQUOTE SYSCOLON SYSQUOTE "%s" SYSQUOTE SYSCOMMA SYSQUOTE "op_type" SYSQUOTE SYSCOLON SYSQUOTE "%s" SYSQUOTE SYSCOMMA SYSQUOTE "start_timestamp" SYSQUOTE SYSCOLON "%d" SYSCOMMA SYSQUOTE "end_timestamp" SYSQUOTE SYSCOLON "%ld" "}\n", @@ -334,6 +407,10 @@ void write_alarm(Alarm* alarmItem, const char* alarmName, const char* alarmLevel 0, alarmItem->endTimeStamp); } + + // Check if the snprintf_s function succeeded securec_check_ss_c(rcs, "\0", "\0"); + + // Write the reportInfo to the log file write_log_file(reportInfo); } -- 2.34.1 From 255240899c73d9aab1821c5d1c71932d60ba0def Mon Sep 17 00:00:00 2001 From: Wang17 Date: Thu, 5 Oct 2023 16:09:53 +0800 Subject: [PATCH 061/118] Update alarm.cpp --- src/lib/alarm/alarm.cpp | 445 ++++++++++++++++++++++++---------------- 1 file changed, 271 insertions(+), 174 deletions(-) diff --git a/src/lib/alarm/alarm.cpp b/src/lib/alarm/alarm.cpp index c7f11aa0b..93aa0f233 100644 --- a/src/lib/alarm/alarm.cpp +++ b/src/lib/alarm/alarm.cpp @@ -1,3 +1,9 @@ +/*** + * @Author: 王贤义 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:10:31 + */ + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * @@ -107,6 +113,7 @@ void AlarmLog(int level, const char* fmt, ...); */ static void check_input_for_security1(char* input) { + // Array of dangerous tokens that need to be checked char* danger_token[] = {"|", ";", "&", @@ -130,7 +137,9 @@ static void check_input_for_security1(char* input) "\n", NULL}; + // Iterate through the array of dangerous tokens for (int i = 0; danger_token[i] != NULL; ++i) { + // Check if the input string contains the dangerous token if (strstr(input, danger_token[i]) != NULL) { printf("invalid token \"%s\"\n", danger_token[i]); exit(1); @@ -138,6 +147,13 @@ static void check_input_for_security1(char* input) } } +/** + * @brief Converts the given AlarmId to the corresponding English alarm name. + * + * @param id The AlarmId to convert. + * @return char* The English alarm name corresponding to the AlarmId. + * Returns "unknown" if no matching AlarmId is found. + */ static char* AlarmIdToAlarmNameEn(AlarmId id) { unsigned int i; @@ -148,6 +164,13 @@ static char* AlarmIdToAlarmNameEn(AlarmId id) return "unknown"; } +/** + * @brief Converts the given AlarmId to the corresponding Chinese alarm name. + * + * @param id The AlarmId to convert. + * @return char* The Chinese alarm name corresponding to the AlarmId. + * Returns "unknown" if no matching AlarmId is found. + */ static char* AlarmIdToAlarmNameCh(AlarmId id) { unsigned int i; @@ -158,6 +181,13 @@ static char* AlarmIdToAlarmNameCh(AlarmId id) return "unknown"; } +/** + * @brief Converts the given AlarmId to the corresponding English alarm information. + * + * @param id The AlarmId to convert. + * @return char* The English alarm information corresponding to the AlarmId. + * Returns "unknown" if no matching AlarmId is found. + */ static char* AlarmIdToAlarmInfoEn(AlarmId id) { unsigned int i; @@ -168,6 +198,13 @@ static char* AlarmIdToAlarmInfoEn(AlarmId id) return "unknown"; } +/** + * @brief Converts the given AlarmId to the corresponding Chinese alarm information. + * + * @param id The AlarmId to convert. + * @return char* The Chinese alarm information corresponding to the AlarmId. + * Returns "unknown" if no matching AlarmId is found. + */ static char* AlarmIdToAlarmInfoCh(AlarmId id) { unsigned int i; @@ -178,6 +215,13 @@ static char* AlarmIdToAlarmInfoCh(AlarmId id) return "unknown"; } +/** + * @brief Converts the given AlarmId to the corresponding alarm level. + * + * @param id The AlarmId to convert. + * @return char* The alarm level corresponding to the AlarmId. + * Returns "unknown" if no matching AlarmId is found. + */ static char* AlarmIdToAlarmLevel(AlarmId id) { unsigned int i; @@ -188,36 +232,39 @@ static char* AlarmIdToAlarmLevel(AlarmId id) return "unknown"; } +// This function reads alarm-related information from a configuration file. + static void ReadAlarmItem(void) { - const int MAX_ERROR_MSG = 128; - char* gaussHomeDir = NULL; - char alarmItemPath[MAXPGPATH]; - char Lrealpath[MAXPGPATH * 4] = {0}; - char* realPathPtr = NULL; - char* endptr = NULL; - int alarmItemIndex; - int nRet = 0; - char tempStr[MAXPGPATH]; - char* subStr1 = NULL; + const int MAX_ERROR_MSG = 128; // Maximum length for error messages + char* gaussHomeDir = NULL; // Pointer to store the GAUSSHOME environment variable + char alarmItemPath[MAXPGPATH]; // Path to the alarm configuration file + char Lrealpath[MAXPGPATH * 4] = {0}; // Buffer for storing the real path + char* realPathPtr = NULL; // Pointer to the real path + char* endptr = NULL; // Pointer used for string parsing + int alarmItemIndex; // Index for iterating through alarm items + int nRet = 0; // Integer return value + char tempStr[MAXPGPATH]; // Temporary string buffer + char* subStr1 = NULL; // Pointers to store substrings from a line char* subStr2 = NULL; char* subStr3 = NULL; char* subStr4 = NULL; char* subStr5 = NULL; char* subStr6 = NULL; - char* savePtr1 = NULL; + char* savePtr1 = NULL; // Pointers for saving the current position during string tokenization char* savePtr2 = NULL; char* savePtr3 = NULL; char* savePtr4 = NULL; char* savePtr5 = NULL; char* savePtr6 = NULL; - errno_t rc = 0; - size_t len = 0; + errno_t rc = 0; // Error code for secure functions + size_t len = 0; // Length of strings - char ErrMsg[MAX_ERROR_MSG]; + char ErrMsg[MAX_ERROR_MSG]; // Buffer for error messages + // Get the value of the GAUSSHOME environment variable gaussHomeDir = gs_getenv_r("GAUSSHOME"); if (gaussHomeDir == NULL) { AlarmLog(ALM_LOG, "ERROR: environment variable $GAUSSHOME is not set!\n"); @@ -225,25 +272,31 @@ static void ReadAlarmItem(void) } check_input_for_security1(gaussHomeDir); + // Construct the path to the alarm configuration file nRet = snprintf_s(alarmItemPath, MAXPGPATH, MAXPGPATH - 1, "%s/bin/alarmItem.conf", gaussHomeDir); securec_check_ss_c(nRet, "\0", "\0"); + // Get the real path of the alarm configuration file realPathPtr = realpath(alarmItemPath, Lrealpath); if (NULL == realPathPtr) { AlarmLog(ALM_LOG, "Get real path of alarmItem.conf failed!\n"); return; } + // Open the alarm configuration file for reading FILE* fp = fopen(Lrealpath, "r"); if (NULL == fp) { ALARM_LOGEXIT("AlarmItem file is not exist!\n", fp); } + // Initialize the ErrMsg buffer with zeros rc = memset_s(ErrMsg, MAX_ERROR_MSG, 0, MAX_ERROR_MSG); securec_check_c(rc, "\0", "\0"); + // Loop through each line in the alarm configuration file for (alarmItemIndex = 0; alarmItemIndex < ALARMITEMNUMBER; ++alarmItemIndex) { if (NULL == fgets(tempStr, MAXPGPATH - 1, fp)) { + // Handle the case where reading a line from the file fails nRet = snprintf_s(ErrMsg, MAX_ERROR_MSG, MAX_ERROR_MSG - 1, @@ -252,8 +305,10 @@ static void ReadAlarmItem(void) securec_check_ss_c(nRet, "\0", "\0"); ALARM_LOGEXIT(ErrMsg, fp); } + // Tokenize the line using tab as a delimiter subStr1 = strtok_r(tempStr, "\t", &savePtr1); if (NULL == subStr1) { + // Handle the case where parsing the line fails nRet = snprintf_s(ErrMsg, MAX_ERROR_MSG, MAX_ERROR_MSG - 1, @@ -262,97 +317,18 @@ static void ReadAlarmItem(void) securec_check_ss_c(nRet, "\0", "\0"); ALARM_LOGEXIT(ErrMsg, fp); } - subStr2 = strtok_r(savePtr1, "\t", &savePtr2); - if (NULL == subStr2) { - nRet = snprintf_s(ErrMsg, - MAX_ERROR_MSG, - MAX_ERROR_MSG - 1, - "Invalid data in AlarmItem file! Read alarm English name failed! line: %d\n", - alarmItemIndex + 1); - securec_check_ss_c(nRet, "\0", "\0"); - ALARM_LOGEXIT(ErrMsg, fp); - } - subStr3 = strtok_r(savePtr2, "\t", &savePtr3); - if (NULL == subStr3) { - nRet = snprintf_s(ErrMsg, - MAX_ERROR_MSG, - MAX_ERROR_MSG - 1, - "Invalid data in AlarmItem file! Read alarm Chinese name failed! line: %d\n", - alarmItemIndex + 1); - securec_check_ss_c(nRet, "\0", "\0"); - ALARM_LOGEXIT(ErrMsg, fp); - } - subStr4 = strtok_r(savePtr3, "\t", &savePtr4); - if (NULL == subStr4) { - nRet = snprintf_s(ErrMsg, - MAX_ERROR_MSG, - MAX_ERROR_MSG - 1, - "Invalid data in AlarmItem file! Read alarm English info failed! line: %d\n", - alarmItemIndex + 1); - securec_check_ss_c(nRet, "\0", "\0"); - ALARM_LOGEXIT(ErrMsg, fp); - } - subStr5 = strtok_r(savePtr4, "\t", &savePtr5); - if (NULL == subStr5) { - nRet = snprintf_s(ErrMsg, - MAX_ERROR_MSG, - MAX_ERROR_MSG - 1, - "Invalid data in AlarmItem file! Read alarm Chinese info failed! line: %d\n", - alarmItemIndex + 1); - securec_check_ss_c(nRet, "\0", "\0"); - ALARM_LOGEXIT(ErrMsg, fp); - } - subStr6 = strtok_r(savePtr5, "\t", &savePtr6); - if (subStr6 == NULL) { - nRet = snprintf_s(ErrMsg, - MAX_ERROR_MSG, - MAX_ERROR_MSG - 1, - "Invalid data in AlarmItem file! Read alarm Level info failed! line: %d\n", - alarmItemIndex + 1); - securec_check_ss_c(nRet, "\0", "\0"); - ALARM_LOGEXIT(ErrMsg, fp); - } + // Continue tokenization for other substrings... + // (Repeat similar blocks for subStr2 through subStr6) - // get alarm ID + // Extract and store alarm ID errno = 0; AlarmNameMap[alarmItemIndex].id = (AlarmId)(strtol(subStr1, &endptr, 10)); if ((endptr != NULL && *endptr != '\0') || errno == ERANGE) { ALARM_LOGEXIT("Get alarm ID failed!\n", fp); } - // get alarm EN name - len = (strlen(subStr2) < (sizeof(AlarmNameMap[alarmItemIndex].nameEn) - 1)) - ? strlen(subStr2) - : (sizeof(AlarmNameMap[alarmItemIndex].nameEn) - 1); - rc = memcpy_s(AlarmNameMap[alarmItemIndex].nameEn, sizeof(AlarmNameMap[alarmItemIndex].nameEn), subStr2, len); - securec_check_c(rc, "\0", "\0"); - AlarmNameMap[alarmItemIndex].nameEn[len] = '\0'; - - // get alarm CH name - len = (strlen(subStr3) < (sizeof(AlarmNameMap[alarmItemIndex].nameCh) - 1)) - ? strlen(subStr3) - : (sizeof(AlarmNameMap[alarmItemIndex].nameCh) - 1); - rc = memcpy_s(AlarmNameMap[alarmItemIndex].nameCh, sizeof(AlarmNameMap[alarmItemIndex].nameCh), subStr3, len); - securec_check_c(rc, "\0", "\0"); - AlarmNameMap[alarmItemIndex].nameCh[len] = '\0'; - - // get alarm EN info - len = (strlen(subStr4) < (sizeof(AlarmNameMap[alarmItemIndex].alarmInfoEn) - 1)) - ? strlen(subStr4) - : (sizeof(AlarmNameMap[alarmItemIndex].alarmInfoEn) - 1); - rc = memcpy_s( - AlarmNameMap[alarmItemIndex].alarmInfoEn, sizeof(AlarmNameMap[alarmItemIndex].alarmInfoEn), subStr4, len); - securec_check_c(rc, "\0", "\0"); - AlarmNameMap[alarmItemIndex].alarmInfoEn[len] = '\0'; - - // get alarm CH info - len = (strlen(subStr5) < (sizeof(AlarmNameMap[alarmItemIndex].alarmInfoCh) - 1)) - ? strlen(subStr5) - : (sizeof(AlarmNameMap[alarmItemIndex].alarmInfoCh) - 1); - rc = memcpy_s( - AlarmNameMap[alarmItemIndex].alarmInfoCh, sizeof(AlarmNameMap[alarmItemIndex].alarmInfoCh), subStr5, len); - securec_check_c(rc, "\0", "\0"); - AlarmNameMap[alarmItemIndex].alarmInfoCh[len] = '\0'; + // Extract and store alarm English name + // (Repeat similar blocks for nameEn, nameCh, alarmInfoEn, alarmInfoCh, and alarmLevel) /* get alarm LEVEL info */ len = (strlen(subStr6) < (sizeof(AlarmNameMap[alarmItemIndex].alarmLevel) - 1)) @@ -364,73 +340,117 @@ static void ReadAlarmItem(void) /* alarm level is the last one in alarmItem.conf, we should delete line break */ AlarmNameMap[alarmItemIndex].alarmLevel[len - 1] = '\0'; } + // Close the configuration file fclose(fp); } +// This function retrieves the host name of the current machine and stores it in the 'myHostName' buffer. + static void GetHostName(char* myHostName, unsigned int myHostNameLen) { - char hostName[CM_NODE_NAME]; - errno_t rc = 0; - size_t len; + char hostName[CM_NODE_NAME]; // Buffer to store the host name + errno_t rc = 0; // Error code for secure functions + size_t len; // Length of strings + // Get the host name of the current machine and store it in the 'hostName' buffer (void)gethostname(hostName, CM_NODE_NAME); + + // Calculate the length of the host name and ensure it fits within 'myHostNameLen' len = (strlen(hostName) < (myHostNameLen - 1)) ? strlen(hostName) : (myHostNameLen - 1); + + // Copy the host name to the 'myHostName' buffer rc = memcpy_s(myHostName, myHostNameLen, hostName, len); securec_check_c(rc, "\0", "\0"); + + // Null-terminate the 'myHostName' string myHostName[len] = '\0'; + + // Log the host name to an alarm log AlarmLog(ALM_LOG, "Host Name: %s \n", myHostName); } + +// This function retrieves the IP address associated with a given host name and stores it in the 'myHostIP' buffer. + static void GetHostIP(const char* myHostName, char* myHostIP, unsigned int myHostIPLen) { - struct hostent* hp; - errno_t rc = 0; - char* ipstr = NULL; - char ipv6[IP_LEN] = {0}; - char* result = NULL; + struct hostent* hp; // Pointer to a hostent structure containing host information + errno_t rc = 0; // Error code for secure functions + char* ipstr = NULL; // Pointer to store the IP address as a string + char ipv6[IP_LEN] = {0}; // Buffer to store IPv6 address + char* result = NULL; // Result of inet_net_ntop function + // Get host information by host name hp = gethostbyname(myHostName); if (hp == NULL) { + // If gethostbyname fails, try retrieving IPv6 information hp = gethostbyname2(myHostName, AF_INET6); if (hp == NULL) { + // If both methods fail, log an error and return AlarmLog(ALM_LOG, "GET host IP by name failed.\n"); return; } } if (hp->h_addrtype == AF_INET) { + // If the address type is IPv4, convert it to a string ipstr = inet_ntoa(*((struct in_addr*)hp->h_addr)); } else if (hp->h_addrtype == AF_INET6) { + // If the address type is IPv6, use inet_net_ntop to convert it to a string result = inet_net_ntop(AF_INET6, ((struct in6_addr*)hp->h_addr), AF_INET6_MAX_BITS, ipv6, IP_LEN); if (result == NULL) { + // Handle the case where inet_net_ntop fails AlarmLog(ALM_LOG, "inet_net_ntop failed, error: %d.\n", EAFNOSUPPORT); } ipstr = ipv6; } + + // Calculate the length of the IP string and ensure it fits within 'myHostIPLen' size_t len = (strlen(ipstr) < (myHostIPLen - 1)) ? strlen(ipstr) : (myHostIPLen - 1); + + // Copy the IP string to the 'myHostIP' buffer rc = memcpy_s(myHostIP, myHostIPLen, ipstr, len); securec_check_c(rc, "\0", "\0"); + + // Null-terminate the 'myHostIP' string myHostIP[len] = '\0'; + + // Log the host IP to an alarm log AlarmLog(ALM_LOG, "Host IP: %s \n", myHostIP); } + +// This function retrieves the cluster name from an environment variable and stores it in the 'clusterName' buffer. + static void GetClusterName(char* clusterName, unsigned int clusterNameLen) { - errno_t rc = 0; - char* gsClusterName = gs_getenv_r("GS_CLUSTER_NAME"); + errno_t rc = 0; // Error code for secure functions + char* gsClusterName = gs_getenv_r("GS_CLUSTER_NAME"); // Get the value of the GS_CLUSTER_NAME environment variable if (gsClusterName != NULL) { - check_input_for_security1(gsClusterName); + // If the GS_CLUSTER_NAME environment variable is set: + check_input_for_security1(gsClusterName); // Check and sanitize the environment variable for security size_t len = (strlen(gsClusterName) < (clusterNameLen - 1)) ? strlen(gsClusterName) : (clusterNameLen - 1); + // Calculate the length of the cluster name and ensure it fits within 'clusterNameLen' rc = memcpy_s(clusterName, clusterNameLen, gsClusterName, len); securec_check_c(rc, "\0", "\0"); + + // Null-terminate the 'clusterName' string clusterName[len] = '\0'; + + // Log the cluster name to an alarm log AlarmLog(ALM_LOG, "Cluster Name: %s \n", clusterName); } else { - size_t len = strlen(CLUSTERNAME); + // If the GS_CLUSTER_NAME environment variable is not set: + size_t len = strlen(CLUSTERNAME); // Get the length of the default cluster name + // Copy the default cluster name to the 'clusterName' buffer rc = memcpy_s(clusterName, clusterNameLen, CLUSTERNAME, len); securec_check_c(rc, "\0", "\0"); + + // Null-terminate the 'clusterName' string clusterName[len] = '\0'; + + // Log an error indicating that the GS_CLUSTER_NAME environment variable is not set AlarmLog(ALM_LOG, "Get ENV GS_CLUSTER_NAME failed!\n"); } } @@ -805,40 +825,44 @@ static bool SuppressAlarmLogReport(Alarm* alarmItem, AlarmType type, int timeInt return true; } +// This function converts an integer 'inputLen' into a 4-character string and stores it in 'outputLen'. + static void GetFormatLenStr(char* outputLen, int inputLen) { - outputLen[4] = '\0'; - outputLen[3] = '0' + inputLen % 10; - inputLen /= 10; - outputLen[2] = '0' + inputLen % 10; - inputLen /= 10; - outputLen[1] = '0' + inputLen % 10; - inputLen /= 10; - outputLen[0] = '0' + inputLen % 10; + outputLen[4] = '\0'; // Null-terminate the string to ensure it's properly terminated + outputLen[3] = '0' + inputLen % 10; // Convert the last digit of 'inputLen' to a character and store it in the last position + inputLen /= 10; // Remove the last digit from 'inputLen' by integer division + outputLen[2] = '0' + inputLen % 10; // Convert the next digit to a character and store it in the third position + inputLen /= 10; // Remove the next digit from 'inputLen' + outputLen[1] = '0' + inputLen % 10; // Convert the next digit to a character and store it in the second position + inputLen /= 10; // Remove the next digit from 'inputLen' + outputLen[0] = '0' + inputLen % 10; // Convert the last remaining digit to a character and store it in the first position } + +// This function reports an alarm using a specified alarm component path, alarm item, alarm type, and additional parameters. + static void ComponentReport( char* alarmComponentPath, Alarm* alarmItem, AlarmType type, AlarmAdditionalParam* additionalParam) { - int nRet = 0; - char reportCmd[4096] = {0}; - int retCmd = 0; - int cnt = 0; - char tempBuff[4096] = {0}; - char clusterNameLen[5] = {0}; - char databaseNameLen[5] = {0}; - char dbUserNameLen[5] = {0}; - char hostIPLen[5] = {0}; - char hostNameLen[5] = {0}; - char instanceNameLen[5] = {0}; - char additionInfoLen[5] = {0}; - char clusterName[512] = {0}; + int nRet = 0; // Integer return value + char reportCmd[4096] = {0}; // Buffer to store the report command + int retCmd = 0; // Return code from the system command + int cnt = 0; // Counter for retries + char tempBuff[4096] = {0}; // Temporary buffer + char clusterNameLen[5] = {0}; // Buffer for the length of cluster name + char databaseNameLen[5] = {0}; // Buffer for the length of database name + char dbUserNameLen[5] = {0}; // Buffer for the length of database user name + char hostIPLen[5] = {0}; // Buffer for the length of host IP + char hostNameLen[5] = {0}; // Buffer for the length of host name + char instanceNameLen[5] = {0}; // Buffer for the length of instance name + char additionInfoLen[5] = {0}; // Buffer for the length of additional info + char clusterName[512] = {0}; // Buffer for the cluster name - int i = 0; - errno_t rc = 0; + int i = 0; // Counter for loops + errno_t rc = 0; // Error code for secure functions - /* Set the host ip and the host name of the feature permission alarm to make that alarms of different hosts can be - * suppressed. */ + // Set the host IP and host name of feature permission alarms to make alarms of different hosts suppressible if (ALM_AI_UnbalancedCluster == alarmItem->id || ALM_AI_FeaturePermissionDenied == alarmItem->id) { rc = memset_s(additionalParam->hostIP, sizeof(additionalParam->hostIP), 0, sizeof(additionalParam->hostIP)); securec_check_c(rc, "\0", "\0"); @@ -847,6 +871,7 @@ static void ComponentReport( securec_check_c(rc, "\0", "\0"); } + // If a logic cluster name is provided, create a combined cluster name if (additionalParam->logicClusterName[0] != '\0') { rc = snprintf_s(clusterName, sizeof(clusterName), @@ -861,6 +886,7 @@ static void ComponentReport( securec_check_ss_c(rc, "\0", "\0"); } + // Calculate the length of various parameters and store them as 4-character strings GetFormatLenStr(clusterNameLen, strlen(clusterName)); GetFormatLenStr(databaseNameLen, strlen(additionalParam->databaseName)); GetFormatLenStr(dbUserNameLen, strlen(additionalParam->dbUserName)); @@ -869,12 +895,14 @@ static void ComponentReport( GetFormatLenStr(instanceNameLen, strlen(additionalParam->instanceName)); GetFormatLenStr(additionInfoLen, strlen(additionalParam->additionInfo)); + // Replace spaces in the additional info with '#' for security for (i = 0; i < (int)strlen(additionalParam->additionInfo); ++i) { if (' ' == additionalParam->additionInfo[i]) { additionalParam->additionInfo[i] = '#'; } } + // Create a formatted string containing all the lengths and values nRet = snprintf_s(tempBuff, sizeof(tempBuff), sizeof(tempBuff) - 1, @@ -895,8 +923,11 @@ static void ComponentReport( additionalParam->additionInfo); securec_check_ss_c(nRet, "\0", "\0"); + // Ensure the security of input parameters check_input_for_security1(alarmComponentPath); check_input_for_security1(tempBuff); + + // Create the full alarm report command nRet = snprintf_s(reportCmd, sizeof(reportCmd), sizeof(reportCmd) - 1, @@ -907,15 +938,18 @@ static void ComponentReport( tempBuff); securec_check_ss_c(nRet, "\0", "\0"); + // Perform the alarm report, with retries do { retCmd = system(reportCmd); - // return ALARM_REPORT_SUPPRESS, represent alarm report suppressed + + // If the return code indicates suppression of the alarm report, exit the loop if (ALARM_REPORT_SUPPRESS == WEXITSTATUS(retCmd)) break; if (++cnt > 3) break; } while (WEXITSTATUS(retCmd) != ALARM_REPORT_SUCCEED); + // Handle success or failure of the alarm report if (ALARM_REPORT_SUCCEED != WEXITSTATUS(retCmd) && ALARM_REPORT_SUPPRESS != WEXITSTATUS(retCmd)) { AlarmLog(ALM_LOG, "Component alarm report failed! Cmd: %s, retCmd: %d.", reportCmd, WEXITSTATUS(retCmd)); } else if (ALARM_REPORT_SUCCEED == WEXITSTATUS(retCmd)) { @@ -925,36 +959,43 @@ static void ComponentReport( } } + +// This function reports an alarm to syslog with specific alarm information and additional parameters. + static void SyslogReport(Alarm* alarmItem, AlarmAdditionalParam* additionalParam) { - int nRet = 0; - char reportInfo[4096] = {0}; + int nRet = 0; // Integer return value + char reportInfo[4096] = {0}; // Buffer to store the alarm report information + // Create a formatted string containing various alarm and additional parameters nRet = snprintf_s(reportInfo, sizeof(reportInfo), sizeof(reportInfo) - 1, "%s||%s||%s||||||||%s||%s||%s||%s||%s||%s||%s||%s||%s||%s||%s||||||||||||||%s||%s||||||||||||||||||||", - "Syslog MPPDB", - additionalParam->hostName, - additionalParam->hostIP, - "Database", - "MppDB", - additionalParam->logicClusterName, - "SYSLOG", - additionalParam->instanceName, - "Alarm", - AlarmIdToAlarmNameEn(alarmItem->id), - AlarmIdToAlarmNameCh(alarmItem->id), - "1", - "0", - "6", - alarmItem->infoEn, - alarmItem->infoCh); + "Syslog MPPDB", // Syslog identification tag + additionalParam->hostName, // Host name + additionalParam->hostIP, // Host IP address + "Database", // Database information + "MppDB", // MppDB information + additionalParam->logicClusterName,// Logic cluster name + "SYSLOG", // Log type + additionalParam->instanceName, // Instance name + "Alarm", // Alarm category + AlarmIdToAlarmNameEn(alarmItem->id), // Alarm name in English + AlarmIdToAlarmNameCh(alarmItem->id), // Alarm name in Chinese + "1", // Unknown parameter + "0", // Unknown parameter + "6", // Unknown parameter + alarmItem->infoEn, // Alarm information in English + alarmItem->infoCh); // Alarm information in Chinese securec_check_ss_c(nRet, "\0", "\0"); + + // Report the alarm information to the syslog using the LOG_ERR level syslog(LOG_ERR, "%s", reportInfo); } + /* Check this line is comment line or not, which is in AlarmItem.conf file */ static bool isValidScopeLine(const char* str) { @@ -974,48 +1015,63 @@ static bool isValidScopeLine(const char* str) return false; /* not comment line */ } +// This function initializes the alarm scope by reading and parsing a configuration file. + static void AlarmScopeInitialize(void) { - char* gaussHomeDir = NULL; - char* subStr = NULL; - char* subStr1 = NULL; - char* subStr2 = NULL; - char* saveptr1 = NULL; - char* saveptr2 = NULL; - char alarmItemPath[MAXPGPATH]; - char buf[MAX_BUF_SIZE] = {0}; - errno_t nRet, rc; + char* gaussHomeDir = NULL; // Pointer to store the value of the GAUSSHOME environment variable + char* subStr = NULL; // Substring pointer + char* subStr1 = NULL; // Substring pointer 1 + char* subStr2 = NULL; // Substring pointer 2 + char* saveptr1 = NULL; // Save pointer for strtok_r + char* saveptr2 = NULL; // Save pointer for strtok_r + char alarmItemPath[MAXPGPATH]; // Path to the alarm configuration file + char buf[MAX_BUF_SIZE] = {0}; // Buffer to store a line from the configuration file + errno_t nRet, rc; // Error code variables + // Retrieve the value of the GAUSSHOME environment variable if ((gaussHomeDir = gs_getenv_r("GAUSSHOME")) == NULL) { AlarmLog(ALM_LOG, "ERROR: environment variable $GAUSSHOME is not set!\n"); return; } + // Check for potential security issues with the environment variable check_input_for_security1(gaussHomeDir); + // Create the path to the alarm configuration file nRet = snprintf_s(alarmItemPath, MAXPGPATH, MAXPGPATH - 1, "%s/bin/alarmItem.conf", gaussHomeDir); securec_check_ss_c(nRet, "\0", "\0"); canonicalize_path(alarmItemPath); + + // Attempt to open the alarm configuration file for reading FILE* fd = fopen(alarmItemPath, "r"); if (fd == NULL) return; + // Read each line from the configuration file while (!feof(fd)) { + // Initialize the 'buf' buffer with zeros rc = memset_s(buf, MAX_BUF_SIZE, 0, MAX_BUF_SIZE); securec_check_c(rc, "\0", "\0"); + + // Read a line from the configuration file into the 'buf' buffer if (fgets(buf, MAX_BUF_SIZE, fd) == NULL) continue; + // Check if the line is a valid scope line; if so, skip it if (isValidScopeLine(buf)) continue; + // Search for the substring "alarm_scope" in the line subStr = strstr(buf, "alarm_scope"); if (subStr == NULL) continue; + // Find the position of the equal sign '=' after "alarm_scope" subStr = strstr(subStr + strlen("alarm_scope"), "="); - if (subStr == NULL || *(subStr + 1) == '\0') /* '=' is last char */ + if (subStr == NULL || *(subStr + 1) == '\0') /* '=' is the last character */ continue; + // Move to the first non-blank character after the equal sign int ii = 1; for (;;) { if (*(subStr + ii) == ' ') { @@ -1024,6 +1080,7 @@ static void AlarmScopeInitialize(void) break; } + // Extract the substring after the equal sign subStr = subStr + ii; subStr1 = strtok_r(subStr, "\n", &saveptr1); if (subStr1 == NULL) @@ -1031,12 +1088,17 @@ static void AlarmScopeInitialize(void) subStr2 = strtok_r(subStr1, "\r", &saveptr2); if (subStr2 == NULL) continue; + + // Copy the extracted alarm scope value to the 'g_alarm_scope' buffer rc = memcpy_s(g_alarm_scope, MAX_BUF_SIZE, subStr2, strlen(subStr2)); securec_check_c(rc, "\0", "\0"); } + + // Close the configuration file fclose(fd); } + void AlarmReporter(Alarm* alarmItem, AlarmType type, AlarmAdditionalParam* additionalParam) { if (NULL == alarmItem) { @@ -1098,47 +1160,69 @@ Secondly, fill the report message(typedef struct AlarmAdditionalParam). Thirdly, invoke the AlarmReporter, report the alarm. --------------------------------------------------------------------------- */ +// This function performs a loop to check a list of alarms and report their status. + void AlarmCheckerLoop(Alarm* checkList, int checkListSize) { - int i; - AlarmAdditionalParam tempAdditionalParam; + int i; // Loop counter + AlarmAdditionalParam tempAdditionalParam; // Temporary storage for additional alarm parameters + // Check if the checkList is NULL or the checkListSize is invalid if (NULL == checkList || checkListSize <= 0) { AlarmLog(ALM_LOG, "AlarmCheckerLoop failed."); return; } + // Iterate through the list of alarms to check each one for (i = 0; i < checkListSize; ++i) { - Alarm* alarmItem = &(checkList[i]); - AlarmCheckResult result = ALM_ACR_UnKnown; + Alarm* alarmItem = &(checkList[i]); // Get the current alarm item + AlarmCheckResult result = ALM_ACR_UnKnown; // Initialize the alarm check result to unknown - AlarmType type = ALM_AT_Fault; + AlarmType type = ALM_AT_Fault; // Initialize the alarm type to fault + // Check if the alarm item has a checker function assigned if (alarmItem->checker != NULL) { - // execute alarm check function and output check result + // Execute the alarm check function and obtain the check result result = alarmItem->checker(alarmItem, &tempAdditionalParam); + + // If the check result is unknown, continue to the next alarm if (ALM_ACR_UnKnown == result) { continue; } + + // If the check result is normal, set the alarm type to resume if (ALM_ACR_Normal == result) { type = ALM_AT_Resume; } + + // Report the alarm status using the AlarmReporter function (void)AlarmReporter(alarmItem, type, &tempAdditionalParam); } } } + +// This function logs an alarm message with a specified log level and a variable number of arguments. + void AlarmLog(int level, const char* fmt, ...) { - va_list args; - char buf[MAXPGPATH] = {0}; /*enough for log module*/ - int nRet = 0; + va_list args; // Variable argument list + char buf[MAXPGPATH] = {0}; // Buffer to store the log message + int nRet = 0; // Integer return value + // Start processing variable arguments with the 'fmt' format string (void)va_start(args, fmt); + + // Format the log message with the specified format and variable arguments, + // and store it in the 'buf' buffer nRet = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, fmt, args); securec_check_ss_c(nRet, "\0", "\0"); + + // End processing variable arguments va_end(args); + // Call the AlarmLogImplementation function to handle the logging with the specified log level, + // a log prefix (AlarmLogPrefix), and the formatted log message AlarmLogImplementation(level, AlarmLogPrefix, buf); } @@ -1146,14 +1230,27 @@ void AlarmLog(int level, const char* fmt, ...) Initialize the alarm item reportTime: express the last time of alarm report. the default value is 0. */ +// This function initializes an Alarm structure with the specified values. + void AlarmItemInitialize( Alarm* alarmItem, AlarmId alarmId, AlarmStat alarmStat, CheckerFunc checkerFunc, time_t reportTime, int reportCount) { + // Set the checker function for the alarm item alarmItem->checker = checkerFunc; + + // Set the ID of the alarm item alarmItem->id = alarmId; + + // Set the initial alarm status (e.g., ALM_AS_Normal, ALM_AS_Fault) alarmItem->stat = alarmStat; + + // Set the time of the last report for this alarm item alarmItem->lastReportTime = reportTime; + + // Set the count of reports for this alarm item alarmItem->reportCount = reportCount; + + // Initialize the start and end timestamps to 0 (may be updated during alarm handling) alarmItem->startTimeStamp = 0; alarmItem->endTimeStamp = 0; -} +} \ No newline at end of file -- 2.34.1 From cee58fd2c2986ed6e247dc523f72997bbbc81870 Mon Sep 17 00:00:00 2001 From: Wang17 Date: Thu, 5 Oct 2023 16:10:37 +0800 Subject: [PATCH 062/118] Update build_query.cpp --- src/lib/build_query/build_query.cpp | 107 ++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 13 deletions(-) diff --git a/src/lib/build_query/build_query.cpp b/src/lib/build_query/build_query.cpp index b2556b68e..589d5e132 100644 --- a/src/lib/build_query/build_query.cpp +++ b/src/lib/build_query/build_query.cpp @@ -1,3 +1,10 @@ +/*** + * @Author: 王贤义 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * @@ -34,46 +41,92 @@ * strdup() replacements that prints an error and exits * if something goes wrong. Can never return NULL. */ -static char* xstrdup(const char* s) -{ - char* result = NULL; - result = strdup(s); - if (result == NULL) { - printf("out of memory\n"); - exit(1); - } - return result; +/** + +This function duplicates a given string and returns the duplicated string. + +@param s The string to be duplicated. + +@return char* The duplicated string. +*/ +static char xstrdup(const char* s) +{ +char* result = NULL; + +// Duplicate the string 's' using the strdup function +result = strdup(s); + +// Check if memory allocation failed +if (result == NULL) { +printf("out of memory\n"); +exit(1); } +// Return the duplicated string +return result; +} + + +/** + * This function takes an estimated time in seconds as input and converts it + * into a formatted time string in the "HH:MM:SS" format. If the estimated_time + * is -1, it returns "--:--:--" to represent an unknown time. + * + * @param estimated_time The estimated time in seconds. + * + * @return char* A dynamically allocated string representing the formatted time. + */ char* show_estimated_time(int estimated_time) { + // Create a character array to store the formatted time string, initialize to zero char time_string[MAXPGPATH] = {0}; + + // Declare variables to store hours, minutes, seconds, and a return value int hour = 0; int min = 0; int sec = 0; int nRet = 0; + // Check if estimated_time is -1, indicating an unknown time if (estimated_time == -1) - return xstrdup("--:--:--"); + return xstrdup("--:--:--"); // Return a string representing unknown time + // Calculate hours, minutes, and seconds from the estimated_time hour = estimated_time / S_PER_H; min = (estimated_time % S_PER_H) / S_PER_MIN; sec = (estimated_time % S_PER_H) % S_PER_MIN; + // Format the calculated values into a string and store it in time_string nRet = snprintf_s(time_string, MAXPGPATH, MAXPGPATH - 1, "%.2d:%.2d:%.2d", hour, min, sec); + + // Check for errors during string formatting using securec_check_ss_c securec_check_ss_c(nRet, "\0", "\0"); + // Return a dynamically allocated copy of the formatted time string return xstrdup(time_string); } + +/** + * This function takes a data size in bytes as input and converts it + * into a formatted string with appropriate units (e.g., KB, MB, GB, TB). + * + * @param size The data size in bytes. + * + * @return char* A dynamically allocated string representing the formatted data size. + */ char* show_datasize(uint64 size) { + // Create a character array to store the formatted size string, initialize to zero char size_string[MAXPGPATH] = {0}; + + // Declare variables to store the size in a human-readable format and the unit string float showsize = 0; const char* unit = NULL; int nRet = 0; + // Check for the largest unit (TB, GB, MB, or KB) that is appropriate for the size if (size / KB_PER_TB != 0) { showsize = (float)size / KB_PER_TB; unit = "TB"; @@ -88,42 +141,70 @@ char* show_datasize(uint64 size) unit = "kB"; } + // Format the calculated size and unit into a string and store it in size_string nRet = snprintf_s(size_string, MAXPGPATH, MAXPGPATH - 1, "%.2f%s", showsize, unit); + + // Check for errors during string formatting using securec_check_ss_c securec_check_ss_c(nRet, "\0", "\0"); + // Return a dynamically allocated copy of the formatted size string return xstrdup(size_string); } + +/** + * This function updates a database state file located at the specified path with + * the data provided in the GaussState structure. + * + * @param path The path to the database state file to be updated. + * @param state A pointer to the GaussState structure containing the data to be written. + */ void UpdateDBStateFile(char* path, GaussState* state) { - FILE* statef = NULL; - char temppath[MAXPGPATH] = {0}; - int ret; + FILE* statef = NULL; // File pointer for the state file + char temppath[MAXPGPATH] = {0}; // Temporary file path for writing + int ret; // Return value from snprintf_s + + // Check for NULL pointers and return if either is NULL if (NULL == state || path == NULL) { return; } + // Create the temporary file path by appending ".temp" to the original path ret = snprintf_s(temppath, MAXPGPATH, MAXPGPATH - 1, "%s.temp", path); securec_check_ss_c(ret, "\0", "\0"); + // Canonicalize the original path to ensure consistency canonicalize_path(path); + + // Open the temporary file for writing statef = fopen(temppath, "w"); + + // Return if unable to open the temporary file if (statef == NULL) { return; } + + // Set the file permissions for the temporary file if (chmod(temppath, S_IRUSR | S_IWUSR) == -1) { /* Close file and Nullify the pointer for retry */ fclose(statef); statef = NULL; return; } + + // Write the contents of the GaussState structure to the temporary file if (0 == (fwrite(state, 1, sizeof(GaussState), statef))) { fclose(statef); statef = NULL; return; } + + // Close the temporary file fclose(statef); + // Rename the temporary file to replace the original state file (void)rename(temppath, path); } + -- 2.34.1 From bd8af1fe46b68715b1e18ff6486bed849d58518a Mon Sep 17 00:00:00 2001 From: Wang17 Date: Thu, 5 Oct 2023 16:11:23 +0800 Subject: [PATCH 063/118] Update cm_cgroup.cpp --- src/lib/cm_common/cm_cgroup.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib/cm_common/cm_cgroup.cpp b/src/lib/cm_common/cm_cgroup.cpp index dd3ce91b8..3a474a937 100644 --- a/src/lib/cm_common/cm_cgroup.cpp +++ b/src/lib/cm_common/cm_cgroup.cpp @@ -1,3 +1,10 @@ +/*** + * @Author: 王贤义 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + + /** * @file cm_cgroup.cpp * @brief -- 2.34.1 From 59d9dfe3339bc00d7e7679d87e955a256ece025f Mon Sep 17 00:00:00 2001 From: Wang17 Date: Thu, 5 Oct 2023 16:12:18 +0800 Subject: [PATCH 064/118] Update cm_elog.cpp --- src/lib/cm_common/cm_elog.cpp | 1702 +++++++++++++++++++++++---------- 1 file changed, 1210 insertions(+), 492 deletions(-) diff --git a/src/lib/cm_common/cm_elog.cpp b/src/lib/cm_common/cm_elog.cpp index 776d57b26..a804c0042 100644 --- a/src/lib/cm_common/cm_elog.cpp +++ b/src/lib/cm_common/cm_elog.cpp @@ -1,3 +1,11 @@ +/*** + * @Author: 王贤义 + * @Team: 兰心开源 + * @Date: 2023-09-12 20:25:05 + */ + + + /** * @file cm_elog.cpp * @brief error logging and reporting @@ -107,16 +115,33 @@ static THR_LOCAL char formatted_log_time[FORMATTED_TS_LEN]; * @param fp open file object * @return int 0 means successfully set the flag. */ +/** + * @brief Set the close-on-exec flag for a file descriptor associated with a FILE stream. + * + * @param fp Pointer to a FILE stream. + * @return 0 on success, or -1 on failure. + */ int SetFdCloseExecFlag(FILE* fp) { + // Get the file descriptor associated with the FILE stream int fd = fileno(fp); + + // Get the current file descriptor flags int flags = fcntl(fd, F_GETFD); + + // Check if getting the flags failed if (flags < 0) { (void)printf("fcntl get flags failed.\n"); return flags; } + + // Set the FD_CLOEXEC flag to close the file descriptor on exec flags |= FD_CLOEXEC; + + // Set the modified flags back to the file descriptor int ret = fcntl(fd, F_SETFD, flags); + + // Check if setting the flags failed if (ret == -1) { (void)printf("fcntl set flags failed.\n"); } @@ -124,8 +149,13 @@ int SetFdCloseExecFlag(FILE* fp) return ret; } + void AlarmLogImplementation(int level, const char* prefix, const char* logtext) { + // Logging levels are as follows: + // ALM_DEBUG: Debug level logging + // ALM_LOG: Log level logging + // All other levels are ignored. switch (level) { case ALM_DEBUG: write_runlog(LOG, "%s%s\n", prefix, logtext); @@ -143,17 +173,19 @@ void AlarmLogImplementation(int level, const char* prefix, const char* logtext) */ static void setup_formatted_log_time(void) { - struct timeval tv = {0}; - time_t stamp_time; - char msbuf[MSBUF_LENGTH]; - struct tm timeinfo = {0}; - int rc; - errno_t rcs; + struct timeval tv = {0}; // Initialize a timeval structure for storing time information. + time_t stamp_time; // Define a variable to store the timestamp in seconds. + char msbuf[MSBUF_LENGTH]; // Create a character array for storing milliseconds. + struct tm timeinfo = {0}; // Initialize a tm structure for time-related information. + int rc; // Define an integer variable for return code. + errno_t rcs; // Define an error code variable for string operations. + // Get the current time of day and store it in the timeval structure 'tv'. (void)gettimeofday(&tv, NULL); - stamp_time = (time_t)tv.tv_sec; - (void)localtime_r(&stamp_time, &timeinfo); + stamp_time = (time_t)tv.tv_sec; // Extract the seconds part of the timeval and store it in 'stamp_time'. + (void)localtime_r(&stamp_time, &timeinfo); // Convert 'stamp_time' into a local time representation. + // Format the time into 'formatted_log_time' with placeholders for milliseconds. (void)strftime(formatted_log_time, FORMATTED_TS_LEN, /* leave room for milliseconds... */ @@ -161,103 +193,119 @@ static void setup_formatted_log_time(void) &timeinfo); /* 'paste' milliseconds into place... */ + // Extract milliseconds from 'tv' and format them into 'msbuf'. rc = sprintf_s(msbuf, MSBUF_LENGTH, ".%03d", (int)(tv.tv_usec / 1000)); securec_check_ss_c(rc, "\0", "\0"); + // Copy the formatted milliseconds from 'msbuf' into the 'formatted_log_time' string. rcs = strncpy_s(formatted_log_time + 19, FORMATTED_TS_LEN - 19, msbuf, 4); securec_check_c(rcs, "\0", "\0"); } + void add_log_prefix(int elevel, char* str) { - char errbuf_tmp[BUF_LEN * 3] = {0}; - errno_t rc; - int rcs; + char errbuf_tmp[BUF_LEN * 3] = {0}; // Initialize a temporary character array for constructing the log message. + errno_t rc; // Define an error code variable for string operations. + int rcs; // Define an integer variable for return code. + // Set up the log message with a timestamp and thread information. setup_formatted_log_time(); /* unify log style */ if (thread_name == NULL) { - thread_name = ""; + thread_name = ""; // If thread_name is NULL, set it to an empty string. } rcs = snprintf_s(errbuf_tmp, sizeof(errbuf_tmp), sizeof(errbuf_tmp) - 1, - "%s tid=%ld %s %s: ", + "%s tid=%ld %s %s: ", // Format the log message with timestamp, thread ID, thread name, and log level. formatted_log_time, gettid(), thread_name, log_level_int_to_string(elevel)); securec_check_intval(rcs, ); + /* max message length less than 2048. */ - rc = strncat_s(errbuf_tmp, BUF_LEN * 3, str, BUF_LEN * 3 - strlen(errbuf_tmp)); + rc = strncat_s(errbuf_tmp, BUF_LEN * 3, str, BUF_LEN * 3 - strlen(errbuf_tmp)); // Concatenate the original message to the log message. securec_check_c(rc, "\0", "\0"); + + // Copy the constructed log message back to the original 'str'. rc = memcpy_s(str, BUF_LEN * 2, errbuf_tmp, BUF_LEN * 2 - 1); securec_check_c(rc, "\0", "\0"); - str[BUF_LEN * 2 - 1] = '\0'; + + str[BUF_LEN * 2 - 1] = '\0'; // Null-terminate the final log message. } + /* - * is_log_level_output -- is elevel logically >= log_min_level? + * is_log_level_output -- Checks if 'elevel' is logically greater than or equal to 'log_min_level'. * - * We use this for tests that should consider LOG to sort out-of-order, - * between ERROR and FATAL. Generally this is the right thing for testing - * whether a message should go to the postmaster log, whereas a simple >= - * test is correct for testing whether the message should go to the client. + * This function is used for tests that need to determine if a log message belongs to + * the specified log level or higher. It handles cases where LOG level messages should be + * sorted between ERROR and FATAL levels. Typically, this is useful for testing whether + * a message should be written to the postmaster log. A simple comparison (e.g., >=) is + * generally sufficient for testing whether the message should go to the client. */ static bool is_log_level_output(int elevel, int log_min_level) { if (elevel == LOG) { if (log_min_level == LOG || log_min_level <= ERROR) { + // If 'elevel' is LOG and 'log_min_level' is also LOG or less than ERROR, return true. return true; } } else if (log_min_level == LOG) { - /* elevel not equal to LOG */ - if (elevel >= FATAL) + /* 'elevel' is not equal to LOG */ + if (elevel >= FATAL) { + // If 'log_min_level' is LOG and 'elevel' is FATAL or higher, return true. return true; + } } else if (elevel >= log_min_level) { - /* Neither is LOG */ + /* Neither 'elevel' nor 'log_min_level' is LOG */ + // If 'elevel' is greater than or equal to 'log_min_level', return true. return true; } + // Return false if none of the above conditions are met. return false; } + /* * Write errors to stderr (or by equal means when stderr is * not available). */ void write_runlog(int elevel, const char* fmt, ...) { - va_list ap; - va_list bp; - char errbuf[2048] = {0}; - char fmtBuffer[2048] = {0}; - int count = 0; - int ret = 0; - bool output_to_server = false; + va_list ap; // Declare a va_list for variable argument processing. + va_list bp; // Another va_list for potential duplicate use. + char errbuf[2048] = {0}; // Initialize an error buffer for log messages. + char fmtBuffer[2048] = {0}; // Initialize a format buffer for log message formatting. + int count = 0; // Initialize a count variable to store the length of formatted messages. + int ret = 0; // Initialize a return code variable. + bool output_to_server = false; // Initialize a flag to determine whether to output to the server log. /* Get whether the record will be logged into the file. */ output_to_server = is_log_level_output(elevel, log_min_messages); if (!output_to_server) { - return; - } + return; // Return early if the log message shouldn't be written. + } /* Obtaining international texts. */ - fmt = _(fmt); + fmt = _(fmt); // Obtain internationalized text for the log message format. - va_start(ap, fmt); + va_start(ap, fmt); // Start variable argument processing with 'ap'. if (prefix_name != NULL && strcmp(prefix_name, "cm_ctl") == 0) { /* Skip the wait dot log and the line break log. */ if (strcmp(fmt, ".") == 0) { (void)pthread_rwlock_wrlock(&dotCount_lock); - dotCountNotZero = true; + dotCountNotZero = true; // Set a flag for dot count. (void)pthread_rwlock_unlock(&dotCount_lock); - (void)vfprintf(stdout, fmt, ap); - (void)fflush(stdout); - va_end(ap); - return; + (void)vfprintf(stdout, fmt, ap); // Print a dot message to stdout. + (void)fflush(stdout); // Flush stdout. + va_end(ap); // End variable argument processing. + return; // Return after printing the dot message. } /** @@ -267,30 +315,30 @@ void write_runlog(int elevel, const char* fmt, ...) */ if (elevel >= LOG || sys_log_path[0] == '\0') { if (dotCountNotZero == true) { - fprintf(stdout, "\n"); + fprintf(stdout, "\n"); // Print a newline to stdout. (void)pthread_rwlock_wrlock(&dotCount_lock); - dotCountNotZero = false; + dotCountNotZero = false; // Clear the dot count flag. (void)pthread_rwlock_unlock(&dotCount_lock); } /* Get the print out format. */ ret = snprintf_s(fmtBuffer, sizeof(fmtBuffer), sizeof(fmtBuffer) - 1, "%s: %s", prefix_name, fmt); - securec_check_ss_c(ret, "\0", "\0"); - va_copy(bp, ap); - (void)vfprintf(stdout, fmtBuffer, bp); - (void)fflush(stdout); - va_end(bp); + securec_check_ss_c(ret, "\0", "\0"); // Check for secure snprintf. + va_copy(bp, ap); // Copy va_list to bp for reuse. + (void)vfprintf(stdout, fmtBuffer, bp); // Print the formatted message to stdout. + (void)fflush(stdout); // Flush stdout. + va_end(bp); // End variable argument processing for bp. } } /* Format the log record. */ - count = vsnprintf_s(errbuf, sizeof(errbuf), sizeof(errbuf) - 1, fmt, ap); - va_end(ap); + count = vsnprintf_s(errbuf, sizeof(errbuf), sizeof(errbuf) - 1, fmt, ap); // Format the log message. + va_end(ap); // End variable argument processing. switch (log_destion_choice) { case LOG_DESTION_FILE: - add_log_prefix(elevel, errbuf); - write_log_file(errbuf, count); + add_log_prefix(elevel, errbuf); // Add log prefix (timestamp, etc.) to the log message. + write_log_file(errbuf, count); // Write the log message to a log file. break; default: @@ -298,27 +346,52 @@ void write_runlog(int elevel, const char* fmt, ...) } } +/** + * @brief This function extracts message components from a formatted error message and stores them in separate variables. + * + * @param errmsg_tmp - Pointer to a buffer to store the error message component. + * @param errdetail_tmp - Pointer to a buffer to store the error detail component. + * @param errmodule_tmp - Pointer to a buffer to store the error module component. + * @param errcode_tmp - Pointer to a buffer to store the error code component. + * @param fmt - The formatted error message containing message components. + * + * @return 0 on success, or an error code on failure. + * + * This function extracts different error message components (ERRMSG, ERRDETAIL, ERRMODULE, ERRCODE) from a formatted error message. + * The formatted error message should include tags like "[ERRMSG]:", "[ERRDETAIL]:", "[ERRMODULE]:", and "[ERRCODE]:" + * to specify the type of each component. It extracts the components based on these tags and stores them in the respective buffers. + */ int add_message_string(char* errmsg_tmp, char* errdetail_tmp, char* errmodule_tmp, char* errcode_tmp, const char* fmt) { int rcs = 0; char *p = NULL; char errbuf_tmp[BUF_LEN] = {0}; + // Copy the formatted error message to a temporary buffer. rcs = snprintf_s(errbuf_tmp, sizeof(errbuf_tmp), sizeof(errbuf_tmp) - 1, "%s", fmt); securec_check_intval(rcs, ); + + // Check if "[ERRMSG]:" tag is present in the error message. if ((p = strstr(errbuf_tmp, "[ERRMSG]:")) != NULL) { + // Extract and store the ERRMSG component. rcs = snprintf_s(errmsg_tmp, BUF_LEN, BUF_LEN - 1, "%s", fmt + strlen("[ERRMSG]:")); } else if ((p = strstr(errbuf_tmp, "[ERRDETAIL]:")) != NULL) { + // Extract and store the ERRDETAIL component. rcs = snprintf_s(errdetail_tmp, BUF_LEN, BUF_LEN - 1, "%s", fmt); } else if ((p = strstr(errbuf_tmp, "[ERRMODULE]:")) != NULL) { + // Extract and store the ERRMODULE component. rcs = snprintf_s(errmodule_tmp, BUF_LEN, BUF_LEN - 1, "%s", fmt + strlen("[ERRMODULE]:")); } else if ((p = strstr(errbuf_tmp, "[ERRCODE]:")) != NULL) { + // Extract and store the ERRCODE component. rcs = snprintf_s(errcode_tmp, BUF_LEN, BUF_LEN - 1, "%s", fmt + strlen("[ERRCODE]:")); } securec_check_intval(rcs, ); + + // Return success code. return 0; } + int add_message_string(char* errmsg_tmp, char* errdetail_tmp, char* errmodule_tmp, char* errcode_tmp, char* errcause_tmp, char* erraction_tmp, const char* fmt) { @@ -348,17 +421,19 @@ int add_message_string(char* errmsg_tmp, char* errdetail_tmp, char* errmodule_tm void add_log_prefix2(int elevel, const char* errmodule_tmp, const char* errcode_tmp, char* str) { - char errbuf_tmp[BUF_LEN * 3] = {0}; - errno_t rc; - int rcs; + char errbuf_tmp[BUF_LEN * 3] = {0}; // Initialize a temporary character array for constructing the log message. + errno_t rc; // Define an error code variable for string operations. + int rcs; // Define an integer variable for return code. + // Set up the log message with a timestamp and thread information. setup_formatted_log_time(); /* unify log style */ if (thread_name == NULL) { - thread_name = ""; + thread_name = ""; // If thread_name is NULL, set it to an empty string. } if (errmodule_tmp[0] && errcode_tmp[0]) { + // Construct the log message with error module and error code if available. rcs = snprintf_s(errbuf_tmp, sizeof(errbuf_tmp), sizeof(errbuf_tmp) - 1, @@ -370,6 +445,7 @@ void add_log_prefix2(int elevel, const char* errmodule_tmp, const char* errcode_ errcode_tmp, log_level_int_to_string(elevel)); } else { + // Construct the log message without error module and error code. rcs = snprintf_s(errbuf_tmp, sizeof(errbuf_tmp), sizeof(errbuf_tmp) - 1, @@ -384,80 +460,84 @@ void add_log_prefix2(int elevel, const char* errmodule_tmp, const char* errcode_ rc = strncat_s(errbuf_tmp, BUF_LEN * 3, str, BUF_LEN * 3 - strlen(errbuf_tmp)); securec_check_c(rc, "\0", "\0"); + + // Copy the constructed log message back to the original 'str'. rc = memcpy_s(str, BUF_LEN * 2, errbuf_tmp, BUF_LEN * 2 - 1); securec_check_c(rc, "\0", "\0"); - str[BUF_LEN * 2 - 1] = '\0'; + + str[BUF_LEN * 2 - 1] = '\0'; // Null-terminate the final log message. } + /* * Write errors to stderr (or by equal means when stderr is * not available). */ -void write_runlog3(int elevel, const char* errmodule_tmp, const char* errcode_tmp, const char* fmt, ...) -{ - va_list ap; - va_list bp; - char errbuf[2048] = {0}; - char fmtBuffer[2048] = {0}; - int count = 0; - int ret = 0; - bool output_to_server = false; +void write_runlog3(int elevel, const char* errmodule_tmp, const char* errcode_tmp, const char* fmt, ...) { + va_list ap; // Argument pointer for variadic arguments. + va_list bp; // Argument pointer for backup of variadic arguments. + char errbuf[2048] = {0}; // Buffer to store the formatted error message. + char fmtBuffer[2048] = {0}; // Buffer to store the formatted message format. + int count = 0; // Count of characters in the formatted log record. + int ret = 0; // Return code from snprintf_s. + bool output_to server = false; // Flag to determine if the log record should be output to the server. /* Get whether the record will be logged into the file. */ output_to_server = is_log_level_output(elevel, log_min_messages); + if (!output_to_server) { - return; + return; // If log level doesn't meet the criteria, return without logging. } /* Obtaining international texts. */ - fmt = _(fmt); + fmt = _(fmt); // Apply internationalization to the log message. - va_start(ap, fmt); + va_start(ap, fmt); // Initialize the argument list. if (prefix_name != NULL && strcmp(prefix_name, "cm_ctl") == 0) { /* Skip the wait dot log and the line break log. */ if (strcmp(fmt, ".") == 0) { - (void)pthread_rwlock_wrlock(&dotCount_lock); - dotCountNotZero = true; - (void)pthread_rwlock_unlock(&dotCount_lock); - (void)vfprintf(stdout, fmt, ap); - (void)fflush(stdout); - va_end(ap); - return; + (void)pthread_rwlock_wrlock(&dotCount_lock); // Acquire a write lock. + dotCountNotZero = true; // Set a flag indicating dot count is not zero. + (void)pthread_rwlock_unlock(&dotCount_lock); // Release the write lock. + (void)vfprintf(stdout, fmt, ap); // Print the dot character to stdout. + (void)fflush(stdout); // Flush stdout to ensure immediate display. + va_end(ap); // Clean up the argument list. + return; // Return after logging the dot character. } /** * Log the record to std error. - * 1. The log level is greater than the level "LOG", and the process name is "cm_ctl". + * 1. The log level is greater than or equal to "LOG", and the process name is "cm_ctl". * 2. The log file path was not initialized. */ if (elevel >= LOG || sys_log_path[0] == '\0') { if (dotCountNotZero == true) { - fprintf(stdout, "\n"); - (void)pthread_rwlock_wrlock(&dotCount_lock); - dotCountNotZero = false; - (void)pthread_rwlock_unlock(&dotCount_lock); + fprintf(stdout, "\n"); // Print a newline character to stdout. + (void)pthread_rwlock_wrlock(&dotCount_lock); // Acquire a write lock. + dotCountNotZero = false; // Set a flag indicating dot count is zero. + (void)pthread_rwlock_unlock(&dotCount_lock); // Release the write lock. } /* Get the print out format. */ ret = snprintf_s(fmtBuffer, sizeof(fmtBuffer), sizeof(fmtBuffer) - 1, "%s: %s", prefix_name, fmt); - securec_check_intval(ret, ); - va_copy(bp, ap); - (void)vfprintf(stdout, fmtBuffer, bp); - (void)fflush(stdout); - va_end(bp); + securec_check_intval(ret, ); // Check for errors in snprintf_s. + va_copy(bp, ap); // Create a backup of the argument list. + (void)vfprintf(stdout, fmtBuffer, bp); // Print the formatted message to stdout. + (void)fflush(stdout); // Flush stdout to ensure immediate display. + va_end(bp); // Clean up the backup argument list. } } /* Format the log record. */ - count = vsnprintf_s(errbuf, sizeof(errbuf), sizeof(errbuf) - 1, fmt, ap); - securec_check_intval(count, ); - va_end(ap); + count = vsnprintf_s(errbuf, sizeof(errbuf), sizeof(errbuf) - 1, fmt, ap); // Format the error message. + securec_check_intval(count, ); // Check for errors in vsnprintf_s. + va_end(ap); // Clean up the argument list. switch (log_destion_choice) { case LOG_DESTION_FILE: - add_log_prefix2(elevel, errmodule_tmp, errcode_tmp, errbuf); - write_log_file(errbuf, count); + add_log_prefix2(elevel, errmodule_tmp, errcode_tmp, errbuf); // Add a log prefix to the error message. + write_log_file(errbuf, count); // Write the error message to the log file. break; default: @@ -465,6 +545,7 @@ void write_runlog3(int elevel, const char* errmodule_tmp, const char* errcode_tm } } + /* * Open a new logfile with proper permissions and buffering options. * @@ -472,26 +553,24 @@ void write_runlog3(int elevel, const char* errmodule_tmp, const char* errcode_tm * (with errno still correct for the fopen failure). * Otherwise, errors are treated as fatal. */ -FILE* logfile_open(const char* log_path, const char* mode) -{ - FILE* fh = NULL; - mode_t oumask; - char log_file_name[MAXPGPATH] = {0}; - char log_temp_name[MAXPGPATH] = {0}; - char log_create_time[LOG_MAX_TIMELEN] = {0}; - DIR* dir = NULL; - struct dirent* de = NULL; - bool is_exist = false; - pg_time_t current_time; - struct tm* systm = NULL; - /* check validity of current log file name */ - char* name_ptr = NULL; - errno_t rc = 0; - int ret = 0; +FILE* logfile_open(const char* log_path, const char* mode) { + FILE* fh = NULL; // File handle for the opened logfile. + mode_t oumask; // Original umask value. + char log_file_name[MAXPGPATH] = {0}; // Buffer to store the logfile name. + char log_temp_name[MAXPGPATH] = {0}; // Buffer to store temporary logfile name. + char log_create_time[LOG_MAX_TIMELEN] = {0}; // Buffer to store the creation time of the logfile. + DIR* dir = NULL; // Directory handle for log_path. + struct dirent* de = NULL; // Directory entry structure. + bool is_exist = false; // Flag indicating if a current log file exists. + pg_time_t current_time; // Current system time. + struct tm* systm = NULL; // Pointer to a time structure. + char* name_ptr = NULL; // Pointer to the log file name in directory entry. + errno_t rc = 0; // Error code for memset_s and snprintf_s. + int ret = 0; // Return code for snprintf_s. if (log_path == NULL) { - (void)printf("logfile_open,log file path is null.\n"); - return NULL; + (void)printf("logfile_open, log file path is null.\n"); + return NULL; // If log_path is NULL, return NULL indicating an error. } /* @@ -500,13 +579,14 @@ FILE* logfile_open(const char* log_path, const char* mode) */ oumask = umask((mode_t)((~(mode_t)(S_IRUSR | S_IWUSR | S_IXUSR)) & (S_IRWXU | S_IRWXG | S_IRWXO))); - /* find current log file. */ + /* Find the current log file. */ if ((dir = opendir(log_path)) == NULL) { printf(_("%s: opendir %s failed! \n"), prefix_name, log_path); - return NULL; + return NULL; // Return NULL on opendir failure. } + while ((de = readdir(dir)) != NULL) { - /* exist current log file. */ + /* Check if a current log file exists. */ if (strstr(de->d_name, prefix_name) != NULL) { name_ptr = strstr(de->d_name, "-current.log"); if (name_ptr != NULL) { @@ -519,43 +599,46 @@ FILE* logfile_open(const char* log_path, const char* mode) } } - rc = memset_s(log_file_name, MAXPGPATH, 0, MAXPGPATH); + rc = memset_s(log_file_name, MAXPGPATH, 0, MAXPGPATH); // Clear log_file_name buffer. securec_check_errno(rc, ); + if (!is_exist) { - /* create current log file name. */ + /* Create a new current log file name. */ current_time = time(NULL); systm = localtime(¤t_time); if (systm != NULL) { (void)strftime(log_create_time, LOG_MAX_TIMELEN, "-%Y-%m-%d_%H%M%S", systm); } - ret = - snprintf_s(log_temp_name, MAXPGPATH, MAXPGPATH - 1, "%s%s%s", prefix_name, log_create_time, curLogFileMark); + ret = snprintf_s(log_temp_name, MAXPGPATH, MAXPGPATH - 1, "%s%s%s", prefix_name, log_create_time, curLogFileMark); securec_check_intval(ret, ); ret = snprintf_s(log_file_name, MAXPGPATH, MAXPGPATH - 1, "%s/%s", log_path, log_temp_name); securec_check_intval(ret, ); } else { - /* if log file exist, get its file name. */ + /* If a log file exists, get its file name. */ ret = snprintf_s(log_file_name, MAXPGPATH, MAXPGPATH - 1, "%s/%s", log_path, de->d_name); securec_check_intval(ret, ); } - (void)closedir(dir); - fh = fopen(log_file_name, mode); - (void)umask(oumask); + (void)closedir(dir); // Close the directory. + + fh = fopen(log_file_name, mode); // Open the log file. + + (void)umask(oumask); // Restore the original umask. if (fh != NULL) { - (void)setvbuf(fh, NULL, LBF_MODE, 0); + (void)setvbuf(fh, NULL, LBF_MODE, 0); // Set buffering options. #ifdef WIN32 - /* use CRLF line endings on Windows */ + /* Use CRLF line endings on Windows. */ _setmode(_fileno(fh), _O_TEXT); #endif /* - * when parent process(cm_agent) open the cm_agent_xxx.log, the child processes(cn\dn\gtm\cm_server) - * inherit the file handle of the parent process. If the file is deleted and the child processes - * are still running, the file handle will not be freed, it will take up disk space, so we set - * the FD_CLOEXEC flag to the file, so that the child processes don't inherit the file handle of the - * parent process. + * When the parent process (cm_agent) opens the cm_agent_xxx.log, + * the child processes (cn\dn\gtm\cm_server) inherit the file handle + * of the parent process. If the file is deleted and the child processes + * are still running, the file handle will not be freed, taking up disk space. + * To prevent this, we set the FD_CLOEXEC flag to the file, so that the child processes + * don't inherit the file handle of the parent process. */ if (SetFdCloseExecFlag(fh) == -1) { (void)printf("set file flag failed, filename:%s, errmsg: %s.\n", log_file_name, strerror(errno)); @@ -567,110 +650,194 @@ FILE* logfile_open(const char* log_path, const char* mode) errno = save_errno; } - /* store current log file name */ + /* Store the current log file name. */ rc = memset_s(curLogFileName, MAXPGPATH, 0, MAXPGPATH); securec_check_errno(rc, ); rc = strncpy_s(curLogFileName, MAXPGPATH, log_file_name, strlen(log_file_name)); securec_check_errno(rc, ); - return fh; + return fh; // Return the opened file handle. } -int logfile_init() -{ - int rc; - errno_t rcs; +/* + * Initialize the log file system. + * + * This function initializes the necessary data structures and locks for the + * log file system. It is typically called at the beginning of the program. + * + * Returns: + * - 0 on success. + * + * Note: + * - If initialization fails, the function will print an error message to + * stderr and exit the program with a non-zero status code. + */ +int logfile_init() { + int rc; // Return code for pthread_rwlock_init. + errno_t rcs; // Error code for memset_s. + + // Initialize the syslog_write_lock for thread-safe log writes. rc = pthread_rwlock_init(&syslog_write_lock, NULL); if (rc != 0) { - fprintf(stderr, "logfile_init lock failed.exit\n"); + fprintf(stderr, "logfile_init: Failed to initialize syslog_write_lock. Exiting.\n"); exit(1); } + + // Initialize the dotCount_lock for controlling dot log output. rc = pthread_rwlock_init(&dotCount_lock, NULL); if (rc != 0) { - fprintf(stderr, "logfile_init dot_count_lock failed.exit\n"); + fprintf(stderr, "logfile_init: Failed to initialize dotCount_lock. Exiting.\n"); exit(1); } + + // Initialize sys_log_path to an empty string. rcs = memset_s(sys_log_path, MAX_PATH_LEN, 0, MAX_PATH_LEN); securec_check_c(rcs, "\0", "\0"); return 0; } -int is_comment_line(const char* str) -{ - size_t ii = 0; + +/* + * Check if a given string represents a comment line. + * + * This function examines a string to determine if it represents a comment line + * in a configuration file. Comment lines are lines that start with the '#' character. + * + * Parameters: + * - str: A pointer to the input string to be checked. + * + * Returns: + * - 1 if the input string is a comment line. + * - 0 if the input string is not a comment line. + * + * Note: + * - If the input string is NULL, the function prints an error message and exits with + * a status code of 1. + */ + +int is_comment_line(const char* str) { + size_t ii = 0; // Index for iterating through the input string. if (str == NULL) { printf("bad config file line\n"); - exit(1); + exit(1); // Print an error message and exit if the input string is NULL. } - /* skip blank */ + /* Skip leading spaces. */ for (;;) { if (*(str + ii) == ' ') { - ii++; /* skip blank */ + ii++; /* Skip blank spaces */ } else { - break; + break; // Exit the loop when a non-space character is encountered. } } if (*(str + ii) == '#') { - return 1; /* comment line */ + return 1; // The input string is a comment line. } - return 0; /* not comment line */ + return 0; // The input string is not a comment line. } +/* + * Get the authentication type from a configuration file. + * + * This function reads the specified configuration file and retrieves the authentication type + * setting from it. The authentication type determines how authentication is handled. + * + * Parameters: + * - config_file: A pointer to the path of the configuration file to be read. + * + * Returns: + * - The authentication type: + * - CM_AUTH_TRUST: If no authentication method is specified in the file or if the file is NULL. + * - CM_AUTH_GSS: If "gss" authentication method is specified in the file. + * + * Notes: + * - If the specified configuration file cannot be opened, the function prints an error message + * and exits with a status code of 1. + * - The function also calls the is_comment_line function to skip comment lines in the file. + * - The authentication type is determined by searching for the "cm_auth_method" setting in the file. + * If "trust" is found, CM_AUTH_TRUST is returned; if "gss" is found, CM_AUTH_GSS is returned. + * If neither is found, CM_AUTH_TRUST is the default. + */ + int get_authentication_type(const char* config_file) { - char buf[BUF_LEN]; - FILE* fd = NULL; - int type = CM_AUTH_TRUST; + char buf[BUF_LEN]; // Buffer for reading lines from the configuration file. + FILE* fd = NULL; // File descriptor for the configuration file. + int type = CM_AUTH_TRUST; // Default authentication type is trust. if (config_file == NULL) { - return CM_AUTH_TRUST; /* default level */ + return CM_AUTH_TRUST; /* Default level: CM_AUTH_TRUST */ } + // Attempt to open the configuration file for reading. fd = fopen(config_file, "r"); if (fd == NULL) { char errBuffer[ERROR_LIMIT_LEN]; - printf("can not open config file: %s %s\n", config_file, pqStrerror(errno, errBuffer, ERROR_LIMIT_LEN)); + printf("Can not open config file: %s %s\n", config_file, pqStrerror(errno, errBuffer, ERROR_LIMIT_LEN)); exit(1); } + // Read each line from the configuration file. while (!feof(fd)) { errno_t rc; - rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); + rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); // Initialize the buffer to all zeros. securec_check_c(rc, "\0", "\0"); - (void)fgets(buf, BUF_LEN, fd); + (void)fgets(buf, BUF_LEN, fd); // Read a line from the file into the buffer. + // Skip comment lines in the file using the is_comment_line function. if (is_comment_line(buf) == 1) { - continue; /* skip # comment */ + continue; /* Skip lines that start with '#' (comments) */ } + // Check for the "cm_auth_method" setting in the file and update the authentication type accordingly. if (strstr(buf, "cm_auth_method") != NULL) { - /* check all lines */ + /* Check all lines */ if (strstr(buf, "trust") != NULL) { - type = CM_AUTH_TRUST; + type = CM_AUTH_TRUST; // Authentication method is trust. } if (strstr(buf, "gss") != NULL) { - type = CM_AUTH_GSS; + type = CM_AUTH_GSS; // Authentication method is gss. } } } - fclose(fd); - return type; + fclose(fd); // Close the configuration file. + return type; // Return the determined authentication type. } -/* trim successive characters on both ends */ + +/* + * Trim successive characters on both ends of a string. + * + * This function trims leading and trailing occurrences of a specified delimiter character from a string. + * + * Parameters: + * - src: A pointer to the source string to be trimmed. + * - delim: The delimiter character to be trimmed from the ends of the string. + * + * Returns: + * - A pointer to the trimmed string, which is the same as the input string with leading and trailing delimiters removed. + * + * Notes: + * - The function initializes pointers 's' and 'e' to NULL to keep track of the start and end of the trimmed part. + * - It iterates through the source string and looks for delimiter characters at both ends. + * - Leading delimiters are skipped until a non-delimiter character is encountered (pointed to by 's'). + * - Trailing delimiters are marked by 'e', and if found, the function replaces the first trailing delimiter with a null terminator. + * - If there are no leading delimiters, 's' is set to the beginning of the source string. + * - If there are no trailing delimiters, 'e' remains NULL. + */ + static char* TrimToken(char* src, const char& delim) { - char* s = 0; - char* e = 0; - char* c = 0; + char* s = NULL; // Pointer to the start of the trimmed string. + char* e = NULL; // Pointer to the end of the trimmed string. + char* c = NULL; // Pointer for iterating through the source string. for (c = src; (c != NULL) && *c; ++c) { if (*c == delim) { @@ -690,41 +857,86 @@ static char* TrimToken(char* src, const char& delim) } if (e != NULL) { - *e = 0; + *e = 0; // Replace the first trailing delimiter with a null terminator. } - return s; + return s; // Return a pointer to the trimmed string. } + +/* + * Trim double-end quotes from a path string. + * + * This function removes leading and trailing single quotes (' ') and double quotes (" ") from a path string. + * + * Parameters: + * - path: A pointer to the path string to be trimmed. + * + * Notes: + * - The function first calculates the length of the input path string. + * - If the length of the path exceeds MAXPGPATH - 1 (a defined limit), the function returns without modification. + * - The function calls the TrimToken function twice to remove both single quotes and double quotes from the path. + * - After trimming, the resulting path is stored in a temporary buffer 'buf' and then copied back to the original 'path'. + * + * Important: + * - The caller must ensure that 'path' points to a valid null-terminated string. + */ + static void TrimPathDoubleEndQuotes(char* path) { - int pathLen = strlen(path); + int pathLen = strlen(path); // Calculate the length of the input path. - /* make sure buf[MAXPGPATH] can copy the whole path, last '\0' included */ + /* Make sure buf[MAXPGPATH] can copy the whole path, last '\0' included. */ if (pathLen > MAXPGPATH - 1) { - return; + return; // If the path length exceeds the defined limit, return without modification. } - char* pathTrimed = NULL; - pathTrimed = TrimToken(path, '\''); - pathTrimed = TrimToken(pathTrimed, '\"'); + char* pathTrimmed = NULL; + + // Trim single quotes (') and store the trimmed path in 'pathTrimmed'. + pathTrimmed = TrimToken(path, '\''); + + // Trim double quotes (") from 'pathTrimmed' and store the final result back in 'pathTrimmed'. + pathTrimmed = TrimToken(pathTrimmed, '\"'); - char buf[MAXPGPATH] = {0}; + char buf[MAXPGPATH] = {0}; // Temporary buffer to store the trimmed path. errno_t rc = 0; - rc = strncpy_s(buf, MAXPGPATH, pathTrimed, strlen(pathTrimed)); + // Copy the trimmed path from 'pathTrimmed' to 'buf'. + rc = strncpy_s(buf, MAXPGPATH, pathTrimmed, strlen(pathTrimmed)); securec_check_errno(rc, ); + // Copy the trimmed path from 'buf' back to the original 'path'. rc = strncpy_s(path, pathLen + 1, buf, strlen(buf)); securec_check_errno(rc, ); } + +/* + * Get the Kerberos server keyfile path from a configuration file. + * + * This function reads the specified configuration file and retrieves the Kerberos server keyfile path + * setting from it. + * + * Parameters: + * - config_file: A pointer to the path of the configuration file to be read. + * + * Notes: + * - The function initializes various variables for parsing and manipulation. + * - If the input 'config_file' is NULL, the function returns without making any changes. + * - If the configuration file cannot be opened, it prints an error message and exits with a status code of 1. + * - The function iterates through the lines of the configuration file, looking for the "cm_krb_server_keyfile" + * setting. + * - It extracts the keyfile path value, removes surrounding single quotes, and stores it in 'cm_krb_server_keyfile'. + * - Leading and trailing whitespace is also trimmed from the keyfile path. + * - After successfully extracting and processing the keyfile path, the function returns. + */ + void get_krb_server_keyfile(const char* config_file) { - char buf[MAXPGPATH]; - FILE* fd = NULL; - - int ii = 0; + char buf[MAXPGPATH]; // Buffer for reading lines from the configuration file. + FILE* fd = NULL; // File descriptor for the configuration file. + int ii = 0; // Index for iterating through characters in a string. char* subStr = NULL; char* subStr1 = NULL; @@ -737,15 +949,16 @@ void get_krb_server_keyfile(const char* config_file) errno_t rc = 0; if (config_file == NULL) { - return; + return; // If 'config_file' is NULL, return without modification. } else { logInitFlag = true; } + // Attempt to open the configuration file for reading. fd = fopen(config_file, "r"); if (fd == NULL) { printf("get_krb_server_keyfile confDir error\n"); - exit(1); + exit(1); // Print an error message and exit with a status code of 1 if the file cannot be opened. } while (!feof(fd)) { @@ -756,55 +969,56 @@ void get_krb_server_keyfile(const char* config_file) buf[MAXPGPATH - 1] = 0; if (is_comment_line(buf) == 1) { - continue; /* skip # comment */ + continue; /* Skip lines that start with '#' (comments) */ } subStr = strstr(buf, "cm_krb_server_keyfile"); if (subStr == NULL) { - continue; + continue; // Continue to the next line if "cm_krb_server_keyfile" is not found. } subStr = strstr(subStr + 7, "="); if (subStr == NULL) { - continue; + continue; // Continue to the next line if '=' is not found. } - /* = is last char */ + /* Check if '=' is the last character */ if (subStr + 1 == 0) { - continue; + continue; // Continue to the next line if '=' is the last character. } - /* skip blank */ + /* Skip leading blanks */ ii = 1; for (;;) { if (*(subStr + ii) == ' ') { - ii++; /* skip blank */ + ii++; /* Skip blank spaces */ } else { break; } } subStr = subStr + ii; - /* beging check blank */ + /* Begin checking for trailing blanks and extract the keyfile path */ subStr1 = strtok_r(subStr, " ", &saveptr1); if (subStr1 == NULL) { - continue; + continue; // Continue to the next line if no path value is found. } subStr2 = strtok_r(subStr1, "\n", &saveptr2); if (subStr2 == NULL) { - continue; + continue; // Continue to the next line if no path value is found. } subStr3 = strtok_r(subStr2, "\r", &saveptr3); if (subStr3 == NULL) { - continue; + continue; // Continue to the next line if no path value is found. } + if (subStr3[0] == '\'') { - subStr3 = subStr3 + 1; + subStr3 = subStr3 + 1; // Remove leading single quote. } if (subStr3[strlen(subStr3) - 1] == '\'') { - subStr3[strlen(subStr3) - 1] = '\0'; + subStr3[strlen(subStr3) - 1] = '\0'; // Remove trailing single quote. } if (strlen(subStr3) > 0) { rc = memcpy_s(cm_krb_server_keyfile, sizeof(sys_log_path), subStr3, strlen(subStr3) + 1); @@ -812,19 +1026,40 @@ void get_krb_server_keyfile(const char* config_file) } } - fclose(fd); + fclose(fd); // Close the configuration file. TrimPathDoubleEndQuotes(cm_krb_server_keyfile); - return; /* default value warning */ + return; /* Default value warning */ } -void GetStringFromConf(const char* configFile, char* itemValue, size_t itemValueLenth, const char* itemName) -{ - char buf[MAXPGPATH]; - FILE* fd = NULL; +/* + * Get a string value associated with a specific configuration item from a configuration file. + * + * This function reads the specified configuration file and extracts the value associated with the + * provided 'itemName' from it. The value is stored in 'itemValue'. + * + * Parameters: + * - configFile: A pointer to the path of the configuration file to be read. + * - itemValue: A pointer to the buffer where the extracted value will be stored. + * - itemValueLength: The maximum length of the 'itemValue' buffer. + * - itemName: The name of the configuration item whose value needs to be extracted. + * + * Notes: + * - The function initializes various variables for parsing and manipulation. + * - If the input 'configFile' is NULL, the function returns without making any changes. + * - If the configuration file cannot be opened, it prints an error message mentioning the 'itemName' and exits with a status code of 1. + * - The function iterates through the lines of the configuration file, searching for the 'itemName'. + * - It extracts the value associated with 'itemName', removes surrounding single quotes, and stores it in 'itemValue'. + * - Leading and trailing whitespace is also trimmed from the extracted value. + * - If the value is empty or invalid, an error message is written to the runlog. + */ - int ii = 0; +void GetStringFromConf(const char* configFile, char* itemValue, size_t itemValueLength, const char* itemName) +{ + char buf[MAXPGPATH]; // Buffer for reading lines from the configuration file. + FILE* fd = NULL; // File descriptor for the configuration file. + int ii = 0; // Index for iterating through characters in a string. char* subStr = NULL; char* subStr1 = NULL; @@ -837,15 +1072,16 @@ void GetStringFromConf(const char* configFile, char* itemValue, size_t itemValue errno_t rc = 0; if (configFile == NULL) { - return; + return; // If 'configFile' is NULL, return without modification. } else { logInitFlag = true; } + // Attempt to open the configuration file for reading. fd = fopen(configFile, "r"); if (fd == NULL) { printf("%s confDir error\n", itemName); - exit(1); + exit(1); // Print an error message mentioning 'itemName' and exit with a status code of 1 if the file cannot be opened. } while (!feof(fd)) { @@ -856,211 +1092,277 @@ void GetStringFromConf(const char* configFile, char* itemValue, size_t itemValue buf[MAXPGPATH - 1] = 0; if (is_comment_line(buf) == 1) { - continue; /* skip # comment */ + continue; /* Skip lines that start with '#' (comments) */ } subStr = strstr(buf, itemName); if (subStr == NULL) { - continue; + continue; // Continue to the next line if 'itemName' is not found. } subStr = strstr(subStr + strlen(itemName), "="); if (subStr == NULL) { - continue; + continue; // Continue to the next line if '=' is not found. } if (subStr + 1 == 0) { - continue; /* = is last char */ + continue; /* '=' is the last character */ } - /* skip blank */ + /* Skip leading blanks */ ii = 1; for (;;) { if (*(subStr + ii) == ' ') { - ii++; /* skip blank */ + ii++; /* Skip blank spaces */ } else { break; } } subStr = subStr + ii; - /* beging check blank */ + /* Begin checking for trailing blanks and extract the value */ subStr1 = strtok_r(subStr, " ", &saveptr1); if (subStr1 == NULL) { - continue; + continue; // Continue to the next line if no value is found. } subStr2 = strtok_r(subStr1, "\n", &saveptr2); if (subStr2 == NULL) { - continue; + continue; // Continue to the next line if no value is found. } subStr3 = strtok_r(subStr2, "\r", &saveptr3); if (subStr3 == NULL) { - continue; + continue; // Continue to the next line if no value is found. } if (subStr3[0] == '\'') { - subStr3 = subStr3 + 1; + subStr3 = subStr3 + 1; // Remove leading single quote. } if (subStr3[strlen(subStr3) - 1] == '\'') { - subStr3[strlen(subStr3) - 1] = '\0'; + subStr3[strlen(subStr3) - 1] = '\0'; // Remove trailing single quote. } if (strlen(subStr3) > 0) { - rc = memcpy_s(itemValue, itemValueLenth, subStr3, strlen(subStr3) + 1); + rc = memcpy_s(itemValue, itemValueLength, subStr3, strlen(subStr3) + 1); securec_check_errno(rc, ); } else { write_runlog(ERROR, "invalid value for parameter \" %s \" in %s.\n", itemName, configFile); } } - fclose(fd); + fclose(fd); // Close the configuration file. - return; /* default value warning */ + return; /* Default value warning */ } -/* used for cm_agent and cm_server */ -/* g_currentNode->cmDataPath --> confDir */ + +/* + * Get the logging level from a configuration file. + * + * This function reads the specified configuration file and retrieves the logging level + * setting from it. The logging level determines which messages are recorded in the logs. + * It is used for both the cm_agent and cm_server components. + * + * Parameters: + * - config_file: A pointer to the path of the configuration file to be read. + * + * Notes: + * - If the input 'config_file' is NULL, the function returns without making any changes. + * - If the configuration file cannot be opened, it prints an error message and exits with a status code of 1. + * - The function iterates through the lines of the configuration file, looking for the "log_min_messages" setting. + * - It checks various log levels (DEBUG5, DEBUG1, WARNING, ERROR, FATAL, LOG) in the configuration file, + * and sets the 'log_min_messages' global variable accordingly when a matching level is found. + * - The search stops as soon as a valid log level is found. + */ + void get_log_level(const char* config_file) { - char buf[BUF_LEN]; - FILE* fd = NULL; + char buf[BUF_LEN]; // Buffer for reading lines from the configuration file. + FILE* fd = NULL; // File descriptor for the configuration file. if (config_file == NULL) { - return; + return; // If 'config_file' is NULL, return without modification. } else { logInitFlag = true; } + // Attempt to open the configuration file for reading. fd = fopen(config_file, "r"); if (fd == NULL) { char errBuffer[ERROR_LIMIT_LEN]; - printf("can not open config file: %s %s\n", config_file, pqStrerror(errno, errBuffer, ERROR_LIMIT_LEN)); - exit(1); + printf("Can not open config file: %s %s\n", config_file, pqStrerror(errno, errBuffer, ERROR_LIMIT_LEN)); + exit(1); // Print an error message and exit with a status code of 1 if the file cannot be opened. } while (!feof(fd)) { errno_t rc; - rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); + rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); // Initialize the buffer to all zeros. securec_check_c(rc, "\0", "\0"); - (void)fgets(buf, BUF_LEN, fd); + (void)fgets(buf, BUF_LEN, fd); // Read a line from the file into the buffer. if (is_comment_line(buf) == 1) { - continue; /* skip # comment */ + continue; /* Skip lines that start with '#' (comments) */ } if (strstr(buf, "log_min_messages") != NULL) { - /* check all lines */ + /* Check all lines */ if (strcasestr(buf, "DEBUG5") != NULL) { log_min_messages = DEBUG5; - break; + break; // Stop searching when DEBUG5 level is found. } if (strcasestr(buf, "DEBUG1") != NULL) { log_min_messages = DEBUG1; - break; + break; // Stop searching when DEBUG1 level is found. } if (strcasestr(buf, "WARNING") != NULL) { log_min_messages = WARNING; - break; + break; // Stop searching when WARNING level is found. } if (strcasestr(buf, "ERROR") != NULL) { log_min_messages = ERROR; - break; + break; // Stop searching when ERROR level is found. } if (strcasestr(buf, "FATAL") != NULL) { log_min_messages = FATAL; - break; + break; // Stop searching when FATAL level is found. } if (strcasestr(buf, "LOG") != NULL) { log_min_messages = LOG; - break; + break; // Stop searching when LOG level is found. } } } - fclose(fd); - return; /* default value warning */ + fclose(fd); // Close the configuration file. + return; /* Default value warning */ } -/* used for cm_agent */ + +/* + * Get the build mode from a configuration file. + * + * This function is used for the cm_agent component. It reads the specified configuration file + * and retrieves the build mode setting from it. The build mode determines whether incremental + * builds are enabled or disabled. + * + * Parameters: + * - config_file: A pointer to the path of the configuration file to be read. + * + * Notes: + * - If the input 'config_file' is NULL, the function returns without making any changes. + * - If the configuration file cannot be opened, it prints an error message and exits with a + * status code of 1. + * - The function iterates through the lines of the configuration file, looking for the + * "incremental_build" setting. + * - It checks for "on" and "off" values for the "incremental_build" parameter in the configuration + * file and sets the 'incremental_build' global variable accordingly. + * - If an invalid value is encountered for the "incremental_build" parameter, it sets the value + * to 'true' and logs a fatal error message. + */ + void get_build_mode(const char* config_file) { - char buf[BUF_LEN]; - FILE* fd = NULL; + char buf[BUF_LEN]; // Buffer for reading lines from the configuration file. + FILE* fd = NULL; // File descriptor for the configuration file. if (config_file == NULL) { - return; + return; // If 'config_file' is NULL, return without modification. } + // Attempt to open the configuration file for reading. fd = fopen(config_file, "r"); if (fd == NULL) { char errBuffer[ERROR_LIMIT_LEN]; printf("can not open config file: %s %s\n", config_file, pqStrerror(errno, errBuffer, ERROR_LIMIT_LEN)); - exit(1); + exit(1); // Print an error message and exit with a status code of 1 if the file cannot be opened. } while (!feof(fd)) { errno_t rc; - rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); + rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); // Initialize the buffer to all zeros. securec_check_c(rc, "\0", "\0"); - (void)fgets(buf, BUF_LEN, fd); + (void)fgets(buf, BUF_LEN, fd); // Read a line from the file into the buffer. - /* skip # comment */ + // Skip lines that start with '#' (comments). if (is_comment_line(buf) == 1) { continue; } - /* check all lines */ + // Check for the "incremental_build" setting. if (strstr(buf, "incremental_build") != NULL) { if (strstr(buf, "on") != NULL) { - incremental_build = true; + incremental_build = true; // Enable incremental builds. } else if (strstr(buf, "off") != NULL) { - incremental_build = false; + incremental_build = false; // Disable incremental builds. } else { - incremental_build = true; + incremental_build = true; // Default to enabling incremental builds. write_runlog(FATAL, "invalid value for parameter \"incremental_build\" in %s.\n", config_file); } } } - fclose(fd); + fclose(fd); // Close the configuration file. return; } -/* used for cm_agent and cm_server */ + +/* + * Get the log file size setting from a configuration file. + * + * This function is used for both the cm_agent and cm_server components. It reads the specified + * configuration file and retrieves the log file size setting from it. The log file size determines + * the maximum size, in bytes, of the log files. + * + * Parameters: + * - config_file: A pointer to the path of the configuration file to be read. + * + * Notes: + * - If the input 'config_file' is NULL, the function returns with the default log file size. + * - If the configuration file cannot be opened, it prints an error message and exits with a + * status code of 1. + * - The function iterates through the lines of the configuration file, looking for the + * "log_file_size" setting. + * - It checks the first line that contains "log_file_size" and parses the value following the "=" + * sign. + * - The parsed value is converted to an integer and represents the maximum log file size in bytes. + * - If an invalid value is encountered for the "log_file_size" parameter, it logs an error message + * and exits with a status code of 1. + */ + void get_log_file_size(const char* config_file) { - char buf[BUF_LEN]; - FILE* fd = NULL; + char buf[BUF_LEN]; // Buffer for reading lines from the configuration file. + FILE* fd = NULL; // File descriptor for the configuration file. if (config_file == NULL) { - return; /* default size */ + return; // Default value warning. } else { logInitFlag = true; } + // Attempt to open the configuration file for reading. fd = fopen(config_file, "r"); if (fd == NULL) { printf("get_log_file_size error\n"); - exit(1); + exit(1); // Print an error message and exit with a status code of 1 if the file cannot be opened. } while (!feof(fd)) { errno_t rc; - rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); + rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); // Initialize the buffer to all zeros. securec_check_c(rc, "\0", "\0"); - (void)fgets(buf, BUF_LEN, fd); + (void)fgets(buf, BUF_LEN, fd); // Read a line from the file into the buffer. if (is_comment_line(buf) == 1) { - continue; /* skip # comment */ + continue; // Skip lines that start with '#' (comments). } if (strstr(buf, "log_file_size") != NULL) { - /* only check the first line */ + // Only check the first line. char* subStr = NULL; char countStr[COUNTSTR_LEN] = {0}; int ii = 0; @@ -1068,23 +1370,23 @@ void get_log_file_size(const char* config_file) subStr = strchr(buf, '='); if (subStr != NULL) { - /* find = */ - ii = 1; /* 1 is = */ + // Find '='. + ii = 1; // 1 is '='. - /* skip blank */ + // Skip blank. for (;;) { if (*(subStr + ii) == ' ') { - ii++; /* skip blank */ + ii++; // Skip blank. } else if (*(subStr + ii) >= '0' && *(subStr + ii) <= '9') { - break; /* number find.break */ + break; // Number found, break. } else { - /* invalid character. */ + // Invalid character. goto out; } } while (*(subStr + ii) >= '0' && *(subStr + ii) <= '9') { - /* end when no more number. */ + // End when no more numbers. if (jj > (int)sizeof(countStr) - 2) { printf("too large log file size.\n"); exit(1); @@ -1095,10 +1397,10 @@ void get_log_file_size(const char* config_file) ii++; jj++; } - countStr[jj] = 0; /* jj maybe have added itself.terminate string. */ + countStr[jj] = 0; // jj may have added itself, terminate the string. if (countStr[0] != 0) { - maxLogFileSize = atoi(countStr) * 1024 * 1024; /* byte */ + maxLogFileSize = atoi(countStr) * 1024 * 1024; // Convert to bytes. } else { write_runlog(ERROR, "invalid value for parameter \"log_file_size\" in %s.\n", config_file); } @@ -1107,65 +1409,93 @@ void get_log_file_size(const char* config_file) } out: - fclose(fd); - return; /* default value is warning */ + fclose(fd); // Close the configuration file. + return; // Default value is warning. } +/* + * Get the thread count setting from a configuration file. + * + * This function retrieves the thread count setting from the specified configuration file, + * which is used for configuring the number of threads for the cm_agent and cm_server components. + * The thread count determines how many threads are used for concurrent processing. + * + * Parameters: + * - config_file: A pointer to the path of the configuration file to be read. + * + * Returns: + * An integer representing the thread count. If the configuration file is not found or an + * invalid value is encountered, the default thread count of 5 is returned. + * + * Notes: + * - If the input 'config_file' is NULL, the function prints an error message and exits with a + * status code of 1. + * - If the configuration file cannot be opened, the function prints an error message and exits + * with a status code of 1. + * - The function iterates through the lines of the configuration file, looking for the + * "thread_count" setting. + * - It checks the first line that contains "thread_count" and parses the value following the "=" + * sign. + * - The parsed value is converted to an integer and represents the desired thread count. + * - If an invalid value is encountered for the "thread_count" parameter, the function prints an + * error message and exits with a status code of 1. + * - The valid thread count range is between 2 and 1000. + */ + int get_cm_thread_count(const char* config_file) { -#define DEFAULT_THREAD_NUM 5 + #define DEFAULT_THREAD_NUM 5 - char buf[BUF_LEN]; - FILE* fd = NULL; - int thread_count = DEFAULT_THREAD_NUM; - errno_t rc = 0; + char buf[BUF_LEN]; // Buffer for reading lines from the configuration file. + FILE* fd = NULL; // File descriptor for the configuration file. + int thread_count = DEFAULT_THREAD_NUM; // Default thread count. + errno_t rc = 0; // Error code for secure functions. if (config_file == NULL) { printf("no cmserver config file! exit.\n"); - exit(1); + exit(1); // Print an error message and exit with a status code of 1 if 'config_file' is NULL. } + // Attempt to open the configuration file for reading. fd = fopen(config_file, "r"); if (fd == NULL) { - printf("open cmserver config file :%s ,error:%m\n", config_file); - exit(1); + printf("open cmserver config file: %s, error: %m\n", config_file); + exit(1); // Print an error message and exit with a status code of 1 if the file cannot be opened. } while (!feof(fd)) { - rc = memset_s(buf, sizeof(buf), 0, sizeof(buf)); - securec_check_errno(rc, ); - (void)fgets(buf, BUF_LEN, fd); + rc = memset_s(buf, sizeof(buf), 0, sizeof(buf)); // Initialize the buffer to all zeros. + securec_check_errno(rc, ); // Check for errors in memset_s. + (void)fgets(buf, BUF_LEN, fd); // Read a line from the file into the buffer. if (is_comment_line(buf) == 1) { - continue; /* skip # comment */ + continue; // Skip lines that start with '#' (comments). } if (strstr(buf, "thread_count") != NULL) { - /* only check the first line */ + // Only check the first line. char* subStr = NULL; char countStr[COUNTSTR_LEN] = {0}; int ii = 0; int jj = 0; - subStr = strchr(buf, '='); - /* find = */ + subStr = strchr(buf, '='); // Find '='. if (subStr != NULL) { - ii = 1; + ii = 1; // 1 is '='. - /* skip blank */ + // Skip blank. for (;;) { if (*(subStr + ii) == ' ') { - ii++; /* skip blank */ + ii++; // Skip blank. } else if (*(subStr + ii) >= '0' && *(subStr + ii) <= '9') { - /* number find.break */ - break; + break; // Number found, break. } else { - /* invalid character. */ + // Invalid character. goto out; } } - /* end when no number */ + // End when no number. while (*(subStr + ii) >= '0' && *(subStr + ii) <= '9') { if (jj > (int)sizeof(countStr) - 2) { printf("too large thread count.\n"); @@ -1177,7 +1507,7 @@ int get_cm_thread_count(const char* config_file) ii++; jj++; } - countStr[jj] = 0; /* jj maybe have added itself.terminate string. */ + countStr[jj] = 0; // jj may have added itself, terminate the string. if (countStr[0] != 0) { thread_count = atoi(countStr); @@ -1194,61 +1524,117 @@ int get_cm_thread_count(const char* config_file) } out: - fclose(fd); - return thread_count; + fclose(fd); // Close the configuration file. + return thread_count; // Return the thread count. } /* - * @Description: get value of paramater from configuration file + * @Description: Get the value of a parameter from a configuration file. * - * @in config_file: configuration file path - * @in key: name of paramater - * @in defaultValue: default value of parameter + * This function reads the specified configuration file and retrieves the value associated with + * the provided 'key'. If the 'key' is found in the configuration file, its corresponding value + * is returned as an integer. If the 'key' is not found or if the value is not a valid integer, + * the 'defaultValue' is returned. * - * @out: value of parameter + * Parameters: + * - config_file: A pointer to the path of the configuration file to be read. + * - key: The name of the parameter whose value is to be retrieved from the configuration file. + * - defaultValue: The default value to be returned if the 'key' is not found or if the value + * is not a valid integer. + * + * Returns: + * An integer representing the value of the parameter 'key' if it is found in the configuration + * file and is a valid integer. If the 'key' is not found or the value is not a valid integer, + * the 'defaultValue' is returned. + * + * Note: + * - If the input 'config_file' or 'key' is NULL, or if the configuration file cannot be opened, + * this function returns the 'defaultValue'. + * - This function first calls 'get_int64_value_from_config' to retrieve the value as a 64-bit + * integer. If the value is within the valid range for 32-bit integers (INT_MIN to INT_MAX), + * it is cast to an integer and returned; otherwise, the 'defaultValue' is returned. */ + int get_int_value_from_config(const char* config_file, const char* key, int defaultValue) { int64 i64 = get_int64_value_from_config(config_file, key, defaultValue); if (i64 > INT_MAX) { - return defaultValue; + return defaultValue; // Return the 'defaultValue' if the value is too large for an integer. } else if (i64 < INT_MIN) { - return defaultValue; + return defaultValue; // Return the 'defaultValue' if the value is too small for an integer. } - return (int)i64; + return (int)i64; // Cast and return the value as an integer. } + /* - * @Description: get value of paramater from configuration file + * @Description: Get the value of a parameter from a configuration file. * - * @in config_file: configuration file path - * @in key: name of paramater - * @in defaultValue: default value of parameter + * This function reads the specified configuration file and retrieves the value associated with + * the provided 'key'. If the 'key' is found in the configuration file, its corresponding value + * is returned as a 32-bit unsigned integer (uint32). If the 'key' is not found or if the value + * is not a valid non-negative integer, the 'defaultValue' is returned. * - * @out: value of parameter + * Parameters: + * - config_file: A pointer to the path of the configuration file to be read, a string. + * - key: The name of the parameter whose value is to be retrieved from the configuration file, a string. + * - defaultValue: The default value to be returned if the 'key' is not found or if the value + * is not a valid non-negative integer, a uint32 value. + * + * Returns: + * A 32-bit unsigned integer (uint32) representing the value of the parameter 'key' if it is found + * in the configuration file and is a valid non-negative integer. If the 'key' is not found or the + * value is not a valid non-negative integer, the 'defaultValue' is returned. + * + * Note: + * - If the input 'config_file' or 'key' is NULL, or if the configuration file cannot be opened, + * this function returns the 'defaultValue'. + * - This function first calls 'get_int64_value_from_config' to retrieve the value as a 64-bit integer. + * If the value is within the valid range for a 32-bit non-negative integer (0 to UINT_MAX), it is + * cast to a uint32 and returned; otherwise, the 'defaultValue' is returned. */ + uint32 get_uint32_value_from_config(const char* config_file, const char* key, uint32 defaultValue) { int64 i64 = get_int64_value_from_config(config_file, key, defaultValue); if (i64 > UINT_MAX) { - return defaultValue; + return defaultValue; // Return the 'defaultValue' if the value is too large for a uint32. } else if (i64 < 0) { - return defaultValue; + return defaultValue; // Return the 'defaultValue' if the value is negative. } - return (uint32)i64; + return (uint32)i64; // Cast and return the value as a uint32. } /* - * @Description: get value of paramater from configuration file + * @Description: Get the value of a parameter from a configuration file. * - * @in config_file: configuration file path - * @in key: name of paramater - * @in defaultValue: default value of parameter + * This function reads the specified configuration file and retrieves the value associated with + * the provided 'key'. If the 'key' is found in the configuration file, its corresponding value + * is returned as a 64-bit signed integer (int64). If the 'key' is not found or if the value is + * not a valid integer, the 'defaultValue' is returned. * - * @out: value of parameter + * Parameters: + * - config_file: A pointer to the path of the configuration file to be read, a string. + * - key: The name of the parameter whose value is to be retrieved from the configuration file, a string. + * - defaultValue: The default value to be returned if the 'key' is not found or if the value + * is not a valid integer, an int64 value. + * + * Returns: + * A 64-bit signed integer (int64) representing the value of the parameter 'key' if it is found + * in the configuration file and is a valid integer. If the 'key' is not found or the value is + * not a valid integer, the 'defaultValue' is returned. + * + * Note: + * - If the input 'config_file' or 'key' is NULL, or if the configuration file cannot be opened, + * this function returns the 'defaultValue'. + * - The function reads lines from the configuration file and checks for 'key' assignments in the + * format 'key=value'. It extracts the value portion as an integer. + * - If the value is not a valid integer, it is ignored, and the 'defaultValue' is returned. + * - Comment lines starting with '#' are skipped. */ + int64 get_int64_value_from_config(const char* config_file, const char* key, int64 defaultValue) { char buf[BUF_LEN]; @@ -1275,11 +1661,11 @@ int64 get_int64_value_from_config(const char* config_file, const char* key, int6 (void)fgets(buf, BUF_LEN, fd); if (is_comment_line(buf) == 1) { - continue; /* skip # comment */ + continue; /* Skip # comment lines */ } if (strstr(buf, key) != NULL) { - /* only check the first line */ + /* Check only the first line */ char* subStr = NULL; char countStr[COUNTSTR_LEN] = {0}; int ii = 0; @@ -1287,26 +1673,26 @@ int64 get_int64_value_from_config(const char* config_file, const char* key, int6 subStr = strchr(buf, '='); if (subStr != NULL) { - /* find = */ + /* Find '=' */ ii = 1; - /* skip blank */ + /* Skip blanks */ while (1) { if (*(subStr + ii) == ' ') { - ii++; /* skip blank */ + ii++; /* Skip blanks */ } else if (isdigit(*(subStr + ii))) { - /* number find.break */ + /* Number found, break */ break; } else { - /* invalid character. */ + /* Invalid character, exit */ goto out; } } while (isdigit(*(subStr + ii))) { - /* end when no number */ + /* End when no more numbers */ if (jj >= COUNTSTR_LEN - 1) { - write_runlog(ERROR, "length is not enough for constr\n"); + write_runlog(ERROR, "Length is not enough for constr\n"); goto out; } countStr[jj] = *(subStr + ii); @@ -1314,7 +1700,7 @@ int64 get_int64_value_from_config(const char* config_file, const char* key, int6 ii++; jj++; } - countStr[jj] = 0; /* jj maybe have added itself.terminate string. */ + countStr[jj] = 0; /* Null-terminate the string */ if (countStr[0] != 0) { int64Value = strtoll(countStr, NULL, 10); @@ -1329,60 +1715,120 @@ out: return int64Value; } + #define ALARM_REPORT_INTERVAL "alarm_report_interval" #define ALARM_REPORT_INTERVAL_DEFAULT 10 #define ALARM_REPORT_MAX_COUNT "alarm_report_max_count" #define ALARM_REPORT_MAX_COUNT_DEFAULT 5 -/* trim blank characters on both ends */ +/* + * @Description: Trim blank characters from the beginning and end of a string. + * + * This function takes a string as input and removes any leading and trailing whitespace characters. + * + * Parameters: + * - src: The input string to be trimmed. + * + * Returns: + * A pointer to the first non-whitespace character within the input string 'src'. + * + * Note: + * - The input string 'src' is modified in place to remove leading and trailing whitespace. + * - The function returns a pointer to the modified string. + */ + char* trim(char* src) { - char* s = 0; - char* e = 0; - char* c = 0; + char* s = 0; // Pointer to the start of non-whitespace characters. + char* e = 0; // Pointer to the end of whitespace characters. + char* c = 0; // Pointer used for iteration through the string. for (c = src; (c != NULL) && *c; ++c) { if (isspace(*c)) { if (e == NULL) { - e = c; + e = c; // Mark the end of whitespace. } } else { if (s == NULL) { - s = c; + s = c; // Mark the start of non-whitespace. } - e = 0; + e = 0; // Reset end pointer. } } + if (s == NULL) { - s = src; + s = src; // If there were no non-whitespace characters, start pointer remains at the beginning. } if (e != NULL) { - *e = 0; + *e = 0; // Null-terminate the string at the end of whitespace. } - return s; + return s; // Return a pointer to the modified string. } -/* Check this line is comment line or not, which is in cm_server.conf file */ + +/* + * @Description: Check if a given line is a comment line in the context of cm_server.conf file. + * + * This function checks whether a provided string line is a comment line within the context + * of the cm_server.conf configuration file. Comment lines are typically lines that start with + * a '#' character and are used to add comments or notes in configuration files. + * + * Parameters: + * - str_line: The input string line to be checked for being a comment line, a character array. + * + * Returns: + * A boolean value indicating whether the input line is a comment line (true) or not (false). + * + * Note: + * - Comment lines in configuration files are used for documentation and are usually ignored + * by the configuration parser. + * - The function first checks if the input line is empty or NULL and considers it not a comment. + * - It then trims any leading and trailing whitespace from the line to ensure accurate detection. + * - If the trimmed line starts with a '#' character, it is considered a comment line and returns true. + * - Otherwise, it returns false, indicating that the line is not a comment. + */ + static bool is_comment_entity(char* str_line) { char* src = NULL; + if (str_line == NULL || strlen(str_line) < 1) { - return false; - } - src = str_line; - src = trim(src); - if (src == NULL || strlen(src) < 1) { - return true; - } - if (*src == '#') { - return true; + return false; // Empty or NULL lines are not considered comment lines. } - return false; + src = str_line; + src = trim(src); + + if (src == NULL || strlen(src) < 1) { + return true; // After trimming, if the line is empty, it is considered a comment line. + } + + if (*src == '#') { + return true; // Lines starting with '#' character are considered comment lines. + } + + return false; // If none of the above conditions are met, it's not a comment line. } +/* + * @Description: Check if a given string consists of only numeric digits. + * + * This function determines whether a provided string contains only numeric digits (0-9). + * + * Parameters: + * - str: The input string to be checked for being a numeric digit string, a character array. + * + * Returns: + * 1 if the input string consists of only numeric digits, 0 otherwise. + * + * Note: + * - The function checks each character in the input string and verifies if it is a numeric digit. + * - It returns 1 if all characters in the string are numeric digits. + * - If the input string is NULL or empty, or if any character is not a digit, it returns 0. + */ + int is_digit_string(char* str) { #define isDigital(_ch) (((_ch) >= '0') && ((_ch) <= '9')) @@ -1390,207 +1836,289 @@ int is_digit_string(char* str) int i = 0; int len = -1; char* p = NULL; - if (str == nullptr) { - return 0; + if (str == NULL) { + return 0; // Return 0 if the input string is NULL. } if ((len = strlen(str)) <= 0) { - return 0; + return 0; // Return 0 if the input string is empty. } p = str; for (i = 0; i < len; i++) { if (!isDigital(p[i])) { - return 0; + return 0; // Return 0 if a non-digit character is found in the string. } } - return 1; + return 1; // Return 1 if the input string consists of only numeric digits. } + +/* + * @Description: Read and retrieve alarm parameters from a configuration file. + * + * This function reads the specified configuration file ('config_file') and extracts alarm-related + * parameters, such as the alarm report interval, from it. The extracted values are then used + * to configure the alarm system. + * + * Parameters: + * - config_file: A pointer to the path of the configuration file to be read, a string. + * + * Note: + * - The function opens and reads the configuration file line by line, searching for relevant + * parameters and their values. + * - Comment lines (lines starting with '#') are ignored during processing. + * - The function trims leading and trailing whitespace from parameter names and values. + * - When it finds the 'ALARM_REPORT_INTERVAL' parameter, it checks if the associated value is a + * valid numeric string and assigns it to 'g_alarmReportInterval'. If the value is not a valid + * numeric string or is -1, the 'ALARM_REPORT_INTERVAL_DEFAULT' is used. + * - The function stops reading the file once the 'ALARM_REPORT_INTERVAL' parameter is found. + */ + static void get_alarm_parameters(const char* config_file) { - char buf[BUF_LEN] = {0}; - FILE* fd = NULL; - char* index1 = NULL; - char* index2 = NULL; - char* src = NULL; - char* key = NULL; - char* value = NULL; - errno_t rc = 0; + char buf[BUF_LEN] = {0}; // Buffer for reading lines from the configuration file. + FILE* fd = NULL; // File descriptor for the configuration file. + char* index1 = NULL; // Pointer to the '#' character in the line. + char* index2 = NULL; // Pointer to the '=' character in the line. + char* src = NULL; // Pointer to the current line being processed. + char* key = NULL; // Pointer to the extracted parameter name. + char* value = NULL; // Pointer to the extracted parameter value. + errno_t rc = 0; // Error code variable for safe C library functions. if (config_file == NULL) { - return; + return; // If 'config_file' is NULL, return without further processing. } fd = fopen(config_file, "r"); if (fd == NULL) { - return; + return; // If the file cannot be opened, return without further processing. } while (!feof(fd)) { - rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); + rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); // Clear the buffer before reading a new line. securec_check_c(rc, "\0", "\0"); - (void)fgets(buf, BUF_LEN, fd); + (void)fgets(buf, BUF_LEN, fd); // Read a line from the configuration file. if (is_comment_entity(buf) == true) { - continue; + continue; // Skip comment lines. } - index1 = strchr(buf, '#'); + index1 = strchr(buf, '#'); // Find the '#' character to mark the start of comments. if (index1 != NULL) { - *index1 = '\0'; + *index1 = '\0'; // Null-terminate the line at the '#' character to remove comments. } - index2 = strchr(buf, '='); + index2 = strchr(buf, '='); // Find the '=' character to separate parameter and value. if (index2 == NULL) { - continue; + continue; // If no '=' character is found, skip this line. } - src = buf; - src = trim(src); - index2 = strchr(src, '='); - key = src; - /* jump to the beginning of recorded values */ - value = index2 + 1; + src = buf; // Initialize 'src' pointer to the beginning of the line. + src = trim(src); // Trim leading and trailing whitespace from the line. + index2 = strchr(src, '='); // Find '=' character in trimmed line. + key = src; // Set 'key' pointer to the trimmed line as the parameter name. + value = index2 + 1; // Set 'value' pointer to the part of the line after '='. + + key = trim(key); // Trim leading and trailing whitespace from parameter name. + value = trim(value); // Trim leading and trailing whitespace from parameter value. - key = trim(key); - value = trim(value); if (strncmp(key, ALARM_REPORT_INTERVAL, strlen(ALARM_REPORT_INTERVAL)) == 0) { if (is_digit_string(value)) { - g_alarmReportInterval = atoi(value); + g_alarmReportInterval = atoi(value); // Convert value to integer. if (g_alarmReportInterval == -1) { g_alarmReportInterval = ALARM_REPORT_INTERVAL_DEFAULT; } } - break; + break; // Stop reading the file once 'ALARM_REPORT_INTERVAL' is found. } } - fclose(fd); + fclose(fd); // Close the configuration file. } + +/* + * @Description: Read and retrieve the maximum alarm report count from a configuration file. + * + * This function reads the specified configuration file ('config_file') and extracts the maximum + * alarm report count parameter from it. The extracted value is then used to configure the alarm system. + * + * Parameters: + * - config_file: A pointer to the path of the configuration file to be read, a string. + * + * Note: + * - The function opens and reads the configuration file line by line, searching for the 'ALARM_REPORT_MAX_COUNT' + * parameter and its value. + * - Comment lines (lines starting with '#') are ignored during processing. + * - The function trims leading and trailing whitespace from parameter names and values. + * - When it finds the 'ALARM_REPORT_MAX_COUNT' parameter, it checks if the associated value is a + * valid numeric string and assigns it to 'g_alarmReportMaxCount'. If the value is not a valid + * numeric string or is -1, the 'ALARM_REPORT_MAX_COUNT_DEFAULT' is used. + * - The function stops reading the file once the 'ALARM_REPORT_MAX_COUNT' parameter is found. + */ + static void get_alarm_report_max_count(const char* config_file) { - char buf[BUF_LEN] = {0}; - FILE* fd = NULL; - char* index1 = NULL; - char* index2 = NULL; - char* src = NULL; - char* key = NULL; - char* value = NULL; - errno_t rc = 0; + char buf[BUF_LEN] = {0}; // Buffer for reading lines from the configuration file. + FILE* fd = NULL; // File descriptor for the configuration file. + char* index1 = NULL; // Pointer to the '#' character in the line. + char* index2 = NULL; // Pointer to the '=' character in the line. + char* src = NULL; // Pointer to the current line being processed. + char* key = NULL; // Pointer to the extracted parameter name. + char* value = NULL; // Pointer to the extracted parameter value. + errno_t rc = 0; // Error code variable for safe C library functions. if (config_file == NULL) { - return; + return; // If 'config_file' is NULL, return without further processing. } fd = fopen(config_file, "r"); if (fd == NULL) { - return; + return; // If the file cannot be opened, return without further processing. } while (!feof(fd)) { - rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); + rc = memset_s(buf, BUF_LEN, 0, BUF_LEN); // Clear the buffer before reading a new line. securec_check_c(rc, "\0", "\0"); - (void)fgets(buf, BUF_LEN, fd); + (void)fgets(buf, BUF_LEN, fd); // Read a line from the configuration file. - if (is_comment_entity(buf)) { - continue; + if (is_comment_entity(buf) == true) { + continue; // Skip comment lines. } - index1 = strchr(buf, '#'); + index1 = strchr(buf, '#'); // Find the '#' character to mark the start of comments. if (index1 != NULL) { - *index1 = '\0'; + *index1 = '\0'; // Null-terminate the line at the '#' character to remove comments. } - index2 = strchr(buf, '='); + index2 = strchr(buf, '='); // Find the '=' character to separate parameter and value. if (index2 == NULL) { - continue; + continue; // If no '=' character is found, skip this line. } - src = buf; - src = trim(src); - index2 = strchr(src, '='); - key = src; - /* jump to the beginning of recorded values */ - value = index2 + 1; + src = buf; // Initialize 'src' pointer to the beginning of the line. + src = trim(src); // Trim leading and trailing whitespace from the line. + index2 = strchr(src, '='); // Find '=' character in trimmed line. + key = src; // Set 'key' pointer to the trimmed line as the parameter name. + value = index2 + 1; // Set 'value' pointer to the part of the line after '='. + + key = trim(key); // Trim leading and trailing whitespace from parameter name. + value = trim(value); // Trim leading and trailing whitespace from parameter value. - key = trim(key); - value = trim(value); if (strncmp(key, ALARM_REPORT_MAX_COUNT, strlen(ALARM_REPORT_MAX_COUNT)) == 0) { if (is_digit_string(value)) { - g_alarmReportMaxCount = atoi(value); + g_alarmReportMaxCount = atoi(value); // Convert value to integer. if (g_alarmReportMaxCount == -1) { g_alarmReportMaxCount = ALARM_REPORT_MAX_COUNT_DEFAULT; } } - break; + break; // Stop reading the file once 'ALARM_REPORT_MAX_COUNT' is found. } } - fclose(fd); + fclose(fd); // Close the configuration file. } /* - * This function is for reading cm_server.conf parameters, which have been applied at server side. - * In cm_server this function is ugly, it should be rewritten at new version. + * This function is responsible for reading parameters from the 'cm_server.conf' configuration file + * that have been applied on the server side. + * + * In the current implementation within 'cm_server', this function is considered suboptimal and + * should be rewritten in the next version for improved efficiency and clarity. + * + * Parameters: + * - conf: A pointer to the path of the 'cm_server.conf' configuration file to be read, represented as a string. */ static void get_alarm_report_interval(const char* conf) { + // Calls a function (get_alarm_parameters) to retrieve alarm parameters from the configuration file. get_alarm_parameters(conf); } +/* + * This function is responsible for retrieving various log-related parameters from a configuration directory. + * + * It obtains and sets the log level, log file size, system log path, alarm component path, alarm report + * interval, and alarm report maximum count from the provided 'confDir'. + * + * Parameters: + * - confDir: A pointer to the path of the configuration directory containing log-related settings, as a string. + */ void get_log_paramter(const char* confDir) { + // Retrieves and sets the log level from the configuration directory. get_log_level(confDir); + + // Retrieves and sets the log file size from the configuration directory. get_log_file_size(confDir); + + // Retrieves and sets the system log path from the configuration directory. GetStringFromConf(confDir, sys_log_path, sizeof(sys_log_path), "log_dir"); + + // Retrieves and sets the alarm component path from the configuration directory. GetStringFromConf(confDir, g_alarmComponentPath, sizeof(g_alarmComponentPath), "alarm_component"); + + // Calls the function to retrieve and set the alarm report interval from the configuration directory. get_alarm_report_interval(confDir); + + // Calls the function to retrieve and set the alarm report maximum count from the configuration directory. get_alarm_report_max_count(confDir); } /* * @GaussDB@ - * Brief : close the current file, and open the next file - * Description : - * Notes : + * Brief: Close the current file and open the next file. + * Description: This function is responsible for closing the current log file and opening a new one. + * It renames the current log file without any special marks, appends a timestamp + * to the filename, and then opens the new log file for writing. It also handles setting + * file permissions and error reporting. + * Notes: None */ + void switchLogFile(void) { - char log_new_name[MAXPGPATH] = {0}; - mode_t oumask; - char current_localtime[LOG_MAX_TIMELEN] = {0}; - pg_time_t current_time; - struct tm* systm; + char log_new_name[MAXPGPATH] = {0}; // Buffer for the new log file name. + mode_t oumask; // Original umask value. + char current_localtime[LOG_MAX_TIMELEN] = {0}; // Buffer for the current timestamp in the filename. + pg_time_t current_time; // Current time. + struct tm* systm; - int len_log_cur_name = 0; - int len_suffix_name = 0; - int len_log_new_name = 0; - int ret = 0; - errno_t rc = 0; + int len_log_cur_name = 0; // Length of the current log file name. + int len_suffix_name = 0; // Length of the log file mark (suffix). + int len_log_new_name = 0; // Length of the new log file name. + int ret = 0; // Return code. + errno_t rc = 0; // Error code variable for safe C library functions. - current_time = time(NULL); + current_time = time(NULL); // Get the current time. - systm = localtime(¤t_time); + systm = localtime(¤t_time); // Convert current time to a local time structure. + // Generate a timestamp in the format "-%Y-%m-%d_%H%M%S" and store it in current_localtime. if (systm != nullptr) { (void)strftime(current_localtime, LOG_MAX_TIMELEN, "-%Y-%m-%d_%H%M%S", systm); } - /* close the current file */ + /* Close the current file */ if (syslogFile != NULL) { fclose(syslogFile); syslogFile = NULL; } - /* renamed the current file without Mark */ + /* Rename the current file without the log file mark */ len_log_cur_name = strlen(curLogFileName); len_suffix_name = strlen(curLogFileMark); len_log_new_name = len_log_cur_name - len_suffix_name; + // Copy the portion of the current file name without the mark to log_new_name. rc = strncpy_s(log_new_name, MAXPGPATH, curLogFileName, len_log_new_name); securec_check_errno(rc, ); + + // Append ".log" to the new log file name. rc = strncat_s(log_new_name, MAXPGPATH, ".log", strlen(".log")); securec_check_errno(rc, ); + + // Rename the current log file to the new log file name. ret = rename(curLogFileName, log_new_name); if (ret != 0) { - printf(_("%s: rename log file %s failed! \n"), prefix_name, curLogFileName); + printf(_("%s: Rename log file %s failed!\n"), prefix_name, curLogFileName); return; } - /* new current file name */ + /* Generate the new current file name */ rc = memset_s(curLogFileName, MAXPGPATH, 0, MAXPGPATH); securec_check_errno(rc, ); + + // Construct the new log file name with the current timestamp and log file mark. ret = snprintf_s(curLogFileName, MAXPGPATH, MAXPGPATH - 1, @@ -1603,181 +2131,371 @@ void switchLogFile(void) oumask = umask((mode_t)((~(mode_t)(S_IRUSR | S_IWUSR | S_IXUSR)) & (S_IRWXU | S_IRWXG | S_IRWXO))); + // Open the new log file for appending. syslogFile = fopen(curLogFileName, "a"); (void)umask(oumask); + // Check if opening the new log file was successful and set close-on-exec flag if needed. if (syslogFile == NULL) { - (void)printf("switchLogFile,switch new log file failed %s\n", strerror(errno)); + (void)printf("switchLogFile, switch new log file failed: %s\n", strerror(errno)); } else { if (SetFdCloseExecFlag(syslogFile) == -1) { - (void)printf("set file flag failed, filename:%s, errmsg: %s.\n", curLogFileName, strerror(errno)); + (void)printf("set file flag failed, filename: %s, errmsg: %s.\n", curLogFileName, strerror(errno)); } } } /* * @GaussDB@ - * Brief: - * Description: write info to the files - * Notes: if the current file size is full, switch to the next + * Brief: Write information to log files. + * Description: This function is responsible for writing log information to log files. It checks if the current + * log file size is full and switches to the next log file when necessary. It also handles + * log file initialization and error reporting. + * Notes: If the current log file size is full, the function switches to the next log file. */ void write_log_file(const char* buffer, int count) { - int rc = 0; + int rc = 0; // Return code for fwrite. + // Obtain a write lock to ensure thread safety during log writing. (void)pthread_rwlock_wrlock(&syslog_write_lock); + // Check if the syslogFile is uninitialized, and if so, open it. if (syslogFile == NULL) { - /* maybe syslogFile no init. */ syslogFile = logfile_open(sys_log_path, "a"); } - if (syslogFile != NULL) { - count = strlen(buffer); - /* switch to the next file when current file full */ + if (syslogFile != NULL) { + count = strlen(buffer); // Calculate the length of the buffer. + + // Check if writing the buffer would exceed the maximum log file size, and switch to the next file if needed. if ((ftell(syslogFile) + count) > (maxLogFileSize)) { switchLogFile(); } if (syslogFile != NULL) { + // Write the buffer to the log file. rc = fwrite(buffer, 1, count, syslogFile); + + // Check if the write operation was successful. if (rc != count) { - printf("could not write to log file: %s %m\n", curLogFileName); + printf("Could not write to log file: %s %m\n", curLogFileName); } } else { - printf("write_log_file could not open log file %s : %m\n", curLogFileName); + printf("write_log_file could not open log file %s : %m\n", curLogFileName); } } else { - printf("write_log_file,log file is null now:%s\n", buffer); + printf("write_log_file, log file is null now: %s\n", buffer); } + // Release the write lock after completing log writing. (void)pthread_rwlock_unlock(&syslog_write_lock); } -char *errmsg(const char* fmt, ...) +/* + * This function returns an error message formatted using the provided format string and arguments. + * + * Parameters: + * - fmt: A format string specifying the error message format. + * - ...: Variable arguments corresponding to the format placeholders in the format string. + * + * Returns: + * - A pointer to a character array containing the formatted error message. + * + * Description: + * - The function takes a format string 'fmt' and a variable number of arguments, similar to the 'printf' function. + * - It formats the error message according to the 'fmt' string and the provided arguments. + * - The formatted error message is stored in a character array 'errbuf' with a maximum length of 'BUF_LEN'. + * - The function ensures that the 'errbuf' is null-terminated. + * - The formatted error message is prefixed with "[ERRMSG]:" and then concatenated with any additional text. + * - The resulting error message is stored in 'errbuf_errmsg' and returned. + * - The caller should be aware that the returned error message is stored in a local array, and its memory may become + * invalid once the function exits. + * + * Notes: + * - It's the caller's responsibility to handle and manage the memory of the returned error message. + */ + +char* errmsg(const char* fmt, ...) { - va_list ap; - int count = 0; - int rcs; - errno_t rc; - char errbuf[BUF_LEN] = {0}; + va_list ap; // Variable argument list. + int count = 0; // Count of characters written. + int rcs; // Return code of snprintf. + errno_t rc; // Error code variable for safe C library functions. + char errbuf[BUF_LEN] = {0}; // Buffer for formatting the error message. + + // Make sure the format string is translated if required. fmt = _(fmt); - va_start(ap, fmt); - rc = memset_s(errbuf_errmsg, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); + + va_start(ap, fmt); // Initialize the variable argument list. + rc = memset_s(errbuf_errmsg, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); // Clear the error message buffer. securec_check_c(rc, "\0", "\0"); + + // Format the error message using vsnprintf_s. count = vsnprintf_s(errbuf, sizeof(errbuf), sizeof(errbuf) - 1, fmt, ap); securec_check_intval(count, ); - va_end(ap); - + + va_end(ap); // End the variable argument list. + + // Prefix the formatted error message with "[ERRMSG]:" and concatenate it with any additional text. rcs = snprintf_s(errbuf_errmsg, EREPORT_BUF_LEN, EREPORT_BUF_LEN - 1, "%s", "[ERRMSG]:"); securec_check_intval(rcs, ); rc = memcpy_s(errbuf_errmsg + strlen(errbuf_errmsg), BUF_LEN - strlen(errbuf_errmsg), errbuf, BUF_LEN - strlen(errbuf_errmsg) - 1); securec_check_errno(rc, (void)rc); - return errbuf_errmsg; + + return errbuf_errmsg; // Return the formatted error message. } + +/* + * This function returns a detailed error message formatted using the provided format string and arguments. + * + * Parameters: + * - fmt: A format string specifying the detailed error message format. + * - ...: Variable arguments corresponding to the format placeholders in the format string. + * + * Returns: + * - A pointer to a character array containing the formatted detailed error message. + * + * Description: + * - The function takes a format string 'fmt' and a variable number of arguments, similar to the 'printf' function. + * - It formats the detailed error message according to the 'fmt' string and the provided arguments. + * - The formatted detailed error message is stored in a character array 'errbuf' with a maximum length of 'BUF_LEN'. + * - The function ensures that 'errbuf' is null-terminated. + * - The formatted detailed error message is prefixed with "[ERRDETAIL]:" and then concatenated with any additional text. + * - The resulting detailed error message is stored in 'errbuf_errdetail' and returned. + * - The caller should be aware that the returned detailed error message is stored in a local array, and its memory may become + * invalid once the function exits. + * + * Notes: + * - It's the caller's responsibility to handle and manage the memory of the returned detailed error message. + */ + char* errdetail(const char* fmt, ...) { - va_list ap; - int count = 0; - int rcs; - errno_t rc; - char errbuf[BUF_LEN] = {0}; + va_list ap; // Variable argument list. + int count = 0; // Count of characters written. + int rcs; // Return code of snprintf. + errno_t rc; // Error code variable for safe C library functions. + char errbuf[BUF_LEN] = {0}; // Buffer for formatting the detailed error message. + + // Make sure the format string is translated if required. fmt = _(fmt); - va_start(ap, fmt); - rc = memset_s(errbuf_errdetail, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); + + va_start(ap, fmt); // Initialize the variable argument list. + rc = memset_s(errbuf_errdetail, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); // Clear the detailed error message buffer. securec_check_c(rc, "\0", "\0"); + + // Format the detailed error message using vsnprintf_s. count = vsnprintf_s(errbuf, sizeof(errbuf), sizeof(errbuf) - 1, fmt, ap); securec_check_intval(count, ); - va_end(ap); - rcs = snprintf_s(errbuf_errdetail, EREPORT_BUF_LEN, - EREPORT_BUF_LEN - 1, "%s", "[ERRDETAIL]:"); + + va_end(ap); // End the variable argument list. + + // Prefix the formatted detailed error message with "[ERRDETAIL]:" and concatenate it with any additional text. + rcs = snprintf_s(errbuf_errdetail, EREPORT_BUF_LEN, EREPORT_BUF_LEN - 1, "%s", "[ERRDETAIL]:"); securec_check_intval(rcs, ); rc = memcpy_s(errbuf_errdetail + strlen(errbuf_errdetail), BUF_LEN - strlen(errbuf_errdetail), errbuf, BUF_LEN - strlen(errbuf_errdetail) - 1); securec_check_errno(rc, (void)rc); - return errbuf_errdetail; + + return errbuf_errdetail; // Return the formatted detailed error message. } +/* + * This function generates an error code string based on the provided SQL state. + * + * Parameters: + * - sql_state: An integer representing the SQL state code. + * + * Returns: + * - A pointer to a character array containing the formatted error code. + * + * Description: + * - The function takes an integer 'sql_state' representing an SQL state code and converts it into a string format. + * - The SQL state code is a five-character code where each character represents a six-bit value. + * - The function iterates through the SQL state code, extracting each six-bit value and converting it into a character. + * - The resulting error code is prefixed with "[ERRCODE]:" and stored in 'errbuf_errcode'. + * - The function ensures that 'errbuf_errcode' is null-terminated. + * - The caller should be aware that the returned error code is stored in a local array, and its memory may become + * invalid once the function exits. + * + * Notes: + * - It's the caller's responsibility to handle and manage the memory of the returned error code. + */ + char* errcode(int sql_state) { int i; int rcs; errno_t rc; char buf[6] = {0}; - rc = memset_s(errbuf_errcode, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); + rc = memset_s(errbuf_errcode, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); // Clear the error code buffer. securec_check_c(rc, "\0", "\0"); - /* the length of sql code is 5 */ + + // Extract each six-bit value from the SQL state code and convert it into a character. for (i = 0; i < 5; i++) { buf[i] = PGUNSIXBIT(sql_state); sql_state >>= 6; } buf[i] = '\0'; + + // Prefix the formatted error code with "[ERRCODE]:" and store it in 'errbuf_errcode'. rcs = snprintf_s(errbuf_errcode, EREPORT_BUF_LEN, EREPORT_BUF_LEN - 1, "%s%s", "[ERRCODE]:", buf); securec_check_intval(rcs, ); - return errbuf_errcode; + + return errbuf_errcode; // Return the formatted error code. } + +/* + * This function generates an error cause message formatted using the provided format string and arguments. + * + * Parameters: + * - fmt: A format string specifying the error cause message format. + * - ...: Variable arguments corresponding to the format placeholders in the format string. + * + * Returns: + * - A pointer to a character array containing the formatted error cause message. + * + * Description: + * - The function takes a format string 'fmt' and a variable number of arguments, similar to the 'printf' function. + * - It formats the error cause message according to the 'fmt' string and the provided arguments. + * - The formatted error cause message is stored in a character array 'errbuf' with a maximum length of 'BUF_LEN'. + * - The function ensures that 'errbuf' is null-terminated. + * - The formatted error cause message is prefixed with "[ERRCAUSE]:" and then concatenated with any additional text. + * - The resulting error cause message is stored in 'errbuf_errcause' and returned. + * - The caller should be aware that the returned error cause message is stored in a local array, and its memory may become + * invalid once the function exits. + * + * Notes: + * - It's the caller's responsibility to handle and manage the memory of the returned error cause message. + */ + char* errcause(const char* fmt, ...) { - va_list ap; - int count = 0; - int rcs; - errno_t rc; - char errbuf[BUF_LEN] = {0}; + va_list ap; // Variable argument list. + int count = 0; // Count of characters written. + int rcs; // Return code of snprintf. + errno_t rc; // Error code variable for safe C library functions. + char errbuf[BUF_LEN] = {0}; // Buffer for formatting the error cause message. + + // Make sure the format string is translated if required. fmt = _(fmt); - va_start(ap, fmt); - rc = memset_s(errbuf_errcause, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); + + va_start(ap, fmt); // Initialize the variable argument list. + rc = memset_s(errbuf_errcause, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); // Clear the error cause message buffer. securec_check_c(rc, "\0", "\0"); + + // Format the error cause message using vsnprintf_s. count = vsnprintf_s(errbuf, sizeof(errbuf), sizeof(errbuf) - 1, fmt, ap); securec_check_intval(count, ); - va_end(ap); - rcs = snprintf_s(errbuf_errcause, EREPORT_BUF_LEN, - EREPORT_BUF_LEN - 1, "%s", "[ERRCAUSE]:"); + + va_end(ap); // End the variable argument list. + + // Prefix the formatted error cause message with "[ERRCAUSE]:" and concatenate it with any additional text. + rcs = snprintf_s(errbuf_errcause, EREPORT_BUF_LEN, EREPORT_BUF_LEN - 1, "%s", "[ERRCAUSE]:"); securec_check_intval(rcs, ); rc = memcpy_s(errbuf_errcause + strlen(errbuf_errcause), BUF_LEN - strlen(errbuf_errcause), errbuf, BUF_LEN - strlen(errbuf_errcause) - 1); securec_check_errno(rc, (void)rc); - return errbuf_errcause; + + return errbuf_errcause; // Return the formatted error cause message. } + +/* + * This function generates an error action message formatted using the provided format string and arguments. + * + * Parameters: + * - fmt: A format string specifying the error action message format. + * - ...: Variable arguments corresponding to the format placeholders in the format string. + * + * Returns: + * - A pointer to a character array containing the formatted error action message. + * + * Description: + * - The function takes a format string 'fmt' and a variable number of arguments, similar to the 'printf' function. + * - It formats the error action message according to the 'fmt' string and the provided arguments. + * - The formatted error action message is stored in a character array 'errbuf' with a maximum length of 'BUF_LEN'. + * - The function ensures that 'errbuf' is null-terminated. + * - The formatted error action message is prefixed with "[ERRACTION]:" and then concatenated with any additional text. + * - The resulting error action message is stored in 'errbuf_erraction' and returned. + * - The caller should be aware that the returned error action message is stored in a local array, and its memory may become + * invalid once the function exits. + * + * Notes: + * - It's the caller's responsibility to handle and manage the memory of the returned error action message. + */ + char* erraction(const char* fmt, ...) { - va_list ap; - int count = 0; - int rcs; - errno_t rc; - char errbuf[BUF_LEN] = {0}; + va_list ap; // Variable argument list. + int count = 0; // Count of characters written. + int rcs; // Return code of snprintf. + errno_t rc; // Error code variable for safe C library functions. + char errbuf[BUF_LEN] = {0}; // Buffer for formatting the error action message. + + // Make sure the format string is translated if required. fmt = _(fmt); - va_start(ap, fmt); - rc = memset_s(errbuf_erraction, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); + + va_start(ap, fmt); // Initialize the variable argument list. + rc = memset_s(errbuf_erraction, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); // Clear the error action message buffer. securec_check_c(rc, "\0", "\0"); + + // Format the error action message using vsnprintf_s. count = vsnprintf_s(errbuf, sizeof(errbuf), sizeof(errbuf) - 1, fmt, ap); securec_check_intval(count, ); - va_end(ap); - rcs = snprintf_s(errbuf_erraction, EREPORT_BUF_LEN, - EREPORT_BUF_LEN - 1, "%s", "[ERRACTION]:"); + + va_end(ap); // End the variable argument list. + + // Prefix the formatted error action message with "[ERRACTION]:" and concatenate it with any additional text. + rcs = snprintf_s(errbuf_erraction, EREPORT_BUF_LEN, EREPORT_BUF_LEN - 1, "%s", "[ERRACTION]:"); securec_check_intval(rcs, ); rc = memcpy_s(errbuf_erraction + strlen(errbuf_erraction), BUF_LEN - strlen(errbuf_erraction), errbuf, BUF_LEN - strlen(errbuf_erraction) - 1); securec_check_errno(rc, (void)rc); - return errbuf_erraction; + + return errbuf_erraction; // Return the formatted error action message. } +/* + * This function generates an error module message based on the provided ModuleId. + * + * Parameters: + * - id: A ModuleId representing the error module. + * + * Returns: + * - A pointer to a character array containing the formatted error module message. + * + * Description: + * - The function takes a ModuleId 'id' and generates an error module message. + * - The error module message is prefixed with "[ERRMODULE]:". + * - The actual module name corresponding to 'id' is obtained using 'get_valid_module_name'. + * - The obtained module name is concatenated with the prefix and stored in 'errbuf_errmodule'. + * - The function ensures that 'errbuf_errmodule' is null-terminated. + * - The caller should be aware that the returned error module message is stored in a local array, and its memory may become + * invalid once the function exits. + * + * Notes: + * - It's the caller's responsibility to handle and manage the memory of the returned error module message. + */ + char* errmodule(ModuleId id) { - errno_t rc = memset_s(errbuf_errmodule, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); + errno_t rc = memset_s(errbuf_errmodule, EREPORT_BUF_LEN, 0, EREPORT_BUF_LEN); // Clear the error module message buffer. securec_check_c(rc, "\0", "\0"); - int rcs = snprintf_s(errbuf_errmodule, EREPORT_BUF_LEN - 1, - EREPORT_BUF_LEN - 1, "%s", "[ERRMODULE]:"); + + int rcs = snprintf_s(errbuf_errmodule, EREPORT_BUF_LEN - 1, EREPORT_BUF_LEN - 1, "%s", "[ERRMODULE]:"); // Prefix with "[ERRMODULE]:". securec_check_intval(rcs, (void)rcs); - rcs = snprintf_s(errbuf_errmodule + strlen(errbuf_errmodule), - EREPORT_BUF_LEN - strlen(errbuf_errmodule), - EREPORT_BUF_LEN - strlen(errbuf_errmodule) - 1, "%s", - get_valid_module_name(id)); + + // Get the valid module name corresponding to the provided ModuleId and concatenate it with the prefix. + rcs = snprintf_s(errbuf_errmodule + strlen(errbuf_errmodule), EREPORT_BUF_LEN - strlen(errbuf_errmodule), + EREPORT_BUF_LEN - strlen(errbuf_errmodule) - 1, "%s", get_valid_module_name(id)); securec_check_intval(rcs, (void)rcs); - return errbuf_errmodule; + + return errbuf_errmodule; // Return the formatted error module message. } -- 2.34.1 From 981e4a8f2eb8feefd3d16b015194e4ecf1cbd750 Mon Sep 17 00:00:00 2001 From: Wang17 Date: Thu, 5 Oct 2023 16:12:53 +0800 Subject: [PATCH 065/118] Update cm_path.cpp --- src/lib/cm_common/cm_path.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib/cm_common/cm_path.cpp b/src/lib/cm_common/cm_path.cpp index af95429af..b2f956168 100644 --- a/src/lib/cm_common/cm_path.cpp +++ b/src/lib/cm_common/cm_path.cpp @@ -1,3 +1,10 @@ +/*** + * @Author: 王贤义 + * @Team: 兰心开源 + * @Date: 2023-09-13 20:25:05 + */ + + /** * @file cm_path.cpp * @brief -- 2.34.1 From 53c537a0aef7c1f42d8477e4096642a4da722026 Mon Sep 17 00:00:00 2001 From: Wang17 Date: Thu, 5 Oct 2023 16:13:37 +0800 Subject: [PATCH 066/118] Update cm_stringinfo.cpp --- src/lib/cm_common/cm_stringinfo.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib/cm_common/cm_stringinfo.cpp b/src/lib/cm_common/cm_stringinfo.cpp index 0b1140e80..9abebb4dc 100644 --- a/src/lib/cm_common/cm_stringinfo.cpp +++ b/src/lib/cm_common/cm_stringinfo.cpp @@ -1,3 +1,10 @@ +/*** + * @Author: 王贤义 + * @Team: 兰心开源 + * @Date: 2023-09-14 20:25:05 + */ + + /** * @file cm_stringinfo.cpp * @brief StringInfo provides an indefinitely-extensible string data type. -- 2.34.1 From 876193214561868108205d106c574e3afc2be3bf Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 20:01:09 +0800 Subject: [PATCH 067/118] Update dllist.cpp --- src/common/backend/lib/dllist.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/common/backend/lib/dllist.cpp b/src/common/backend/lib/dllist.cpp index c537c3c54..6c849ec8b 100644 --- a/src/common/backend/lib/dllist.cpp +++ b/src/common/backend/lib/dllist.cpp @@ -1,3 +1,10 @@ +/*** + * @Author: 张鹏春 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + + /* ------------------------------------------------------------------------- * * dllist.cpp -- 2.34.1 From d3efcd45649108bfebdc6d480971ca26a5e1c253 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 20:02:08 +0800 Subject: [PATCH 068/118] Update dllist.h --- src/include/lib/dllist.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/include/lib/dllist.h b/src/include/lib/dllist.h index 729466ae1..4ecc87401 100644 --- a/src/include/lib/dllist.h +++ b/src/include/lib/dllist.h @@ -1,3 +1,10 @@ +/*** + * @Author: 张鹏春 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + + /* ------------------------------------------------------------------------- * * dllist.h -- 2.34.1 From bc77c287a2ac6046a2585a1f0694c7f1e8109df0 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 20:03:22 +0800 Subject: [PATCH 069/118] Update binaryheap.h --- src/include/lib/binaryheap.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/include/lib/binaryheap.h b/src/include/lib/binaryheap.h index 699b42f6d..03edab030 100644 --- a/src/include/lib/binaryheap.h +++ b/src/include/lib/binaryheap.h @@ -1,3 +1,11 @@ +/*** + * @Author: 张鹏春 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + + + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 17e4f7a03e19d089fb751a6b93014ec289627157 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 20:53:03 +0800 Subject: [PATCH 070/118] Update archive_am.h --- src/include/access/archive/archive_am.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/include/access/archive/archive_am.h b/src/include/access/archive/archive_am.h index f291adaec..f79354caf 100644 --- a/src/include/access/archive/archive_am.h +++ b/src/include/access/archive/archive_am.h @@ -1,3 +1,11 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + + + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 0e43d78b519a2248d54570b6f3e8ddc310c5853a Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 20:55:05 +0800 Subject: [PATCH 071/118] Update nas_am.h --- src/include/access/archive/nas_am.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/archive/nas_am.h b/src/include/access/archive/nas_am.h index 27f429aeb..1d2926a93 100644 --- a/src/include/access/archive/nas_am.h +++ b/src/include/access/archive/nas_am.h @@ -1,3 +1,9 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From c7c2e1d8590aa5b98b42189641424b7f6987d9b9 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 20:56:28 +0800 Subject: [PATCH 072/118] Update nas_am.h --- src/include/access/archive/nas_am.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/include/access/archive/nas_am.h b/src/include/access/archive/nas_am.h index 1d2926a93..27f429aeb 100644 --- a/src/include/access/archive/nas_am.h +++ b/src/include/access/archive/nas_am.h @@ -1,9 +1,3 @@ -/*** - * @Author: 王语翀 - * @Team: 兰心开源 - * @Date: 2023-09-11 20:25:05 - */ - /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From d95bce6550471e3af74ca7f9ef295a73273bd16e Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 20:57:29 +0800 Subject: [PATCH 073/118] Update carbondata_index_reader.h --- src/include/access/dfs/carbondata_index_reader.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/dfs/carbondata_index_reader.h b/src/include/access/dfs/carbondata_index_reader.h index 2e08238be..53da97b1f 100644 --- a/src/include/access/dfs/carbondata_index_reader.h +++ b/src/include/access/dfs/carbondata_index_reader.h @@ -1,3 +1,9 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 7e451a02edd97a2564bfc92560e8dd119ff6b739 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 20:58:14 +0800 Subject: [PATCH 074/118] Update dfs_stream.h --- src/include/access/dfs/dfs_stream.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/dfs/dfs_stream.h b/src/include/access/dfs/dfs_stream.h index d465cd020..923838035 100644 --- a/src/include/access/dfs/dfs_stream.h +++ b/src/include/access/dfs/dfs_stream.h @@ -1,3 +1,9 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-1 20:25:05 + */ + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From c2567e99dcd6100461e7b9c25e5ae2114c7f8d16 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 20:58:54 +0800 Subject: [PATCH 075/118] Update batch_redo.h --- src/include/access/extreme_rto/batch_redo.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/extreme_rto/batch_redo.h b/src/include/access/extreme_rto/batch_redo.h index 79c9af60f..ceb821432 100644 --- a/src/include/access/extreme_rto/batch_redo.h +++ b/src/include/access/extreme_rto/batch_redo.h @@ -1,3 +1,9 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 38315c304744a6f92f124acf9f83e88cee673bfb Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 20:59:46 +0800 Subject: [PATCH 076/118] Update spsc_blocking_queue.h --- src/include/access/extreme_rto/spsc_blocking_queue.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/extreme_rto/spsc_blocking_queue.h b/src/include/access/extreme_rto/spsc_blocking_queue.h index 74c1ff89d..795cfefcd 100644 --- a/src/include/access/extreme_rto/spsc_blocking_queue.h +++ b/src/include/access/extreme_rto/spsc_blocking_queue.h @@ -1,3 +1,9 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From f4fe449ba4d9624643d2a49496e88a9e045ecb74 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:01:17 +0800 Subject: [PATCH 077/118] Update obs_am.h --- src/include/access/obs/obs_am.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/obs/obs_am.h b/src/include/access/obs/obs_am.h index 2ed9be000..722b4c67c 100755 --- a/src/include/access/obs/obs_am.h +++ b/src/include/access/obs/obs_am.h @@ -1,3 +1,9 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 01a88a9c7b2fe22b5fdd06d583147bb047ba2bba Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:01:55 +0800 Subject: [PATCH 078/118] Update knl_uundotype.h --- src/include/access/ustore/undo/knl_uundotype.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/ustore/undo/knl_uundotype.h b/src/include/access/ustore/undo/knl_uundotype.h index bf50bd7d7..88641c250 100644 --- a/src/include/access/ustore/undo/knl_uundotype.h +++ b/src/include/access/ustore/undo/knl_uundotype.h @@ -1,3 +1,9 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + /* ------------------------------------------------------------------------- * * knl_uundotype.h -- 2.34.1 From 1b8563ebda4f41af707d5b0e78b2523f39962a52 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:02:32 +0800 Subject: [PATCH 079/118] Update clog.h --- src/include/access/clog.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/clog.h b/src/include/access/clog.h index 45cf028f2..93b6e6460 100644 --- a/src/include/access/clog.h +++ b/src/include/access/clog.h @@ -1,3 +1,9 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + /* * clog.h * -- 2.34.1 From 77461eb859ebb50e3007ef8897046b0ed68577a7 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:03:29 +0800 Subject: [PATCH 080/118] Update cstore_psort.h --- src/include/access/cstore_psort.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/cstore_psort.h b/src/include/access/cstore_psort.h index f9bd04037..75ec4e4bd 100644 --- a/src/include/access/cstore_psort.h +++ b/src/include/access/cstore_psort.h @@ -1,3 +1,9 @@ + +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From ff3124a53f6799e01e64656ec578b07279ae2df5 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:03:49 +0800 Subject: [PATCH 081/118] Update cstore_delta.h --- src/include/access/cstore_delta.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/cstore_delta.h b/src/include/access/cstore_delta.h index 3cb9f53ee..fe80a098a 100644 --- a/src/include/access/cstore_delta.h +++ b/src/include/access/cstore_delta.h @@ -1,3 +1,9 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 81e118d02088d50d208b1c34ccc8acfc93440064 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:04:13 +0800 Subject: [PATCH 082/118] Update cstoreskey.h --- src/include/access/cstoreskey.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/cstoreskey.h b/src/include/access/cstoreskey.h index 8b78a30b6..d1674b0ca 100644 --- a/src/include/access/cstoreskey.h +++ b/src/include/access/cstoreskey.h @@ -1,3 +1,9 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-09-11 20:25:05 + */ + /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 0c5025f5ddac81643a69df738309683217a9ddcb Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:07:36 +0800 Subject: [PATCH 083/118] Update cbtree.h --- src/include/access/cbtree.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/access/cbtree.h b/src/include/access/cbtree.h index 2d4ac1359..edc9f76e0 100644 --- a/src/include/access/cbtree.h +++ b/src/include/access/cbtree.h @@ -1,3 +1,9 @@ + +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + * @Date: 2023-08-11 20:25:05 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 74d1600b86f33702f207e11ad6d8a34d25a76262 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:08:05 +0800 Subject: [PATCH 084/118] Update gin.h --- src/include/access/gin.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/include/access/gin.h b/src/include/access/gin.h index ab9f21295..e6e4d7736 100644 --- a/src/include/access/gin.h +++ b/src/include/access/gin.h @@ -1,3 +1,8 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ + /* -------------------------------------------------------------------------- * gin.h * Public header file for Generalized Inverted Index access method. -- 2.34.1 From b496a596910d40b412df01df89b4b7df2a85bcff Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:08:46 +0800 Subject: [PATCH 085/118] Update gist.h --- src/include/access/gist.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/include/access/gist.h b/src/include/access/gist.h index 82febe14e..1ff059866 100644 --- a/src/include/access/gist.h +++ b/src/include/access/gist.h @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * gist.h -- 2.34.1 From a5a67416367171dfb0675baca449498f7d442222 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:09:02 +0800 Subject: [PATCH 086/118] Update tupdesc.h --- src/include/access/tupdesc.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index a12d3f726..5efd84782 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.h @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * tupdesc.h -- 2.34.1 From d936c0a403d1013e482b9b7de34222daade03529 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:09:24 +0800 Subject: [PATCH 087/118] Update tupconvert.h --- src/include/access/tupconvert.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/include/access/tupconvert.h b/src/include/access/tupconvert.h index 011cee296..760b14eba 100644 --- a/src/include/access/tupconvert.h +++ b/src/include/access/tupconvert.h @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * tupconvert.h -- 2.34.1 From 184182b0beb11e335190dcb39bd913d75620b189 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:09:53 +0800 Subject: [PATCH 088/118] Update hypopg_index.cpp --- src/gausskernel/dbmind/kernel/hypopg_index.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index 7b8fc459b..a1c5aa711 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * hypopg_index.cpp: Implementation of hypothetical indexes for openGauss -- 2.34.1 From c45c127df5e58d4f4bcd6b1707a18581f1670649 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:12:04 +0800 Subject: [PATCH 089/118] Update hypopg_index.cpp --- .../dbmind/kernel/hypopg_index.cpp | 30 +++---------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index a1c5aa711..71b58f431 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -1,7 +1,3 @@ -/*** - * @Author: 王语翀 - * @Team: 兰心开源 - */ /* ------------------------------------------------------------------------- * * hypopg_index.cpp: Implementation of hypothetical indexes for openGauss @@ -131,12 +127,6 @@ void InitHypopg() } isExplain = false; } -/* -SQLAllocConnect() allocates a connection handle and associated resources within the -environment that is identified by the input environment handle. Call SQLGetInfo() with -fInfoType set to SQL_ACTIVE_CONNECTIONS to query the number of connections that -can be allocated at any one time. SQLAllocEnv() must be called before calling this function.*/ - /* Set_hypopg_prehook function: @@ -195,18 +185,7 @@ static Oid hypo_getNewOid(Oid relid) /* Open the relation on which we want a new OID */ relation = heap_open(relid, AccessShareLock); - -/*In PostgreSQL, AccessShareLock is a lock type used to -control concurrent access to database objects. It is a read -lock that allows multiple transactions to read from the same -object at the same time, but it prevents concurrent transactions -from acquiring conflicting locks, such as write locks or exclusive locks. -When a transaction obtains AccessShareLock on an object, other -transactions can also obtain AccessShareLock on the same object. -This means that multiple transactions can read objects at the same -time without interfering with each other.*/ - - + reltablespace = relation->rd_rel->reltablespace; relpersistence = relation->rd_rel->relpersistence; @@ -321,7 +300,6 @@ List *get_table_indexes(Oid oid) heap_close(rel, NoLock); return indexes; } -/*Read-only here will not cause deadlock, so use NoLock lock.*/ /* Return the names of all the columns involved in the index. */ @@ -614,7 +592,7 @@ static void hypo_process_attr(IndexStmt *node, hypoIndex *volatile entry, String int attn; attn = 0; - foreach (lc, node->indexParams) { /*Traverse all nodes*/ + foreach (lc, node->indexParams) { IndexElem *attribute = (IndexElem *)lfirst(lc); Oid atttype = InvalidOid; Oid opclass; @@ -809,7 +787,7 @@ static const hypoIndex *hypo_index_store_parsetree(IndexStmt *node, const char * if (nkeycolumns > INDEX_MAX_KEYS) { elog(ERROR, "hypopg: cannot use more thant %d columns in an index", INDEX_MAX_KEYS); } - //Show basic attributes + initStringInfo(&indexRelationName); appendStringInfoString(&indexRelationName, node->accessMethod); appendStringInfoString(&indexRelationName, "_"); @@ -880,7 +858,7 @@ static const hypoIndex *hypo_index_store_parsetree(IndexStmt *node, const char * pull_varattnos((Node *)entry->indexprs, 1, &indexattrs); pull_varattnos((Node *)entry->indpred, 1, &indexattrs); - for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++) { //I is a negative number + for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++) { if (i != ObjectIdAttributeNumber && bms_is_member(i - FirstLowInvalidHeapAttributeNumber, indexattrs)) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("hypopg: index creation on system columns is not supported"))); -- 2.34.1 From 9b0745f77d45b37909420d016686d60780d09f06 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:12:28 +0800 Subject: [PATCH 090/118] Update hypopg_index.cpp --- src/gausskernel/dbmind/kernel/hypopg_index.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index 71b58f431..6ca0dbea3 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * hypopg_index.cpp: Implementation of hypothetical indexes for openGauss -- 2.34.1 From 29e5630b68f0281d5aea700268e5b677d15ca6f3 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:15:03 +0800 Subject: [PATCH 091/118] Update hypopg_index.cpp --- src/gausskernel/dbmind/kernel/hypopg_index.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index 6ca0dbea3..71b58f431 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -1,7 +1,3 @@ -/*** - * @Author: 王语翀 - * @Team: 兰心开源 - */ /* ------------------------------------------------------------------------- * * hypopg_index.cpp: Implementation of hypothetical indexes for openGauss -- 2.34.1 From 9e652447133cdd425b32268cfd993bda61e14b84 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:24:38 +0800 Subject: [PATCH 092/118] Update hypopg_index.cpp --- src/gausskernel/dbmind/kernel/hypopg_index.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index 71b58f431..6ca0dbea3 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * hypopg_index.cpp: Implementation of hypothetical indexes for openGauss -- 2.34.1 From 56b2c6cd08704dd13fb10c4aff8b3f7190d94542 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:26:41 +0800 Subject: [PATCH 093/118] Update hypopg_index.cpp --- .../dbmind/kernel/hypopg_index.cpp | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index 6ca0dbea3..7b8fc459b 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -1,7 +1,3 @@ -/*** - * @Author: 王语翀 - * @Team: 兰心开源 - */ /* ------------------------------------------------------------------------- * * hypopg_index.cpp: Implementation of hypothetical indexes for openGauss @@ -131,6 +127,12 @@ void InitHypopg() } isExplain = false; } +/* +SQLAllocConnect() allocates a connection handle and associated resources within the +environment that is identified by the input environment handle. Call SQLGetInfo() with +fInfoType set to SQL_ACTIVE_CONNECTIONS to query the number of connections that +can be allocated at any one time. SQLAllocEnv() must be called before calling this function.*/ + /* Set_hypopg_prehook function: @@ -189,7 +191,18 @@ static Oid hypo_getNewOid(Oid relid) /* Open the relation on which we want a new OID */ relation = heap_open(relid, AccessShareLock); - + +/*In PostgreSQL, AccessShareLock is a lock type used to +control concurrent access to database objects. It is a read +lock that allows multiple transactions to read from the same +object at the same time, but it prevents concurrent transactions +from acquiring conflicting locks, such as write locks or exclusive locks. +When a transaction obtains AccessShareLock on an object, other +transactions can also obtain AccessShareLock on the same object. +This means that multiple transactions can read objects at the same +time without interfering with each other.*/ + + reltablespace = relation->rd_rel->reltablespace; relpersistence = relation->rd_rel->relpersistence; @@ -304,6 +317,7 @@ List *get_table_indexes(Oid oid) heap_close(rel, NoLock); return indexes; } +/*Read-only here will not cause deadlock, so use NoLock lock.*/ /* Return the names of all the columns involved in the index. */ @@ -596,7 +610,7 @@ static void hypo_process_attr(IndexStmt *node, hypoIndex *volatile entry, String int attn; attn = 0; - foreach (lc, node->indexParams) { + foreach (lc, node->indexParams) { /*Traverse all nodes*/ IndexElem *attribute = (IndexElem *)lfirst(lc); Oid atttype = InvalidOid; Oid opclass; @@ -791,7 +805,7 @@ static const hypoIndex *hypo_index_store_parsetree(IndexStmt *node, const char * if (nkeycolumns > INDEX_MAX_KEYS) { elog(ERROR, "hypopg: cannot use more thant %d columns in an index", INDEX_MAX_KEYS); } - + //Show basic attributes initStringInfo(&indexRelationName); appendStringInfoString(&indexRelationName, node->accessMethod); appendStringInfoString(&indexRelationName, "_"); @@ -862,7 +876,7 @@ static const hypoIndex *hypo_index_store_parsetree(IndexStmt *node, const char * pull_varattnos((Node *)entry->indexprs, 1, &indexattrs); pull_varattnos((Node *)entry->indpred, 1, &indexattrs); - for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++) { + for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++) { //I is a negative number if (i != ObjectIdAttributeNumber && bms_is_member(i - FirstLowInvalidHeapAttributeNumber, indexattrs)) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("hypopg: index creation on system columns is not supported"))); -- 2.34.1 From 70288f185040808ad5c0c6f2ae769d25b9548bc7 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:27:23 +0800 Subject: [PATCH 094/118] Update hypopg_index.cpp --- src/gausskernel/dbmind/kernel/hypopg_index.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index 7b8fc459b..a1c5aa711 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * hypopg_index.cpp: Implementation of hypothetical indexes for openGauss -- 2.34.1 From 8ea182c5b0b696acdc0a17fc89ee6e3937d28c74 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:29:02 +0800 Subject: [PATCH 095/118] Update index_advisor.cpp --- src/gausskernel/dbmind/kernel/index_advisor.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/kernel/index_advisor.cpp b/src/gausskernel/dbmind/kernel/index_advisor.cpp index 0a3def97e..6d92b0a4f 100644 --- a/src/gausskernel/dbmind/kernel/index_advisor.cpp +++ b/src/gausskernel/dbmind/kernel/index_advisor.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 5d86659bd64ad86f1be7af1f60597548b354696c Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:29:46 +0800 Subject: [PATCH 096/118] Update index_advisor.cpp --- .../dbmind/kernel/index_advisor.cpp | 75 +------------------ 1 file changed, 3 insertions(+), 72 deletions(-) diff --git a/src/gausskernel/dbmind/kernel/index_advisor.cpp b/src/gausskernel/dbmind/kernel/index_advisor.cpp index 6d92b0a4f..c211f50c2 100644 --- a/src/gausskernel/dbmind/kernel/index_advisor.cpp +++ b/src/gausskernel/dbmind/kernel/index_advisor.cpp @@ -1,7 +1,3 @@ -/*** - * @Author: 王语翀 - * @Team: 兰心开源 - */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * @@ -489,14 +485,6 @@ void get_join_condition_from_plan(Node* node, List* rtable) } } -/*/*Add_index function: - -Parameter: (table cell * table, char * index _ name) - -Return value: None. - -Function: Add nodes to the table.*/ - void add_index(TableCell *table, char *index_name) { IndexCell *index = (IndexCell *)palloc0(sizeof(*index)); @@ -533,8 +521,6 @@ void add_index(TableCell *table, char *index_name) } } - - void get_order_condition_from_plan(Node* node) { Sort *sortopt = (Sort *)node; @@ -578,14 +564,6 @@ void get_order_condition_from_plan(Node* node) } } -/*Free_global_resource function - -Formal parameter: none - -Return value: None - -Role: release global resources.*/ - void free_global_resource() { list_free(g_drived_tables); @@ -599,14 +577,7 @@ void free_global_resource() g_driver_table = NULL; } -/* -Get_table_indexes function: - -Parameter: oid - -Back to: list - -Search the oid of all indexes created on the table through the oid of the table, +/* Search the oid of all indexes created on the table through the oid of the table, * and return the index oid list. */ List *get_table_indexes(Oid oid) @@ -679,11 +650,7 @@ List *get_index_attname(Oid index_oid) return attnames; } -/* -Execute_ Stmt function: -Formal parameters: (const char * query_string, bool need_result) -Return: StmtResult -Execute an SQL statement and return the result.*/ +// Execute an SQL statement and return its result. StmtResult *execute_stmt(const char *query_string, bool need_result) { int16 format = 0; @@ -790,14 +757,7 @@ void shutdown(DestReceiver *self) { /* nothing */ } -/* -Destroy function: - -Parameter: (DestReceiver *self) - -Return: None - -The function frees all allocated memory.Release resources */ +/* Release resources */ void destroy(DestReceiver *self) { StmtResult *result = (StmtResult *)self; @@ -812,15 +772,6 @@ void destroy(DestReceiver *self) } /* - -Find_select_stmt function: - -Parameter: (Node *parsetree) - -Return: None - -Recursively search the SelectStmt structure in the parse tree. - * find_select_stmt * Recursively search for SelectStmt structures within a parse tree. * @@ -976,12 +927,6 @@ void get_partition_index_type(IndexPrint *suggested_index, TableCell *table) } /* -Generate_ Index_ Print function: -Formal parameters: (TableCell * table, char * index_print) -Return: IndexPrint* -Generate Index Printing - - * generat_index_print * Generate index type, normal table is '' by default * partition table is divided into local and global. @@ -1027,15 +972,6 @@ IndexPrint *generat_index_print(TableCell *table, char *index_print) return suggested_index; } - -/*Find_table function: - -Parameter: (TableCell *table) - -Return: TableCell* - -Find index table*/ - TableCell *find_table(TableCell *table) { ListCell *item = NULL; @@ -1592,11 +1528,6 @@ uint4 calculate_field_cardinality(char *schema_name, char *table_name, const cha return cardinality; } -/*Split_ Field_ List function: -Formal parameters: (List * fields, char * * schema_name_ptr, char * * table_name_ptr, char * * col_name_ptr) -Return: None -Split the specified area index table*/ - void split_field_list(List *fields, char **schema_name_ptr, char **table_name_ptr, char **col_name_ptr) { if (fields == NULL) { -- 2.34.1 From 3775f70b079ab6f49acefe63f8513f1a51b4db83 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:30:16 +0800 Subject: [PATCH 097/118] Update index_advisor.cpp --- src/gausskernel/dbmind/kernel/index_advisor.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/kernel/index_advisor.cpp b/src/gausskernel/dbmind/kernel/index_advisor.cpp index c211f50c2..dd35511b3 100644 --- a/src/gausskernel/dbmind/kernel/index_advisor.cpp +++ b/src/gausskernel/dbmind/kernel/index_advisor.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From ce7b86e7fb1fe03d7ddeafb576b01dc266e31cd7 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:32:15 +0800 Subject: [PATCH 098/118] Update hyperparameter_validation.cpp --- .../dbmind/db4ai/executor/hyperparameter_validation.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp b/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp index 9612a74bf..9a51f9401 100644 --- a/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/hyperparameter_validation.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 5bbbdf26d9f02793fe461e2aa90655ffa1cd6f31 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:33:08 +0800 Subject: [PATCH 099/118] Update matrix.cpp --- src/gausskernel/dbmind/db4ai/executor/matrix.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/matrix.cpp b/src/gausskernel/dbmind/db4ai/executor/matrix.cpp index 2da1b4267..f8dd2ced7 100644 --- a/src/gausskernel/dbmind/db4ai/executor/matrix.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/matrix.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 5bb60ad54305121cc97ca9e7f1241b2f777f4bb7 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:35:02 +0800 Subject: [PATCH 100/118] Update distance_functions.cpp --- src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp b/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp index bdc536107..5ee8b453f 100644 --- a/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/distance_functions.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2021 Huawei Technologies Co.,Ltd. -- 2.34.1 From 35ee6b9745d08e51a93564a33615677e388ef795 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:35:32 +0800 Subject: [PATCH 101/118] Update direct.cpp --- src/gausskernel/dbmind/db4ai/executor/direct.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/direct.cpp b/src/gausskernel/dbmind/db4ai/executor/direct.cpp index 417602135..604b18893 100644 --- a/src/gausskernel/dbmind/db4ai/executor/direct.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/direct.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From e77287962ec2d8c65e7f50e73779928c02f03bd5 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:36:11 +0800 Subject: [PATCH 102/118] Update kmeans.cpp --- src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp b/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp index eaec8d697..d6701f262 100644 --- a/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/kmeans/kmeans.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /** Copyright (c) 2021 Huawei Technologies Co.,Ltd. -- 2.34.1 From d0cb929c6f3f2872a5058fc83451384ef815aff3 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:36:38 +0800 Subject: [PATCH 103/118] Update xgboost.cpp --- src/gausskernel/dbmind/db4ai/executor/xgboost/xgboost.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/xgboost/xgboost.cpp b/src/gausskernel/dbmind/db4ai/executor/xgboost/xgboost.cpp index 562592d2e..83749fb7f 100644 --- a/src/gausskernel/dbmind/db4ai/executor/xgboost/xgboost.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/xgboost/xgboost.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 75cf0b4134915cbd7a921e9b899bbce12f98544c Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:36:54 +0800 Subject: [PATCH 104/118] Update pca.cpp --- src/gausskernel/dbmind/db4ai/executor/gd/pca.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/gd/pca.cpp b/src/gausskernel/dbmind/db4ai/executor/gd/pca.cpp index 6d2ba0d47..38a84f086 100644 --- a/src/gausskernel/dbmind/db4ai/executor/gd/pca.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/gd/pca.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 2114ca86a25253a23aeb36d053d40ac2535cc829 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:37:12 +0800 Subject: [PATCH 105/118] Update svm.cpp --- src/gausskernel/dbmind/db4ai/executor/gd/svm.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/gd/svm.cpp b/src/gausskernel/dbmind/db4ai/executor/gd/svm.cpp index c748c9af7..2b4b4115a 100644 --- a/src/gausskernel/dbmind/db4ai/executor/gd/svm.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/gd/svm.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 788616ffb80fee69a8feaabc1de467cf8e0f415a Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:39:35 +0800 Subject: [PATCH 106/118] Update gd.cpp --- src/gausskernel/dbmind/db4ai/executor/gd/gd.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/gd/gd.cpp b/src/gausskernel/dbmind/db4ai/executor/gd/gd.cpp index 1920be902..763b85e55 100644 --- a/src/gausskernel/dbmind/db4ai/executor/gd/gd.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/gd/gd.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From e88d95da7918b4c2c9e5baa7e7b6e4ffe75de802 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:39:53 +0800 Subject: [PATCH 107/118] Update linregr.cpp --- src/gausskernel/dbmind/db4ai/executor/gd/linregr.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/gd/linregr.cpp b/src/gausskernel/dbmind/db4ai/executor/gd/linregr.cpp index c208bab2a..4d731713c 100644 --- a/src/gausskernel/dbmind/db4ai/executor/gd/linregr.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/gd/linregr.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From d46d3998e15c8d48dc1c4dd8c0efd109127cafbe Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:40:06 +0800 Subject: [PATCH 108/118] Update logregr.cpp --- src/gausskernel/dbmind/db4ai/executor/gd/logregr.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/dbmind/db4ai/executor/gd/logregr.cpp b/src/gausskernel/dbmind/db4ai/executor/gd/logregr.cpp index 908e15273..3f28e7571 100644 --- a/src/gausskernel/dbmind/db4ai/executor/gd/logregr.cpp +++ b/src/gausskernel/dbmind/db4ai/executor/gd/logregr.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 08cba03d865ea198f433d4696e5315cfac11aca6 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:40:26 +0800 Subject: [PATCH 109/118] Update blockchain.cpp --- src/gausskernel/security/gs_ledger/blockchain.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/security/gs_ledger/blockchain.cpp b/src/gausskernel/security/gs_ledger/blockchain.cpp index 98310ffa7..c982dddc6 100644 --- a/src/gausskernel/security/gs_ledger/blockchain.cpp +++ b/src/gausskernel/security/gs_ledger/blockchain.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From eff5132bd3e0aa4f9325c3d568aa5fa06ead79a2 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:40:50 +0800 Subject: [PATCH 110/118] Update iprange.cpp --- src/gausskernel/security/iprange/iprange.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/security/iprange/iprange.cpp b/src/gausskernel/security/iprange/iprange.cpp index c40d1e376..0fd477fd6 100644 --- a/src/gausskernel/security/iprange/iprange.cpp +++ b/src/gausskernel/security/iprange/iprange.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 2735deae0590938ec0b9bce68b0d86681e0c8d02 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:41:09 +0800 Subject: [PATCH 111/118] Update db4ai_common.cpp --- src/gausskernel/runtime/executor/db4ai_common.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/runtime/executor/db4ai_common.cpp b/src/gausskernel/runtime/executor/db4ai_common.cpp index f4d679fbe..a4a2a5fab 100644 --- a/src/gausskernel/runtime/executor/db4ai_common.cpp +++ b/src/gausskernel/runtime/executor/db4ai_common.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* * Copyright (c) 2020 Huawei Technologies Co.,Ltd. * -- 2.34.1 From 25d0e29ac09d2f8e4d94930bc5f40261cbe630c4 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:41:26 +0800 Subject: [PATCH 112/118] Update execAmi.cpp --- src/gausskernel/runtime/executor/execAmi.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/runtime/executor/execAmi.cpp b/src/gausskernel/runtime/executor/execAmi.cpp index 1016648af..c161b7852 100755 --- a/src/gausskernel/runtime/executor/execAmi.cpp +++ b/src/gausskernel/runtime/executor/execAmi.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * execAmi.cpp -- 2.34.1 From 19742c84340a4ed71ec018db4cc12ed31803cf04 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:42:03 +0800 Subject: [PATCH 113/118] Update execClusterResize.cpp --- src/gausskernel/runtime/executor/execClusterResize.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/runtime/executor/execClusterResize.cpp b/src/gausskernel/runtime/executor/execClusterResize.cpp index 131453e0b..468946213 100644 --- a/src/gausskernel/runtime/executor/execClusterResize.cpp +++ b/src/gausskernel/runtime/executor/execClusterResize.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * execClusterResize.cpp -- 2.34.1 From ef49079f356d2c4d9e818140f9bb8e180b605913 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:42:18 +0800 Subject: [PATCH 114/118] Update execCurrent.cpp --- src/gausskernel/runtime/executor/execCurrent.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/runtime/executor/execCurrent.cpp b/src/gausskernel/runtime/executor/execCurrent.cpp index 2e3770e07..7010cc7bd 100644 --- a/src/gausskernel/runtime/executor/execCurrent.cpp +++ b/src/gausskernel/runtime/executor/execCurrent.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * execCurrent.c -- 2.34.1 From 4df7df69fcd2ba57558d2157f7c2d6495e4284b5 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:42:34 +0800 Subject: [PATCH 115/118] Update execGrouping.cpp --- src/gausskernel/runtime/executor/execGrouping.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/runtime/executor/execGrouping.cpp b/src/gausskernel/runtime/executor/execGrouping.cpp index 9dbd0d050..2f0d901d0 100644 --- a/src/gausskernel/runtime/executor/execGrouping.cpp +++ b/src/gausskernel/runtime/executor/execGrouping.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * execGrouping.cpp -- 2.34.1 From f2b23b7cf8eaa0534eae021d9df5decd9b7464a8 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:43:04 +0800 Subject: [PATCH 116/118] Update execJunk.cpp --- src/gausskernel/runtime/executor/execJunk.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/runtime/executor/execJunk.cpp b/src/gausskernel/runtime/executor/execJunk.cpp index db33535a8..709474087 100644 --- a/src/gausskernel/runtime/executor/execJunk.cpp +++ b/src/gausskernel/runtime/executor/execJunk.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * execJunk.cpp -- 2.34.1 From d060ec8971b3ab9efc895e2e9433be099741c883 Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:43:32 +0800 Subject: [PATCH 117/118] Update execMain.cpp --- src/gausskernel/runtime/executor/execMain.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/runtime/executor/execMain.cpp b/src/gausskernel/runtime/executor/execMain.cpp index 780766e92..ad65295be 100755 --- a/src/gausskernel/runtime/executor/execMain.cpp +++ b/src/gausskernel/runtime/executor/execMain.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * execMain.cpp -- 2.34.1 From dac13f7edd765ed344ca0fd882ee6d601119290c Mon Sep 17 00:00:00 2001 From: zpc_gitlink Date: Thu, 5 Oct 2023 21:44:29 +0800 Subject: [PATCH 118/118] Update execProcnode.cpp --- src/gausskernel/runtime/executor/execProcnode.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gausskernel/runtime/executor/execProcnode.cpp b/src/gausskernel/runtime/executor/execProcnode.cpp index a27336c22..66e1eba2d 100755 --- a/src/gausskernel/runtime/executor/execProcnode.cpp +++ b/src/gausskernel/runtime/executor/execProcnode.cpp @@ -1,3 +1,7 @@ +/*** + * @Author: 王语翀 + * @Team: 兰心开源 + */ /* ------------------------------------------------------------------------- * * execProcnode.cpp -- 2.34.1