8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 04:43:03 +01:00

Another bunch of changes for CORE-4004: Sometimes long-running operations cannot be interrupted by asynchronous shutdown / cancellation requests. The looper nodes should never ignore req_unwind and transform it to something else.

Review and testing would be appreciated, especially in regard to EXE_assignment.
This commit is contained in:
dimitr 2012-12-06 12:09:11 +00:00
parent bc1edae943
commit 3971e49b30
3 changed files with 68 additions and 53 deletions

View File

@ -378,7 +378,10 @@ AssignmentNode* AssignmentNode::pass2(thread_db* tdbb, CompilerScratch* csb)
const StmtNode* AssignmentNode::execute(thread_db* tdbb, jrd_req* request, ExeState* /*exeState*/) const
{
if (request->req_operation == jrd_req::req_evaluate)
{
EXE_assignment(tdbb, this);
request->req_operation = jrd_req::req_return;
}
return parentStmt;
}
@ -884,9 +887,12 @@ void ContinueLeaveNode::genBlr(DsqlCompilerScratch* dsqlScratch)
const StmtNode* ContinueLeaveNode::execute(thread_db* /*tdbb*/, jrd_req* request, ExeState* /*exeState*/) const
{
request->req_operation = jrd_req::req_unwind;
request->req_label = labelNumber;
request->req_flags |= (blrOp == blr_continue_loop ? req_continue_loop : req_leave);
if (request->req_operation == jrd_req::req_evaluate)
{
request->req_operation = jrd_req::req_unwind;
request->req_label = labelNumber;
request->req_flags |= (blrOp == blr_continue_loop ? req_continue_loop : req_leave);
}
return parentStmt;
}
@ -1841,25 +1847,28 @@ DeclareVariableNode* DeclareVariableNode::pass2(thread_db* /*tdbb*/, CompilerScr
const StmtNode* DeclareVariableNode::execute(thread_db* tdbb, jrd_req* request, ExeState* /*exeState*/) const
{
impure_value* variable = request->getImpure<impure_value>(impureOffset);
variable->vlu_desc = varDesc;
variable->vlu_desc.dsc_flags = 0;
if (variable->vlu_desc.dsc_dtype <= dtype_varying)
if (request->req_operation == jrd_req::req_evaluate)
{
if (!variable->vlu_string)
impure_value* variable = request->getImpure<impure_value>(impureOffset);
variable->vlu_desc = varDesc;
variable->vlu_desc.dsc_flags = 0;
if (variable->vlu_desc.dsc_dtype <= dtype_varying)
{
const USHORT len = variable->vlu_desc.dsc_length;
variable->vlu_string = FB_NEW_RPT(*tdbb->getDefaultPool(), len) VaryingString();
variable->vlu_string->str_length = len;
if (!variable->vlu_string)
{
const USHORT len = variable->vlu_desc.dsc_length;
variable->vlu_string = FB_NEW_RPT(*tdbb->getDefaultPool(), len) VaryingString();
variable->vlu_string->str_length = len;
}
variable->vlu_desc.dsc_address = variable->vlu_string->str_data;
}
else
variable->vlu_desc.dsc_address = (UCHAR*) &variable->vlu_misc;
variable->vlu_desc.dsc_address = variable->vlu_string->str_data;
request->req_operation = jrd_req::req_return;
}
else
variable->vlu_desc.dsc_address = (UCHAR*) &variable->vlu_misc;
request->req_operation = jrd_req::req_return;
return parentStmt;
}
@ -2693,12 +2702,12 @@ ExecProcedureNode* ExecProcedureNode::pass2(thread_db* tdbb, CompilerScratch* cs
const StmtNode* ExecProcedureNode::execute(thread_db* tdbb, jrd_req* request, ExeState* /*exeState*/) const
{
if (request->req_operation == jrd_req::req_unwind)
return parentStmt;
if (request->req_operation == jrd_req::req_evaluate)
{
executeProcedure(tdbb, request);
request->req_operation = jrd_req::req_return;
}
executeProcedure(tdbb, request);
request->req_operation = jrd_req::req_return;
return parentStmt;
}
@ -5990,21 +5999,23 @@ PostEventNode* PostEventNode::pass2(thread_db* tdbb, CompilerScratch* csb)
const StmtNode* PostEventNode::execute(thread_db* tdbb, jrd_req* request, ExeState* /*exeState*/) const
{
jrd_tra* transaction = request->req_transaction;
if (request->req_operation == jrd_req::req_evaluate)
{
jrd_tra* transaction = request->req_transaction;
DeferredWork* work = DFW_post_work(transaction, dfw_post_event,
EVL_expr(tdbb, request, event), 0);
DeferredWork* work = DFW_post_work(transaction, dfw_post_event,
EVL_expr(tdbb, request, event), 0);
if (argument)
DFW_post_work_arg(transaction, work, EVL_expr(tdbb, request, argument), 0);
if (argument)
DFW_post_work_arg(transaction, work, EVL_expr(tdbb, request, argument), 0);
// For an autocommit transaction, events can be posted without any updates.
// For an autocommit transaction, events can be posted without any updates.
if (transaction->tra_flags & TRA_autocommit)
transaction->tra_flags |= TRA_perform_autocommit;
if (transaction->tra_flags & TRA_autocommit)
transaction->tra_flags |= TRA_perform_autocommit;
if (request->req_operation == jrd_req::req_evaluate)
request->req_operation = jrd_req::req_return;
}
return parentStmt;
}
@ -6857,9 +6868,9 @@ const StmtNode* UserSavepointNode::execute(thread_db* tdbb, jrd_req* request, Ex
BUGCHECK(232);
break;
}
}
request->req_operation = jrd_req::req_return;
request->req_operation = jrd_req::req_return;
}
return parentStmt;
}
@ -7231,18 +7242,19 @@ const StmtNode* StallNode::execute(thread_db* /*tdbb*/, jrd_req* request, ExeSta
{
switch (request->req_operation)
{
case jrd_req::req_sync:
return parentStmt;
case jrd_req::req_evaluate:
case jrd_req::req_return:
request->req_message = this;
request->req_operation = jrd_req::req_return;
request->req_flags |= req_stall;
return this;
case jrd_req::req_proceed:
request->req_operation = jrd_req::req_return;
return parentStmt;
default:
request->req_message = this;
request->req_operation = jrd_req::req_return;
request->req_flags |= req_stall;
return this;
return parentStmt;
}
}
@ -7445,6 +7457,8 @@ const StmtNode* SavePointNode::execute(thread_db* tdbb, jrd_req* request, ExeSta
// Start a save point.
if (transaction != sysTransaction)
VIO_start_save_point(tdbb, transaction);
request->req_operation = jrd_req::req_return;
}
break;
@ -7461,11 +7475,16 @@ const StmtNode* SavePointNode::execute(thread_db* tdbb, jrd_req* request, ExeSta
++transaction->tra_save_point->sav_verb_count;
EXE_verb_cleanup(tdbb, transaction);
}
if (request->req_operation == jrd_req::req_evaluate)
request->req_operation = jrd_req::req_return;
}
break;
default:
fb_assert(false);
}
request->req_operation = jrd_req::req_return;
return parentStmt;
}

View File

@ -216,8 +216,6 @@ void EXE_assignment(thread_db* tdbb, const AssignmentNode* node)
EXE_assignment(tdbb, node->asgnTo, from_desc, (request->req_flags & req_null),
node->missing, node->missing2);
request->req_operation = jrd_req::req_return;
}
// Perform an assignment.
@ -231,8 +229,6 @@ void EXE_assignment(thread_db* tdbb, const ValueExprNode* source, const ValueExp
dsc* from_desc = EVL_expr(tdbb, request, source);
EXE_assignment(tdbb, target, from_desc, (request->req_flags & req_null), NULL, NULL);
request->req_operation = jrd_req::req_return;
}
// Perform an assignment.
@ -1470,13 +1466,16 @@ const StmtNode* EXE_looper(thread_db* tdbb, jrd_req* request, const StmtNode* no
goto end;
}
if (request->req_operation == jrd_req::req_evaluate && (--tdbb->tdbb_quantum < 0))
JRD_reschedule(tdbb, 0, true);
if (request->req_operation == jrd_req::req_evaluate && node->hasLineColumn)
if (request->req_operation == jrd_req::req_evaluate)
{
request->req_src_line = node->line;
request->req_src_column = node->column;
if (--tdbb->tdbb_quantum < 0)
JRD_reschedule(tdbb, 0, true);
if (node->hasLineColumn)
{
request->req_src_line = node->line;
request->req_src_column = node->column;
}
}
node = node->execute(tdbb, request, &exeState);

View File

@ -78,8 +78,6 @@ void ProcedureScan::open(thread_db* tdbb) const
if (m_sourceList)
{
enum jrd_req::req_s saved_state = request->req_operation;
const NestConst<ValueExprNode>* const sourceEnd = m_sourceList->items.end();
const NestConst<ValueExprNode>* sourcePtr = m_sourceList->items.begin();
const NestConst<ValueExprNode>* targetPtr = m_targetList->items.begin();
@ -87,7 +85,6 @@ void ProcedureScan::open(thread_db* tdbb) const
for (; sourcePtr != sourceEnd; ++sourcePtr, ++targetPtr)
EXE_assignment(tdbb, *sourcePtr, *targetPtr);
request->req_operation = saved_state;
iml = m_message->format->fmt_length;
im = request->getImpure<UCHAR>(m_message->impureOffset);
}