8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 10:00:38 +01:00

cleaning up

This commit is contained in:
tamlin 2001-12-28 06:31:38 +00:00
parent 217a1f6092
commit c15f569b4a
2 changed files with 206 additions and 230 deletions

View File

@ -21,7 +21,7 @@
* Contributor(s): ______________________________________. * Contributor(s): ______________________________________.
*/ */
/* /*
$Id: exe.cpp,v 1.4 2001-12-24 02:50:51 tamlin Exp $ $Id: exe.cpp,v 1.5 2001-12-28 06:31:38 tamlin Exp $
*/ */
#include "firebird.h" #include "firebird.h"
@ -176,6 +176,27 @@ static SLONG memory_count = 0;
#define RECORD_LOCK_CHECK_INTERVAL 10 #define RECORD_LOCK_CHECK_INTERVAL 10
#ifdef PC_ENGINE
// TMN: RAII class for LCK. Unlocks the LCK on destruction.
class LCK_RAII_wrapper
{
LCK_RAII_wrapper() : l(0) {}
~LCK_RAII_wrapper() {
if (l) {
RLCK_unlock_record_implicit(l, 0);
}
}
void assign(LCK lock) { l = lck; }
LCK l;
private:
LCK_RAII_wrapper(const LCK_RAII_wrapper&); // no impl.
void operator=(const LCK_RAII_wrapper&); // no impl.
};
#endif
void EXE_assignment(TDBB tdbb, NOD node) void EXE_assignment(TDBB tdbb, NOD node)
{ {
@ -552,7 +573,6 @@ void EXE_receive(TDBB tdbb,
FMT format; FMT format;
TRA transaction; TRA transaction;
SAV save_sav_point; SAV save_sav_point;
JMP_BUF env, *old_env;
SET_TDBB(tdbb); SET_TDBB(tdbb);
@ -583,9 +603,6 @@ void EXE_receive(TDBB tdbb,
if (!transaction->tra_save_point) { if (!transaction->tra_save_point) {
VIO_start_save_point(tdbb, transaction); VIO_start_save_point(tdbb, transaction);
} }
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
tdbb->tdbb_setjmp = (UCHAR *) env;
} }
if (request->req_message->nod_type == nod_stall if (request->req_message->nod_type == nod_stall
@ -620,7 +637,6 @@ void EXE_receive(TDBB tdbb,
execute_looper(tdbb, request, transaction, req::req_proceed); execute_looper(tdbb, request, transaction, req::req_proceed);
if (request->req_flags & req_proc_fetch) { if (request->req_flags & req_proc_fetch) {
tdbb->tdbb_setjmp = (UCHAR *) old_env;
save_sav_point = transaction->tra_save_point; save_sav_point = transaction->tra_save_point;
transaction->tra_save_point = request->req_proc_sav_point; transaction->tra_save_point = request->req_proc_sav_point;
request->req_proc_sav_point = save_sav_point; request->req_proc_sav_point = save_sav_point;
@ -631,7 +647,6 @@ void EXE_receive(TDBB tdbb,
} //try } //try
catch (...) catch (...)
{ {
tdbb->tdbb_setjmp = (UCHAR *) old_env;
save_sav_point = transaction->tra_save_point; save_sav_point = transaction->tra_save_point;
transaction->tra_save_point = request->req_proc_sav_point; transaction->tra_save_point = request->req_proc_sav_point;
request->req_proc_sav_point = save_sav_point; request->req_proc_sav_point = save_sav_point;
@ -989,9 +1004,7 @@ static NOD erase(TDBB tdbb, NOD node, SSHORT which_trig)
FMT format; FMT format;
TRA transaction; TRA transaction;
#ifdef PC_ENGINE #ifdef PC_ENGINE
LCK implicit_lock = NULL;
RSB rsb = NULL; RSB rsb = NULL;
JMP_BUF env, *old_env;
IRSB impure; IRSB impure;
#endif #endif
@ -1086,6 +1099,8 @@ static NOD erase(TDBB tdbb, NOD node, SSHORT which_trig)
try { try {
LCK_RAII_wrapper implicit_lock;
if (!(transaction->tra_flags & TRA_degree3)) if (!(transaction->tra_flags & TRA_degree3))
{ {
/* check whether record locking is turned on */ /* check whether record locking is turned on */
@ -1095,13 +1110,10 @@ static NOD erase(TDBB tdbb, NOD node, SSHORT which_trig)
{ {
/* get an implicit lock on the record */ /* get an implicit lock on the record */
implicit_lock = implicit_record_lock(transaction, rpb); implicit_lock.assign(implicit_record_lock(transaction, rpb));
/* set up to catch any errors so that we can /* set up to catch any errors so that we can
release the implicit lock */ release the implicit lock */
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
tdbb->tdbb_setjmp = (UCHAR *) env;
} }
} }
#endif #endif
@ -1159,18 +1171,9 @@ static NOD erase(TDBB tdbb, NOD node, SSHORT which_trig)
} // try } // try
catch (...) { catch (...) {
tdbb->tdbb_setjmp = (UCHAR *) old_env;
if (implicit_lock) {
RLCK_unlock_record_implicit(implicit_lock, 0);
}
Firebird::status_longjmp_error::raise(-1); Firebird::status_longjmp_error::raise(-1);
} }
if (implicit_lock) {
tdbb->tdbb_setjmp = (UCHAR *) old_env;
RLCK_unlock_record_implicit(implicit_lock, 0);
}
/* if the stream is navigational, it is now positioned on a crack */ /* if the stream is navigational, it is now positioned on a crack */
if (rsb) { if (rsb) {
@ -1254,7 +1257,6 @@ static void execute_procedure(TDBB tdbb, NOD node)
STR temp_buffer = NULL; STR temp_buffer = NULL;
SLONG save_point_number; SLONG save_point_number;
TRA transaction; TRA transaction;
JMP_BUF env, *old_env;
JrdMemoryPool *old_pool; JrdMemoryPool *old_pool;
SET_TDBB(tdbb); SET_TDBB(tdbb);
@ -1300,9 +1302,6 @@ static void execute_procedure(TDBB tdbb, NOD node)
/* Catch errors so we can unwind cleanly */ /* Catch errors so we can unwind cleanly */
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
tdbb->tdbb_setjmp = (UCHAR *) env;
try { try {
transaction = request->req_transaction; transaction = request->req_transaction;
@ -1331,7 +1330,6 @@ static void execute_procedure(TDBB tdbb, NOD node)
} // try } // try
catch (...) { catch (...) {
tdbb->tdbb_setjmp = (UCHAR *) old_env;
tdbb->tdbb_default = old_pool; tdbb->tdbb_default = old_pool;
tdbb->tdbb_request = request; tdbb->tdbb_request = request;
EXE_unwind(tdbb, proc_request); EXE_unwind(tdbb, proc_request);
@ -1341,19 +1339,20 @@ static void execute_procedure(TDBB tdbb, NOD node)
Firebird::status_longjmp_error::raise(-1); Firebird::status_longjmp_error::raise(-1);
} }
tdbb->tdbb_setjmp = (UCHAR *) old_env;
tdbb->tdbb_default = old_pool; tdbb->tdbb_default = old_pool;
EXE_unwind(tdbb, proc_request); EXE_unwind(tdbb, proc_request);
tdbb->tdbb_request = request; tdbb->tdbb_request = request;
if ( (temp = node->nod_arg[e_esp_outputs]) ) {
temp = node->nod_arg[e_esp_outputs];
if (temp) {
NOD *ptr, *end; NOD *ptr, *end;
for (ptr = temp->nod_arg, end = ptr + temp->nod_count; ptr < end; for (ptr = temp->nod_arg, end = ptr + temp->nod_count; ptr < end;
ptr++) ptr++)
EXE_assignment(tdbb, *ptr); EXE_assignment(tdbb, *ptr);
} }
if (temp_buffer)
delete temp_buffer; delete temp_buffer;
proc_request->req_attachment = NULL; proc_request->req_attachment = NULL;
proc_request->req_flags &= ~(req_in_use | req_proc_fetch); proc_request->req_flags &= ~(req_in_use | req_proc_fetch);
proc_request->req_timestamp = 0; proc_request->req_timestamp = 0;
@ -1361,9 +1360,10 @@ static void execute_procedure(TDBB tdbb, NOD node)
#ifndef GATEWAY #ifndef GATEWAY
static REQ execute_triggers( static REQ execute_triggers(TDBB tdbb,
TDBB tdbb, VEC* triggers,
VEC * triggers, REC old_rec, REC new_rec) REC old_rec,
REC new_rec)
{ {
/************************************** /**************************************
* *
@ -1376,56 +1376,50 @@ static REQ execute_triggers(
* if any blow up. * if any blow up.
* *
**************************************/ **************************************/
REQ result;
vec::iterator ptr, end;
VOLATILE REQ trigger = NULL; VOLATILE REQ trigger = NULL;
TRA transaction;
VOLATILE VEC vector;
JMP_BUF env, *old_env;
DEV_BLKCHK(*triggers, type_vec); DEV_BLKCHK(*triggers, type_vec);
DEV_BLKCHK(old_rec, type_rec); DEV_BLKCHK(old_rec, type_rec);
DEV_BLKCHK(new_rec, type_rec); DEV_BLKCHK(new_rec, type_rec);
if (!*triggers) if (!*triggers) {
return NULL; return NULL;
}
SET_TDBB(tdbb); SET_TDBB(tdbb);
transaction = tdbb->tdbb_request->req_transaction; TRA transaction = tdbb->tdbb_request->req_transaction;
vector = *triggers; VEC vector = *triggers;
result = NULL; REQ result = NULL;
old_env = (JMP_BUF *) tdbb->tdbb_setjmp; try
tdbb->tdbb_setjmp = (UCHAR *) env; {
for (vec::iterator ptr = vector->begin(); ptr != vector->end(); ++ptr)
try { {
trigger = EXE_find_request(tdbb, (REQ)(*ptr), FALSE);
for (ptr = vector->begin(), end = vector->end(); ptr < end; ptr++) { trigger->req_rpb[0].rpb_record = old_rec;
trigger = EXE_find_request(tdbb, (REQ)(*ptr), FALSE); trigger->req_rpb[1].rpb_record = new_rec;
trigger->req_rpb[0].rpb_record = old_rec; trigger->req_timestamp = tdbb->tdbb_request->req_timestamp;
trigger->req_rpb[1].rpb_record = new_rec; EXE_start(tdbb, trigger, transaction);
trigger->req_timestamp = tdbb->tdbb_request->req_timestamp; trigger->req_attachment = NULL;
EXE_start(tdbb, trigger, transaction); trigger->req_flags &= ~req_in_use;
trigger->req_attachment = NULL; trigger->req_timestamp = 0;
trigger->req_flags &= ~req_in_use; if (trigger->req_operation == req::req_unwind) {
trigger->req_timestamp = 0; result = trigger;
if (trigger->req_operation == req::req_unwind) { break;
result = trigger; }
break;
} }
if (vector != *triggers) {
release_triggers(tdbb, vector);
}
return result;
} }
catch (std::exception&)
tdbb->tdbb_setjmp = (UCHAR *) old_env; {
if (vector != *triggers)
release_triggers(tdbb, vector);
return result;
} // try
catch (...) {
tdbb->tdbb_setjmp = (UCHAR *) old_env;
if (vector != *triggers) { if (vector != *triggers) {
release_triggers(tdbb, vector); release_triggers(tdbb, vector);
} }
@ -1453,51 +1447,64 @@ static NOD find(TDBB tdbb, register NOD node)
* Assume that the stream is open. * Assume that the stream is open.
* *
**************************************/ **************************************/
register REQ request;
RSB rsb;
USHORT operator, direction;
SET_TDBB(tdbb); SET_TDBB(tdbb);
request = tdbb->tdbb_request; REQ request = tdbb->tdbb_request;
BLKCHK(node, type_nod); BLKCHK(node, type_nod);
if (request->req_operation == req::req_evaluate) { if (request->req_operation == req::req_evaluate)
rsb = *((RSB *) node->nod_arg[e_find_rsb]); {
RSB rsb = *((RSB *) node->nod_arg[e_find_rsb]);
operator = (USHORT) MOV_get_long(EVL_expr(tdbb, USHORT operator_ =
node->nod_arg (USHORT) MOV_get_long(EVL_expr( tdbb,
[e_find_operator]), 0); node->nod_arg
if (operator != blr_eql && operator != blr_leq && operator != blr_lss [e_find_operator]),
&& operator != blr_geq && operator != blr_gtr) 0);
if (operator_ != blr_eql &&
operator_ != blr_leq &&
operator_ != blr_lss &&
operator_ != blr_geq &&
operator_ != blr_gtr)
{
ERR_post(gds_invalid_operator, 0); ERR_post(gds_invalid_operator, 0);
}
direction = (USHORT) MOV_get_long(EVL_expr(tdbb, USHORT direction = (USHORT) MOV_get_long(EVL_expr(tdbb,
node->nod_arg node->nod_arg
[e_find_direction]), 0); [e_find_direction]),
if (direction != blr_backward && direction != blr_forward 0);
&& direction != blr_backward_starting if (direction != blr_backward &&
&& direction != direction != blr_forward &&
blr_forward_starting) ERR_post(gds_invalid_direction, 0); direction != blr_backward_starting &&
direction != blr_forward_starting)
{
ERR_post(gds_invalid_direction, 0);
}
/* try to find the record; the position is defined to be on a crack /* try to find the record; the position is defined to be on a crack
regardless of whether we are at BOF or EOF; also be sure to perpetuate regardless of whether we are at BOF or EOF; also be sure to perpetuate
the forced crack (bug #7024) */ the forced crack (bug #7024) */
if (! if (!RSE_find_record( tdbb,
(RSE_find_record rsb,
(tdbb, rsb, operator, direction, operator_,
node->nod_arg[e_find_args]))) if (EXE_crack(tdbb, rsb, direction,
irsb_bof | irsb_eof node->nod_arg[e_find_args]))
| irsb_crack)) {
if (EXE_crack(tdbb, rsb, irsb_forced_crack)) if (EXE_crack(tdbb, rsb, irsb_bof | irsb_eof | irsb_crack))
{
if (EXE_crack(tdbb, rsb, irsb_forced_crack)) {
EXE_mark_crack(tdbb, rsb, irsb_crack | irsb_forced_crack); EXE_mark_crack(tdbb, rsb, irsb_crack | irsb_forced_crack);
else if (EXE_crack(tdbb, rsb, irsb_bof)) } else if (EXE_crack(tdbb, rsb, irsb_bof)) {
EXE_mark_crack(tdbb, rsb, irsb_bof); EXE_mark_crack(tdbb, rsb, irsb_bof);
else if (EXE_crack(tdbb, rsb, irsb_eof)) } else if (EXE_crack(tdbb, rsb, irsb_eof)) {
EXE_mark_crack(tdbb, rsb, irsb_eof); EXE_mark_crack(tdbb, rsb, irsb_eof);
else } else {
EXE_mark_crack(tdbb, rsb, irsb_crack); EXE_mark_crack(tdbb, rsb, irsb_crack);
}
}
}
request->req_operation = req::req_return; request->req_operation = req::req_return;
} }
@ -1522,21 +1529,22 @@ static NOD find_dbkey(TDBB tdbb, register NOD node)
* resetting the position of the stream to that record. * resetting the position of the stream to that record.
* *
**************************************/ **************************************/
register REQ request;
RSB rsb;
SET_TDBB(tdbb); SET_TDBB(tdbb);
request = tdbb->tdbb_request; REQ request = tdbb->tdbb_request;
BLKCHK(node, type_nod); BLKCHK(node, type_nod);
if (request->req_operation == req::req_evaluate) { if (request->req_operation == req::req_evaluate)
rsb = *((RSB *) node->nod_arg[e_find_dbkey_rsb]); {
RSB rsb = *((RSB *) node->nod_arg[e_find_dbkey_rsb]);
if (! if (!RSE_find_dbkey(tdbb,
(RSE_find_dbkey rsb,
(tdbb, rsb, node->nod_arg[e_find_dbkey_dbkey], node->nod_arg[e_find_dbkey_dbkey],
node->nod_arg[e_find_dbkey_version]))) EXE_mark_crack(tdbb, rsb, node->nod_arg[e_find_dbkey_version]))
irsb_crack); {
EXE_mark_crack(tdbb, rsb, irsb_crack);
}
request->req_operation = req::req_return; request->req_operation = req::req_return;
} }
@ -1607,20 +1615,14 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
* execution on stall or request complete. * execution on stall or request complete.
* *
**************************************/ **************************************/
DBB dbb;
STA impure;
SSHORT error_pending;
SLONG save_point_number;
SSHORT which_erase_trig = 0, which_sto_trig = 0, which_mod_trig = 0;
REQ old_request;
VOLATILE NOD node, top_node = NULL, prev_node;
TRA transaction;
JMP_BUF env, *old_env;
JrdMemoryPool *old_pool;
#if defined(DEBUG_GDS_ALLOC) && FALSE
int node_type;
#endif
STA impure;
SSHORT which_erase_trig = 0;
SSHORT which_sto_trig = 0;
SSHORT which_mod_trig = 0;
VOLATILE NOD top_node = 0;
VOLATILE NOD prev_node;
TRA transaction;
/* If an error happens during the backout of a savepoint, then the transaction /* If an error happens during the backout of a savepoint, then the transaction
must be marked 'dead' because that is the only way to clean up after a must be marked 'dead' because that is the only way to clean up after a
@ -1628,51 +1630,42 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
by calling bugcheck. by calling bugcheck.
To facilitate catching errors during VIO_verb_cleanup, the following To facilitate catching errors during VIO_verb_cleanup, the following
define is used. */ define is used. */
#define VERB_CLEANUP \ #define VERB_CLEANUP \
{ \ try { \
JMP_BUF env2, *old_env2; \ VIO_verb_cleanup (tdbb, transaction); \
old_env2 = (JMP_BUF*) tdbb->tdbb_setjmp; \ } \
tdbb->tdbb_setjmp = (UCHAR*) env2; \ catch (std::exception&) { \
if (!SETJMP (env2)) \ if (dbb->dbb_flags & DBB_bugcheck) { \
{ \ Firebird::status_longjmp_error::raise(tdbb->tdbb_status_vector[1]); \
VIO_verb_cleanup (tdbb, transaction); \ } \
tdbb->tdbb_setjmp = (UCHAR*) old_env2; /* restore old env */\ BUGCHECK (290); /* msg 290 error during savepoint backout */ \
} \
else \
{ \
/* Cause bugcheck to longjmp out of looper. */ \
tdbb->tdbb_setjmp = (UCHAR*) old_env; \
if (dbb->dbb_flags & DBB_bugcheck) \
LONGJMP (reinterpret_cast<jmp_buf&>(old_env), (int) tdbb->tdbb_status_vector [1]); \
else \
BUGCHECK (290); /* msg 290 error during savepoint backout */\
} \
} }
if (!(transaction = request->req_transaction)) if (!(transaction = request->req_transaction)) {
ERR_post(gds_req_no_trans, 0); ERR_post(gds_req_no_trans, 0);
}
SET_TDBB(tdbb); SET_TDBB(tdbb);
dbb = tdbb->tdbb_database; DBB dbb = tdbb->tdbb_database;
BLKCHK(in_node, type_nod); BLKCHK(in_node, type_nod);
/* Save the old pool and request to restore on exit */ // Save the old pool and request to restore on exit
old_pool = tdbb->tdbb_default; JrdMemoryPool* old_pool = tdbb->tdbb_default;
tdbb->tdbb_default = request->req_pool; tdbb->tdbb_default = request->req_pool;
old_request = tdbb->tdbb_request;
REQ old_request = tdbb->tdbb_request;
tdbb->tdbb_request = request; tdbb->tdbb_request = request;
tdbb->tdbb_transaction = transaction; tdbb->tdbb_transaction = transaction;
save_point_number = (transaction->tra_save_point) ?
SLONG save_point_number = (transaction->tra_save_point) ?
transaction->tra_save_point->sav_number : 0; transaction->tra_save_point->sav_number : 0;
node = in_node; VOLATILE NOD node = in_node;
/* Catch errors so we can unwind cleanly */ /* Catch errors so we can unwind cleanly */
old_env = (JMP_BUF *) tdbb->tdbb_setjmp; SSHORT error_pending = FALSE;
tdbb->tdbb_setjmp = (UCHAR *) env;
error_pending = FALSE;
try { try {
@ -1687,7 +1680,7 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
#endif #endif
#if defined(DEBUG_GDS_ALLOC) && FALSE #if defined(DEBUG_GDS_ALLOC) && FALSE
node_type = node->nod_type; int node_type = node->nod_type;
#endif #endif
switch (node->nod_type) { switch (node->nod_type) {
case nod_asn_list: case nod_asn_list:
@ -1734,7 +1727,8 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
case nod_erase: case nod_erase:
if ((request->req_operation == req::req_return) && if ((request->req_operation == req::req_return) &&
(node->nod_arg[e_erase_sub_erase])) { (node->nod_arg[e_erase_sub_erase]))
{
if (!top_node) { if (!top_node) {
top_node = node; top_node = node;
which_erase_trig = PRE_TRIG; which_erase_trig = PRE_TRIG;
@ -1757,7 +1751,9 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
node = erase(tdbb, node, ALL_TRIGS); node = erase(tdbb, node, ALL_TRIGS);
if (!(prev_node->nod_arg[e_erase_sub_erase]) && if (!(prev_node->nod_arg[e_erase_sub_erase]) &&
which_erase_trig == PRE_TRIG) which_erase_trig == PRE_TRIG)
{
which_erase_trig = POST_TRIG; which_erase_trig = POST_TRIG;
}
} }
break; break;
@ -1949,7 +1945,6 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
engine out of looper there by abruptly engine out of looper there by abruptly
terminating the processing. */ terminating the processing. */
tdbb->tdbb_setjmp = (UCHAR *) env;
tdbb->tdbb_default = request->req_pool; tdbb->tdbb_default = request->req_pool;
tdbb->tdbb_request = request; tdbb->tdbb_request = request;
/* The error is dealt with by the application, cleanup /* The error is dealt with by the application, cleanup
@ -1995,7 +1990,6 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
case nod_error_handler: case nod_error_handler:
if (request->req_flags & req_error_handler && !error_pending) { if (request->req_flags & req_error_handler && !error_pending) {
tdbb->tdbb_setjmp = (UCHAR *) old_env;
return node; return node;
} }
node = node->nod_parent; node = node->nod_parent;
@ -2092,14 +2086,18 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
top_node = NULL; top_node = NULL;
which_mod_trig = ALL_TRIGS; which_mod_trig = ALL_TRIGS;
} }
else else {
request->req_operation = req::req_evaluate; request->req_operation = req::req_evaluate;
}
} }
else { else {
prev_node = node; prev_node = node;
node = modify(tdbb, node, ALL_TRIGS); node = modify(tdbb, node, ALL_TRIGS);
if (!(prev_node->nod_arg[e_mod_sub_mod]) && if (!(prev_node->nod_arg[e_mod_sub_mod]) &&
which_mod_trig == PRE_TRIG) which_mod_trig = POST_TRIG; which_mod_trig == PRE_TRIG)
{
which_mod_trig = POST_TRIG;
}
} }
break; break;
@ -2336,10 +2334,9 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
tdbb->tdbb_default = old_pool; tdbb->tdbb_default = old_pool;
tdbb->tdbb_transaction = (tdbb->tdbb_request = old_request) ? tdbb->tdbb_transaction = (tdbb->tdbb_request = old_request) ?
old_request->req_transaction : NULL; old_request->req_transaction : NULL;
tdbb->tdbb_setjmp = (UCHAR *) old_env;
/* in the case of a pending error condition (one which did not /* in the case of a pending error condition (one which did not
result in a longjmp to the top of looper), we need to delete result in a exception to the top of looper), we need to delete
the last savepoint */ the last savepoint */
if (error_pending) { if (error_pending) {
@ -2383,7 +2380,7 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
Set up special error handling in case something Set up special error handling in case something
happens there. */ happens there. */
FRGN_unwind(request); FRGN_unwind(request);
/* Continue with normal JRD unwind */ /* Continue with normal JRD unwind */
@ -2400,7 +2397,6 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
} }
error_pending = TRUE; error_pending = TRUE;
tdbb->tdbb_setjmp = (UCHAR *) old_env;
request->req_operation = req::req_unwind; request->req_operation = req::req_unwind;
request->req_label = 0; request->req_label = 0;
} }
@ -2409,24 +2405,6 @@ static NOD looper(TDBB tdbb, REQ request, NOD in_node)
} }
#ifdef PC_ENGINE
// TMN: Quick wrapper to remove one try/catch
class LCK_RAII_wrapper
{
explicit LCK_RAII_wrapper(LCK lock) : l(lock) {}
~LCK_RAII_wrapper() {
if (l) {
}
}
LCK l;
private:
LCK_RAII_wrapper(const LCK_RAII_wrapper&); // no impl.
void operator=(const LCK_RAII_wrapper&); // no impl.
};
#endif
static NOD modify(TDBB tdbb, register NOD node, SSHORT which_trig) static NOD modify(TDBB tdbb, register NOD node, SSHORT which_trig)
{ {
/************************************** /**************************************
@ -2450,8 +2428,7 @@ static NOD modify(TDBB tdbb, register NOD node, SSHORT which_trig)
TRA transaction; TRA transaction;
#ifdef PC_ENGINE #ifdef PC_ENGINE
RSB rsb = NULL; RSB rsb = NULL;
LCK implicit_lock = NULL, record_locking; LCK record_locking;
JMP_BUF env, *old_env;
IRSB irsb; IRSB irsb;
#endif #endif
@ -2500,11 +2477,12 @@ static NOD modify(TDBB tdbb, register NOD node, SSHORT which_trig)
org_rpb, org_rpb,
NULL, NULL,
transaction, transaction,
reinterpret_cast < BLK > reinterpret_cast<BLK>(tdbb->tdbb_default))))
(tdbb->tdbb_default)))) {
ERR_post(gds_deadlock, gds_arg_gds, gds_update_conflict, 0); ERR_post(gds_deadlock, gds_arg_gds, gds_update_conflict, 0);
}
VIO_data(tdbb, org_rpb, VIO_data(tdbb, org_rpb,
reinterpret_cast < BLK > (tdbb->tdbb_request->req_pool)); reinterpret_cast<BLK>(tdbb->tdbb_request->req_pool));
/* If record is present, and the transaction is read committed, /* If record is present, and the transaction is read committed,
* make sure the record has not been updated. Also, punt after * make sure the record has not been updated. Also, punt after
@ -2513,7 +2491,9 @@ static NOD modify(TDBB tdbb, register NOD node, SSHORT which_trig)
if ((transaction->tra_flags & TRA_read_committed) && if ((transaction->tra_flags & TRA_read_committed) &&
(tid_fetch != org_rpb->rpb_transaction)) (tid_fetch != org_rpb->rpb_transaction))
{
ERR_post(gds_deadlock, gds_arg_gds, gds_update_conflict, 0); ERR_post(gds_deadlock, gds_arg_gds, gds_update_conflict, 0);
}
org_rpb->rpb_stream_flags &= ~RPB_s_refetch; org_rpb->rpb_stream_flags &= ~RPB_s_refetch;
} }
@ -2540,19 +2520,17 @@ static NOD modify(TDBB tdbb, register NOD node, SSHORT which_trig)
will be able to read or write the record but not when an explicit will be able to read or write the record but not when an explicit
lock has been taken out */ lock has been taken out */
try { try
{
LCK_RAII_wrapper implicit_lock;
if (!(transaction->tra_flags & TRA_degree3)) if (!(transaction->tra_flags & TRA_degree3))
{ {
record_locking = RLCK_record_locking(relation); record_locking = RLCK_record_locking(relation);
if (record_locking->lck_physical != LCK_PR) if (record_locking->lck_physical != LCK_PR)
{ {
implicit_lock = implicit_record_lock(transaction, org_rpb); implicit_lock.assign(implicit_record_lock(transaction, org_rpb));
/* set up to catch any errors so that we can release the lock */
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
tdbb->tdbb_setjmp = (UCHAR *) env;
} }
} }
#endif #endif
@ -2634,28 +2612,21 @@ static NOD modify(TDBB tdbb, register NOD node, SSHORT which_trig)
} // try } // try
catch (...) { catch (...) {
tdbb->tdbb_setjmp = (UCHAR *) old_env;
if (implicit_lock) {
RLCK_unlock_record_implicit(implicit_lock, 0);
}
Firebird::status_longjmp_error::raise(-1); Firebird::status_longjmp_error::raise(-1);
} }
if (implicit_lock) {
tdbb->tdbb_setjmp = (UCHAR *) old_env;
RLCK_unlock_record_implicit(implicit_lock, 0);
}
/* if the stream is navigational, we must position the stream on the new /* if the stream is navigational, we must position the stream on the new
record version, but first set the record number */ record version, but first set the record number */
new_rpb->rpb_number = org_rpb->rpb_number; new_rpb->rpb_number = org_rpb->rpb_number;
if (rsb) if (rsb) {
RSE_reset_position(tdbb, rsb, new_rpb); RSE_reset_position(tdbb, rsb, new_rpb);
}
#endif #endif
#else #else
if (node->nod_arg[e_mod_validate]) if (node->nod_arg[e_mod_validate]) {
validate(tdbb, node->nod_arg[e_mod_validate]); validate(tdbb, node->nod_arg[e_mod_validate]);
}
VIO_modify(tdbb, org_rpb, new_rpb, transaction, VIO_modify(tdbb, org_rpb, new_rpb, transaction,
node->nod_arg[e_mod_sql]); node->nod_arg[e_mod_sql]);
#endif #endif

View File

@ -89,6 +89,11 @@ extern "C" {
#else #else
#define HASH_SIZE 101 #define HASH_SIZE 101
// fwd. decl.
class vec;
class dbb : private pool_alloc<type_dbb> class dbb : private pool_alloc<type_dbb>
{ {
public: public:
@ -97,8 +102,8 @@ public:
class dbb *dbb_next; /* Next database block in system */ class dbb *dbb_next; /* Next database block in system */
class att *dbb_attachments; /* Active attachments */ class att *dbb_attachments; /* Active attachments */
struct bcb *dbb_bcb; /* Buffer control block */ struct bcb *dbb_bcb; /* Buffer control block */
struct vec *dbb_relations; /* relation vector */ vec* dbb_relations; /* relation vector */
struct vec *dbb_procedures; /* scanned procedures */ vec* dbb_procedures; /* scanned procedures */
struct lck *dbb_lock; /* granddaddy lock */ struct lck *dbb_lock; /* granddaddy lock */
struct tra *dbb_sys_trans; /* system transaction */ struct tra *dbb_sys_trans; /* system transaction */
struct fil *dbb_file; /* files for I/O operations */ struct fil *dbb_file; /* files for I/O operations */
@ -144,8 +149,8 @@ public:
pool_vec_type dbb_pools; /* pools */ pool_vec_type dbb_pools; /* pools */
USHORT dbb_next_pool_id; USHORT dbb_next_pool_id;
struct vec *dbb_internal; /* internal requests */ vec* dbb_internal; /* internal requests */
struct vec *dbb_dyn_req; /* internal dyn requests */ vec* dbb_dyn_req; /* internal dyn requests */
struct jrn *dbb_journal; /* journal block */ struct jrn *dbb_journal; /* journal block */
SLONG dbb_oldest_active; /* Cached "oldest active" transaction */ SLONG dbb_oldest_active; /* Cached "oldest active" transaction */
@ -183,8 +188,8 @@ public:
class map *dbb_blob_map; /* mapping of blobs for REPLAY */ class map *dbb_blob_map; /* mapping of blobs for REPLAY */
struct log *dbb_log; /* log file for REPLAY */ struct log *dbb_log; /* log file for REPLAY */
struct vec *dbb_text_objects; /* intl text type descriptions */ vec* dbb_text_objects; /* intl text type descriptions */
struct vec *dbb_charsets; /* intl character set descriptions */ vec* dbb_charsets; /* intl character set descriptions */
struct wal *dbb_wal; /* WAL handle for WAL API */ struct wal *dbb_wal; /* WAL handle for WAL API */
struct tpc *dbb_tip_cache; /* cache of latest known state of all transactions in system */ struct tpc *dbb_tip_cache; /* cache of latest known state of all transactions in system */
class vcl *dbb_pc_transactions; /* active precommitted transactions */ class vcl *dbb_pc_transactions; /* active precommitted transactions */
@ -368,16 +373,16 @@ public:
class scl* att_security_class; // security class for database class scl* att_security_class; // security class for database
class scl* att_security_classes; // security classes class scl* att_security_classes; // security classes
class vcl* att_counts[DBB_max_count]; class vcl* att_counts[DBB_max_count];
struct vec* att_relation_locks; // explicit persistent locks for relations vec* att_relation_locks; // explicit persistent locks for relations
struct bkm* att_bookmarks; // list of bookmarks taken out using this attachment struct bkm* att_bookmarks; // list of bookmarks taken out using this attachment
struct lck* att_record_locks; // explicit or implicit record locks taken out during attachment struct lck* att_record_locks; // explicit or implicit record locks taken out during attachment
struct vec* att_bkm_quick_ref; // correspondence table of bookmarks vec* att_bkm_quick_ref; // correspondence table of bookmarks
struct vec* att_lck_quick_ref; // correspondence table of locks vec* att_lck_quick_ref; // correspondence table of locks
ULONG att_flags; // Flags describing the state of the attachment ULONG att_flags; // Flags describing the state of the attachment
SSHORT att_charset; // user's charset specified in dpb SSHORT att_charset; // user's charset specified in dpb
class str* att_lc_messages; // attachment's preference for message natural language class str* att_lc_messages; // attachment's preference for message natural language
struct lck* att_long_locks; // outstanding two phased locks struct lck* att_long_locks; // outstanding two phased locks
struct vec* att_compatibility_table; // hash table of compatible locks vec* att_compatibility_table; // hash table of compatible locks
class vcl* att_val_errors; class vcl* att_val_errors;
class str* att_working_directory; // Current working directory is cached class str* att_working_directory; // Current working directory is cached
}; };
@ -429,8 +434,8 @@ class prc : public pool_alloc_rpt<SCHAR, type_prc>
struct fmt *prc_input_fmt; struct fmt *prc_input_fmt;
struct fmt *prc_output_fmt; struct fmt *prc_output_fmt;
struct fmt *prc_format; struct fmt *prc_format;
struct vec *prc_input_fields; /* vector of field blocks */ vec* prc_input_fields; /* vector of field blocks */
struct vec *prc_output_fields; /* vector of field blocks */ vec* prc_output_fields; /* vector of field blocks */
struct req *prc_request; /* compiled procedure request */ struct req *prc_request; /* compiled procedure request */
class str *prc_security_name; /* pointer to security class name for procedure */ class str *prc_security_name; /* pointer to security class name for procedure */
USHORT prc_use_count; /* requests compiled with relation */ USHORT prc_use_count; /* requests compiled with relation */
@ -469,17 +474,17 @@ typedef prm* PRM;
primary/unique keys */ primary/unique keys */
typedef struct prim { typedef struct prim {
struct vec *prim_reference_ids; vec* prim_reference_ids;
struct vec *prim_relations; vec* prim_relations;
struct vec *prim_indexes; vec* prim_indexes;
} *PRIM; } *PRIM;
/* Foreign references to other relations' primary/unique keys */ /* Foreign references to other relations' primary/unique keys */
typedef struct frgn { typedef struct frgn {
struct vec *frgn_reference_ids; vec* frgn_reference_ids;
struct vec *frgn_relations; vec* frgn_relations;
struct vec *frgn_indexes; vec* frgn_indexes;
} *FRGN; } *FRGN;
/* Relation block; one is created for each relation referenced /* Relation block; one is created for each relation referenced
@ -494,11 +499,11 @@ public:
USHORT rel_current_fmt; /* Current format number */ USHORT rel_current_fmt; /* Current format number */
UCHAR rel_length; /* length of ascii relation name */ UCHAR rel_length; /* length of ascii relation name */
struct fmt *rel_current_format; /* Current record format */ struct fmt *rel_current_format; /* Current record format */
TEXT *rel_name; /* pointer to ascii relation name */ TEXT* rel_name; /* pointer to ascii relation name */
struct vec *rel_formats; /* Known record formats */ vec* rel_formats; /* Known record formats */
TEXT *rel_owner_name; /* pointer to ascii owner */ TEXT *rel_owner_name; /* pointer to ascii owner */
class vcl *rel_pages; /* vector of pointer page numbers */ class vcl *rel_pages; /* vector of pointer page numbers */
struct vec *rel_fields; /* vector of field blocks */ vec* rel_fields; /* vector of field blocks */
struct rse *rel_view_rse; /* view record select expression */ struct rse *rel_view_rse; /* view record select expression */
class vcx *rel_view_contexts; /* linked list of view contexts */ class vcx *rel_view_contexts; /* linked list of view contexts */
@ -508,7 +513,7 @@ public:
SLONG rel_index_root; /* index root page number */ SLONG rel_index_root; /* index root page number */
SLONG rel_data_pages; /* count of relation data pages */ SLONG rel_data_pages; /* count of relation data pages */
struct vec *rel_gc_rec; /* vector of records for garbage collection */ vec* rel_gc_rec; /* vector of records for garbage collection */
#ifdef GARBAGE_THREAD #ifdef GARBAGE_THREAD
struct sbm *rel_gc_bitmap; /* garbage collect bitmap of data page sequences */ struct sbm *rel_gc_bitmap; /* garbage collect bitmap of data page sequences */
#endif #endif
@ -530,12 +535,12 @@ public:
struct idl *rel_index_locks; /* index existence locks */ struct idl *rel_index_locks; /* index existence locks */
struct idb *rel_index_blocks; /* index blocks for caching index info */ struct idb *rel_index_blocks; /* index blocks for caching index info */
struct vec *rel_pre_erase; /* Pre-operation erase trigger */ vec* rel_pre_erase; /* Pre-operation erase trigger */
struct vec *rel_post_erase; /* Post-operation erase trigger */ vec* rel_post_erase; /* Post-operation erase trigger */
struct vec *rel_pre_modify; /* Pre-operation modify trigger */ vec* rel_pre_modify; /* Pre-operation modify trigger */
struct vec *rel_post_modify; /* Post-operation modify trigger */ vec* rel_post_modify; /* Post-operation modify trigger */
struct vec *rel_pre_store; /* Pre-operation store trigger */ vec* rel_pre_store; /* Pre-operation store trigger */
struct vec *rel_post_store; /* Post-operation store trigger */ vec* rel_post_store; /* Post-operation store trigger */
struct prim rel_primary_dpnds; /* foreign dependencies on this relation's primary key */ struct prim rel_primary_dpnds; /* foreign dependencies on this relation's primary key */
struct frgn rel_foreign_refs; /* foreign references to other relations' primary keys */ struct frgn rel_foreign_refs; /* foreign references to other relations' primary keys */
}; };