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

The files rng.cpp, rng.h, rng_proto.h, bookmark.cpp and bookmark.h belong exclusively to PC_ENGINE, that's obsolete functionality.

Sixth step: remove the places protected by the macro PC_ENGINE. More to come. (I guess all of you who have pending functional changes to post will love this commit. <g>)
This commit is contained in:
robocop 2006-02-02 07:32:07 +00:00
parent 7c90e51ce7
commit 2b99e764e3
23 changed files with 18 additions and 3726 deletions

View File

@ -148,10 +148,6 @@ static bool stream_in_rse(USHORT, RecordSelExpr*);
static void build_external_access(thread_db* tdbb, ExternalAccessList& list, jrd_req* request);
static void verify_trigger_access(thread_db* tdbb, jrd_rel* owner_relation, trig_vec* triggers, jrd_rel* view);
#ifdef PC_ENGINE
static USHORT base_stream(CompilerScratch*, jrd_nod**, bool);
#endif
#ifdef CMP_DEBUG
IMPLEMENT_TRACE_ROUTINE(cmp_trace, "CMP")
#endif
@ -876,13 +872,6 @@ void CMP_get_desc(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node, DSC * de
case nod_count:
case nod_gen_id:
case nod_lock_state:
#ifdef PC_ENGINE
case nod_lock_record:
case nod_lock_relation:
case nod_seek:
case nod_seek_no_warn:
case nod_crack:
#endif
desc->dsc_dtype = dtype_long;
desc->dsc_length = sizeof(SLONG);
desc->dsc_scale = 0;
@ -890,16 +879,6 @@ void CMP_get_desc(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node, DSC * de
desc->dsc_flags = 0;
return;
#ifdef PC_ENGINE
case nod_begin_range:
desc->dsc_dtype = dtype_text;
desc->dsc_ttype() = ttype_ascii;
desc->dsc_scale = 0;
desc->dsc_length = RANGE_NAME_LENGTH;
desc->dsc_flags = 0;
return;
#endif
case nod_field:
{
const USHORT id = (USHORT) (IPTR) node->nod_arg[e_fld_id];
@ -2183,39 +2162,6 @@ void CMP_post_resource( ResourceList* rsc_ptr,
}
#ifdef PC_ENGINE
void CMP_release_resource(ResourceList* rsc_ptr, enum Resource::rsc_s type, USHORT id)
{
/**************************************
*
* C M P _ r e l e a s e _ r e s o u r c e
*
**************************************
*
* Functional description
* Release resource from request.
*
* 10-Apr-2004, Nickolay Samofatov
* This code is broken because it doesn't account case when resource is used more than once
*
**************************************/
Resource* resource;
for (; (resource = *rsc_ptr); rsc_ptr = &resource->rsc_next) {
if (resource->rsc_type == type && resource->rsc_id == id)
break;
}
if (!resource)
return;
// take out of the linked list and release
*rsc_ptr = resource->rsc_next;
delete resource;
}
#endif
void CMP_decrement_prc_use_count(thread_db* tdbb, jrd_prc* procedure)
{
/*********************************************
@ -2327,10 +2273,6 @@ void CMP_release(thread_db* tdbb, jrd_req* request)
EXE_unwind(tdbb, request);
#ifdef PC_ENGINE
RNG_release_ranges(request);
#endif
if (request->req_attachment) {
for (jrd_req** next = &request->req_attachment->att_requests;
*next; next = &(*next)->req_request)
@ -2455,54 +2397,6 @@ static UCHAR* alloc_map(thread_db* tdbb, CompilerScratch* csb, USHORT stream)
}
#ifdef PC_ENGINE
static USHORT base_stream(CompilerScratch* csb, jrd_nod** stream_number, bool nav_stream)
{
/**************************************
*
* b a s e _ s t r e a m
*
**************************************
*
* Functional description
* Find the base stream of a view for navigational
* access. If there is more than one base table,
* give an error.
*
**************************************/
DEV_BLKCHK(csb, type_csb);
// note: *stream_number is NOT a jrd_nod*
USHORT stream = (USHORT) *stream_number;
// if the stream references a view, follow map
UCHAR* map = csb->csb_rpt[stream].csb_map;
if (map) {
if (map[2]) {
if (nav_stream) {
// navigational stream %ld references a view with more than one base table
ERR_post(isc_complex_view, isc_arg_number, (SLONG) stream, 0);
}
}
else {
map++;
stream = *map;
}
}
// if this is a navigational stream, fix up the stream number
// in the node tree to point to the base table from now on
if (nav_stream) {
*stream_number = (jrd_nod*) stream;
}
return stream;
}
#endif
static jrd_nod* catenate_nodes(thread_db* tdbb, NodeStack& stack)
{
/**************************************
@ -4771,121 +4665,6 @@ static jrd_nod* pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node
}
break;
#ifdef PC_ENGINE
// the remainder of the node types are for IDAPI support:
// fix up the stream to point to the base table, and preserve
// the pointers to the navigational rsb for easy reference
// later during execution
case nod_stream:
{
RecordSelExpr* rse = (RecordSelExpr*) node;
rse_node = node;
// setting the stream flag will allow the optimizer to
// detect that a SET INDEX may be done on this stream
rse_node->nod_flags |= rse_stream;
rsb_ptr = &rse->rse_rsb;
jrd_nod* relation = rse->rse_relation[0];
stream = base_stream(csb, &relation->nod_arg[e_rel_stream], true);
csb->csb_rpt[stream].csb_rsb_ptr = &rse->rse_rsb;
}
break;
case nod_find:
stream = base_stream(csb, &node->nod_arg[e_find_stream], true);
if (!(node->nod_arg[e_find_rsb] =
(jrd_nod*) csb->csb_rpt[stream].csb_rsb_ptr))
{
ERR_post(isc_stream_not_defined, 0);
}
break;
case nod_find_dbkey:
case nod_find_dbkey_version:
stream = base_stream(csb, &node->nod_arg[e_find_dbkey_stream], true);
if (!(node->nod_arg[e_find_dbkey_rsb] =
(jrd_nod*) csb->csb_rpt[stream].csb_rsb_ptr))
{
ERR_post(isc_stream_not_defined, 0);
}
break;
case nod_set_index:
stream = base_stream(csb, &node->nod_arg[e_index_stream], true);
if (!(node->nod_arg[e_index_rsb] =
(jrd_nod*) csb->csb_rpt[stream].csb_rsb_ptr))
{
ERR_post(isc_stream_not_defined, 0);
}
break;
case nod_get_bookmark:
stream = base_stream(csb, &node->nod_arg[e_getmark_stream], true);
if (!(node->nod_arg[e_getmark_rsb] =
(jrd_nod*) csb->csb_rpt[stream].csb_rsb_ptr))
{
ERR_post(isc_stream_not_defined, 0);
}
break;
case nod_set_bookmark:
stream = base_stream(csb, &node->nod_arg[e_setmark_stream], true);
if (!(node->nod_arg[e_setmark_rsb] =
(jrd_nod*) csb->csb_rpt[stream].csb_rsb_ptr))
{
ERR_post(isc_stream_not_defined, 0);
}
break;
case nod_lock_record:
stream = base_stream(csb, &node->nod_arg[e_lockrec_stream], true);
if (!(node->nod_arg[e_lockrec_rsb] =
(jrd_nod*) csb->csb_rpt[stream].csb_rsb_ptr))
{
ERR_post(isc_stream_not_defined, 0);
}
break;
case nod_crack:
case nod_force_crack:
stream = base_stream(csb, &node->nod_arg[0], true);
if (!(node->nod_arg[1] = (jrd_nod*) csb->csb_rpt[stream].csb_rsb_ptr))
ERR_post(isc_stream_not_defined, 0);
break;
case nod_reset_stream:
stream = base_stream(csb, &node->nod_arg[e_reset_from_stream], true);
if (!(node->nod_arg[e_reset_from_rsb] =
(jrd_nod*) csb->csb_rpt[stream].csb_rsb_ptr))
{
ERR_post(isc_stream_not_defined, 0);
}
break;
case nod_cardinality:
stream = base_stream(csb, &node->nod_arg[e_card_stream], true);
if (!(node->nod_arg[e_card_rsb] =
(jrd_nod*) csb->csb_rpt[stream].csb_rsb_ptr))
{
ERR_post(isc_stream_not_defined, 0);
}
break;
// the following DML nodes need to have their rsb's stored when
// they are referencing a navigational stream, so that we can
// follow proper IDAPI semantics in manipulating a stream
case nod_erase:
stream = base_stream(csb, &node->nod_arg[e_erase_stream], false);
node->nod_arg[e_erase_rsb] = (jrd_nod*) csb->csb_rpt[stream].csb_rsb_ptr;
break;
case nod_modify:
stream = base_stream(csb, &node->nod_arg[e_mod_org_stream], false);
node->nod_arg[e_mod_rsb] = (jrd_nod*) csb->csb_rpt[stream].csb_rsb_ptr;
break;
#endif
default:
break;
}
@ -5080,10 +4859,6 @@ static jrd_nod* pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node
case nod_lowcase:
case nod_prot_mask:
case nod_lock_state:
#ifdef PC_ENGINE
case nod_lock_record:
case nod_lock_relation:
#endif
case nod_scalar:
case nod_cast:
case nod_extract:
@ -5091,13 +4866,6 @@ static jrd_nod* pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node
case nod_current_time:
case nod_current_timestamp:
case nod_current_date:
#ifdef PC_ENGINE
case nod_cardinality:
case nod_seek:
case nod_seek_no_warn:
case nod_crack:
case nod_begin_range:
#endif
{
dsc descriptor_a;
CMP_get_desc(tdbb, csb, node, &descriptor_a);
@ -5704,13 +5472,6 @@ static RecordSource* post_rse(thread_db* tdbb, CompilerScratch* csb, RecordSelEx
rsb->rsb_flags |= rsb_singular;
}
#ifdef PC_ENGINE
// this flag lets the VIO layer know to add a page to the cache range
if (rse->nod_flags & rse_stream) {
rsb->rsb_flags |= rsb_stream_type;
}
#endif
// mark all the substreams as inactive
jrd_nod** ptr = rse->rse_relation;

View File

@ -45,9 +45,6 @@ Jrd::jrd_req* CMP_make_request(Jrd::thread_db*, Jrd::CompilerScratch*);
void CMP_post_access(Jrd::thread_db*, Jrd::CompilerScratch*, const Firebird::MetaName&, SLONG,
Jrd::SecurityClass::flags_t, const TEXT*, const Firebird::MetaName&);
void CMP_post_resource(Jrd::ResourceList*, blk*, Jrd::Resource::rsc_s, USHORT);
#ifdef PC_ENGINE
void CMP_release_resource(Jrd::ResourceList&, Jrd::Resource::rsc_s, USHORT);
#endif
void CMP_release(Jrd::thread_db*, Jrd::jrd_req*);
void CMP_shutdown_database(Jrd::thread_db*);
void CMP_verify_access(Jrd::thread_db* tdbb, Jrd::jrd_req* request);

View File

@ -152,10 +152,6 @@ static SINT64 get_day_fraction(const dsc* d);
static dsc* get_mask(thread_db*, jrd_nod*, impure_value*);
static SINT64 get_timestamp_to_isc_ticks(const dsc* d);
static void init_agg_distinct(thread_db*, const jrd_nod*);
#ifdef PC_ENGINE
static dsc* lock_record(thread_db*, jrd_nod*, impure_value*);
static dsc* lock_relation(thread_db*, jrd_nod*, impure_value*);
#endif
static dsc* lock_state(thread_db*, jrd_nod*, impure_value*);
static dsc* multiply(const dsc*, impure_value*, const jrd_nod*);
static dsc* multiply2(const dsc*, impure_value*, const jrd_nod*);
@ -893,16 +889,7 @@ dsc* EVL_expr(thread_db* tdbb, jrd_nod* const node)
case nod_lock_state:
return lock_state(tdbb, node, impure);
#ifdef PC_ENGINE
case nod_lock_record:
return lock_record(tdbb, node, impure);
case nod_lock_relation:
return lock_relation(tdbb, node, impure);
case nod_begin_range:
return RNG_begin(node, impure);
#endif
case nod_null:
request->req_flags |= req_null;
return NULL;
@ -1039,46 +1026,6 @@ dsc* EVL_expr(thread_db* tdbb, jrd_nod* const node)
case nod_trim:
return trim(tdbb, node, impure);
#ifdef PC_ENGINE
case nod_crack:
{
RecordSource* rsb = *(RecordSource**) node->nod_arg[1];
if (rsb->rsb_type == rsb_boolean)
rsb = rsb->rsb_next;
IRSB irsb = (IRSB) ((UCHAR *) request + rsb->rsb_impure);
impure->vlu_desc.dsc_address =
(UCHAR *) & impure->vlu_misc.vlu_long;
impure->vlu_desc.dsc_dtype = dtype_long;
impure->vlu_desc.dsc_length = sizeof(ULONG);
impure->vlu_desc.dsc_scale = 0;
impure->vlu_misc.vlu_long =
irsb->irsb_flags & (irsb_bof | irsb_eof | irsb_crack);
return &impure->vlu_desc;
}
case nod_get_bookmark:
{
Bookmark* bookmark =
RSE_get_bookmark(tdbb, *(RecordSource**) node->nod_arg[e_getmark_rsb]);
return &bookmark->bkm_desc;
}
case nod_bookmark:
{
Bookmark* bookmark = BKM_lookup(node->nod_arg[e_bookmark_id]);
return &bookmark->bkm_key_desc;
}
case nod_cardinality:
impure->vlu_misc.vlu_long =
(*(RecordSource**) node->nod_arg[e_card_rsb])->rsb_cardinality;
impure->vlu_desc.dsc_dtype = dtype_long;
impure->vlu_desc.dsc_length = sizeof(ULONG);
impure->vlu_desc.dsc_scale = 0;
impure->vlu_desc.dsc_sub_type = 0;
impure->vlu_desc.dsc_address = (UCHAR *) & impure->vlu_misc.vlu_long;
return &impure->vlu_desc;
#endif
default: /* Shut up some compiler warnings */
break;
}
@ -3511,144 +3458,6 @@ static void init_agg_distinct(thread_db* tdbb, const jrd_nod* node)
}
#ifdef PC_ENGINE
static dsc* lock_record(thread_db* tdbb, jrd_nod* node, impure_value* impure)
{
/**************************************
*
* l o c k _ r e c o r d
*
**************************************
*
* Functional description
* Lock a record and return a descriptor
* pointing to the lock handle.
*
**************************************/
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
DEV_BLKCHK(node, type_nod);
/* Initialize descriptor */
impure->vlu_desc.dsc_address = (UCHAR *) & impure->vlu_misc.vlu_long;
impure->vlu_desc.dsc_dtype = dtype_long;
impure->vlu_desc.dsc_length = sizeof(ULONG);
impure->vlu_desc.dsc_scale = 0;
/* get the locking level */
dsc* desc = EVL_expr(tdbb, node->nod_arg[e_lockrec_level]);
const USHORT lock_level = (USHORT) MOV_get_long(desc, 0);
if (lock_level > LCK_EX)
ERR_post(isc_bad_lock_level, isc_arg_number, (SLONG) lock_level, 0);
/* perform the actual lock (or unlock) */
RecordSource* rsb = *(RecordSource**) node->nod_arg[e_lockrec_rsb];
record_param* rpb = request->req_rpb + rsb->rsb_stream;
Lock* lock = NULL;
if (!lock_level)
RLCK_unlock_record(0, rpb);
else if (!(lock = RLCK_lock_record(rpb, lock_level, 0, 0)))
ERR_warning(isc_record_lock, 0);
/* return the lock handle (actually the pointer to the lock block) */
#if SIZEOF_VOID_P != 8
impure->vlu_misc.vlu_long = (ULONG) lock;
#else
{
/* The lock pointer can't be stored in a ULONG. Therefore we must
generate a ULONG value that can be used to retrieve the pointer.
Basically we will keep a vector of user locks and give the user
an index into this vector. When the user releases a lock, its
slot in the vector is zeroed and it becomes available for reuse. */
Attachment* att = tdbb->tdbb_attachment;
const ULONG slot = ALL_get_free_object(tdbb->tdbb_database->dbb_permanent,
&att->att_lck_quick_ref, 50);
(*att->att_lck_quick_ref)[slot] = lock;
impure->vlu_misc.vlu_long = slot;
}
#endif
return &impure->vlu_desc;
}
#endif
#ifdef PC_ENGINE
static dsc* lock_relation(thread_db* tdbb, jrd_nod* node, impure_value* impure)
{
/**************************************
*
* l o c k _ r e l a t i o n
*
**************************************
*
* Functional description
* Lock a relation and return a descriptor
* pointing to the lock handle.
*
**************************************/
SET_TDBB(tdbb);
DEV_BLKCHK(node, type_nod);
/* Initialize descriptor */
impure->vlu_desc.dsc_address = (UCHAR *) & impure->vlu_misc.vlu_long;
impure->vlu_desc.dsc_dtype = dtype_long;
impure->vlu_desc.dsc_length = sizeof(ULONG);
impure->vlu_desc.dsc_scale = 0;
/* get the locking level */
dsc* desc = EVL_expr(tdbb, node->nod_arg[e_lockrel_level]);
const USHORT lock_level = (USHORT) MOV_get_long(desc, 0);
if (lock_level > LCK_EX)
ERR_post(isc_bad_lock_level, isc_arg_number, (SLONG) lock_level, 0);
/* perform the actual lock (or unlock) */
jrd_nod* relation_node = node->nod_arg[e_lockrel_relation];
jrd_rel* relation = (jrd_rel*) relation_node->nod_arg[e_rel_relation];
Lock* lock = NULL;
if (!lock_level)
RLCK_unlock_relation(0, relation);
else
lock = RLCK_lock_relation(relation, lock_level, 0, relation);
/* return the lock handle (actually the pointer to the lock block) */
#if SIZEOF_VOID_P != 8
impure->vlu_misc.vlu_long = (ULONG) lock;
#else
{
SET_TDBB(tdbb);
/* The lock pointer can't be stored in a ULONG. Therefore we must
generate a ULONG value that can be used to retrieve the pointer.
Basically we will keep a vector of user locks and give the user
an index into this vector. When the user releases a lock, its
slot in the vector is zeroed and it becomes available for reuse. */
Attachment* att = tdbb->tdbb_attachment;
const ULONG slot =
ALL_get_free_object(tdbb->tdbb_database->dbb_permanent,
&att->att_lck_quick_ref, 50);
(*att->att_lck_quick_ref)[slot] = lock;
impure->vlu_misc.vlu_long = slot;
}
#endif
return &impure->vlu_desc;
}
#endif
static dsc* lock_state(thread_db* tdbb, jrd_nod* node, impure_value* impure)
{
/**************************************

View File

@ -216,15 +216,6 @@ inline void PreModifyEraseTriggers(thread_db*, trig_vec**, SSHORT, record_param*
Record*, jrd_req::req_ta);
static void stuff_stack_trace(const jrd_req*);
#ifdef PC_ENGINE
static jrd_nod* find(thread_db*, jrd_nod*);
static jrd_nod* find_dbkey(thread_db*, jrd_nod*);
static Lock* implicit_record_lock(jrd_tra*, record_param*);
static jrd_nod* release_bookmark(thread_db*, jrd_nod*);
static jrd_nod* set_bookmark(thread_db*, jrd_nod*);
static jrd_nod* set_index(thread_db*, jrd_nod*);
static jrd_nod* stream(thread_db*, jrd_nod*);
#endif
/* macro definitions */
@ -255,26 +246,6 @@ const size_t MAX_STACK_TRACE = 2048;
const int RECORD_LOCK_CHECK_INTERVAL = 10;
#ifdef PC_ENGINE
// TMN: RAII class for Lock. Unlocks the Lock on destruction.
class LCK_RAII_wrapper
{
LCK_RAII_wrapper() : l(0) {}
~LCK_RAII_wrapper() {
if (l) {
RLCK_unlock_record_implicit(l, 0);
}
}
void assign(Lock* lock) { l = lock; }
Lock* l;
private:
LCK_RAII_wrapper(const LCK_RAII_wrapper&); // no impl.
void operator=(const LCK_RAII_wrapper&); // no impl.
};
#endif
void EXE_assignment(thread_db* tdbb, jrd_nod* node)
{
@ -499,38 +470,6 @@ void EXE_assignment(thread_db* tdbb, jrd_nod* node)
}
#ifdef PC_ENGINE
bool EXE_crack(thread_db* tdbb, RecordSource* rsb, USHORT flags)
{
/**************************************
*
* E X E _ c r a c k
*
**************************************
*
* Functional description
* Check whether stream is on a crack, BOF
* or EOF, according to the flags passed.
*
**************************************/
DEV_BLKCHK(rsb, type_rsb);
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
/* correct boolean rsbs to point to the "real" rsb */
if (rsb->rsb_type == rsb_boolean)
rsb = rsb->rsb_next;
irsb* impure = (IRSB) ((UCHAR *) request + rsb->rsb_impure);
/* if any of the passed flags are set, return true */
return (impure->irsb_flags & flags);
}
#endif
jrd_req* EXE_find_request(thread_db* tdbb, jrd_req* request, bool validate)
{
/**************************************
@ -602,42 +541,6 @@ jrd_req* EXE_find_request(thread_db* tdbb, jrd_req* request, bool validate)
}
#ifdef PC_ENGINE
void EXE_mark_crack(thread_db* tdbb, RecordSource* rsb, USHORT flag)
{
/**************************************
*
* E X E _ m a r k _ c r a c k
*
**************************************
*
* Functional description
* Mark a stream as being at a crack,
* plus report the fact in the status
* vector.
*
**************************************/
SET_TDBB(tdbb);
DEV_BLKCHK(rsb, type_rsb);
/* correct boolean rsbs to point to the "real" rsb */
if (rsb->rsb_type == rsb_boolean)
rsb = rsb->rsb_next;
RSE_MARK_CRACK(tdbb, rsb, flag);
if (flag == irsb_eof)
ERR_warning(isc_stream_eof, 0);
else if (flag == irsb_bof)
ERR_warning(isc_stream_bof, 0);
else if (flag & irsb_crack)
ERR_warning(isc_stream_crack, 0);
}
#endif
void EXE_receive(thread_db* tdbb,
jrd_req* request,
USHORT msg,
@ -1203,16 +1106,6 @@ static jrd_nod* erase(thread_db* tdbb, jrd_nod* node, SSHORT which_trig)
ERR_post(isc_no_cur_rec, 0);
}
#ifdef PC_ENGINE
/* for navigational streams, retrieve the rsb */
RecordSource* rsb = NULL;
irsb* impure = NULL;
if (node->nod_arg[e_erase_rsb]) {
rsb = *(RecordSource**) node->nod_arg[e_erase_rsb];
impure = (IRSB) ((UCHAR *) request + rsb->rsb_impure);
}
#endif
switch (request->req_operation) {
case jrd_req::req_evaluate:
{
@ -1234,17 +1127,6 @@ static jrd_nod* erase(thread_db* tdbb, jrd_nod* node, SSHORT which_trig)
return node->nod_parent;
}
#ifdef PC_ENGINE
/* if we are on a crack in a navigational stream, erase
is not a valid operation */
if (rsb && EXE_crack(tdbb, rsb, irsb_bof | irsb_eof | irsb_crack)) {
EXE_mark_crack(tdbb, rsb, impure->irsb_flags);
request->req_operation = jrd_req::req_return;
return node->nod_parent;
}
#endif
request->req_operation = jrd_req::req_return;
RLCK_reserve_relation(tdbb, transaction, relation, true, true);
@ -1257,30 +1139,6 @@ static jrd_nod* erase(thread_db* tdbb, jrd_nod* node, SSHORT which_trig)
rpb->rpb_stream_flags &= ~RPB_s_refetch;
}
#ifdef PC_ENGINE
/* set up to do record locking; in case of a consistency
mode transaction, we already have an exclusive lock on
the table, so don't bother */
LCK_RAII_wrapper implicit_lock;
if (!(transaction->tra_flags & TRA_degree3))
{
/* check whether record locking is turned on */
Lock* record_locking = RLCK_record_locking(relation);
if (record_locking->lck_physical != LCK_PR)
{
/* get an implicit lock on the record */
implicit_lock.assign(implicit_record_lock(transaction, rpb));
/* set up to catch any errors so that we can
release the implicit lock */
}
}
#endif
if (transaction != dbb->dbb_sys_trans)
++transaction->tra_save_point->sav_verb_count;
@ -1347,15 +1205,6 @@ static jrd_nod* erase(thread_db* tdbb, jrd_nod* node, SSHORT which_trig)
--transaction->tra_save_point->sav_verb_count;
}
#ifdef PC_ENGINE
/* if the stream is navigational, it is now positioned on a crack */
if (rsb) {
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
}
#endif
return node->nod_parent;
}
@ -1657,172 +1506,6 @@ static jrd_req* execute_triggers(thread_db* tdbb,
}
#ifdef PC_ENGINE
static jrd_nod* find(thread_db* tdbb, jrd_nod* node)
{
/**************************************
*
* f i n d
*
**************************************
*
* Functional description
* Find the given key value in a stream.
* Assume that the stream is open.
*
**************************************/
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
BLKCHK(node, type_nod);
if (request->req_operation == jrd_req::req_evaluate)
{
RecordSource* rsb = *((RecordSource**) node->nod_arg[e_find_rsb]);
const dsc* desc = EVL_expr(tdbb, node->nod_arg[e_find_operator]);
const USHORT blr_operator = (desc && !(request->req_flags & req_null)) ?
(USHORT) MOV_get_long(desc, 0) : MAX_USHORT;
if (blr_operator != blr_equiv &&
blr_operator != blr_eql &&
blr_operator != blr_leq &&
blr_operator != blr_lss &&
blr_operator != blr_geq &&
blr_operator != blr_gtr)
{
ERR_post(isc_invalid_operator, 0);
}
desc = EVL_expr(tdbb, node->nod_arg[e_find_direction]);
const USHORT direction = (desc && !(request->req_flags & req_null)) ?
(USHORT) MOV_get_long(desc, 0) : MAX_USHORT;
if (direction != blr_backward &&
direction != blr_forward &&
direction != blr_backward_starting &&
direction != blr_forward_starting)
{
ERR_post(isc_invalid_direction, 0);
}
/* 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
the forced crack (bug #7024) */
if (!RSE_find_record(tdbb, rsb, blr_operator, direction,
node->nod_arg[e_find_args]))
{
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);
}
else if (EXE_crack(tdbb, rsb, irsb_bof)) {
EXE_mark_crack(tdbb, rsb, irsb_bof);
}
else if (EXE_crack(tdbb, rsb, irsb_eof)) {
EXE_mark_crack(tdbb, rsb, irsb_eof);
}
else {
EXE_mark_crack(tdbb, rsb, irsb_crack);
}
}
}
request->req_operation = jrd_req::req_return;
}
return node->nod_parent;
}
#endif
#ifdef PC_ENGINE
static jrd_nod* find_dbkey(thread_db* tdbb, jrd_nod* node)
{
/**************************************
*
* f i n d _ d b k e y
*
**************************************
*
* Functional description
* Find the given dbkey in a navigational stream,
* resetting the position of the stream to that record.
*
**************************************/
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
BLKCHK(node, type_nod);
if (request->req_operation == jrd_req::req_evaluate)
{
RecordSource* rsb = *((RecordSource**) node->nod_arg[e_find_dbkey_rsb]);
if (!RSE_find_dbkey(tdbb,
rsb,
node->nod_arg[e_find_dbkey_dbkey],
node->nod_arg[e_find_dbkey_version]))
{
EXE_mark_crack(tdbb, rsb, irsb_crack);
}
request->req_operation = jrd_req::req_return;
}
return node->nod_parent;
}
#endif
#ifdef PC_ENGINE
static Lock* implicit_record_lock(jrd_tra* transaction, record_param* rpb)
{
/**************************************
*
* i m p l i c i t _ r e c o r d _ l o c k
*
**************************************
*
* Functional description
* An update to a record is being attempted and
* record locking has been initiated. Take out
* an implicit record lock to prevent updating
* a record that someone has explicitly locked.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
DEV_BLKCHK(transaction, type_tra);
jrd_rel* relation = rpb->rpb_relation;
Lock* record_locking = relation->rel_record_locking;
/* occasionally we should check whether we really still need to
do record locking; this is defined as RECORD_LOCK_CHECK_INTERVAL--
if we can get a PR on the record locking lock there is no need
to do implicit locking anymore */
if ((record_locking->lck_physical == LCK_none) &&
!(relation->rel_lock_total % RECORD_LOCK_CHECK_INTERVAL) &&
LCK_lock_non_blocking(tdbb, record_locking, LCK_PR, LCK_NO_WAIT))
{
return NULL;
}
Lock* lock = RLCK_lock_record_implicit(transaction, rpb, LCK_SW, 0, 0);
if (!lock) {
ERR_post(isc_record_lock, 0);
}
return lock;
}
#endif
static void stuff_stack_trace(const jrd_req* request)
{
Firebird::string sTrace;
@ -2717,107 +2400,6 @@ static jrd_nod* looper(thread_db* tdbb, jrd_req* request, jrd_nod* in_node)
break;
#endif
#ifdef PC_ENGINE
case nod_stream:
node = stream(tdbb, node);
break;
case nod_find:
node = find(tdbb, node);
break;
case nod_find_dbkey:
case nod_find_dbkey_version:
node = find_dbkey(tdbb, node);
break;
case nod_set_index:
node = set_index(tdbb, node);
break;
case nod_set_bookmark:
node = set_bookmark(tdbb, node);
break;
case nod_release_bookmark:
node = release_bookmark(tdbb, node);
break;
case nod_end_range:
node = RNG_end(node);
break;
case nod_delete_range:
node = RNG_delete(node);
break;
case nod_delete_ranges:
if (request->req_operation == jrd_req::req_evaluate) {
RNG_delete_ranges(request);
request->req_operation = jrd_req::req_return;
}
node = node->nod_parent;
break;
case nod_range_relation:
node = RNG_add_relation(node);
break;
case nod_release_lock:
if (request->req_operation == jrd_req::req_evaluate) {
DSC *desc;
desc = EVL_expr(tdbb, node->nod_arg[e_rellock_lock]);
#if SIZEOF_VOID_P != 8
RLCK_release_lock(*(Lock**) desc->dsc_address);
#else
{
Attachment* attachment = tdbb->tdbb_attachment;
Lock* lock = NULL;
const ULONG slot = *(ULONG *) desc->dsc_address;
vec<Lock*>* vector = attachment->att_lck_quick_ref;
if (vector && slot < vector->count()) {
lock = (*vector)[slot];
}
RLCK_release_lock(lock);
(*vector)[slot] = NULL;
}
#endif
request->req_operation = jrd_req::req_return;
}
node = node->nod_parent;
break;
case nod_release_locks:
if (request->req_operation == jrd_req::req_evaluate) {
RLCK_release_locks(request->req_attachment);
request->req_operation = jrd_req::req_return;
}
node = node->nod_parent;
break;
case nod_force_crack:
if (request->req_operation == jrd_req::req_evaluate) {
RSE_MARK_CRACK(tdbb, *(RecordSource**) node->nod_arg[1],
irsb_crack | irsb_forced_crack);
request->req_operation = jrd_req::req_return;
}
node = node->nod_parent;
break;
case nod_reset_stream:
if (request->req_operation == jrd_req::req_evaluate) {
RSE_reset_position(tdbb,
*(RecordSource**) node->nod_arg[e_reset_from_rsb],
request->req_rpb +
(USHORT)(ULONG) node->nod_arg[e_reset_to_stream]);
request->req_operation = jrd_req::req_return;
}
node = node->nod_parent;
break;
#endif
case nod_set_generator:
if (request->req_operation == jrd_req::req_evaluate) {
dsc* desc = EVL_expr(tdbb, node->nod_arg[e_gen_value]);
@ -2981,25 +2563,6 @@ static jrd_nod* modify(thread_db* tdbb, jrd_nod* node, SSHORT which_trig)
const SSHORT new_stream = (USHORT)(IPTR) node->nod_arg[e_mod_new_stream];
record_param* new_rpb = &request->req_rpb[new_stream];
#ifdef PC_ENGINE
/* for navigational streams, retrieve the rsb */
RecordSource* rsb = NULL;
IRSB irsb;
if (node->nod_arg[e_mod_rsb]) {
rsb = *(RecordSource**) node->nod_arg[e_mod_rsb];
irsb = (IRSB) ((UCHAR *) request + rsb->rsb_impure);
}
/* if we are on a crack in a navigational stream, modify is an illegal operation */
if (rsb && EXE_crack(tdbb, rsb, irsb_bof | irsb_eof | irsb_crack)) {
EXE_mark_crack(tdbb, rsb, irsb->irsb_flags);
request->req_operation = jrd_req::req_return;
return node->nod_parent;
}
#endif
/* If the stream was sorted, the various fields in the rpb are
probably junk. Just to make sure that everything is cool,
refetch and release the record. */
@ -3029,24 +2592,6 @@ static jrd_nod* modify(thread_db* tdbb, jrd_nod* node, SSHORT which_trig)
varchar field whose tail may contain garbage. */
cleanup_rpb(tdbb, new_rpb);
#ifdef PC_ENGINE
/* check to see if record locking has been initiated in this database;
if so then lock the record for shared write so that normal processing
will be able to read or write the record but not when an explicit
lock has been taken out */
LCK_RAII_wrapper implicit_lock;
if (!(transaction->tra_flags & TRA_degree3))
{
const Lock* record_locking = RLCK_record_locking(relation);
if (record_locking->lck_physical != LCK_PR)
{
implicit_lock.assign(implicit_record_lock(transaction, org_rpb));
}
}
#endif
if (transaction != dbb->dbb_sys_trans)
++transaction->tra_save_point->sav_verb_count;
@ -3113,17 +2658,6 @@ static jrd_nod* modify(thread_db* tdbb, jrd_nod* node, SSHORT which_trig)
--transaction->tra_save_point->sav_verb_count;
}
#ifdef PC_ENGINE
/* if the stream is navigational, we must position the stream on the new
record version, but first set the record number */
new_rpb->rpb_number = org_rpb->rpb_number;
if (rsb) {
RSE_reset_position(tdbb, rsb, new_rpb);
}
#endif
/* CVC: Increment the counter only if we called VIO/EXT_modify() and
we were successful. */
if (!(request->req_view_flags & req_first_modify_return)) {
@ -3323,33 +2857,6 @@ static void release_blobs(thread_db* tdbb, jrd_req* request)
}
#ifdef PC_ENGINE
static jrd_nod* release_bookmark(thread_db* tdbb, jrd_nod* node)
{
/**************************************
*
* r e l e a s e _ b o o k m a r k
*
**************************************
*
* Functional description
* Deallocate the passed bookmark.
*
**************************************/
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
BLKCHK(node, type_nod);
if (request->req_operation == jrd_req::req_evaluate) {
BKM_release(node->nod_arg[e_relmark_id]);
request->req_operation = jrd_req::req_return;
}
return node->nod_parent;
}
#endif
static void release_proc_save_points(jrd_req* request)
{
/**************************************
@ -3510,12 +3017,7 @@ static void seek_rsb(
switch (direction) {
case blr_forward: /* go forward from the current location */
#ifdef PC_ENGINE
if ((offset == 1) && request->req_begin_ranges)
impure->irsb_flags |= irsb_refresh;
#endif
/* the rsb_backwards flag is used to indicate the direction to seek in;
/* the rsb_backwards flag is used to indicate the direction to seek in;
this is sticky in the sense that after the user has seek'ed in the
backward direction, the next retrieval from a blr_for loop will also
be in the backward direction--this allows us to continue scrolling
@ -3532,11 +3034,6 @@ static void seek_rsb(
case blr_backward: /* go backward from the current location */
#ifdef PC_ENGINE
if ((offset == 1) && request->req_begin_ranges)
impure->irsb_flags |= irsb_refresh;
#endif
impure->irsb_flags |= irsb_last_backwards;
while (offset) {
@ -3587,10 +3084,6 @@ static void seek_rsb(
// check above, but anyway...
BUGCHECK(232);
}
#ifdef PC_ENGINE
impure->irsb_flags &= ~irsb_refresh;
#endif
}
#endif
@ -3668,59 +3161,6 @@ static jrd_nod* send_msg(thread_db* tdbb, jrd_nod* node)
}
#ifdef PC_ENGINE
static jrd_nod* set_bookmark(thread_db* tdbb, jrd_nod* node)
{
/**************************************
*
* s e t _ b o o k m a r k
*
**************************************
*
* Functional description
* Set a stream to the location of the
* specified bookmark.
*
**************************************/
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
BLKCHK(node, type_nod);
if (request->req_operation == jrd_req::req_evaluate) {
Bookmark* bookmark = BKM_lookup(node->nod_arg[e_setmark_id]);
const USHORT stream = (USHORT)(ULONG) node->nod_arg[e_setmark_stream];
record_param* rpb = &request->req_rpb[stream];
RecordSource* rsb = *((RecordSource**) node->nod_arg[e_setmark_rsb]);
irsb* impure = (IRSB) ((UCHAR *) request + rsb->rsb_impure);
/* check if the bookmark was at beginning or end of file
and flag the rsb accordingly */
RSE_MARK_CRACK(tdbb, rsb, 0);
if (bookmark->bkm_flags & bkm_bof)
RSE_MARK_CRACK(tdbb, rsb, irsb_bof);
else if (bookmark->bkm_flags & bkm_eof)
RSE_MARK_CRACK(tdbb, rsb, irsb_eof);
else if (bookmark->bkm_flags & bkm_crack) {
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
if (bookmark->bkm_flags & bkm_forced_crack)
RSE_MARK_CRACK(tdbb, rsb, irsb_forced_crack);
}
if (!RSE_set_bookmark(tdbb, rsb, rpb, bookmark)) {
EXE_mark_crack(tdbb, rsb,
impure->irsb_flags & (irsb_crack | irsb_eof |
irsb_bof));
}
request->req_operation = jrd_req::req_return;
}
return node->nod_parent;
}
#endif
static void set_error(thread_db* tdbb, const xcp_repeat* exception, jrd_nod* msg_node)
{
/**************************************
@ -3837,58 +3277,6 @@ static void set_error(thread_db* tdbb, const xcp_repeat* exception, jrd_nod* msg
}
#ifdef PC_ENGINE
static jrd_nod* set_index(thread_db* tdbb, jrd_nod* node)
{
/**************************************
*
* s e t _ i n d e x
*
**************************************
*
* Functional description
* Execute a SET INDEX statement.
*
**************************************/
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
BLKCHK(node, type_nod);
if (request->req_operation == jrd_req::req_evaluate) {
const USHORT stream = (USHORT)(ULONG) node->nod_arg[e_index_stream];
record_param* rpb = &request->req_rpb[stream];
jrd_rel* relation = rpb->rpb_relation;
/* if id is non-zero, get the index definition;
otherwise it indicates revert to natural order */
const dsc* desc = EVL_expr(tdbb, node->nod_arg[e_index_index]);
const USHORT id = (desc && !(request->req_flags & req_null)) ?
MOV_get_long(desc, 0) : 0;
index_desc idx;
if (id && BTR_lookup(tdbb, relation, id - 1, &idx))
{
ERR_post(isc_indexnotdefined, isc_arg_string, relation->rel_name,
isc_arg_number, (SLONG) id, 0);
}
/* generate a new rsb in place of the old */
RSE_close(tdbb, *(RecordSource**) node->nod_arg[e_index_rsb]);
OPT_set_index(tdbb, request, (RecordSource**) node->nod_arg[e_index_rsb],
relation, id ? &idx : NULL);
RSE_open(tdbb, *(RecordSource**) node->nod_arg[e_index_rsb]);
request->req_operation = jrd_req::req_return;
}
return node->nod_parent;
}
#endif
static jrd_nod* stall(thread_db* tdbb, jrd_nod* node)
{
/**************************************
@ -4092,45 +3480,7 @@ static jrd_nod* store(thread_db* tdbb, jrd_nod* node, SSHORT which_trig)
}
#ifdef PC_ENGINE
static jrd_nod* stream(thread_db* tdbb, jrd_nod* node)
{
/**************************************
*
* s t r e a m
*
**************************************
*
* Functional description
* Execute a STREAM statement.
*
**************************************/
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
BLKCHK(node, type_nod);
RecordSource* rsb = ((RecordSelExpr*) node)->rse_rsb;
switch (request->req_operation) {
case jrd_req::req_evaluate:
RSE_open(tdbb, rsb);
request->req_operation = jrd_req::req_return;
case jrd_req::req_return:
node = node->nod_parent;
break;
default:
RSE_close(tdbb, rsb);
node = node->nod_parent;
}
return node;
}
#endif
static bool test_and_fixup_error(thread_db* tdbb, const PsqlException* conditions,
static bool test_and_fixup_error(thread_db* tdbb, const PsqlException* conditions,
jrd_req* request)
{
/**************************************

View File

@ -40,11 +40,5 @@ void EXE_unwind(Jrd::thread_db*, Jrd::jrd_req*);
void EXE_seek(Jrd::thread_db*, Jrd::jrd_req*, USHORT, ULONG);
#endif
#ifdef PC_ENGINE
bool EXE_crack(Jrd::thread_db*, Jrd::RecordSource*, USHORT);
void EXE_mark_crack(Jrd::thread_db*, Jrd::RecordSource*, USHORT);
#endif
#endif // JRD_EXE_PROTO_H

View File

@ -2222,9 +2222,6 @@ ISC_STATUS GDS_DDL(ISC_STATUS* user_status,
* a rollback_retain (). This will backout the
* effects of the transaction, mark it dead and
* start a new transaction.
* For now only ExpressLink will use this feature. Later
* a new entry point may be added.
*/
if (transaction->tra_flags & TRA_perform_autocommit)
@ -5726,32 +5723,6 @@ static void release_attachment(Attachment* attachment)
attachment->att_val_errors = NULL;
}
#ifdef PC_ENGINE
// Release the persistent locks taken out during the attachment
vec<Lock*>* lock_vector = attachment->att_relation_locks;
if (lock_vector)
{
size_t i = 0;
for (vec<Lock*>::iterator lock = lock_vector->begin();
i < lock_vector->count(); i++, lock++)
{
if (*lock)
{
LCK_release(tdbb, *lock);
delete *lock;
}
}
delete lock_vector;
}
Lock* record_lock;
for (record_lock = attachment->att_record_locks; record_lock;
record_lock = record_lock->lck_att_next)
{
LCK_release(tdbb, record_lock);
}
#endif
/* bug #7781, need to null out the attachment pointer of all locks which
were hung off this attachment block, to ensure that the attachment
block doesn't get dereferenced after it is released */
@ -6564,22 +6535,6 @@ static void purge_attachment(thread_db* tdbb,
delete user;
}
#ifdef PC_ENGINE
Bookmark* bookmark;
while ( (bookmark = attachment->att_bookmarks) ) {
attachment->att_bookmarks = bookmark->bkm_next;
delete bookmark;
}
if (attachment->att_bkm_quick_ref) {
delete attachment->att_bkm_quick_ref;
}
if (attachment->att_lck_quick_ref) {
delete attachment->att_lck_quick_ref;
}
#endif
delete attachment;
}
else

View File

@ -462,13 +462,6 @@ public:
att_event_session(0),
att_security_class(0),
att_security_classes(0),
#ifdef PC_ENGINE
att_relation_locks(0),
att_bookmarks(0),
att_record_locks(0),
att_bkm_quick_ref(0),
att_lck_quick_ref(0),
#endif
att_flags(0),
att_charset(0),
att_lc_messages(0),
@ -495,13 +488,6 @@ public:
SecurityClass* att_security_class; // security class for database
SecurityClass* att_security_classes; // security classes
vcl* att_counts[DBB_max_count];
#ifdef PC_ENGINE
vec<Lock*>* att_relation_locks; // explicit persistent locks for relations
Bookmark* att_bookmarks; // list of bookmarks taken out using this attachment
Lock* att_record_locks; // explicit or implicit record locks taken out during attachment
vec<Bookmark*>* att_bkm_quick_ref; // correspondence table of bookmarks
vec<Lock*>* att_lck_quick_ref; // correspondence table of locks
#endif
ULONG att_flags; // Flags describing the state of the attachment
SSHORT att_charset; // user's charset specified in dpb
Firebird::PathName att_lc_messages; // attachment's preference for message natural language
@ -751,15 +737,6 @@ public:
SSHORT rel_scan_count; /* concurrent sequential scan count */
Lock* rel_existence_lock; /* existence lock, if any */
#ifdef PC_ENGINE
Lock* rel_interest_lock; /* interest lock to ensure compatibility of relation and record locks */
Lock* rel_record_locking; /* lock to start record locking on relation */
ULONG rel_explicit_locks; /* count of records explicitly locked in relation */
ULONG rel_read_locks; /* count of records read locked in relation (implicit or explicit) */
ULONG rel_write_locks; /* count of records write locked in relation (implicit or explicit) */
ULONG rel_lock_total; /* count of records locked since database first attached */
#endif
Lock* rel_partners_lock; /* partners lock */
IndexLock* rel_index_locks; /* index existence locks */
IndexBlock* rel_index_blocks; /* index blocks for caching index info */

View File

@ -61,10 +61,6 @@ static int compare_keys(const index_desc*, const UCHAR*, USHORT,
#ifdef SCROLLABLE_CURSORS
static void expand_index(WIN *);
#endif
#ifdef PC_ENGINE
static bool find_dbkey(RecordSource*, ULONG);
static bool find_record(RecordSource*, RSE_GET_MODE, temporary_key*, USHORT, USHORT);
#endif
static btree_exp* find_current(exp_index_buf*, Ods::btree_page*, const UCHAR*);
static bool find_saved_node(RecordSource*, IRSB_NAV, WIN *, UCHAR **);
static UCHAR* get_position(thread_db*, RecordSource*, IRSB_NAV, WIN *, RSE_GET_MODE, btree_exp**);
@ -150,318 +146,6 @@ exp_index_buf* NAV_expand_index(WIN * window, IRSB_NAV impure)
#endif
#ifdef PC_ENGINE
bool NAV_find_record(RecordSource* rsb,
USHORT blr_operator, USHORT direction, jrd_nod* find_key)
{
/**************************************
*
* N A V _ f i n d _ r e c o r d
*
**************************************
*
* Functional description
* Find a record with the specified key value
* in a stream opened on a navigational index.
* This routine must set BOF, EOF, or CRACK.
*
**************************************/
const bool backwards = (direction == blr_backward
|| direction == blr_backward_starting);
USHORT search_flags;
if (direction == blr_forward_starting || direction == blr_backward_starting)
search_flags = irb_starting;
else
search_flags = 0;
thread_db* tdbb = JRD_get_thread_data();
jrd_req* request = tdbb->tdbb_request;
irsb_nav* impure = (IRSB_NAV) ((UCHAR *) request + rsb->rsb_impure);
WIN window(-1);
btree_nod* expanded_node;
init_fetch(impure);
if (!impure->irsb_nav_page) {
nav_open(tdbb, rsb, impure, &window, RSE_get_forward, &expanded_node);
CCH_RELEASE(tdbb, &window);
}
// finding a record invalidates the visited records
SBM_reset(&impure->irsb_nav_records_visited);
index_desc* idx =
(index_desc*) ((SCHAR *) impure + (SLONG) rsb->rsb_arg[RSB_NAV_idx_offset]);
if ((idx == NULL) || (find_key->nod_count == 0) ||
(find_key->nod_count > idx->idx_count))
{
ERR_post(gds__invalid_key, 0);
}
if (find_key->nod_count < idx->idx_count)
search_flags |= irb_partial;
temporary_key key_value;
BTR_make_key(tdbb, find_key->nod_count, &find_key->nod_arg[0], idx,
&key_value, (search_flags & irb_starting) != 0);
// save the key value
impure->irsb_nav_length = key_value.key_length;
MOVE_FAST(key_value.key_data, impure->irsb_nav_data,
key_value.key_length);
// for descending indices, reverse the sense of the comparison operator
// to simplify the following switch statement
if (idx->idx_flags & idx_descending) {
switch (blr_operator)
{
case blr_lss:
blr_operator = blr_gtr;
break;
case blr_leq:
blr_operator = blr_geq;
break;
case blr_gtr:
blr_operator = blr_lss;
break;
case blr_geq:
blr_operator = blr_leq;
break;
default: // silence compiler
break;
}
}
// find the proper record by comparing the passed key with the records in
// the record stream, optimizing the fetch as best as possible by using the
// index to get as close to the proper record as possible
switch (blr_operator) {
case blr_lss:
if (backwards)
// find the first record before the given key value
{
find_record(rsb, RSE_get_first, &key_value, find_key->nod_count,
search_flags);
return NAV_get_record(rsb, impure,
request->req_rpb + rsb->rsb_stream,
RSE_get_backward);
}
else
// find the first record in the stream, assuming its key value is < the passed key
{
nav_open(tdbb, rsb, impure, &window, RSE_get_forward,
&expanded_node);
CCH_RELEASE(tdbb, &window);
if (!NAV_get_record
(rsb, impure, request->req_rpb + rsb->rsb_stream,
RSE_get_forward))
{
return false;
}
if (compare_keys
(idx, impure->irsb_nav_data, impure->irsb_nav_length,
&key_value, search_flags) < 0)
{
return true;
}
else {
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
return false;
}
}
// break; unreachable
case blr_leq:
if (backwards)
// find the last record with the matching key; barring that, find the first less than
{
if (find_record
(rsb, RSE_get_last, &key_value, find_key->nod_count,
search_flags))
{
return true;
}
return NAV_get_record(rsb, impure,
request->req_rpb + rsb->rsb_stream,
RSE_get_backward);
}
else
// find the first record in the stream, assuming its key value is <= the passed key
{
nav_open(tdbb, rsb, impure, &window, RSE_get_forward,
&expanded_node);
CCH_RELEASE(tdbb, &window);
if (!NAV_get_record
(rsb, impure, request->req_rpb + rsb->rsb_stream,
RSE_get_forward))
{
return false;
}
if (compare_keys
(idx, impure->irsb_nav_data, impure->irsb_nav_length,
&key_value, search_flags) <= 0)
{
return true;
}
else {
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
return false;
}
}
// break; unreachable
case blr_equiv:
case blr_eql:
if (find_record(rsb, backwards ? RSE_get_last : RSE_get_first,
&key_value, find_key->nod_count, search_flags))
{
return true;
}
else {
// We need to override the crack semantics of find_record, because even
// if we go to EOF or BOF as a result of the find, this is defined as a
// crack. On the other hand, we do need to retain a forced crack if
// one was set. bug #7024
if (impure->irsb_flags & irsb_forced_crack)
RSE_MARK_CRACK(tdbb, rsb, irsb_crack | irsb_forced_crack);
else
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
return false;
}
// break; unreachable
case blr_gtr:
if (backwards)
// find the last record in the stream, assuming its key value is > the passed key
{
nav_open(tdbb, rsb, impure, &window, RSE_get_backward,
&expanded_node);
CCH_RELEASE(tdbb, &window);
if (!NAV_get_record
(rsb, impure, request->req_rpb + rsb->rsb_stream,
RSE_get_backward))
{
return false;
}
if (compare_keys
(idx, impure->irsb_nav_data, impure->irsb_nav_length,
&key_value, search_flags) > 0)
{
return true;
}
else {
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
return false;
}
}
else
// find the first record after the last matching record
{
find_record(rsb, RSE_get_last, &key_value, find_key->nod_count,
search_flags);
// special case when the key is greater than the last record in the file;
// stream is defined to be on EOF; see bug #6151
if (impure->irsb_flags & irsb_eof)
return false;
return NAV_get_record(rsb, impure,
request->req_rpb + rsb->rsb_stream,
RSE_get_forward);
}
// break; unreachable
case blr_geq:
if (backwards)
// find the last record in the stream, assuming its key value is >= the passed key
{
nav_open(tdbb, rsb, impure, &window, RSE_get_backward,
&expanded_node);
CCH_RELEASE(tdbb, &window);
if (!NAV_get_record
(rsb, impure, request->req_rpb + rsb->rsb_stream,
RSE_get_backward))
{
return false;
}
if (compare_keys
(idx, impure->irsb_nav_data, impure->irsb_nav_length,
&key_value, search_flags) >= 0)
{
return true;
}
else {
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
return false;
}
}
else
// find the first record of matching key; barring that, find the first greater
{
if (find_record
(rsb, RSE_get_first, &key_value, find_key->nod_count,
search_flags))
{
return true;
}
// special case when the key is greater than the last record in the file;
// stream is defined to be on EOF; see bug #6151
if (impure->irsb_flags & irsb_eof)
return false;
return NAV_get_record(rsb, impure,
request->req_rpb + rsb->rsb_stream,
RSE_get_forward);
}
// break; unreachable
}
}
#endif
#ifdef PC_ENGINE
void NAV_get_bookmark(RecordSource* rsb, IRSB_NAV impure, Bookmark* bookmark)
{
/**************************************
*
* N A V _ g e t _ b o o k m a r k
*
**************************************
*
* Functional description
* Return a descriptor containing a pointer
* to a bookmark data structure which describes
* the current location of a navigational stream.
*
**************************************/
// store the info necessary to return to this location in the index
bookmark->bkm_number = impure->irsb_nav_number;
bookmark->bkm_page = impure->irsb_nav_page;
bookmark->bkm_incarnation = impure->irsb_nav_incarnation;
bookmark->bkm_offset = impure->irsb_nav_offset;
bookmark->bkm_expanded_offset = impure->irsb_nav_expanded_offset;
// store the current key value, setting up the key descriptor to point at it
bookmark->bkm_key_desc.dsc_dtype = dtype_text;
bookmark->bkm_key_desc.dsc_length = impure->irsb_nav_length;
bookmark->bkm_key_desc.dsc_address = bookmark->bkm_key_data;
MOVE_FAST(impure->irsb_nav_data, bookmark->bkm_key_data,
impure->irsb_nav_length);
}
#endif
bool NAV_get_record(thread_db* tdbb,
RecordSource* rsb,
IRSB_NAV impure, record_param* rpb, RSE_GET_MODE direction)
@ -611,10 +295,6 @@ bool NAV_get_record(thread_db* tdbb,
}
page = BTR_left_handoff(tdbb, &window, page, LCK_read);
#ifdef PC_ENGINE
RNG_add_page(window.win_page);
#endif
expanded_page = NAV_expand_index(&window, 0);
nextPointer = BTR_last_node(page, expanded_page, &expanded_next);
@ -637,9 +317,6 @@ bool NAV_get_record(thread_db* tdbb,
page = (Ods::btree_page*) window.win_buffer;
page = (Ods::btree_page*) CCH_HANDOFF(tdbb, &window, page->btr_sibling,
LCK_read, pag_index);
#ifdef PC_ENGINE
RNG_add_page(window.win_page);
#endif
nextPointer = BTreeNode::getPointerFirstNode(page);
exp_index_buf* expanded_page = window.win_expanded_buffer;
if (expanded_page) {
@ -769,31 +446,15 @@ bool NAV_get_record(thread_db* tdbb,
// reset the current navigational position in the index
rpb->rpb_number = number;
#ifdef PC_ENGINE
if (direction != RSE_get_current)
#endif
set_position(impure, rpb, &window, pointer, expanded_node,
key.key_data, key.key_length);
set_position(impure, rpb, &window, pointer, expanded_node,
key.key_data, key.key_length);
CCH_RELEASE(tdbb, &window);
if (get_record(rsb, impure, rpb, &key, false)) {
#ifdef PC_ENGINE
if (impure->irsb_flags & irsb_refresh)
RNG_add_record(rpb);
#endif
return true;
}
#ifdef PC_ENGINE
// if we're here, we didn't find the record at the current position,
// so it must have been deleted out from under us; by definition we
// are on a crack (already marked by get_record())
if (direction == RSE_get_current) {
return false;
}
#endif
nextPointer = get_position(tdbb, rsb, impure, &window, direction, &expanded_next);
}
@ -804,106 +465,6 @@ bool NAV_get_record(thread_db* tdbb,
}
#ifdef PC_ENGINE
bool NAV_reset_position(RecordSource* rsb, record_param* new_rpb)
{
/**************************************
*
* N A V _ r e s e t _ p o s i t i o n
*
**************************************
*
* Functional description
* Reset the stream represented by the passed
* rsb to the record indicated by the passed rpb.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
jrd_req* request = tdbb->tdbb_request;
irsb_nav* impure = (IRSB_NAV) ((UCHAR *) request + rsb->rsb_impure);
WIN window(-1);
btree_nod* expanded_node;
init_fetch(impure);
if (!impure->irsb_nav_page) {
nav_open(tdbb, rsb, impure, &window, RSE_get_current, &expanded_node);
CCH_RELEASE(tdbb, &window);
}
// resetting the stream invalidates the visited records
SBM_reset(&impure->irsb_nav_records_visited);
index_desc* idx = (index_desc*) ((SCHAR*) impure + (SLONG) rsb->rsb_arg[RSB_NAV_idx_offset]);
// save the record number, in case the passed new_rpb is
// the same as the one on the rpb, in which case it will
// be updated by find_record()--bug #7426
const RecordNumber record_number = new_rpb->rpb_number;
// find the key value of the new position, and set the stream to it
temporary_key key_value;
BTR_key(tdbb, new_rpb->rpb_relation, new_rpb->rpb_record, idx,
&key_value, 0);
if (!find_record(rsb, RSE_get_first, &key_value, idx->idx_count, 0)) // XXX
return false;
// now find the dbkey of the new record within the
// duplicates of this key value
return find_dbkey(rsb, record_number);
}
#endif
#ifdef PC_ENGINE
bool NAV_set_bookmark(RecordSource* rsb, IRSB_NAV impure, record_param* rpb, Bookmark* bookmark)
{
/**************************************
*
* N A V _ s e t _ b o o k m a r k
*
**************************************
*
* Functional description
* Set up the impure area so that the current
* position of the stream is that of the
* stored bookmark.
*
**************************************/
// setting to bookmark invalidates the visited records
SBM_reset(&impure->irsb_nav_records_visited);
// save the bookmark state in the impure area for the stream
impure->irsb_nav_number = bookmark->bkm_number;
impure->irsb_nav_incarnation = bookmark->bkm_incarnation;
impure->irsb_nav_offset = bookmark->bkm_offset;
impure->irsb_nav_expanded_offset = bookmark->bkm_expanded_offset;
// assuming we had already fetched a page when
// we set the bookmark, make sure the "first" flag
// is not set so that we don't reopen the stream--bug 5709
if (impure->irsb_nav_page = bookmark->bkm_page) {
impure->irsb_flags &= ~irsb_first;
}
// store the current key value, setting up the key descriptor to point at it
impure->irsb_nav_length = bookmark->bkm_key_desc.dsc_length;
MOVE_FAST(bookmark->bkm_key_data, impure->irsb_nav_data,
bookmark->bkm_key_desc.dsc_length);
if (impure->irsb_flags & (irsb_bof | irsb_eof | irsb_crack)) {
return false;
}
// if we didn't find the record, it must have been deleted
// from under us; the desired semantics is to be on a crack
// at the previous position of the record
return NAV_get_record(rsb, impure, rpb, RSE_get_current);
}
#endif
static int compare_keys(
const index_desc* idx,
const UCHAR* key_string1,
@ -1094,249 +655,6 @@ static void expand_index(WIN * window)
#endif
#ifdef PC_ENGINE
static bool find_dbkey(RecordSource* rsb, RecordNumber record_number)
{
/**************************************
*
* f i n d _ d b k e y
*
**************************************
*
* Functional description
* Look for the record with the passed dbkey in the
* set of records with key value equal to the current
* record's key. This is used to find a particular
* record within a set of equivalent keys.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
jrd_req* request = tdbb->tdbb_request;
irsb_nav* impure = (IRSB_NAV) ((UCHAR *) request + rsb->rsb_impure);
record_param* rpb = request->req_rpb + rsb->rsb_stream;
init_fetch(impure);
// if we're on a crack, this isn't going very far
if (impure->irsb_flags & (irsb_bof | irsb_eof | irsb_crack)) {
return false;
}
// find the last fetched position from the index,
// and get the current key value
btree_exp* expanded_node = NULL;
WIN window(impure->irsb_nav_page);
btree_nod* node =
get_position(tdbb, rsb, impure, &window, RSE_get_current,
&expanded_node);
temporary_key key;
MOVE_FAST(impure->irsb_nav_data, key.key_data, impure->irsb_nav_length);
key.key_length = impure->irsb_nav_length;
// In case of an error, we still need to release the window we hold
// during the parse. See HACKs for bug 7041
try {
// loop through the equivalent values of the given key, looking for a
// record which matches the passed dbkey
for (;;) {
rpb->rpb_number = get_long(node->btn_number);
// if we find an index entry with the proper dbkey, try to fetch the record
if (rpb->rpb_number == record_number) {
if (get_record(rsb, impure, rpb, &key, true)) {
set_position(impure, rpb, &window, node, expanded_node,
key.key_data, key.key_length);
CCH_RELEASE(tdbb, &window);
return true;
}
CCH_RELEASE(tdbb, &window);
return false;
}
// go to the next node; if we find a non-equivalent node, give up
node = BTR_next_node(node, &expanded_node);
if (node->btn_length) {
CCH_RELEASE(tdbb, &window);
return false;
}
}
} // try
catch (const std::exception&) {
CCH_RELEASE(tdbb, &window);
throw;
}
}
#endif
#ifdef PC_ENGINE
static bool find_record(
RecordSource* rsb,
RSE_GET_MODE mode,
temporary_key* find_key,
USHORT find_count, USHORT search_flags)
{
/**************************************
*
* f i n d _ r e c o r d
*
**************************************
*
* Functional description
* Find a record with the specified key value
* in a stream opened on a navigational index.
* Depending on the mode, get the first or
* last value with the given key. This routine
* must handle CRACK semantics.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
jrd_req* request = tdbb->tdbb_request;
irsb_nav* impure = (IRSB_NAV) ((UCHAR *) request + rsb->rsb_impure);
record_param* rpb = request->req_rpb + rsb->rsb_stream;
WIN window(-1);
jrd_nod* retrieval_node = (jrd_nod*) rsb->rsb_arg[RSB_NAV_index];
IndexRetrieval* retrieval =
(IndexRetrieval*) retrieval_node->nod_arg[e_idx_retrieval];
// save the current equality retrieval key
temporary_key* const tmp = retrieval->irb_key;
const USHORT lower_count = retrieval->irb_lower_count;
const USHORT upper_count = retrieval->irb_upper_count;
// find the page that the key value should be on
retrieval->irb_key = find_key;
retrieval->irb_upper_count = retrieval->irb_lower_count = find_count;
index_desc* idx =
(index_desc*) ((SCHAR *) impure + (SLONG) rsb->rsb_arg[RSB_NAV_idx_offset]);
temporary_key lower, upper;
btree_page* page =
BTR_find_page(tdbb, retrieval, &window, idx, &lower, &upper, false);
// restore the saved equality retrieval key
retrieval->irb_key = tmp;
retrieval->irb_lower_count = lower_count;
retrieval->irb_upper_count = upper_count;
// find the appropriate leaf node
btree_nod* node;
while (!(node = BTR_find_leaf(page, find_key, impure->irsb_nav_data,
0, (idx->idx_flags & idx_descending) != 0, true)))
{
page =
(btree_page*) CCH_HANDOFF(tdbb, &window, page->btr_sibling, LCK_read,
pag_index);
}
btree_exp* expanded_node;
exp_index_buf* expanded_page = window.win_expanded_buffer;
if (expanded_page) {
expanded_node = find_current(expanded_page, page, node);
}
else {
expanded_node = NULL;
}
// seed the key value with the prefix seen up to the current key
temporary_key value;
MOVE_FAST(impure->irsb_nav_data, value.key_data, node->btn_prefix);
// In case of an error, we still need to release the window we hold
// during the parse. See HACKs for bug 7041
try {
bool result = false;
bool position_set = false;
// loop through the equivalent values of the given key, finding
// a valid record if possible; for RSE_get_last, save the last
// valid record and keep looking for more
// NOTE: this whole process could be made more efficient if we
// implemented a means of finding the last index key via
// BTR_find_page() and BTR_find_leaf(), then proceeding backwards
// to find a valid record -deej
for (;;)
{
rpb->rpb_number = get_long(node->btn_number);
// if we have gone past the search key value, stop looking
if (rpb->rpb_number == END_LEVEL) {
CCH_RELEASE(tdbb, &window);
RSE_MARK_CRACK(tdbb, rsb, irsb_eof);
return false;
}
if (rpb->rpb_number == END_BUCKET) {
page =
(btree_page*) CCH_HANDOFF(tdbb, &window, page->btr_sibling, LCK_read,
pag_index);
node = (btree_nod*) page->btr_nodes;
if (expanded_page = window.win_expanded_buffer)
expanded_node = (btree_exp*) expanded_page->exp_nodes;
continue;
}
// update the current stored key value
value.key_length = node->btn_length + node->btn_prefix;
UCHAR* p = value.key_data + node->btn_prefix;
const UCHAR* q = node->btn_data;
for (USHORT l = node->btn_length; l--;)
*p++ = *q++;
// if the index key is greater than the search key, we didn't find the key
if (compare_keys
(idx, value.key_data, value.key_length, find_key,
search_flags) > 0)
{
// if we never saw a valid record, mark as a forced crack so that
// we will be at a position before the current record
if (!position_set) {
set_position(impure, rpb, &window, node, expanded_node,
value.key_data, value.key_length);
RSE_MARK_CRACK(tdbb, rsb, irsb_crack | irsb_forced_crack);
}
CCH_RELEASE(tdbb, &window);
return result;
}
// anytime we successfully retrieve a record, set position
// to it in case we go past a viable record in looking for
// the last record of equivalent key
if (result = get_record(rsb, impure, rpb, &value, true)) {
set_position(impure, rpb, &window, node, expanded_node,
value.key_data, value.key_length);
position_set = true;
}
// if we're looking for the first record, we're done
if (result && mode == RSE_get_first) {
CCH_RELEASE(tdbb, &window);
return result;
}
node = BTR_next_node(node, &expanded_node);
}
} // try
catch (const std::exception&) {
CCH_RELEASE(tdbb, &window);
throw;
}
}
#endif
static btree_exp* find_current(exp_index_buf* expanded_page, Ods::btree_page* page,
const UCHAR* current_pointer)
{
@ -1495,17 +813,6 @@ static UCHAR* get_position(
exp_index_buf* expanded_page = NULL;
#ifdef PC_ENGINE
// if we are on a forced crack, don't really get the next node in
// the forward direction, since we are really supposed to be on a
// position before the current node
if ((impure->irsb_flags & irsb_forced_crack)
&& (direction == RSE_get_forward))
{
direction = RSE_get_current;
}
#endif
// Re-fetch page and get incarnation counter
Ods::btree_page* page = (Ods::btree_page*) CCH_FETCH(tdbb, window, LCK_read, pag_index);

View File

@ -42,13 +42,5 @@ exp_index_buf* NAV_expand_index(Jrd::win*, Jrd::irsb_nav*);
bool NAV_get_record(Jrd::thread_db* tdbb, Jrd::RecordSource*, Jrd::irsb_nav*,
Jrd::record_param*, Jrd::rse_get_mode);
#ifdef PC_ENGINE
bool NAV_find_record(Jrd::RecordSource*, USHORT, USHORT, Jrd::jrd_nod*);
void NAV_get_bookmark(Jrd::RecordSource*, Jrd::irsb_nav*, Bookmark*);
bool NAV_reset_position(Jrd::RecordSource*, Jrd::record_param*);
bool NAV_set_bookmark(Jrd::RecordSource*, Jrd::irsb_nav*, Jrd::record_param*,
Jrd::Bookmark*);
#endif
#endif // JRD_NAV_PROTO_H

View File

@ -1264,161 +1264,6 @@ int OPT_match_index(OptimizerBlk* opt, USHORT stream, index_desc* idx)
}
#ifdef PC_ENGINE
void OPT_set_index(thread_db* tdbb,
jrd_req* request, RecordSource** rsb_ptr, jrd_rel* relation, index_desc* idx)
{
/**************************************
*
* O P T _ s e t _ i n d e x
*
**************************************
*
* Functional description
* Reset the navigational order of a stream.
* Given a sequential or navigational rsb,
* reset the rsb to be a navigational rsb
* on the specified index.
*
**************************************/
DEV_BLKCHK(request, type_req);
DEV_BLKCHK(*rsb_ptr, type_rsb);
DEV_BLKCHK(relation, type_rel);
SET_TDBB(tdbb);
Database* dbb = tdbb->tdbb_database;
RecordSource* old_rsb = *rsb_ptr;
/* fix up a boolean rsb to point to the actual stream rsb */
if (old_rsb->rsb_type == rsb_boolean) {
rsb_ptr = &old_rsb->rsb_next;
old_rsb = old_rsb->rsb_next;
}
/* check if there is an existing inversion for
a boolean expression mapped to an index */
jrd_nod* inversion = NULL;
if (old_rsb->rsb_type == rsb_indexed) {
inversion = (jrd_nod*) old_rsb->rsb_arg[0];
}
else if (old_rsb->rsb_type == rsb_navigate) {
inversion = (jrd_nod*) old_rsb->rsb_arg[RSB_NAV_inversion];
}
/* set up a dummy optimizer block just for the purposes
of the set index, to pass information to subroutines */
OptimizerBlk* opt = FB_NEW(*tdbb->getDefaultPool()) OptimizerBlk(tdbb->getDefaultPool());
opt->opt_g_flags |= opt_g_stream;
/* generate a new rsb for the retrieval, making sure to
preserve the inversion generated for the last rsb; note
that if the bitmap for the inversion has already been
generated, it will be reused since it is already part of
the impure area--I can't think of any reason not to reuse it--deej */
RecordSource* new_rsb;
if (idx) {
new_rsb = gen_nav_rsb(tdbb, opt, old_rsb->rsb_stream, relation, 0, idx
#ifdef SCROLLABLE_CURSORS
, RSE_get_forward
#endif
);
new_rsb->rsb_arg[RSB_NAV_inversion] = (RecordSource*) inversion;
new_rsb->rsb_cardinality = old_rsb->rsb_cardinality;
}
else {
new_rsb = gen_rsb(tdbb, opt, 0, inversion, old_rsb->rsb_stream,
relation, 0, 0, (float) old_rsb->rsb_cardinality);
}
/* point the impure area of the new rsb to the impure area of the
old; since impure area is pre-allocated it would be difficult
to change now, so just use the same area; NOTE: this implies
that we must take some pains to ensure that the impure area is
always large enough to handle a maximum-key index */
new_rsb->rsb_impure = old_rsb->rsb_impure;
/* find index node if the old rsb was navigational */
jrd_nod* index_node = NULL;
if (old_rsb->rsb_type == rsb_navigate) {
index_node = (jrd_nod*) old_rsb->rsb_arg[RSB_NAV_index];
}
/* if the new rsb is navigational, set up impure space in request
for new index node; to convert from non-navigational to navigational,
we need to adjust the impure area upwards to make room for an impure_inversion
structure, and vice versa to convert the other way */
if (idx) {
jrd_nod* new_index_node = (jrd_nod*) new_rsb->rsb_arg[RSB_NAV_index];
if (old_rsb->rsb_type == rsb_navigate)
new_index_node->nod_impure = index_node->nod_impure;
else {
new_index_node->nod_impure = old_rsb->rsb_impure;
new_rsb->rsb_impure += sizeof(impure_inversion);
}
}
else if (old_rsb->rsb_type == rsb_navigate) {
new_rsb->rsb_impure -= sizeof(impure_inversion);
}
/* if there was a previous index, release its lock
and remove its resource from the request */
if (old_rsb->rsb_type == rsb_navigate) {
IndexRetrieval* retrieval =
(IndexRetrieval*) index_node->nod_arg[e_idx_retrieval];
const USHORT index_id = retrieval->irb_index;
IndexLock* index = CMP_get_index_lock(tdbb, relation, index_id);
if (index) {
if (index->idl_count)
--index->idl_count;
if (!index->idl_count) {
LCK_release(tdbb, index->idl_lock);
}
}
CMP_release_resource(&request->req_resources, Resource::rsc_index, index_id);
}
/* get lock on new index */
if (idx) {
IndexLock* index = CMP_get_index_lock(tdbb, relation, idx->idx_id);
if (index) {
if (!index->idl_count) {
LCK_lock_non_blocking(tdbb, index->idl_lock, LCK_SR, LCK_WAIT);
}
++index->idl_count;
}
}
/* go out to the vector which stores all rsbs for the
request, and replace the old with the new */
for (size_t i = 0; i < request->req_fors.getCount(); i++) {
if (request->req_fors[i] == old_rsb) {
request->req_fors[i] = new_rsb;
break;
}
}
/* release unneeded blocks */
delete opt;
if (index_node) {
delete index_node;
}
delete old_rsb;
*rsb_ptr = new_rsb;
}
#endif
static bool augment_stack(jrd_nod* node, NodeStack& stack)
{
/**************************************

View File

@ -52,10 +52,5 @@ Jrd::jrd_nod* OPT_make_index(Jrd::thread_db*, Jrd::OptimizerBlk*, Jrd::jrd_rel*,
int OPT_match_index(Jrd::OptimizerBlk*, USHORT, Jrd::index_desc*);
// End only exported for VMS
#ifdef PC_ENGINE
void OPT_set_index(Jrd::thread_db*, Jrd::jrd_req*, Jrd::RecordSource**, Jrd::jrd_rel*,
Jrd::index_desc*);
#endif
#endif // JRD_OPT_PROTO_H

View File

@ -2896,148 +2896,6 @@ static jrd_nod* parse(thread_db* tdbb, CompilerScratch* csb, USHORT expected,
node = par_stream(tdbb, csb);
break;
#ifdef PC_ENGINE
case blr_set_index:
n = BLR_BYTE;
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
error(csb, isc_ctxnotdef, 0);
node->nod_arg[e_index_stream] =
(jrd_nod*) (SLONG) csb->csb_rpt[n].csb_stream;
node->nod_arg[e_index_index] = parse(tdbb, csb, VALUE);
break;
case blr_find:
n = BLR_BYTE;
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
error(csb, isc_ctxnotdef, 0);
node->nod_arg[e_find_stream] =
(jrd_nod*) (SLONG) csb->csb_rpt[n].csb_stream;
node->nod_arg[e_find_operator] = parse(tdbb, csb, VALUE);
node->nod_arg[e_find_direction] = parse(tdbb, csb, VALUE);
node->nod_arg[e_find_args] = par_args(tdbb, csb, VALUE);
break;
case blr_find_dbkey:
case blr_find_dbkey_version:
n = BLR_BYTE;
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
error(csb, isc_ctxnotdef, 0);
node->nod_arg[e_find_dbkey_stream] =
(jrd_nod*) (SLONG) csb->csb_rpt[n].csb_stream;
node->nod_arg[e_find_dbkey_dbkey] = parse(tdbb, csb, VALUE);
if (blr_operator == blr_find_dbkey_version)
node->nod_arg[e_find_dbkey_version] = parse(tdbb, csb, VALUE);
break;
case blr_get_bookmark:
n = BLR_BYTE;
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
error(csb, isc_ctxnotdef, 0);
node->nod_arg[e_getmark_stream] =
(jrd_nod*) (SLONG) csb->csb_rpt[n].csb_stream;
break;
case blr_set_bookmark:
n = BLR_BYTE;
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
error(csb, isc_ctxnotdef, 0);
node->nod_arg[e_setmark_stream] =
(jrd_nod*) (SLONG) csb->csb_rpt[n].csb_stream;
node->nod_arg[e_setmark_id] = parse(tdbb, csb, VALUE);
break;
case blr_release_bookmark:
node->nod_arg[e_relmark_id] = parse(tdbb, csb, VALUE);
break;
case blr_bookmark:
node->nod_arg[e_bookmark_id] = parse(tdbb, csb, VALUE);
break;
case blr_force_crack:
case blr_crack:
n = BLR_BYTE;
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
error(csb, isc_ctxnotdef, 0);
node->nod_arg[0] = (jrd_nod*) (SLONG) csb->csb_rpt[n].csb_stream;
break;
case blr_reset_stream:
n = BLR_BYTE;
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
error(csb, isc_ctxnotdef, 0);
node->nod_arg[e_reset_from_stream] =
(jrd_nod*) (SLONG) csb->csb_rpt[n].csb_stream;
n = BLR_BYTE;
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
error(csb, isc_ctxnotdef, 0);
node->nod_arg[e_reset_to_stream] =
(jrd_nod*) (SLONG) csb->csb_rpt[n].csb_stream;
break;
case blr_release_lock:
node->nod_arg[e_rellock_lock] = parse(tdbb, csb, VALUE);
break;
case blr_lock_relation:
n = BLR_BYTE;
if (n != blr_relation && n != blr_relation2 &&
n != blr_rid && n != blr_rid2)
syntax_error(csb, elements[RELATION]);
node->nod_arg[e_lockrel_relation] = par_relation(tdbb, csb, n, false);
node->nod_arg[e_lockrel_level] = parse(tdbb, csb, VALUE);
break;
case blr_lock_record:
n = BLR_BYTE;
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
error(csb, isc_ctxnotdef, 0);
node->nod_arg[e_lockrec_stream] =
(jrd_nod*) (SLONG) csb->csb_rpt[n].csb_stream;
node->nod_arg[e_lockrec_level] = parse(tdbb, csb, VALUE);
break;
case blr_begin_range:
node->nod_arg[e_brange_number] = parse(tdbb, csb, VALUE);
break;
case blr_end_range:
node->nod_arg[e_erange_number] = parse(tdbb, csb, VALUE);
break;
case blr_delete_range:
node->nod_arg[e_drange_number] = parse(tdbb, csb, VALUE);
break;
case blr_range_relation:
node->nod_arg[e_range_relation_number] = parse(tdbb, csb, VALUE);
n = BLR_BYTE;
if (n != blr_relation && n != blr_relation2 &&
n != blr_rid && n != blr_rid2)
{
syntax_error(csb, elements[RELATION]);
}
node->nod_arg[e_range_relation_relation] =
par_relation(tdbb, csb, n, false);
break;
case blr_release_locks:
case blr_delete_ranges:
node = PAR_make_node(tdbb, 0);
node->nod_count = 0;
break;
case blr_cardinality:
n = BLR_BYTE;
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
error(csb, isc_ctxnotdef, 0);
node->nod_arg[e_card_stream] =
(jrd_nod*) (SLONG) csb->csb_rpt[n].csb_stream;
break;
#endif
#ifdef SCROLLABLE_CURSORS
case blr_seek:
case blr_seek_no_warn:

View File

@ -199,10 +199,6 @@ public:
jrd_nod* req_message; /* Current message for send/receive */
#ifdef SCROLLABLE_CURSORS
jrd_nod* req_async_message; /* Asynchronous message (used in scrolling) */
#endif
#ifdef PC_ENGINE
vec<RefreshRange*>* req_refresh_ranges; /* Vector of refresh_ranges */
RefreshRange* req_begin_ranges; /* Vector of refresh_ranges */
#endif
jrd_prc* req_procedure; /* procedure, if any */
Firebird::MetaName req_trg_name; /* name of request (trigger), if any */

View File

@ -43,358 +43,7 @@
using namespace Jrd;
#ifdef PC_ENGINE
static Lock* allocate_record_lock(jrd_tra*, record_param*);
#endif
static Lock* allocate_relation_lock(MemoryPool*, jrd_rel*);
#ifdef PC_ENGINE
static Lock* attachment_relation_lock(jrd_rel*);
static void drop_record_lock(Lock*);
static Lock* find_record_lock(record_param*);
static bool obtain_lock(jrd_tra*, Lock*, USHORT);
static int start_record_locking(void*);
#endif
#ifdef PC_ENGINE
Lock* RLCK_lock_record(record_param* rpb,
USHORT lock_level, lock_ast_t ast, BLK ast_arg)
{
/**************************************
*
* R L C K _ l o c k _ r e c o r d
*
**************************************
*
* Functional description
* Lock the current record in the provided
* record parameter block at the specified level.
*
**************************************/
// SLONG process_count;
/* first get a record lock on the desired record;
if we can't get one then there is no point
in signalling that this process needs to acquire locks */
Lock* lock = RLCK_lock_record_implicit(0, rpb, lock_level, ast, ast_arg);
if (!lock)
return NULL;
thread_db* tdbb = JRD_get_thread_data();
/*
if the record is trying to be locked, check
whether the record has already been updated on page
by a transaction whose updates we cannot see yet--
in which case we effectively cannot get the lock */
if (VIO_check_if_updated(tdbb, rpb)) {
RLCK_unlock_record_implicit(lock, rpb);
return NULL;
}
/* if this process has no record locks outstanding,
indicate through the lock manager that we are
starting the record locking protocol */
jrd_rel* relation = rpb->rpb_relation;
if (!relation->rel_explicit_locks) {
Lock* record_locking = RLCK_record_locking(relation);
/* get a shared write lock to be compatible with other processes
that are doing record locking, but incompatible with those who aren't */
if (record_locking->lck_logical == LCK_none)
LCK_lock_non_blocking(tdbb, record_locking, LCK_SW, LCK_WAIT);
else
LCK_convert_non_blocking(tdbb, tdbb, record_locking, LCK_SW,
LCK_WAIT);
}
relation->rel_explicit_locks++;
return lock;
}
#endif
#ifdef PC_ENGINE
Lock* RLCK_lock_record_implicit(jrd_tra* transaction,
record_param* rpb,
USHORT lock_level,
lock_ast_t ast, BLK ast_arg)
{
/**************************************
*
* R L C K _ l o c k _ r e c o r d _ i m p l i c i t
*
**************************************
*
* Functional description
* Lock the given record for implicit access, a subset
* of what we need to do to lock it explicitly.
*
* transaction is NULL for explicit record locking.
*
**************************************/
USHORT interest_lock_level = 0;
Lock* lock = allocate_record_lock(transaction, rpb);
lock->lck_ast = ast;
lock->lck_object = ast_arg;
/* To ensure that relation and record locks respect each other,
utilize a multigranularity locking scheme, establishing
an interest lock level in the parent relation according to
the following scheme:
read lock on record := protected read
(implies) interest read lock on relation := shared read
write lock on record := exclusive
(implies) interest write lock on relation := shared write
Then as long as PR and EX locks are used to implement read
and write locking on relations, the relation locks will
be respected.
This also guarantees that implicit record locks won't result
in interest locks being taken out, since implicit record locks
are SW. Relations are already implicitly reserved in
RLCK_reserve_relation(), so there is no need for an additional
interest lock.
implicit read lock on record := NO LOCK
(implies) NO interest read lock on relation
implicit write lock on record := shared write
(implies) interest write lock on relation := shared write
*/
jrd_rel* relation = rpb->rpb_relation;
if (lock_level == LCK_EX) {
interest_lock_level = LCK_SW;
relation->rel_write_locks++;
relation->rel_lock_total++;
}
else if (lock_level == LCK_PR) {
interest_lock_level = LCK_SR;
relation->rel_read_locks++;
relation->rel_lock_total++;
}
/* first attempt to get the parent lock then get the record lock,
using two-phase locking to help prevent deadlocks */
if (interest_lock_level
&& !obtain_lock(transaction, lock->lck_parent, interest_lock_level)
|| !obtain_lock(transaction, lock, lock_level))
{
RLCK_unlock_record_implicit(lock, rpb);
return NULL;
}
return lock;
}
#endif
#ifdef PC_ENGINE
Lock* RLCK_lock_relation(jrd_rel* relation,
USHORT lock_level, lock_ast_t ast, BLK ast_arg)
{
/**************************************
*
* R L C K _ l o c k _ r e l a t i o n
*
**************************************
*
* Functional description
* Lock a relation at the specified level.
*
**************************************/
/* allocate a relation lock hanging off the attachment
block, then keep a count of the number of times it
is used so that we know when to release it (bug #7478) */
Lock* lock = attachment_relation_lock(relation);
lock->lck_count++;
lock->lck_ast = ast;
lock->lck_object = ast_arg;
if (!obtain_lock(0, lock, lock_level))
{
ERR_post(isc_relation_lock, isc_arg_string,
relation->rel_name.c_str(), 0);
}
return lock;
}
#endif
#ifdef PC_ENGINE
Lock* RLCK_range_relation(jrd_tra* transaction,
jrd_rel* relation, lock_ast_t ast, BLK ast_arg)
{
/**************************************
*
* R L C K _ r a n g e _ r e l a t i o n
*
**************************************
*
* Functional description
* Lock a relation for a refresh range.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Attachment* attachment = tdbb->tdbb_attachment;
if (transaction->tra_flags & TRA_system)
return NULL;
Lock* lock = allocate_relation_lock(transaction->tra_pool, relation);
lock->lck_owner = attachment;
lock->lck_ast = ast;
lock->lck_object = ast_arg;
lock->lck_type = LCK_range_relation;
const USHORT level = LCK_PR;
/* get lock */
const USHORT result =
LCK_lock_non_blocking(tdbb, lock, level, transaction->getLockWait());
if (result)
return lock;
else
return NULL;
}
#endif
#ifdef PC_ENGINE
Lock* RLCK_record_locking(jrd_rel* relation)
{
/**************************************
*
* R L C K _ r e c o r d _ l o c k i n g
*
**************************************
*
* Functional description
* Allocate a record locking lock, which determines
* when record locking is necessary for a particular
* relation.
*
**************************************/
if (relation->rel_record_locking)
return relation->rel_record_locking;
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = GET_DBB();
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, sizeof(SLONG)) Lock();
lock->lck_parent = dbb->dbb_lock;
lock->lck_dbb = dbb;
lock->lck_type = LCK_record_locking;
lock->lck_owner_handle = LCK_get_owner_handle(tdbb, lock->lck_type);
/* make the lock specific to the relation */
lock->lck_length = sizeof(SLONG);
lock->lck_key.lck_long = relation->rel_id;
relation->rel_record_locking = lock;
/* set up an ast to start record locking if
someone gets an incompatible lock */
lock->lck_ast = start_record_locking;
lock->lck_object = relation;
/* now attempt to get a PR on the lock to detect when
anyone locks a record explicitly */
LCK_lock(tdbb, _non_blocking(lock, LCK_PR, LCK_NO_WAIT));
return lock;
}
#endif
#ifdef PC_ENGINE
void RLCK_release_lock(Lock* lock)
{
/**************************************
*
* R L C K _ r e l e a s e _ l o c k
*
**************************************
*
* Functional description
* Release a lock of record or relation
* type. The lock handle came from the
* user, so validate it carefully.
*
**************************************/
/* first do basic validation of the handle */
if (!lock)
ERR_post(isc_bad_lock_handle, 0);
if (((blk*) lock)->blk_type != (UCHAR) type_lck)
ERR_post(isc_bad_lock_handle, 0);
/* now use the lock type to determine the type
of lock to release */
if (lock->lck_type == LCK_relation)
RLCK_unlock_relation(0, (jrd_rel*) lock->lck_object);
else if (lock->lck_type == LCK_record)
RLCK_unlock_record(lock, 0);
else
ERR_post(isc_bad_lock_handle, 0);
}
#endif
#ifdef PC_ENGINE
void RLCK_release_locks(Attachment* attachment)
{
/**************************************
*
* R L C K _ r e l e a s e _ l o c k s
*
**************************************
*
* Functional description
* Release all relation and record locks
* explicitly taken out during this attachment.
*
**************************************/
// unlock all explicit relation locks
vec<Lock*>* vector = attachment->att_relation_locks;
if (vector) {
vec<Lock*>::iterator lptr = vector->begin();
for (const vec::const_iterator lend = vector->end(); lptr < lend; lptr++)
{
Lock* lock = *lptr;
if (lock)
RLCK_unlock_relation(0, (jrd_rel*) lock->lck_object);
}
}
// unlock all explicit record locks
Lock* lock;
while (lock = attachment->att_record_locks) {
RLCK_unlock_record(lock, 0);
}
// clear the vector of user locks
if (vector = attachment->att_lck_quick_ref) {
vec<Lock*>::iterator lptr = vector->begin();
for (const vec<Lock*>::const_iterator lend = vector->end(); lptr < lend; lptr++)
{
*lptr = NULL;
}
}
}
#endif
Lock* RLCK_reserve_relation(thread_db* tdbb,
@ -462,129 +111,6 @@ Lock* RLCK_reserve_relation(thread_db* tdbb,
}
#ifdef PC_ENGINE
void RLCK_shutdown_attachment(Attachment* attachment)
{
/**************************************
*
* R L C K _ s h u t d o w n _ a t t a c h m e n t
*
**************************************
*
* Functional description
* Shutdown the attachment's persistent record
* and relation locks. This runs at AST level.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
/* Release child record locks before parent relation locks */
for (Lock* record_lock = attachment->att_record_locks;
record_lock;
record_lock = record_lock->lck_att_next)
{
LCK_release(tdbb, record_lock);
}
vec<Lock*>* lock_vector = attachment->att_relation_locks;
if (lock_vector) {
for (vec<Lock*>::iterator lock = lock_vector->begin();
lock != lock_vector->end(); ++lock)
{
if (*lock) {
LCK_release(tdbb, *lock);
}
}
}
}
#endif
#ifdef PC_ENGINE
void RLCK_shutdown_database(Database* dbb)
{
/**************************************
*
* R L C K _ s h u t d o w n _ d a t a b a s e
*
**************************************
*
* Functional description
* Shutdown the database locks shared for relation
* interest and record locking locks. This can be called
* at AST level.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
vec<jrd_rel*>* vector = dbb->dbb_relations;
if (!vector)
return;
vec<jrd_rel*>::iterator ptr = vector->begin();
for (const vec<jrd_rel*>::const_iterator end = vector->end(); ptr < end; ptr++)
{
jrd_rel* relation = *ptr;
if (relation) {
if (relation->rel_record_locking)
LCK_release(tdbb, relation->rel_record_locking);
if (relation->rel_interest_lock)
LCK_release(tdbb, relation->rel_interest_lock);
relation->rel_explicit_locks = 0;
relation->rel_read_locks = 0;
relation->rel_write_locks = 0;
relation->rel_lock_total = 0;
}
}
}
#endif
#ifdef PC_ENGINE
void RLCK_signal_refresh(jrd_tra* transaction)
{
/**************************************
*
* R L C K _ s i g n a l _ r e f r e s h
*
**************************************
*
* Functional description
* For each reserved relation, get a refresh relation
* lock to signal possible refresh range users.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
/* for each relation, take out a range relation lock and then release it */
vec<Lock*>* vector = transaction->tra_relation_locks;
if (vector) {
/* allocate a local lock */
Lock* local_lock = FB_NEW_RPT(*dbb->dbb_permanent, sizeof(SLONG)) Lock();
local_lock->lck_dbb = dbb;
local_lock->lck_length = sizeof(SLONG);
local_lock->lck_type = LCK_range_relation;
local_lock->lck_owner_handle =
LCK_get_owner_handle(tdbb, local_lock->lck_type);
local_lock->lck_parent = dbb->dbb_lock;
local_lock->lck_compatible = tdbb->tdbb_attachment;
for (size_t i = 0; i < vector->count(); i++) {
Lock* lock = (*vector)[i];
if (lock) {
jrd_rel* relation = (jrd_rel*) lock->lck_object;
local_lock->lck_key.lck_long = relation->rel_id;
local_lock->lck_object = relation;
LCK_lock_non_blocking(tdbb, local_lock, LCK_SW, LCK_NO_WAIT);
LCK_release(tdbb, local_lock);
}
}
ALL_release(local_lock);
}
}
#endif
Lock* RLCK_transaction_relation_lock(jrd_tra* transaction, jrd_rel* relation)
{
/**************************************
@ -627,205 +153,6 @@ Lock* RLCK_transaction_relation_lock(jrd_tra* transaction, jrd_rel* relation)
}
#ifdef PC_ENGINE
void RLCK_unlock_record(Lock* lock, record_param* rpb)
{
/**************************************
*
* R L C K _ u n l o c k _ r e c o r d
*
**************************************
*
* Functional description
* Unlock the specified record lock, or if
* it's not available use the current record
* in the specified record parameter block.
*
**************************************/
jrd_rel* relation;
if (rpb)
relation = rpb->rpb_relation;
else if (lock)
relation = (jrd_rel*) lock->lck_parent->lck_object;
else
relation = NULL; /* theoretically impossible */
RLCK_unlock_record_implicit(lock, rpb);
thread_db* tdbb = JRD_get_thread_data();
Attachment* attachment = tdbb->tdbb_attachment;
if (attachment->att_flags & ATT_shutdown)
return;
/* decrement the count of explicit locks this process has taken out;
if there are none, go back to a PR on the lock--
if we cannot obtain this, it means someone else has explicit
record locks taken out and we should just release the lock */
if (relation && !--relation->rel_explicit_locks) {
Lock* record_locking = relation->rel_record_locking;
if (!LCK_convert_non_blocking(tdbb, record_locking, LCK_PR, LCK_NO_WAIT))
LCK_release(tdbb, record_locking);
}
}
#endif
#ifdef PC_ENGINE
void RLCK_unlock_record_implicit(Lock* lock, record_param* rpb)
{
/**************************************
*
* R L C K _ u n l o c k _ r e c o r d _ i m p l i c i t
*
**************************************
*
* Functional description
* Unlock a record-level lock.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
if (!lock)
lock = find_record_lock(rpb);
const USHORT lock_level = lock->lck_logical;
drop_record_lock(lock);
LCK_release(tdbb, lock);
Attachment* attachment = tdbb->tdbb_attachment;
if (attachment->att_flags & ATT_shutdown) {
ALL_release(lock);
return;
}
/* handle the release half of the multigranularity locking scheme:
if there are no more write locks, downgrade the interest
lock on the parent relation; if there are no more read or
write locks, release the lock entirely
For implicit locks, there are no relation intrest locks.
So do nothing.
*/
jrd_rel* relation = (jrd_rel*) lock->lck_parent->lck_object;
if (lock_level == LCK_EX) {
if (!--relation->rel_write_locks)
if (!relation->rel_read_locks)
LCK_release(tdbb, relation->rel_interest_lock);
else
LCK_convert_non_blocking(tdbb, relation->rel_interest_lock,
LCK_SR, LCK_WAIT);
}
else if (lock_level == LCK_PR) {
if (!--relation->rel_read_locks && !relation->rel_write_locks)
LCK_release(tdbb, relation->rel_interest_lock);
}
ALL_release(lock);
}
#endif
#ifdef PC_ENGINE
void RLCK_unlock_relation(Lock* lock, jrd_rel* relation)
{
/**************************************
*
* R L C K _ u n l o c k _ r e l a t i o n
*
**************************************
*
* Functional description
* Release the attachment's persistent lock
* on the specified relation.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Attachment* attachment = tdbb->tdbb_attachment;
vec<Lock*>* vector = attachment->att_relation_locks;
if (!vector)
return;
if (relation) {
const USHORT id = relation->rel_id;
if (id >= vector->count())
return;
lock = (*vector)[id];
}
else {
for (int id = 0; id < vector->count(); id++)
if (lock == (*vector)[id])
break;
}
if (!lock)
return;
/* decrement the use count; if it goes to zero,
there are no further locks taken out in this
attachment so we can release the lock (bug #7478) */
if (lock->lck_count > 1) {
lock->lck_count--;
return;
}
LCK_release(tdbb, lock);
ALL_release(lock);
(*vector)[id] = NULL;
}
#endif
#ifdef PC_ENGINE
static Lock* allocate_record_lock(jrd_tra* transaction, record_param* rpb)
{
/**************************************
*
* a l l o c a t e _ r e c o r d _ l o c k
*
**************************************
*
* Functional description
* Create a record lock block for the current
* record in the passed rpb.
* transaction used only for implicit record locks.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
Attachment* attachment = tdbb->tdbb_attachment;
if (!rpb->rpb_record)
ERR_post(isc_no_cur_rec, 0);
/* allocate a lock block for the record lock */
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, sizeof(SLONG)) Lock();
lock->lck_dbb = dbb;
lock->lck_object = reinterpret_cast<blk*>(dbb);
lock->lck_type = LCK_record;
lock->lck_owner_handle = LCK_get_owner_handle(tdbb, lock->lck_type);
/* use the relation lock as the lock parent */
jrd_rel* relation = rpb->rpb_relation;
if (transaction)
lock->lck_parent =
RLCK_transaction_relation_lock(transaction, relation);
else {
if (!relation->rel_interest_lock)
relation->rel_interest_lock =
allocate_relation_lock(dbb->dbb_permanent, relation);
lock->lck_parent = relation->rel_interest_lock;
}
/* indicate that this lock should be compatible at the attachment
level--meaning that two record locks taken out within the same
attachment should always be compatible; ditto for the interest lock */
lock->lck_compatible = attachment;
lock->lck_parent->lck_compatible = attachment;
/* link in the record lock with the other record locks
taken out by this attachment */
lock->lck_att_next = attachment->att_record_locks;
attachment->att_record_locks = lock;
/* fill in the lock value using the record number */
lock->lck_length = sizeof(SLONG);
lock->lck_key.lck_long = rpb->rpb_number;
return lock;
}
#endif
static Lock* allocate_relation_lock(MemoryPool* pool, jrd_rel* relation)
{
/**************************************
@ -856,165 +183,3 @@ static Lock* allocate_relation_lock(MemoryPool* pool, jrd_rel* relation)
return lock;
}
#ifdef PC_ENGINE
static Lock* attachment_relation_lock(jrd_rel* relation)
{
/**************************************
*
* a t t a c h m e n t _ r e l a t i o n _ l o c k
*
**************************************
*
* Functional description
* Take out a persistent relation lock at the
* attachment level.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
Attachment* attachment = tdbb->tdbb_attachment;
Lock* lock;
vec<Lock*>* vector = attachment->att_relation_locks;
if (vector &&
(relation->rel_id < vector->count()) &&
(lock = (*vector)[relation->rel_id]))
{
return lock;
}
vector = attachment->att_relation_locks =
vec<Lock*>::newVector(*dbb->dbb_permanent, attachment->att_relation_locks,
relation->rel_id + 1);
if ( (lock = (*vector)[relation->rel_id]) )
return lock;
lock = allocate_relation_lock(dbb->dbb_permanent, relation);
lock->lck_owner = attachment;
(*vector)[relation->rel_id] = lock;
return lock;
}
#endif
#ifdef PC_ENGINE
static void drop_record_lock(Lock* record_lock)
{
/**************************************
*
* d r o p _ r e c o r d _ l o c k
*
**************************************
*
* Functional description
* Find the record lock in the linked list off
* the attachment block, and drop it from the list.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
/* look through all the record locks taken out by this attachment
looking for one with the same record number and relation id */
Attachment* attachment = tdbb->tdbb_attachment;
for (Lock** lock = &attachment->att_record_locks; *lock;
lock = &(*lock)->lck_att_next)
{
if (*lock == record_lock) {
*lock = (*lock)->lck_att_next;
break;
}
}
}
#endif
#ifdef PC_ENGINE
static Lock* find_record_lock(record_param* rpb)
{
/**************************************
*
* f i n d _ r e c o r d _ l o c k
*
**************************************
*
* Functional description
* Find the record lock previously
* defined for a record.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
/* look through all the record locks taken out by this attachment
looking for one with the same record number and relation */
Attachment* attachment = tdbb->tdbb_attachment;
Lock* lock;
for (lock = attachment->att_record_locks; lock; lock = lock->lck_att_next)
{
if ((rpb->rpb_number == lock->lck_key.lck_long)
&& (rpb->rpb_relation == (jrd_rel*) lock->lck_parent->lck_object))
{
break;
}
}
return lock;
}
#endif
#ifdef PC_ENGINE
static bool obtain_lock(jrd_tra* transaction, Lock* lock, USHORT lock_level)
{
/**************************************
*
* o b t a i n _ l o c k
*
**************************************
*
* Functional description
* Obtain the specified lock at the
* necessary level.
*
**************************************/
const SSHORT wait_flag =
transaction ? transaction->getLockWait() : 0;
/* return if lock level OK and if the lock has not been released
(like as part of a refresh range) */
if ((lock_level <= lock->lck_logical) && (lock->lck_id != -1))
return true;
if ((lock->lck_logical) && (lock->lck_id != -1)) {
if (LCK_convert_non_blocking(NULL, lock, lock_level, wait_flag))
return true;
}
else if (LCK_lock_non_blocking(NULL, lock, lock_level, wait_flag))
return true;
return false;
}
#endif
#ifdef PC_ENGINE
static int start_record_locking(void* relation_void)
{
/**************************************
*
* s t a r t _ r e c o r d _ l o c k i n g
*
**************************************
*
* Functional description
* A blocking AST has been issued to give up
* the lock on the record locking semaphore.
* Flag the fact that record locking is now
* necessary for reading and writing records.
*
**************************************/
jrd_rel* relation = static_cast<jrd_rel*>(relation_void);
Lock* record_locking = relation->rel_record_locking;
/* if we have shared write, it means we have records
locked; we won't give up this lock for anyone! */
if (record_locking->lck_physical == LCK_SW)
return 0;
ISC_ast_enter();
LCK_release(NULL, record_locking);
ISC_ast_exit();
return 0;
}
#endif

View File

@ -32,36 +32,10 @@ namespace Jrd {
class Attachment;
class thread_db;
}
struct blk;
#ifdef PC_ENGINE
Jrd::Lock* RLCK_lock_record(Jrd::record_param*, USHORT, lock_ast_t, blk*);
Jrd::Lock* RLCK_lock_record_implicit(Jrd::jrd_tra*, Jrd::record_param*,
USHORT, lock_ast_t, blk*);
Jrd::Lock* RLCK_lock_relation(Jrd::jrd_rel*, USHORT, lock_ast_t, blk*);
Jrd::Lock* RLCK_range_relation(Jrd::jrd_tra*, Jrd::jrd_rel*, lock_ast_t, blk*);
Jrd::Lock* RLCK_record_locking(Jrd::jrd_rel*);
void RLCK_release_lock(Jrd::Lock*);
void RLCK_release_locks(Jrd::Attachment*);
#endif
Jrd::Lock* RLCK_reserve_relation(Jrd::thread_db*, Jrd::jrd_tra*,
Jrd::jrd_rel*, bool, bool);
#ifdef PC_ENGINE
void RLCK_shutdown_attachment(Jrd::Attachment*);
void RLCK_shutdown_database(Jrd::Database*);
void RLCK_signal_refresh(Jrd::jrd_tra*);
#endif
Jrd::Lock* RLCK_transaction_relation_lock(Jrd::jrd_tra*, Jrd::jrd_rel*);
#ifdef PC_ENGINE
void RLCK_unlock_record(Lock*, Jrd::record_param*);
void RLCK_unlock_record_implicit(Lock*, Jrd::record_param*);
void RLCK_unlock_relation(Lock*, Jrd::jrd_rel*);
#endif
#endif // JRD_RLCK_PROTO_H

View File

@ -225,186 +225,6 @@ void RSE_close(thread_db* tdbb, RecordSource* rsb)
}
#ifdef PC_ENGINE
bool RSE_find_dbkey(thread_db* tdbb, RecordSource* rsb, jrd_nod* find_key, jrd_nod* record_version)
{
/**************************************
*
* R S E _ f i n d _ d b k e y
*
**************************************
*
* Functional description
* Find the passed dbkey in the stream
* with equivalent key values. Optionally,
* check for a record version also.
*
**************************************/
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
/* get the record number from the passed dbkey */
const dsc* desc = EVL_expr(tdbb, find_key);
ULONG dbkey[2];
dsc desc2;
desc2.dsc_address = (UCHAR *) dbkey;
desc2.dsc_length = sizeof(dbkey);
desc2.dsc_dtype = dtype_text;
desc2.dsc_scale = 0;
desc2.dsc_sub_type = ttype_binary;
desc2.dsc_flags = 0;
MOV_move(desc, &desc2);
/* now get the record version to use in comparing
against the tid of the record */
ULONG version_number;
if (record_version) {
desc = EVL_expr(tdbb, record_version);
desc2.dsc_address = (UCHAR *) & version_number;
desc2.dsc_length = sizeof(version_number);
desc2.dsc_dtype = dtype_text;
desc2.dsc_scale = 0;
desc2.dsc_sub_type = ttype_binary;
desc2.dsc_flags = 0;
MOV_move(desc, &desc2);
}
record_param* rpb;
irsb_index* impure;
RecordBitmap* bitmap;
switch (rsb->rsb_type) {
case rsb_boolean:
if (!RSE_find_dbkey(tdbb, rsb->rsb_next, find_key, record_version))
return false;
if ((rsb->rsb_arg[0]) && (!EVL_boolean(tdbb, rsb->rsb_arg[0]))) {
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
return false;
}
return true;
case rsb_navigate:
rpb = request->req_rpb + rsb->rsb_stream;
rpb->rpb_number = dbkey[1] - 1;
/* first, fetch the indicated record */
if (!VIO_get
(tdbb, rpb, rsb, request->req_transaction,
request->req_pool))
{
return false;
}
if (record_version && version_number != rpb->rpb_transaction_nr)
return false;
/* next, set the stream position to that of the fetched record */
RSE_MARK_CRACK(tdbb, rsb, 0);
if (NAV_reset_position(rsb, rpb))
return true;
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
return false;
case rsb_sequential:
rpb = request->req_rpb + rsb->rsb_stream;
rpb->rpb_number = dbkey[1] - 1;
RSE_MARK_CRACK(tdbb, rsb, 0);
if (VIO_get
(tdbb, rpb, rsb, request->req_transaction, request->req_pool)
&& (!record_version || version_number == rpb->rpb_transaction_nr))
{
return true;
}
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
return false;
case rsb_indexed:
rpb = request->req_rpb + rsb->rsb_stream;
rpb->rpb_number = dbkey[1] - 1;
impure = (irsb_index*) ((UCHAR *) request + rsb->rsb_impure);
RSE_MARK_CRACK(tdbb, rsb, 0);
if ((bitmap = impure->irsb_bitmap) &&
SBM_next(*bitmap, &rpb->rpb_number, RSE_get_current) &&
VIO_get(tdbb, rpb, rsb, request->req_transaction,
request->req_pool) &&
(!record_version || version_number == rpb->rpb_transaction_nr))
{
return true;
}
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
return false;
default:
BUGCHECK(166); /* msg 166 invalid rsb type */
return false; /* Added to remove compiler warnings */
}
}
#endif
#ifdef PC_ENGINE
bool RSE_find_record(thread_db* tdbb,
RecordSource* rsb,
USHORT blr_operator, USHORT direction, jrd_nod* find_key)
{
/**************************************
*
* R S E _ f i n d _ r e c o r d
*
**************************************
*
* Functional description
* Find the record with the passed key
* value, using the passed operator to
* compare records with the key value.
* Search forwards or backwards.
*
**************************************/
SET_TDBB(tdbb);
switch (rsb->rsb_type) {
case rsb_indexed:
return RSE_find_record(tdbb, rsb->rsb_next, blr_operator, direction,
find_key);
case rsb_boolean:
if (!RSE_find_record
(tdbb, rsb->rsb_next, blr_operator, direction, find_key))
{
return false;
}
if ((rsb->rsb_arg[0]) && (!EVL_boolean(tdbb, rsb->rsb_arg[0]))) {
RSE_MARK_CRACK(tdbb, rsb, irsb_crack);
return false;
}
return true;
case rsb_navigate:
return NAV_find_record(rsb, blr_operator, direction, find_key);
default:
BUGCHECK(166); /* msg 166 invalid rsb type */
return false; /* Added to remove compiler warnings */
}
}
#endif
bool RSE_get_record(thread_db* tdbb, RecordSource* rsb, RSE_GET_MODE mode)
{
/**************************************
@ -503,106 +323,6 @@ bool RSE_get_record(thread_db* tdbb, RecordSource* rsb, RSE_GET_MODE mode)
}
#ifdef PC_ENGINE
Bookmark* RSE_get_bookmark(thread_db* tdbb, RecordSource* rsb)
{
/**************************************
*
* R S E _ g e t _ b o o k m a r k
*
**************************************
*
* Functional description
* Return a descriptor whose value is a pointer
* to a bookmark describing the location of
* the current record in a navigational stream.
*
**************************************/
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
if (request->req_flags & req_abort)
return FALSE;
switch (rsb->rsb_type) {
case rsb_boolean:
return RSE_get_bookmark(rsb->rsb_next);
case rsb_navigate:
{
IRSB_NAV impure = (IRSB_NAV) ((UCHAR *) request + rsb->rsb_impure);
Bookmark* bookmark = BKM_allocate(rsb, impure->irsb_nav_length);
NAV_get_bookmark(rsb, impure, bookmark);
return bookmark;
}
case rsb_indexed:
case rsb_sequential:
{
record_param* rpb = request->req_rpb + rsb->rsb_stream;
Bookmark* bookmark = BKM_allocate(rsb, (USHORT) 0);
bookmark->bkm_number = rpb->rpb_number;
bookmark->bkm_key_desc.dsc_dtype = dtype_long;
bookmark->bkm_key_desc.dsc_length = sizeof(bookmark->bkm_number);
bookmark->bkm_key_desc.dsc_address = (UCHAR *) & bookmark->bkm_number;
return bookmark;
}
default:
BUGCHECK(166); /* msg 166 invalid rsb type */
return FALSE; /* Added to remove compiler warnings */
}
}
#endif
#ifdef PC_ENGINE
void RSE_mark_crack(thread_db* tdbb, RecordSource* rsb, USHORT flags)
{
/**************************************
*
* R S E _ m a r k _ c r a c k
*
**************************************
*
* Functional description
* Position stream on a crack.
*
**************************************/
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
/* correct boolean rsbs to point to the "real" rsb */
if (rsb->rsb_type == rsb_boolean)
rsb = rsb->rsb_next;
/* clear all the flag bits first to make sure
no conflicting bits are set */
irsb* impure = (IRSB) ((UCHAR *) request + rsb->rsb_impure);
impure->irsb_flags &=
~(irsb_bof | irsb_eof | irsb_crack | irsb_forced_crack);
impure->irsb_flags |= flags;
/* release the current record to make sure
that no one erroneously tries to retrieve it */
if (flags) {
record_param* rpb = &request->req_rpb[rsb->rsb_stream];
if (rpb->rpb_record) {
delete rpb->rpb_record;
rpb->rpb_record = NULL;
}
if (rpb->rpb_copy) {
delete rpb->rpb_copy;
rpb->rpb_copy = NULL;
}
}
}
#endif
void RSE_open(thread_db* tdbb, RecordSource* rsb)
{
/**************************************
@ -808,129 +528,6 @@ void RSE_open(thread_db* tdbb, RecordSource* rsb)
}
#ifdef PC_ENGINE
bool RSE_reset_position(thread_db* tdbb, RecordSource* rsb, record_param* new_rpb)
{
/**************************************
*
* R S E _ r e s e t _ p o s i t i o n
*
**************************************
*
* Functional description
* Reset the position of a navigational stream to
* the position indicated by the passed record.
*
**************************************/
record_param* rpb;
irsb_index* impure;
RecordBitmap* bitmap;
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
if (request->req_flags & req_abort)
return false;
switch (rsb->rsb_type) {
case rsb_boolean:
return RSE_reset_position(rsb->rsb_next, new_rpb);
case rsb_navigate:
RSE_MARK_CRACK(rsb, 0);
if (!(NAV_reset_position(rsb, new_rpb))) {
RSE_MARK_CRACK(rsb, irsb_crack);
return false;
}
return true;
case rsb_sequential:
RSE_MARK_CRACK(rsb, 0);
rpb = request->req_rpb + rsb->rsb_stream;
rpb->rpb_number = new_rpb->rpb_number;
if (!
(VIO_get
(tdbb, rpb, rsb, request->req_transaction, request->req_pool)))
{
RSE_MARK_CRACK(rsb, irsb_crack);
return false;
}
return true;
case rsb_indexed:
RSE_MARK_CRACK(rsb, 0);
rpb = request->req_rpb + rsb->rsb_stream;
rpb->rpb_number = new_rpb->rpb_number;
impure = (irsb_index*) ((UCHAR *) request + rsb->rsb_impure);
if ((bitmap = impure->irsb_bitmap) &&
SBM_next(*bitmap, &rpb->rpb_number, RSE_get_current) &&
VIO_get(tdbb, rpb, rsb, request->req_transaction,
request->req_pool))
{
return true;
}
RSE_MARK_CRACK(rsb, irsb_crack);
return false;
default:
BUGCHECK(166); /* msg 166 invalid rsb type */
return false; /* Added to remove compiler warnings */
}
}
#endif
#ifdef PC_ENGINE
bool RSE_set_bookmark(thread_db* tdbb, RecordSource* rsb, record_param* rpb, Bookmark* bookmark)
{
/**************************************
*
* R S E _ s e t _ b o o k m a r k
*
**************************************
*
* Functional description
* Set the location of a stream to the location
* specified by the given bookmark.
*
**************************************/
SET_TDBB(tdbb);
jrd_req* request = tdbb->tdbb_request;
if (request->req_flags & req_abort)
return false;
IRSB impure = (IRSB) ((UCHAR *) request + rsb->rsb_impure);
switch (rsb->rsb_type) {
case rsb_boolean:
return RSE_set_bookmark(rsb->rsb_next, rpb, bookmark);
case rsb_navigate:
return NAV_set_bookmark(rsb, impure, rpb, bookmark);
case rsb_sequential:
case rsb_indexed:
rpb->rpb_number = bookmark->bkm_number;
if (impure->irsb_flags & (irsb_bof | irsb_eof | irsb_crack))
return false;
if (!(get_record(tdbb, rsb, NULL, RSE_get_current))) {
RSE_MARK_CRACK(rsb, irsb_crack);
return false;
}
return true;
default:
BUGCHECK(166); /* msg 166 invalid rsb type */
return false; /* Added to remove compiler warnings */
}
}
#endif
static void close_merge(thread_db* tdbb, RecordSource* rsb, irsb_mrg* impure)
{
/**************************************
@ -2232,12 +1829,8 @@ static bool get_record(thread_db* tdbb,
{
if (((mode == RSE_get_forward) && (impure->irsb_flags & irsb_eof)) ||
((mode == RSE_get_backward) && (impure->irsb_flags & irsb_bof)))
#ifdef PC_ENGINE
||((mode == RSE_get_current)
&& (impure->irsb_flags & (irsb_bof | irsb_eof)))
#endif
{
return false;
return false;
}
}
#endif
@ -2252,34 +1845,20 @@ static bool get_record(thread_db* tdbb,
}
#endif
#ifdef PC_ENGINE
if (mode == RSE_get_current)
{
if (!VIO_get(tdbb,
rpb,
rsb,
request->req_transaction,
request->req_pool))
{
return false;
}
}
else
#endif
if (!VIO_next_record(tdbb,
rpb,
rsb,
request->req_transaction,
request->req_pool,
if (!VIO_next_record(tdbb,
rpb,
rsb,
request->req_transaction,
request->req_pool,
#ifdef SCROLLABLE_CURSORS
(mode == RSE_get_backward),
(mode == RSE_get_backward),
#else
false,
false,
#endif
false))
{
return false;
}
false))
{
return false;
}
break;
case rsb_indexed:
@ -2398,10 +1977,6 @@ static bool get_record(thread_db* tdbb,
any_true = true;
break;
}
#ifdef PC_ENGINE
else if (mode == RSE_get_current)
break;
#endif
/* check for select stream and nulls */
@ -2458,10 +2033,6 @@ static bool get_record(thread_db* tdbb,
result = true;
break;
}
#ifdef PC_ENGINE
else if (mode == RSE_get_current)
break;
#endif
}
request->req_flags &= ~req_null;
if (result)
@ -2510,10 +2081,6 @@ static bool get_record(thread_db* tdbb,
break;
}
}
#ifdef PC_ENGINE
else if (mode == RSE_get_current)
break;
#endif
}
request->req_flags &= ~req_null;
if (any_false)
@ -2557,10 +2124,6 @@ static bool get_record(thread_db* tdbb,
break;
}
}
#ifdef PC_ENGINE
else if (mode == RSE_get_current)
break;
#endif
}
request->req_flags &= ~req_null;
if (any_false)
@ -2580,14 +2143,6 @@ static bool get_record(thread_db* tdbb,
result = true;
break;
}
#ifdef PC_ENGINE
/* If we are trying to "RSE_get_current" and there is a
* "where" clause which is not true, someone must have
* modified it after we positioned on the record
*/
else if (mode == RSE_get_current)
break;
#endif
if (request->req_flags & req_null)
flag = true;

View File

@ -34,26 +34,9 @@ namespace Jrd {
}
void RSE_close(Jrd::thread_db*, Jrd::RecordSource*);
#ifdef PC_ENGINE
bool RSE_find_dbkey(Jrd::thread_db*, Jrd::RecordSource*, Jrd::jrd_nod*, Jrd::jrd_nod*);
bool RSE_find_record(Jrd::thread_db*, Jrd::RecordSource*, USHORT, USHORT, Jrd::jrd_nod*);
#endif
bool RSE_get_record(Jrd::thread_db*, Jrd::RecordSource*, Jrd::rse_get_mode);
#ifdef PC_ENGINE
Bookmark* RSE_get_bookmark(Jrd::thread_db*, Jrd::RecordSource*);
void RSE_mark_crack(Jrd::thread_db*, Jrd::RecordSource*, USHORT);
#endif
void RSE_open(Jrd::thread_db*, Jrd::RecordSource*);
#ifdef PC_ENGINE
bool RSE_reset_position(Jrd::thread_db*, Jrd::RecordSource*, Jrd::record_param*);
bool RSE_set_bookmark(Jrd::thread_db*, Jrd::RecordSource*, Jrd::record_param*, Jrd::Bookmark*);
#endif
#ifdef PC_ENGINE
#define RSE_MARK_CRACK(t, var1, var2) RSE_mark_crack (t, var1, var2)
#else
#define RSE_MARK_CRACK(t, var1, var2)
#endif
#endif // JRD_RSE_PROTO_H

View File

@ -523,10 +523,6 @@ static bool shutdown_locks(Database* dbb, SSHORT flag)
if (attachment->att_id_lock)
LCK_release(tdbb, attachment->att_id_lock);
#ifdef PC_ENGINE
RNG_shutdown_attachment(attachment);
RLCK_shutdown_attachment(attachment);
#endif
TRA_shutdown_attachment(tdbb, attachment);
}
@ -535,9 +531,6 @@ static bool shutdown_locks(Database* dbb, SSHORT flag)
as, relation interest and record locking locks for PC semantic
record locking. */
#ifdef PC_ENGINE
RLCK_shutdown_database(dbb);
#endif
CMP_shutdown_database(tdbb);
/* If shutdown manager is here, leave enough database lock context

View File

@ -19,7 +19,7 @@
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* $Id: sort.cpp,v 1.75 2005-05-27 22:44:05 asfernandes Exp $
* $Id: sort.cpp,v 1.76 2006-02-02 07:32:07 robocop Exp $
*
* 2001-09-24 SJL - Temporary fix for large sort file bug
*
@ -624,17 +624,6 @@ void SORT_get(ISC_STATUS * status_vector,
scb->scb_next_pointer++;
break;
#ifdef PC_ENGINE
case RSE_get_current:
if (scb->scb_next_pointer <= scb->scb_first_pointer ||
scb->scb_next_pointer > scb->scb_last_pointer)
{
record = NULL;
}
record = *scb->scb_next_pointer;
break;
#endif
default:
fb_assert(FALSE);
break;

View File

@ -109,9 +109,6 @@ static void retain_context(thread_db*, jrd_tra*, bool, SSHORT);
#ifdef VMS
static void compute_oldest_retaining(thread_db*, jrd_tra*, bool);
#endif
#ifdef PC_ENGINE
static int downgrade_lock(void*);
#endif
static void expand_view_lock(jrd_tra*, jrd_rel*, SCHAR);
static tx_inv_page* fetch_inventory_page(thread_db*, WIN *, SLONG, USHORT);
static SLONG inventory_page(thread_db*, SLONG);
@ -461,12 +458,6 @@ void TRA_commit(thread_db* tdbb, jrd_tra* transaction, const bool retaining_flag
}
#endif
/* signal refresh range relations for ExpressLink */
#ifdef PC_ENGINE
RLCK_signal_refresh(transaction);
#endif
if (retaining_flag) {
retain_context(tdbb, transaction, true, tra_committed);
return;
@ -1285,9 +1276,7 @@ void TRA_rollback(thread_db* tdbb, jrd_tra* transaction, const bool retaining_fl
state = tra_committed;
}
/* if this is a rollback retain (used only by ExpressLink), abort
* this transaction and start a new one.
*/
// If this is a rollback retain abort this transaction and start a new one.
if (retaining_flag) {
retain_context(tdbb, transaction, false, state);
@ -1585,12 +1574,6 @@ jrd_tra* TRA_start(thread_db* tdbb, int tpb_length, const SCHAR* tpb)
trans->tra_lock = lock;
lock->lck_key.lck_long = number;
/* Support refresh range notification in ExpressLink */
#ifdef PC_ENGINE
lock->lck_ast = downgrade_lock;
#endif
/* Put the TID of the oldest active transaction (from the header page)
in the new transaction's lock. */
@ -2330,60 +2313,6 @@ static void compute_oldest_retaining(
}
#endif
#ifdef PC_ENGINE
static int downgrade_lock(void* transaction_void)
{
/**************************************
*
* d o w n g r a d e _ l o c k
*
**************************************
*
* Functional description
* Someone is trying to establish an interest
* lock in this transaction. Downgrade to a
* shared write, to allow transactions to wait
* on this transaction or, alternatively, be
* notified if and when the transaction commits.
*
**************************************/
ISC_ast_enter();
jrd_tra* transaction = static_cast<jrd_tra*>(transaction_void);
/* Since this routine will be called asynchronously, we must establish
a thread context. */
thread_db thd_context, *tdbb;
JRD_set_thread_data(tdbb, thd_context);
/* Ignore the request if the transaction or lock block does not appear
to be valid or if the lock is not a write lock. */
if (transaction->tra_use_count);
else {
tdbb->tdbb_database = transaction->tra_attachment->att_database;
tdbb->tdbb_attachment = transaction->tra_attachment;
tdbb->tdbb_quantum = QUANTUM;
tdbb->tdbb_request = NULL;
tdbb->tdbb_transaction = transaction;
++transaction->tra_use_count;
Lock* lock = transaction->tra_lock;
if (lock && lock->lck_logical == LCK_write) {
lock->lck_ast = NULL;
LCK_convert(tdbb, lock, LCK_SW, TRUE);
}
--transaction->tra_use_count;
}
/* Restore the prior thread context */
JRD_restore_thread_data();
ISC_ast_exit();
return 0;
}
#endif
static void expand_view_lock(jrd_tra* transaction, jrd_rel* relation, SCHAR lock_type)
{
@ -2638,12 +2567,6 @@ static void retain_context(thread_db* tdbb, jrd_tra* transaction,
new_lock->lck_key.lck_long = new_number;
new_lock->lck_data = transaction->tra_lock->lck_data;
/* Support refresh range notification in ExpressLink */
#ifdef PC_ENGINE
new_lock->lck_ast = downgrade_lock;
#endif
if (!LCK_lock_non_blocking(tdbb, new_lock, LCK_write, LCK_WAIT)) {
#ifndef SUPERSERVER_V2
if (!(dbb->dbb_flags & DBB_read_only))

View File

@ -105,9 +105,6 @@ class jrd_tra : public pool_alloc_rpt<SCHAR, type_tra>
Savepoint* tra_save_point; /* list of savepoints */
SLONG tra_save_point_number; /* next save point number to use */
ULONG tra_flags;
#ifdef PC_ENGINE
SLONG tra_range_id; /* unique id of cache range within transaction */
#endif
class DeferredWork* tra_deferred_work; /* work deferred to commit time */
ResourceList tra_resources; /* resource existence list */
Firebird::StringMap tra_context_vars; // Context variables for the transaction

View File

@ -761,18 +761,6 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, RecordSource*
}
#endif
#ifdef PC_ENGINE
/* for refresh ranges, we want to know about uncommitted record versions */
if (rsb) {
const jrd_req* request = tdbb->tdbb_request;
const irsb_nav* impure = (IRSB_NAV) ((UCHAR *) request + rsb->rsb_impure);
if (impure->irsb_flags & irsb_refresh) {
RNG_add_uncommitted_record(rpb);
}
}
#endif
/* we can't use this one so if there aren't any more just stop now. */
if (rpb->rpb_b_page == 0) {
@ -962,103 +950,6 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, RecordSource*
}
#ifdef PC_ENGINE
bool VIO_check_if_updated(thread_db* tdbb, record_param* rpb)
{
/**************************************
*
* V I O _ c h e c k _ i f _ u p d a t e d
*
**************************************
*
* Functional description
* Check to see if the record specified in the passed
* rpb has been updated by an uncommitted transaction.
* This involves looking at the latest and greatest
* version of the record, checking its transaction id,
* then checking the TIP page to see if that transaction
* has been committed.
*
**************************************/
SET_TDBB(tdbb);
/* loop through till we find a real version of the record;
one that isn't going to be garbage collected */
jrd_tra* transaction = tdbb->tdbb_request->req_transaction;
while (true) {
if (!DPM_get(tdbb, rpb, LCK_read)) {
return false;
}
else {
CCH_RELEASE(tdbb, &rpb->rpb_window);
}
/* if the system transaction updated this record,
it automatically is considered committed */
if (!rpb->rpb_transaction_nr) {
return false;
}
if (rpb->rpb_transaction_nr == transaction->tra_number) {
return false;
}
/* get the state of the given transaction */
USHORT state = TRA_get_state(tdbb, rpb->rpb_transaction_nr);
/* Reset the garbage collect active flag if the transaction state is
in a terminal state. If committed it must have been a precommitted
transaction that was backing out a dead record version and the
system crashed. Clear the flag and set the state to tra_dead to
reattempt the backout. */
if (rpb->rpb_flags & rpb_gc_active) {
switch (state) {
case tra_committed:
state = tra_dead;
rpb->rpb_flags &= ~rpb_gc_active;
break;
case tra_dead:
rpb->rpb_flags &= ~rpb_gc_active;
break;
default:
break;
}
}
switch (state) {
case tra_committed:
return false;
case tra_active:
if (!(rpb->rpb_flags & rpb_gc_active)) {
return true;
}
case tra_precommitted:
THREAD_EXIT();
THREAD_SLEEP(100); /* milliseconds */
THREAD_ENTER();
break;
case tra_limbo:
return true;
case tra_dead:
VIO_backout(tdbb, rpb, transaction);
break;
}
}
}
#endif
void VIO_data(thread_db* tdbb, record_param* rpb, JrdMemoryPool* pool)
{
/**************************************
@ -1804,12 +1695,6 @@ bool VIO_get(thread_db* tdbb, record_param* rpb, RecordSource* rsb, jrd_tra* tra
return false;
}
#ifdef PC_ENGINE
if (rsb && rsb->rsb_flags & rsb_stream_type) {
RNG_add_page(rpb->rpb_page);
}
#endif
#ifdef VIO_DEBUG
if (debug_flag > DEBUG_READS_INFO) {
printf
@ -2486,11 +2371,6 @@ bool VIO_next_record(thread_db* tdbb,
return false;
} while (!VIO_chase_record_version(tdbb, rpb, rsb, transaction, pool, false));
#ifdef PC_ENGINE
if (rsb && rsb->rsb_flags & rsb_stream_type)
RNG_add_page(rpb->rpb_page);
#endif
if (pool) {
VIO_data(tdbb, rpb, pool);
}

View File

@ -40,9 +40,6 @@ void VIO_backout(Jrd::thread_db*, Jrd::record_param*, const Jrd::jrd_tra*);
void VIO_bump_count(Jrd::thread_db*, USHORT, Jrd::jrd_rel*, bool);
bool VIO_chase_record_version(Jrd::thread_db*, Jrd::record_param*, Jrd::RecordSource*,
Jrd::jrd_tra*, JrdMemoryPool*, bool);
#ifdef PC_ENGINE
bool VIO_check_if_updated(Jrd::thread_db*, Jrd::record_param*);
#endif
void VIO_data(Jrd::thread_db*, Jrd::record_param*, JrdMemoryPool*);
void VIO_erase(Jrd::thread_db*, Jrd::record_param*, Jrd::jrd_tra*);
#ifdef GARBAGE_THREAD