mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 22:43:04 +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.
Fifth step: remove the aforementioned files. More to come.
This commit is contained in:
parent
151b6555d1
commit
87637b49de
@ -1,182 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Access Method
|
||||
* MODULE: bookmark.cpp
|
||||
* DESCRIPTION: Bookmark Handler
|
||||
*
|
||||
* The contents of this file are subject to the Interbase Public
|
||||
* License Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.Inprise.com/IPL.html
|
||||
*
|
||||
* Software distributed under the License is distributed on an
|
||||
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Inprise Corporation
|
||||
* and its predecessors. Portions created by Inprise Corporation are
|
||||
* Copyright (C) Inprise Corporation.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../jrd/jrd.h"
|
||||
#include "../jrd/exe.h"
|
||||
#include "../jrd/rse.h"
|
||||
#include "gen/iberror.h"
|
||||
#include "../jrd/all_proto.h"
|
||||
#include "../jrd/bookmark.h"
|
||||
#include "../jrd/err_proto.h"
|
||||
#include "../jrd/evl_proto.h"
|
||||
#include "../jrd/mov_proto.h"
|
||||
#include "../jrd/thd.h"
|
||||
|
||||
using namespace Jrd;
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
Bookmark* BKM_allocate(RecordSource* rsb, USHORT length)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* B K M _ a l l o c a t e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Allocate and initialize a bookmark structure.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Database* dbb = tdbb->tdbb_database;
|
||||
jrd_req* request = tdbb->tdbb_request;
|
||||
irsb* impure = (irsb*) ((UCHAR *) request + rsb->rsb_impure);
|
||||
|
||||
/* allocate the bookmark and link it into the
|
||||
linked list hanging off the attachment block */
|
||||
|
||||
Bookmark* bookmark = FB_NEW_RPT(*dbb->dbb_permanent, length) Bookmark();
|
||||
|
||||
Attachment* attachment = tdbb->tdbb_attachment;
|
||||
bookmark->bkm_next = attachment->att_bookmarks;
|
||||
attachment->att_bookmarks = bookmark;
|
||||
|
||||
/* set up a self-referential descriptor to contain the pointer
|
||||
to the bookmark block; used for convenience in passing the
|
||||
bookmark descriptor around within looper() */
|
||||
|
||||
bookmark->bkm_desc.dsc_dtype = dtype_long;
|
||||
bookmark->bkm_desc.dsc_length = sizeof(SLONG);
|
||||
bookmark->bkm_desc.dsc_address = (UCHAR *) & bookmark->bkm_handle;
|
||||
#if SIZEOF_VOID_P != 8
|
||||
bookmark->bkm_handle = (ULONG) bookmark;
|
||||
#else
|
||||
{
|
||||
/* The bookmark 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 active bookmarks
|
||||
and give the user an index into this vector. When the user releases
|
||||
a bookmark, its slot in the vector is zeroed and it becomes available
|
||||
for reuse. */
|
||||
|
||||
const ULONG slot =
|
||||
ALL_get_free_object(dbb->dbb_permanent,
|
||||
&attachment->att_bkm_quick_ref, 50);
|
||||
(*attachment->att_bkm_quick_ref)[slot] = bookmark;
|
||||
bookmark->bkm_handle = slot;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set up the bookmark flags */
|
||||
|
||||
if (impure->irsb_flags & irsb_bof)
|
||||
bookmark->bkm_flags |= bkm_bof;
|
||||
else if (impure->irsb_flags & irsb_eof)
|
||||
bookmark->bkm_flags |= bkm_eof;
|
||||
else if (impure->irsb_flags & irsb_crack) {
|
||||
bookmark->bkm_flags |= bkm_crack;
|
||||
if (impure->irsb_flags & irsb_forced_crack)
|
||||
bookmark->bkm_flags |= bkm_forced_crack;
|
||||
}
|
||||
|
||||
return bookmark;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
Bookmark* BKM_lookup(jrd_nod* node)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* B K M _ l o o k u p
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Find a bookmark using a user supplied value.
|
||||
*
|
||||
**************************************/
|
||||
Bookmark* bookmark;
|
||||
|
||||
#if SIZEOF_VOID_P != 8
|
||||
bookmark = (Bookmark*) MOV_get_long(EVL_expr(tdbb, node), 0);
|
||||
#else
|
||||
{
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Attachment* attachment = tdbb->tdbb_attachment;
|
||||
|
||||
bookmark = NULL;
|
||||
const ULONG slot = MOV_get_long(EVL_expr(tdbb, node), 0);
|
||||
vec<Bookmark*>* vector = attachment->att_bkm_quick_ref;
|
||||
if (vector && slot < vector->count()) {
|
||||
bookmark = (*vector)[slot];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!bookmark || bookmark->bkm_header.blk_type != type_bkm)
|
||||
ERR_post(gds__invalid_bookmark, 0);
|
||||
|
||||
return bookmark;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
void BKM_release(jrd_nod* node)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* B K M _ r e l e a s e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Release a bookmark using a user supplied value.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Attachment* attachment = tdbb->tdbb_attachment;
|
||||
|
||||
Bookmark* bookmark = BKM_lookup(node);
|
||||
|
||||
/* unlink the bookmark from the attachment linked list */
|
||||
|
||||
for (Bookmark** bptr = &attachment->att_bookmarks; *bptr; bptr = &(*bptr)->bkm_next)
|
||||
if (*bptr == bookmark) {
|
||||
*bptr = bookmark->bkm_next;
|
||||
break;
|
||||
}
|
||||
|
||||
#if SIZEOF_VOID_P == 8
|
||||
const ULONG slot = MOV_get_long(EVL_expr(tdbb, node), 0);
|
||||
(*attachment->att_bkm_quick_ref)[slot] = NULL;
|
||||
#endif
|
||||
|
||||
ALL_release(bookmark);
|
||||
}
|
||||
#endif
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Access Method
|
||||
* MODULE: bookmark.h
|
||||
* DESCRIPTION: Prototype header file for bookmark.cpp
|
||||
*
|
||||
* The contents of this file are subject to the Interbase Public
|
||||
* License Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.Inprise.com/IPL.html
|
||||
*
|
||||
* Software distributed under the License is distributed on an
|
||||
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Inprise Corporation
|
||||
* and its predecessors. Portions created by Inprise Corporation are
|
||||
* Copyright (C) Inprise Corporation.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef JRD_BOOKMARK_H
|
||||
#define JRD_BOOKMARK_H
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
Jrd::Bookmark* BKM_allocate(Jrd::RecordSource*, USHORT);
|
||||
Jrd::Bookmark* BKM_lookup(Jrd::jrd_nod*);
|
||||
void BKM_release(Jrd::jrd_nod*);
|
||||
#endif
|
||||
|
||||
#endif /* JRD_BOOKMARK_H */
|
852
src/jrd/rng.cpp
852
src/jrd/rng.cpp
@ -1,852 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Access Method
|
||||
* MODULE: rng.cpp
|
||||
* DESCRIPTION: Refresh Range Handler
|
||||
*
|
||||
* The contents of this file are subject to the Interbase Public
|
||||
* License Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.Inprise.com/IPL.html
|
||||
*
|
||||
* Software distributed under the License is distributed on an
|
||||
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Inprise Corporation
|
||||
* and its predecessors. Portions created by Inprise Corporation are
|
||||
* Copyright (C) Inprise Corporation.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../jrd/common.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "../jrd/jrd.h"
|
||||
#include "../jrd/req.h"
|
||||
#include "../jrd/ods.h"
|
||||
#include "../jrd/val.h"
|
||||
#include "../jrd/exe.h"
|
||||
#include "gen/iberror.h"
|
||||
#include "../jrd/rse.h"
|
||||
#include "../jrd/lck.h"
|
||||
#include "../jrd/cch.h"
|
||||
#include "../jrd/rng.h"
|
||||
#include "../jrd/sbm.h"
|
||||
#include "../jrd/all.h"
|
||||
#include "../jrd/intl.h"
|
||||
#include "../jrd/tra.h"
|
||||
#include "../jrd/all_proto.h"
|
||||
#include "../jrd/cch_proto.h"
|
||||
#include "../jrd/err_proto.h"
|
||||
#include "../jrd/evl_proto.h"
|
||||
|
||||
#include "../jrd/lck_proto.h"
|
||||
#include "../jrd/mov_proto.h"
|
||||
#include "../jrd/rlck_proto.h"
|
||||
#include "../jrd/rng_proto.h"
|
||||
#include "../jrd/thd.h"
|
||||
#include "../jrd/tra_proto.h"
|
||||
#include "../jrd/event_proto.h"
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
static void delete_range(RefreshRange*);
|
||||
static void post_event(RefreshRange*);
|
||||
static int post_event_ast(void*);
|
||||
static void stop_creating(RefreshRange*);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
void RNG_add_page(ULONG page_number)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* R N G _ a d d _ p a g e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Add page lock to any refresh range(s)
|
||||
* currently being defined.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
jrd_req* request = tdbb->tdbb_request;
|
||||
|
||||
RefreshRange* next_refresh_range;
|
||||
for (RefreshRange* refresh_range = request->req_begin_ranges; refresh_range;
|
||||
refresh_range = next_refresh_range)
|
||||
{
|
||||
next_refresh_range = refresh_range->rng_next;
|
||||
if (refresh_range->rng_flags & RNG_posted)
|
||||
continue;
|
||||
|
||||
/* see if this refresh range already has a page lock on this page */
|
||||
|
||||
bool next_range = false;
|
||||
vec<Lock*>* page_locks = refresh_range->rng_page_locks;
|
||||
if (page_locks) {
|
||||
for (size_t i = 0; i < refresh_range->rng_pages; i++) {
|
||||
Lock* page_lock = (*page_locks)[i];
|
||||
if (page_lock->lck_key.lck_long == page_number) {
|
||||
next_range = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (next_range)
|
||||
continue;
|
||||
|
||||
/* allocate and set up the page lock for this page */
|
||||
|
||||
Lock* page_lock = CCH_page_lock(tdbb);
|
||||
page_lock->lck_key.lck_long = page_number;
|
||||
page_lock->lck_ast = post_event_ast;
|
||||
page_lock->lck_object = refresh_range;
|
||||
|
||||
/* if we can get the lock, place it in a vector of page locks for this
|
||||
refresh range; otherwise just post the range event assuming that the
|
||||
page is being updated */
|
||||
|
||||
if (LCK_lock_non_blocking(tdbb, page_lock, LCK_read, LCK_NO_WAIT)) {
|
||||
/* place all page locks into a vector */
|
||||
|
||||
page_locks = ALL_vector(request->req_pool,
|
||||
&refresh_range->rng_page_locks,
|
||||
EXTEND(refresh_range->rng_pages));
|
||||
(*page_locks)[refresh_range->rng_pages] = page_lock;
|
||||
refresh_range->rng_pages++;
|
||||
}
|
||||
else {
|
||||
post_event(refresh_range);
|
||||
delete_range(refresh_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
void RNG_add_record(record_param* rpb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* R N G _ a d d _ r e c o r d
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Add record to refresh range(s)
|
||||
* currently being defined.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
jrd_req* request = tdbb->tdbb_request;
|
||||
|
||||
RefreshRange* next_refresh_range;
|
||||
for (RefreshRange* refresh_range = request->req_begin_ranges; refresh_range;
|
||||
refresh_range = next_refresh_range)
|
||||
{
|
||||
next_refresh_range = refresh_range->rng_next;
|
||||
if (refresh_range->rng_flags & RNG_posted)
|
||||
continue;
|
||||
|
||||
/* see if this refresh range already has a lock on this record */
|
||||
|
||||
bool next_range = false;
|
||||
vec<Lock*> record_locks = refresh_range->rng_record_locks;
|
||||
if (record_locks) {
|
||||
for (size_t i = 0; i < refresh_range->rng_records; i++) {
|
||||
Lock* record_lock = (*record_locks)[i];
|
||||
if (record_lock->lck_key.lck_long == rpb->rpb_number) {
|
||||
next_range = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (next_range)
|
||||
continue;
|
||||
|
||||
/* get a lock on the passed record; if we can't, don't bother
|
||||
to wait for it or retry, just post the event to let the
|
||||
client know that an update is in process--if we're lucky
|
||||
the lock will be released before the client tries to reestablish
|
||||
the refresh range, otherwise we will thrash trying to establish */
|
||||
|
||||
Lock* record_lock = RLCK_lock_record(rpb, LCK_PR,
|
||||
post_event_ast,
|
||||
refresh_range);
|
||||
if (!record_lock) {
|
||||
post_event(refresh_range);
|
||||
delete_range(refresh_range);
|
||||
}
|
||||
|
||||
/* place all record locks into a vector for easy access later */
|
||||
|
||||
record_locks = ALL_vector(request->req_pool,
|
||||
&refresh_range->rng_record_locks,
|
||||
EXTEND(refresh_range->rng_records));
|
||||
(*record_locks)[refresh_range->rng_records] = record_lock;
|
||||
refresh_range->rng_records++;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
jrd_nod* RNG_add_relation(jrd_nod* node)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* R N G _ a d d _ r e l a t i o n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Add relation to refresh range(s)
|
||||
* currently being defined.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
jrd_req* request = tdbb->tdbb_request;
|
||||
|
||||
if (request->req_operation == req_evaluate) {
|
||||
const dsc* desc = EVL_expr(tdbb, node->nod_arg[e_range_relation_number]);
|
||||
const size_t range_number = (USHORT) MOV_get_long(desc, 0);
|
||||
|
||||
jrd_nod* relation_node = node->nod_arg[e_range_relation_relation];
|
||||
jrd_rel* relation = (jrd_rel*) relation_node->nod_arg[e_rel_relation];
|
||||
|
||||
/* check to see if the range exists */
|
||||
|
||||
RefreshRange* refresh_range;
|
||||
vec<RefreshRange*>* refresh_ranges = request->req_refresh_ranges;
|
||||
if (refresh_ranges &&
|
||||
(range_number < refresh_ranges->count()) &&
|
||||
(refresh_range = (*refresh_ranges)[range_number]))
|
||||
{
|
||||
/* lock the relation in such a way that we'll be notified
|
||||
if it is locked for update; if we can't get the lock just
|
||||
give up and post the range */
|
||||
|
||||
Lock* relation_lock = RLCK_range_relation(request->req_transaction,
|
||||
relation,
|
||||
post_event_ast,
|
||||
refresh_range);
|
||||
if (!relation_lock) {
|
||||
post_event(refresh_range);
|
||||
delete_range(refresh_range);
|
||||
}
|
||||
|
||||
/* place all relation locks into a vector for easy access later */
|
||||
|
||||
vec<Lock*> relation_locks = ALL_vector(request->req_pool,
|
||||
&refresh_range->rng_relation_locks,
|
||||
EXTEND(refresh_range->rng_relations));
|
||||
(*relation_locks)[refresh_range->rng_relations] = relation_lock;
|
||||
/* Unused stuff.
|
||||
vec<jrd_tra*>* relation_locks2 =
|
||||
ALL_vector(request->req_pool,
|
||||
&refresh_range->rng_relation_trans,
|
||||
EXTEND(refresh_range->rng_relations));
|
||||
(*relation_locks2)[refresh_range->rng_relations] = request->req_transaction;
|
||||
*/
|
||||
refresh_range->rng_relations++;
|
||||
|
||||
}
|
||||
request->req_operation = req_return;
|
||||
}
|
||||
|
||||
return node->nod_parent;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
void RNG_add_uncommitted_record(record_param* rpb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* R N G _ a d d _ u n c o m m i t t e d _ r e c o r d
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Add interest in an uncommitted record version to
|
||||
* any refresh ranges being created. This is done by
|
||||
* registering interest in the transaction that created it.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
jrd_req* request = tdbb->tdbb_request;
|
||||
|
||||
RefreshRange* next_refresh_range;
|
||||
for (RefreshRange* refresh_range = request->req_begin_ranges; refresh_range;
|
||||
refresh_range = next_refresh_range)
|
||||
{
|
||||
next_refresh_range = refresh_range->rng_next;
|
||||
if (refresh_range->rng_flags & RNG_posted)
|
||||
continue;
|
||||
|
||||
/* see if this refresh range already has a lock on this record */
|
||||
|
||||
bool next_range = false;
|
||||
vec<Lock*>* transaction_locks = refresh_range->rng_transaction_locks;
|
||||
if (transaction_locks)
|
||||
{
|
||||
for (size_t i = 0; i < refresh_range->rng_transactions; i++) {
|
||||
Lock* transaction_lock = (*transaction_locks)[i];
|
||||
if (transaction_lock->lck_key.lck_long ==
|
||||
rpb->rpb_transaction_nr)
|
||||
{
|
||||
next_range = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (next_range)
|
||||
continue;
|
||||
|
||||
// We aren't using this code, but passing txn number is plain wrong.
|
||||
// Passing refresh_range (type compatible) will achieve the same result
|
||||
// than having to correct the lck_object data member.
|
||||
Lock* transaction_lock =
|
||||
TRA_transaction_lock(tdbb, refresh_range);//rpb->rpb_transaction_nr);
|
||||
transaction_lock->lck_key.lck_long = rpb->rpb_transaction_nr;
|
||||
transaction_lock->lck_ast = post_event_ast;
|
||||
//transaction_lock->lck_object = refresh_range;
|
||||
|
||||
/* try to get a shared read on the transaction lock, which will force
|
||||
the holder of an exclusive lock to downgrade; this is also his notification
|
||||
that he needs to upgrade back to exclusive at transaction commit */
|
||||
|
||||
if (LCK_lock_non_blocking(tdbb, transaction_lock, LCK_SR, LCK_WAIT)) {
|
||||
/* place all transaction locks into a vector */
|
||||
|
||||
transaction_locks = ALL_vector(request->req_pool,
|
||||
&refresh_range->rng_transaction_locks,
|
||||
EXTEND
|
||||
(refresh_range->rng_transactions));
|
||||
(*transaction_locks)[refresh_range->rng_transactions] = transaction_lock;
|
||||
refresh_range->rng_transactions++;
|
||||
}
|
||||
else {
|
||||
post_event(refresh_range);
|
||||
delete_range(refresh_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
DSC *RNG_begin(jrd_nod* node, impure_value* impure)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* R N G _ b e g i n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Initialize a refresh range.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
jrd_req* request = tdbb->tdbb_request;
|
||||
Database* dbb = tdbb->tdbb_database;
|
||||
jrd_tra* transaction = request->req_transaction;
|
||||
|
||||
/* check to make sure the range number is not already in use */
|
||||
|
||||
const dsc* desc2 = EVL_expr(tdbb, node->nod_arg[e_brange_number]);
|
||||
const size_t range_number = (USHORT) MOV_get_long(desc2, 0);
|
||||
|
||||
RefreshRange* refresh_range;
|
||||
vec<RefreshRange*>* refresh_ranges = request->req_refresh_ranges;
|
||||
if (refresh_ranges &&
|
||||
(range_number < refresh_ranges->count()) &&
|
||||
(refresh_range = (*refresh_ranges)[range_number]))
|
||||
{
|
||||
if (refresh_range->rng_flags & RNG_posted)
|
||||
delete_range(refresh_range);
|
||||
else
|
||||
ERR_post(isc_range_in_use, isc_arg_number, (SLONG) range_number,
|
||||
0);
|
||||
}
|
||||
|
||||
/* generate a name unique to this particular event within this database,
|
||||
of the form "ISC_$RANGE_<tid>_<range_id>
|
||||
use the transaction id as a start, even though this event is not
|
||||
related to the transction per se; it is just a means of generating
|
||||
an id unique to the database */
|
||||
|
||||
char event_name[RANGE_NAME_LENGTH];
|
||||
char* p = event_name;
|
||||
for (const char* q = "ISC$RANGE_"; *q;)
|
||||
*p++ = *q++;
|
||||
|
||||
/* move in the transaction id */
|
||||
|
||||
sprintf(p, "%ld_", transaction->tra_number);
|
||||
while (*p)
|
||||
p++;
|
||||
|
||||
/* move in the transaction-unique cache range id */
|
||||
|
||||
sprintf(p, "%ld", transaction->tra_range_id++);
|
||||
while (*p)
|
||||
p++;
|
||||
|
||||
/* allocate the range block and move the event name into it */
|
||||
|
||||
refresh_range = FB_NEW_RPT(*tdbb->getDefaultPool(), p - event_name + 1) RefreshRange();
|
||||
refresh_range->rng_event_length = p - event_name;
|
||||
strcpy(refresh_range->rng_event, event_name);
|
||||
|
||||
/* fill out the descriptor to point to the event name */
|
||||
|
||||
impure->vlu_desc.dsc_dtype = dtype_text;
|
||||
impure->vlu_desc.dsc_scale = 0;
|
||||
impure->vlu_desc.dsc_ttype() = ttype_ascii;
|
||||
impure->vlu_desc.dsc_address = refresh_range->rng_event;
|
||||
impure->vlu_desc.dsc_length = refresh_range->rng_event_length;
|
||||
|
||||
/* save the range's attachment */
|
||||
|
||||
refresh_range->rng_attachment = tdbb->tdbb_attachment;
|
||||
|
||||
/* put the refresh range into a vector of ranges for this request */
|
||||
|
||||
refresh_range->rng_number = range_number;
|
||||
refresh_ranges =
|
||||
ALL_vector(tdbb->getDefaultPool(), &request->req_refresh_ranges,
|
||||
EXTEND(range_number));
|
||||
(*refresh_ranges)[range_number] = refresh_range;
|
||||
|
||||
/* insert the range into the list of ranges actively being created */
|
||||
|
||||
refresh_range->rng_next = request->req_begin_ranges;
|
||||
request->req_begin_ranges = refresh_range;
|
||||
++dbb->dbb_refresh_ranges;
|
||||
|
||||
/* downgrade ourselves to avoid selfdeadlock if another user attaches */
|
||||
|
||||
CCH_down_grade_dbb(dbb);
|
||||
|
||||
return &impure->vlu_desc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
jrd_nod* RNG_delete(jrd_nod* node)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* R N G _ d e l e t e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Delete a previously created refresh range.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
jrd_req* request = tdbb->tdbb_request;
|
||||
|
||||
if (request->req_operation == req_evaluate) {
|
||||
const dsc* desc = EVL_expr(tdbb, node->nod_arg[e_drange_number]);
|
||||
const size_t range_number = (USHORT) MOV_get_long(desc, 0);
|
||||
|
||||
/* check to see if the range exists */
|
||||
RefreshRange* refresh_range;
|
||||
vec<RefreshRange*>* refresh_ranges = request->req_refresh_ranges;
|
||||
if (!refresh_ranges ||
|
||||
(range_number >= refresh_ranges->count()) ||
|
||||
!(refresh_range = (*refresh_ranges)[range_number]))
|
||||
{
|
||||
ERR_post(isc_range_not_found, isc_arg_number,
|
||||
(SLONG) range_number, 0);
|
||||
}
|
||||
|
||||
delete_range(refresh_range);
|
||||
|
||||
request->req_operation = req_return;
|
||||
}
|
||||
|
||||
return node->nod_parent;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
void RNG_delete_ranges(jrd_req* request)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* R N G _ d e l e t e _ r a n g e s
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Delete all refresh ranges in a request.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
/* release all refresh ranges associated with request */
|
||||
vec<RefreshRange*>* refresh_ranges = request->req_refresh_ranges;
|
||||
if (refresh_ranges) {
|
||||
for (size_t range_number = 0; range_number < refresh_ranges->count();
|
||||
range_number++)
|
||||
{
|
||||
RefreshRange* refresh_range = (*refresh_ranges)[range_number];
|
||||
if (refresh_range)
|
||||
delete_range(refresh_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
jrd_nod* RNG_end(jrd_nod* node)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* R N G _ e n d
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Stop adding records to refresh range.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
jrd_req* request = tdbb->tdbb_request;
|
||||
|
||||
if (request->req_operation == req_evaluate) {
|
||||
const dsc* desc = EVL_expr(tdbb, node->nod_arg[e_erange_number]);
|
||||
const size_t range_number = (USHORT) MOV_get_long(desc, 0);
|
||||
|
||||
/* check to see if the range exists */
|
||||
RefreshRange* refresh_range;
|
||||
vec<RefreshRange*>* refresh_ranges = request->req_refresh_ranges;
|
||||
if (refresh_ranges &&
|
||||
(range_number < refresh_ranges->count()) &&
|
||||
(refresh_range = (*refresh_ranges)[range_number]))
|
||||
{
|
||||
/* if we've already posted the range, go ahead
|
||||
and delete it; otherwise stop adding locks */
|
||||
|
||||
if (refresh_range->rng_flags & RNG_posted)
|
||||
delete_range(refresh_range);
|
||||
else
|
||||
stop_creating(refresh_range);
|
||||
}
|
||||
|
||||
request->req_operation = req_return;
|
||||
}
|
||||
|
||||
return node->nod_parent;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
void RNG_release_locks(RefreshRange* refresh_range)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* R N G _ r e l e a s e _ l o c k s
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Release all locks held by a refresh range.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
/* release all the relation locks */
|
||||
|
||||
if (refresh_range->rng_relation_locks) {
|
||||
Lock** lock_ptr = &*refresh_range->rng_relation_locks->begin();
|
||||
for (int i = 0; i < refresh_range->rng_relations; i++) {
|
||||
LCK_release(tdbb, *lock_ptr);
|
||||
ALL_release(*lock_ptr);
|
||||
*lock_ptr = NULL;
|
||||
lock_ptr++;
|
||||
}
|
||||
}
|
||||
refresh_range->rng_relation_locks = 0;
|
||||
|
||||
/* release all the record locks */
|
||||
|
||||
if (refresh_range->rng_record_locks) {
|
||||
Lock** lock_ptr = &*refresh_range->rng_record_locks->begin();
|
||||
for (int i = 0; i < refresh_range->rng_records; i++) {
|
||||
RLCK_unlock_record(*lock_ptr, 0);
|
||||
*lock_ptr = NULL;
|
||||
lock_ptr++;
|
||||
}
|
||||
}
|
||||
refresh_range->rng_record_locks = 0;
|
||||
|
||||
/* release all page locks */
|
||||
|
||||
if (refresh_range->rng_page_locks) {
|
||||
Lock** lock_ptr = &*refresh_range->rng_page_locks->begin();
|
||||
for (int i = 0; i < refresh_range->rng_pages; i++) {
|
||||
LCK_release(tdbb, *lock_ptr);
|
||||
ALL_release(*lock_ptr);
|
||||
*lock_ptr = NULL;
|
||||
lock_ptr++;
|
||||
}
|
||||
}
|
||||
refresh_range->rng_page_locks = 0;
|
||||
|
||||
/* release all transaction locks */
|
||||
|
||||
if (refresh_range->rng_transaction_locks) {
|
||||
Lock** lock_ptr = &*refresh_range->rng_transaction_locks->begin();
|
||||
for (int i = 0; i < refresh_range->rng_transactions; i++) {
|
||||
LCK_release(tdbb, *lock_ptr);
|
||||
ALL_release(*lock_ptr);
|
||||
*lock_ptr = NULL;
|
||||
lock_ptr++;
|
||||
}
|
||||
}
|
||||
refresh_range->rng_transaction_locks = 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
void RNG_release_ranges(jrd_req* request)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* R N G _ r e l e a s e _ r a n g e s
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Release the locks for all ranges in a request.
|
||||
*
|
||||
**************************************/
|
||||
Database* dbb = GET_DBB();
|
||||
|
||||
vec<RefreshRange*>* refresh_ranges = request->req_refresh_ranges;
|
||||
if (refresh_ranges) {
|
||||
for (size_t range_number = 0; range_number < refresh_ranges->count();
|
||||
range_number++)
|
||||
{
|
||||
RefreshRange* refresh_range = (*refresh_ranges)[range_number];
|
||||
if (refresh_range) {
|
||||
RNG_release_locks(refresh_range);
|
||||
--dbb->dbb_refresh_ranges;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
void RNG_shutdown_attachment(Attachment* attachment)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* R N G _ s h u t d o w n _ a t t a c h m e n t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Release refresh range locks for an attachment.
|
||||
* This may be called at AST level, don't release memory.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
for (jrd_req* request = attachment->att_requests; request;
|
||||
request = request->req_request)
|
||||
{
|
||||
vec<RefreshRange*>* refresh_ranges = request->req_refresh_ranges;
|
||||
if (refresh_ranges)
|
||||
{
|
||||
for (size_t range_number = 0; range_number < refresh_ranges->count();
|
||||
range_number++)
|
||||
{
|
||||
RefreshRange* refresh_range = (*refresh_ranges)[range_number];
|
||||
if (refresh_range)
|
||||
{
|
||||
/* Shutdown range page locks */
|
||||
|
||||
if (refresh_range->rng_page_locks) {
|
||||
Lock** lock_ptr = &*refresh_range->rng_page_locks->begin();
|
||||
for (int i = 0; i < refresh_range->rng_pages; i++) {
|
||||
LCK_release(tdbb, *lock_ptr);
|
||||
lock_ptr++;
|
||||
}
|
||||
}
|
||||
/* Shutdown range transaction locks */
|
||||
|
||||
if (refresh_range->rng_transaction_locks) {
|
||||
Lock** lock_ptr = &*refresh_range->rng_transaction_locks->begin();
|
||||
for (int i = 0; i < refresh_range->rng_transactions; i++) {
|
||||
LCK_release(tdbb, *lock_ptr);
|
||||
lock_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
static void delete_range(RefreshRange* refresh_range)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* d e l e t e _ r a n g e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Release all resources associated with
|
||||
* a refresh range.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Database* dbb = tdbb->tdbb_database;
|
||||
jrd_req* request = tdbb->tdbb_request;
|
||||
|
||||
/* remove from the vector of refresh ranges for the request */
|
||||
|
||||
vec<RefreshRange*>* refresh_ranges = request->req_refresh_ranges;
|
||||
(*refresh_ranges)[refresh_range->rng_number] = NULL;
|
||||
|
||||
stop_creating(refresh_range);
|
||||
|
||||
if (!(refresh_range->rng_flags & RNG_posted))
|
||||
RNG_release_locks(refresh_range);
|
||||
|
||||
ALL_release(refresh_range);
|
||||
--dbb->dbb_refresh_ranges;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
static void post_event(RefreshRange* refresh_range)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p o s t _ e v e n t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Post the event associated with the
|
||||
* refresh range.
|
||||
*
|
||||
**************************************/
|
||||
Database* dbb = GET_DBB();
|
||||
Lock* dbb_lock = dbb->dbb_lock;
|
||||
|
||||
/* detect duplicate posts and filter them out */
|
||||
|
||||
if (refresh_range->rng_flags & RNG_posted)
|
||||
return;
|
||||
refresh_range->rng_flags |= RNG_posted;
|
||||
|
||||
/* post the event to the interested client */
|
||||
|
||||
ISC_STATUS_ARRAY status;
|
||||
EVENT_post(status,
|
||||
dbb_lock->lck_length,
|
||||
(TEXT *) & dbb_lock->lck_key,
|
||||
refresh_range->rng_event_length, refresh_range->rng_event, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
static int post_event_ast(void* refresh_range_void)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p o s t _ e v e n t _ a s t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Post the event associated with the
|
||||
* refresh range.
|
||||
*
|
||||
**************************************/
|
||||
thread_db thd_context, *tdbb;
|
||||
|
||||
/* Since this routine will be called asynchronously, we must establish
|
||||
a thread context. */
|
||||
|
||||
JRD_set_thread_data(tdbb, thd_context);
|
||||
|
||||
RefreshRange* refresh_range = static_cast<RefreshRange*>(refresh_range_void);
|
||||
tdbb->tdbb_database = refresh_range->rng_attachment->att_database;
|
||||
tdbb->tdbb_attachment = refresh_range->rng_attachment;
|
||||
tdbb->tdbb_quantum = QUANTUM;
|
||||
tdbb->tdbb_request = NULL;
|
||||
tdbb->tdbb_transaction = NULL;
|
||||
|
||||
post_event(refresh_range);
|
||||
RNG_release_locks(refresh_range);
|
||||
|
||||
/* Restore the prior thread context */
|
||||
|
||||
JRD_restore_thread_data();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
static void stop_creating(RefreshRange* refresh_range)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* s t o p _ c r e a t i n g
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Remove the refresh range from the list of
|
||||
* those being created.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
jrd_req* request = tdbb->tdbb_request;
|
||||
|
||||
/* delete from the list of ranges being created */
|
||||
|
||||
for (RefreshRange** ptr = &request->req_begin_ranges; *ptr;
|
||||
ptr = &(*ptr)->rng_next)
|
||||
{
|
||||
if (*ptr == refresh_range) {
|
||||
*ptr = (*ptr)->rng_next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Access Method
|
||||
* MODULE: rng.h
|
||||
* DESCRIPTION: Refresh Range Definitions
|
||||
*
|
||||
* The contents of this file are subject to the Interbase Public
|
||||
* License Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.Inprise.com/IPL.html
|
||||
*
|
||||
* Software distributed under the License is distributed on an
|
||||
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Inprise Corporation
|
||||
* and its predecessors. Portions created by Inprise Corporation are
|
||||
* Copyright (C) Inprise Corporation.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef JRD_RNG_H
|
||||
#define JRD_RNG_H
|
||||
|
||||
/* refresh range block used to store info about a particular
|
||||
set of records in a refresh range */
|
||||
|
||||
namespace Jrd {
|
||||
class Attachment;
|
||||
template <typename T> class vec;
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
class RefreshRange : public pool_alloc_rpt<SCHAR, type_rng>
|
||||
{
|
||||
public:
|
||||
RefreshRange* rng_next; /* next in list of ranges being created */
|
||||
Attachment* rng_attachment; /* attachment that owns range */
|
||||
RefreshRange* rng_lck_next; /* next in list of ranges interested in a lock */
|
||||
vec<Lock*>* rng_relation_locks; /* relation locks */
|
||||
// vec<jrd_tra*>* rng_relation_trans; // relation transactions CVC: Unused stuff.
|
||||
vec<Lock*>* rng_record_locks; /* record locks */
|
||||
vec<Lock*>* rng_page_locks; /* page locks */
|
||||
vec<Lock*>* rng_transaction_locks; /* transaction locks */
|
||||
USHORT rng_relations; /* count of relations in range */
|
||||
USHORT rng_records; /* count of records in range */
|
||||
USHORT rng_pages; /* count of index pages in range */
|
||||
USHORT rng_transactions; /* count of uncommitted transactions in range */
|
||||
USHORT rng_number; /* range number */
|
||||
USHORT rng_flags; /* see flags below */
|
||||
USHORT rng_event_length; /* length of event name */
|
||||
UCHAR rng_event[1]; /* event name to post */
|
||||
};
|
||||
|
||||
const USHORT RNG_posted = 1; /* range has already been posted */
|
||||
|
||||
const int RANGE_NAME_LENGTH = 31; /* max. length of range name for the event */
|
||||
#endif
|
||||
|
||||
} //namespace Jrd
|
||||
|
||||
#endif // JRD_RNG_H
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Access Method
|
||||
* MODULE: rng_proto.h
|
||||
* DESCRIPTION: Prototype header file for rng.cpp
|
||||
*
|
||||
* The contents of this file are subject to the Interbase Public
|
||||
* License Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.Inprise.com/IPL.html
|
||||
*
|
||||
* Software distributed under the License is distributed on an
|
||||
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Inprise Corporation
|
||||
* and its predecessors. Portions created by Inprise Corporation are
|
||||
* Copyright (C) Inprise Corporation.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef JRD_RNG_PROTO_H
|
||||
#define JRD_RNG_PROTO_H
|
||||
|
||||
#ifdef PC_ENGINE
|
||||
|
||||
namespace Jrd {
|
||||
class jrd_req;
|
||||
struct record_param;
|
||||
class jrd_nod;
|
||||
class RefreshRange;
|
||||
struct impure_value;
|
||||
class Attachment;
|
||||
}
|
||||
|
||||
struct dsc;
|
||||
|
||||
void RNG_add_page(ULONG);
|
||||
void RNG_add_record(Jrd::record_param*);
|
||||
jrd_nod* RNG_add_relation(Jrd::jrd_nod*);
|
||||
void RNG_add_uncommitted_record(Jrd::record_param*);
|
||||
dsc *RNG_begin(Jrd::jrd_nod*, Jrd::impure_value*);
|
||||
jrd_nod *RNG_delete(Jrd::jrd_nod*);
|
||||
void RNG_delete_ranges(Jrd::jrd_req *);
|
||||
jrd_nod* RNG_end(Jrd::jrd_nod*);
|
||||
void RNG_release_locks(Jrd::RefreshRange*);
|
||||
void RNG_release_ranges(Jrd::jrd_req *);
|
||||
void RNG_shutdown_attachment(Jrd::Attachment*);
|
||||
#endif
|
||||
|
||||
#endif // JRD_RNG_PROTO_H
|
||||
|
Loading…
Reference in New Issue
Block a user