PostgreSQL 소스 코드 판독 (7) - 데이터 삽입 \ # 6 (ExecProcNode 와 ExecPro...
기초 정보
ExecProcNode / ExecProcNodeFirst 함수 가 사용 하 는 데이터 구조, 매크로 정의 및 의존 함수 등.데이터 구조 / 매크로 정의 1, ExecProcNodeMtdExecProcNodeMtd 는 함수 포인터 형식 으로 가리 키 는 함수 입력 매개 변 수 는 PlanState 구조 체 지침 이 고 출력 매개 변 수 는 TupleTableSlot 구조 체 지침 입 니 다.
/* ----------------
* ExecProcNodeMtd
*
* This is the method called by ExecProcNode to return the next tuple
* from an executor node. It returns NULL, or an empty TupleTableSlot,
* if no more tuples are available.
* ----------------
*/
typedef TupleTableSlot *(*ExecProcNodeMtd) (struct PlanState *pstate);
의존 함수 1 、 checkstack_depth
// stack , ,
/*
* check_stack_depth/stack_is_too_deep: check for excessively deep recursion
*
* This should be called someplace in any recursive routine that might possibly
* recurse deep enough to overflow the stack. Most Unixen treat stack
* overflow as an unrecoverable SIGSEGV, so we want to error out ourselves
* before hitting the hardware limit.
*
* check_stack_depth() just throws an error summarily. stack_is_too_deep()
* can be used by code that wants to handle the error condition itself.
*/
void
check_stack_depth(void)
{
if (stack_is_too_deep())
{
ereport(ERROR,
(errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
errmsg("stack depth limit exceeded"),
errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), "
"after ensuring the platform's stack depth limit is adequate.",
max_stack_depth)));
}
}
bool
stack_is_too_deep(void)
{
char stack_top_loc;
long stack_depth;
/*
* Compute distance from reference point to my local variables
*/
stack_depth = (long) (stack_base_ptr - &stack_top_loc);
/*
* Take abs value, since stacks grow up on some machines, down on others
*/
if (stack_depth < 0)
stack_depth = -stack_depth;
/*
* Trouble?
*
* The test on stack_base_ptr prevents us from erroring out if called
* during process setup or in a non-backend process. Logically it should
* be done first, but putting it here avoids wasting cycles during normal
* cases.
*/
if (stack_depth > max_stack_depth_bytes &&
stack_base_ptr != NULL)
return true;
/*
* On IA64 there is a separate "register" stack that requires its own
* independent check. For this, we have to measure the change in the
* "BSP" pointer from PostgresMain to here. Logic is just as above,
* except that we know IA64's register stack grows up.
*
* Note we assume that the same max_stack_depth applies to both stacks.
*/
#if defined(__ia64__) || defined(__ia64)
stack_depth = (long) (ia64_get_bsp() - register_stack_base_ptr);
if (stack_depth > max_stack_depth_bytes &&
register_stack_base_ptr != NULL)
return true;
#endif /* IA64 */
return false;
}
2、ExecProcNodeInstr
/*
* ExecProcNode wrapper that performs instrumentation calls. By keeping
* this a separate function, we avoid overhead in the normal case where
* no instrumentation is wanted.
*/
static TupleTableSlot *
ExecProcNodeInstr(PlanState *node)
{
TupleTableSlot *result;
InstrStartNode(node->instrument);
result = node->ExecProcNodeReal(node);
InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
return result;
}
2. 소스 코드 해독
1、ExecProcNode
// node
/* ----------------------------------------------------------------
* ExecProcNode
*
* Execute the given node to return a(nother) tuple.
* ----------------------------------------------------------------
*/
#ifndef FRONTEND
static inline TupleTableSlot *
ExecProcNode(PlanState *node)
{
if (node->chgParam != NULL) /* something changed? */
ExecReScan(node); /* let ReScan handle this */
return node->ExecProcNode(node);
}
#endif
2、ExecProcNodeFirst
/*
* ExecProcNode wrapper that performs some one-time checks, before calling
* the relevant node method (possibly via an instrumentation wrapper).
*/
/*
:
node-PlanState
:
Tuple Slot
*/
static TupleTableSlot *
ExecProcNodeFirst(PlanState *node)
{
/*
* Perform stack depth check during the first execution of the node. We
* only do so the first time round because it turns out to not be cheap on
* some common architectures (eg. x86). This relies on the assumption
* that ExecProcNode calls for a given plan node will always be made at
* roughly the same stack depth.
*/
// Stack
check_stack_depth();
/*
* If instrumentation is required, change the wrapper to one that just
* does instrumentation. Otherwise we can dispense with all wrappers and
* have ExecProcNode() directly call the relevant function from now on.
*/
// instrument(TODO)
if (node->instrument)
node->ExecProcNode = ExecProcNodeInstr;
else
node->ExecProcNode = node->ExecProcNodeReal;
// Node
return node->ExecProcNode(node);
}
3. 추적 분석
테스트 데이터 삽입:
testdb=# -- pid
testdb=# select pg_backend_pid();
pg_backend_pid
----------------
2835
(1 row)
testdb=# -- 1
testdb=# insert into t_insert values(14,'ExecProcNodeFirst','ExecProcNodeFirst','ExecProcNodeFirst');
( )
gdb 분석 시작:
[root@localhost ~]# gdb -p 2835
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7
Copyright (C) 2013 Free Software Foundation, Inc.
...
(gdb) b ExecProcNodeFirst
Breakpoint 1 at 0x69a797: file execProcnode.c, line 433.
(gdb) c
Continuing.
Breakpoint 1, ExecProcNodeFirst (node=0x2cca790) at execProcnode.c:433
433 check_stack_depth();
#
(gdb) p *node
$1 = {type = T_ModifyTableState, plan = 0x2c1d028, state = 0x2cca440, ExecProcNode = 0x69a78b , ExecProcNodeReal = 0x6c2485 , instrument = 0x0,
worker_instrument = 0x0, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x2ccb6a0, ps_ExprContext = 0x0, ps_ProjInfo = 0x0,
scandesc = 0x0}
#ExecProcNode ExecProcNodeFirst
#ExecProcNodeReal ExecModifyTable( )
(gdb) next
440 if (node->instrument)
(gdb)
# ExecModifyTable ( )
443 node->ExecProcNode = node->ExecProcNodeReal;
(gdb)
445 return node->ExecProcNode(node);
(gdb) next
# (TODO)
Breakpoint 1, ExecProcNodeFirst (node=0x2ccac80) at execProcnode.c:433
433 check_stack_depth();
(gdb) next
440 if (node->instrument)
(gdb) next
443 node->ExecProcNode = node->ExecProcNodeReal;
(gdb) next
445 return node->ExecProcNode(node);
(gdb) next
446 }
(gdb) next
ExecProcNode (node=0x2ccac80) at ../../../src/include/executor/executor.h:238
238 }
#
(gdb) p *node
$2 = {type = T_ResultState, plan = 0x2cd0488, state = 0x2cca440, ExecProcNode = 0x6c5094 , ExecProcNodeReal = 0x6c5094 , instrument = 0x0, worker_instrument = 0x0, qual = 0x0,
lefttree = 0x0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x2ccad90, ps_ExprContext = 0x2ccab30, ps_ProjInfo = 0x2ccabc0, scandesc = 0x0}
#ExecProcNode ExecResult
(gdb)
소결
1. C 언어 중의 다 형: C 언어 에서 함수 지침 을 사용 하여 함수 의 '다 형' 을 실현 하고 코드 의 재 활용 성 을 강화 했다. 물론 대 가 는 복잡 도가 향상 되 었 다.2. 매개 변수 구조: 더욱 상세 한 매개 변수 구 조 는 상부 호출 의 진일보 한 해석 이 필요 하 다.
"ITPUB 블 로그" 에서 왔 습 니 다. 링크:http://blog.itpub.net/6906/viewspace-2374909/전재 가 필요 하 다 면 출처 를 밝 혀 주 십시오. 그렇지 않 으 면 법 적 책임 을 추궁 할 것 입 니 다.
다음으로 전송:http://blog.itpub.net/6906/viewspace-2374909/
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.