mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 17:23:04 +01:00
The merge continued.
This commit is contained in:
parent
6cb91c6433
commit
6666fd1e4a
1317
src/jrd/SimilarToMatcher.h
Normal file
1317
src/jrd/SimilarToMatcher.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -33,6 +33,7 @@
|
||||
|
||||
#include "../jrd/exe.h"
|
||||
#include "../jrd/RecordNumber.h"
|
||||
#include "../common/classes/stack.h"
|
||||
#include "../common/classes/timestamp.h"
|
||||
|
||||
|
||||
@ -108,8 +109,9 @@ const USHORT rpb_gc_active = 256; /* garbage collecting dead record version */
|
||||
|
||||
/* Stream flags */
|
||||
|
||||
const USHORT RPB_s_refetch = 0x1; /* re-fetch required due to sort */
|
||||
const USHORT RPB_s_update = 0x2; /* input stream fetched for update */
|
||||
const USHORT RPB_s_refetch = 0x1; // re-fetch required due to sort
|
||||
const USHORT RPB_s_update = 0x2; // input stream fetched for update
|
||||
const USHORT RPB_s_no_data = 0x4; // nobody is going to access the data
|
||||
|
||||
#define SET_NULL(record, id) record->rec_data [id >> 3] |= (1 << (id & 7))
|
||||
#define CLEAR_NULL(record, id) record->rec_data [id >> 3] &= ~(1 << (id & 7))
|
||||
@ -190,7 +192,7 @@ public:
|
||||
req_blobs(pool), req_external(*pool), req_access(*pool), req_resources(*pool),
|
||||
req_trg_name(*pool), req_fors(*pool), req_exec_sta(*pool),
|
||||
req_invariants(*pool), req_timestamp(true), req_sql_text(*pool), req_domain_validation(NULL),
|
||||
req_map_field_info(*pool)
|
||||
req_map_field_info(*pool), req_map_item_info(*pool), req_auto_trans(*pool)
|
||||
{}
|
||||
|
||||
Attachment* req_attachment; // database attachment
|
||||
@ -256,6 +258,8 @@ public:
|
||||
|
||||
dsc* req_domain_validation; // Current VALUE for constraint validation
|
||||
MapFieldInfo req_map_field_info; // Map field name to field info
|
||||
MapItemInfo req_map_item_info; // Map item to item info
|
||||
Firebird::Stack<jrd_tra*> req_auto_trans; // Autonomous transactions
|
||||
|
||||
enum req_ta {
|
||||
// order should be maintained because the numbers are stored in BLR
|
||||
|
117
src/jrd/rlck.cpp
117
src/jrd/rlck.cpp
@ -26,28 +26,18 @@
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../jrd/common.h"
|
||||
#include "../jrd/jrd.h"
|
||||
#include "../jrd/tra.h"
|
||||
#include "../jrd/lck.h"
|
||||
#include "../jrd/req.h"
|
||||
#include "gen/iberror.h"
|
||||
#include "../jrd/all.h"
|
||||
#include "../jrd/err_proto.h"
|
||||
#include "../jrd/isc_proto.h"
|
||||
|
||||
#include "../jrd/lck_proto.h"
|
||||
#include "../jrd/rlck_proto.h"
|
||||
#include "../jrd/thd.h"
|
||||
#include "../jrd/vio_proto.h"
|
||||
|
||||
using namespace Jrd;
|
||||
|
||||
static Lock* allocate_relation_lock(MemoryPool*, jrd_rel*);
|
||||
|
||||
|
||||
Lock* RLCK_reserve_relation(thread_db* tdbb,
|
||||
jrd_tra* transaction,
|
||||
jrd_rel* relation, bool write_flag, bool error_flag)
|
||||
jrd_tra* transaction,
|
||||
jrd_rel* relation,
|
||||
bool write_flag)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -60,15 +50,19 @@ Lock* RLCK_reserve_relation(thread_db* tdbb,
|
||||
* is already locked at a lower level, upgrade the lock.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
if (transaction->tra_flags & TRA_system)
|
||||
return NULL;
|
||||
if (write_flag && (tdbb->getDatabase()->dbb_flags & DBB_read_only))
|
||||
ERR_post(isc_read_only_database, 0);
|
||||
if (write_flag && (transaction->tra_flags & TRA_readonly))
|
||||
ERR_post(isc_read_only_trans, 0);
|
||||
Lock* lock = RLCK_transaction_relation_lock(transaction, relation);
|
||||
|
||||
/* Next, figure out what kind of lock we need */
|
||||
|
||||
Lock* lock = RLCK_transaction_relation_lock(tdbb, transaction, relation);
|
||||
|
||||
// Next, figure out what kind of lock we need
|
||||
|
||||
USHORT level;
|
||||
if (transaction->tra_flags & TRA_degree3) {
|
||||
if (write_flag)
|
||||
@ -83,38 +77,30 @@ Lock* RLCK_reserve_relation(thread_db* tdbb,
|
||||
level = LCK_none;
|
||||
}
|
||||
|
||||
/* If the lock is already "good enough", we're done */
|
||||
// If the lock is already "good enough", we're done
|
||||
|
||||
if (level <= lock->lck_logical)
|
||||
return lock;
|
||||
|
||||
/* Nobody activates it. Same in FB1.
|
||||
if (transaction->tra_flags & TRA_reserving)
|
||||
{
|
||||
ERR_post(isc_unres_rel, isc_arg_string,
|
||||
relation->rel_name.c_str(), 0);
|
||||
}
|
||||
*/
|
||||
// Get lock
|
||||
|
||||
/* get lock */
|
||||
USHORT result;
|
||||
if (lock->lck_logical)
|
||||
result = LCK_convert_non_blocking(NULL, lock, level,
|
||||
result = LCK_convert_non_blocking(tdbb, lock, level,
|
||||
transaction->getLockWait());
|
||||
else
|
||||
result = LCK_lock_non_blocking(NULL, lock, level,
|
||||
result = LCK_lock_non_blocking(tdbb, lock, level,
|
||||
transaction->getLockWait());
|
||||
if (result)
|
||||
return lock;
|
||||
else {
|
||||
if (error_flag)
|
||||
ERR_punt();
|
||||
return NULL;
|
||||
}
|
||||
if (!result)
|
||||
ERR_punt();
|
||||
|
||||
return lock;
|
||||
}
|
||||
|
||||
|
||||
Lock* RLCK_transaction_relation_lock(jrd_tra* transaction, jrd_rel* relation)
|
||||
Lock* RLCK_transaction_relation_lock(thread_db* tdbb,
|
||||
jrd_tra* transaction,
|
||||
jrd_rel* relation)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -127,6 +113,8 @@ Lock* RLCK_transaction_relation_lock(jrd_tra* transaction, jrd_rel* relation)
|
||||
* a transaction.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
Lock* lock;
|
||||
vec<Lock*>* vector = transaction->tra_relation_locks;
|
||||
if (vector &&
|
||||
@ -139,53 +127,28 @@ Lock* RLCK_transaction_relation_lock(jrd_tra* transaction, jrd_rel* relation)
|
||||
vector = transaction->tra_relation_locks =
|
||||
vec<Lock*>::newVector(*transaction->tra_pool, transaction->tra_relation_locks,
|
||||
relation->rel_id + 1);
|
||||
|
||||
if ( (lock = (*vector)[relation->rel_id]) )
|
||||
return lock;
|
||||
|
||||
lock = allocate_relation_lock(transaction->tra_pool, relation);
|
||||
lock->lck_owner = transaction;
|
||||
/* for relations locked within a transaction, add a second level of
|
||||
compatibility within the intra-process lock manager which specifies
|
||||
that relation locks are incompatible with locks taken out by other
|
||||
transactions, if a transaction is specified */
|
||||
lock->lck_compatible2 = transaction;
|
||||
(*vector)[relation->rel_id] = lock;
|
||||
|
||||
return lock;
|
||||
}
|
||||
|
||||
|
||||
static Lock* allocate_relation_lock(MemoryPool* pool, jrd_rel* relation)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* a l l o c a t e _ r e l a t i o n _ l o c k
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Allocate a lock block for a relation lock.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
|
||||
SSHORT relLockLen = relation->getRelLockKeyLength();
|
||||
|
||||
Lock* lock = FB_NEW_RPT(*pool, relLockLen) Lock();
|
||||
lock->lck_dbb = dbb;
|
||||
const SSHORT relLockLen = relation->getRelLockKeyLength();
|
||||
lock = FB_NEW_RPT(*transaction->tra_pool, relLockLen) Lock();
|
||||
lock->lck_dbb = tdbb->tdbb_database;
|
||||
lock->lck_length = relLockLen;
|
||||
relation->getRelLockKey(tdbb, &lock->lck_key.lck_string[0]);
|
||||
lock->lck_type = LCK_relation;
|
||||
lock->lck_owner_handle = LCK_get_owner_handle(tdbb, lock->lck_type);
|
||||
lock->lck_parent = dbb->dbb_lock;
|
||||
/* enter all relation locks into the intra-process lock manager and treat
|
||||
them as compatible within the attachment according to IPLM rules */
|
||||
lock->lck_compatible = tdbb->getAttachment();
|
||||
/* the lck_object is used here to find the relation
|
||||
block from the lock block */
|
||||
lock->lck_parent = tdbb->tdbb_database->dbb_lock;
|
||||
// the lck_object is used here to find the relation
|
||||
// block from the lock block
|
||||
lock->lck_object = relation;
|
||||
// enter all relation locks into the intra-process lock manager and treat
|
||||
// them as compatible within the attachment according to IPLM rules
|
||||
lock->lck_compatible = tdbb->tdbb_attachment;
|
||||
// for relations locked within a transaction, add a second level of
|
||||
// compatibility within the intra-process lock manager which specifies
|
||||
// that relation locks are incompatible with locks taken out by other
|
||||
// transactions, if a transaction is specified
|
||||
lock->lck_compatible2 = transaction;
|
||||
|
||||
(*vector)[relation->rel_id] = lock;
|
||||
|
||||
return lock;
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,9 @@ namespace Jrd {
|
||||
}
|
||||
|
||||
Jrd::Lock* RLCK_reserve_relation(Jrd::thread_db*, Jrd::jrd_tra*,
|
||||
Jrd::jrd_rel*, bool, bool);
|
||||
Jrd::Lock* RLCK_transaction_relation_lock(Jrd::jrd_tra*, Jrd::jrd_rel*);
|
||||
Jrd::jrd_rel*, bool);
|
||||
Jrd::Lock* RLCK_transaction_relation_lock(Jrd::thread_db*, Jrd::jrd_tra*,
|
||||
Jrd::jrd_rel*);
|
||||
|
||||
#endif // JRD_RLCK_PROTO_H
|
||||
|
||||
|
157
src/jrd/rse.cpp
157
src/jrd/rse.cpp
@ -311,7 +311,7 @@ bool RSE_get_record(thread_db* tdbb, RecordSource* rsb, RSE_GET_MODE mode)
|
||||
ERR_post(isc_record_lock_not_supp, 0);
|
||||
}
|
||||
|
||||
RLCK_reserve_relation(tdbb, transaction, relation, true, true);
|
||||
RLCK_reserve_relation(tdbb, transaction, relation, true);
|
||||
|
||||
// Fetch next record if current was deleted before being locked
|
||||
if (!VIO_writelock(tdbb, org_rpb, rsb, transaction)) {
|
||||
@ -419,7 +419,7 @@ void RSE_open(thread_db* tdbb, RecordSource* rsb)
|
||||
}
|
||||
|
||||
RLCK_reserve_relation(tdbb, request->req_transaction,
|
||||
rpb->rpb_relation, false, true);
|
||||
rpb->rpb_relation, false);
|
||||
|
||||
rpb->rpb_number.setValue(BOF_NUMBER);
|
||||
return;
|
||||
@ -648,23 +648,25 @@ static SSHORT compare(thread_db* tdbb, jrd_nod* node1, jrd_nod* node2)
|
||||
const dsc* desc1 = EVL_expr(tdbb, *ptr1);
|
||||
const ULONG flags = request->req_flags;
|
||||
const dsc* desc2 = EVL_expr(tdbb, *ptr2);
|
||||
if (flags & req_null) {
|
||||
if (flags & req_null)
|
||||
{
|
||||
if (!(request->req_flags & req_null)) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
// AB: When both expression evaluated NULL then
|
||||
// we return 0 ( (NULL = NULL) = true).
|
||||
//
|
||||
// Currently this (0 and higher) isn't used by the
|
||||
// MERGE procedure, but when we allow MERGE to
|
||||
// handle outer-joins we must not forget this one !!!
|
||||
return 0;
|
||||
}
|
||||
|
||||
// AB: When both expression evaluated NULL then
|
||||
// we return 0 ( (NULL = NULL) = true).
|
||||
//
|
||||
// Currently this (0 and higher) isn't used by the
|
||||
// MERGE procedure, but when we allow MERGE to
|
||||
// handle outer-joins we must not forget this one !!!
|
||||
return 0;
|
||||
}
|
||||
else if (request->req_flags & req_null) {
|
||||
|
||||
if (request->req_flags & req_null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// AB: MOV_compare can't handle NULL parameters
|
||||
// therefore check before passing all null flags.
|
||||
const SSHORT result = MOV_compare(desc1, desc2);
|
||||
@ -690,10 +692,12 @@ static SSHORT compare_longs(const SLONG* p, const SLONG* q, USHORT count)
|
||||
*
|
||||
**************************************/
|
||||
for (; count; p++, q++, --count)
|
||||
{
|
||||
if (*p > *q)
|
||||
return 1;
|
||||
else if (*p < *q)
|
||||
if (*p < *q)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -803,11 +807,9 @@ static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure, RSE_GET_
|
||||
{
|
||||
if (mode == RSE_get_backward)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
if (!rsb->rsb_arg[RSB_LEFT_inner_streams])
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rsb->rsb_left_inner_streams)
|
||||
return false;
|
||||
|
||||
/* We have a full outer join. Open up the inner stream
|
||||
one more time. */
|
||||
@ -821,7 +823,7 @@ static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure, RSE_GET_
|
||||
/* check if the outer record qualifies for the boolean */
|
||||
|
||||
if (rsb->rsb_arg[RSB_LEFT_boolean] &&
|
||||
!EVL_boolean(tdbb, rsb->rsb_arg[RSB_LEFT_boolean]))
|
||||
!EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[RSB_LEFT_boolean]))
|
||||
{
|
||||
/* The boolean pertaining to the left sub-stream is false
|
||||
so just join sub-stream to a null valued right sub-stream */
|
||||
@ -839,7 +841,7 @@ static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure, RSE_GET_
|
||||
while (get_record(tdbb, rsb->rsb_arg[RSB_LEFT_inner], NULL, mode))
|
||||
{
|
||||
if (!rsb->rsb_arg[RSB_LEFT_inner_boolean] ||
|
||||
EVL_boolean(tdbb, rsb->rsb_arg[RSB_LEFT_inner_boolean]))
|
||||
EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[RSB_LEFT_inner_boolean]))
|
||||
{
|
||||
impure->irsb_flags |= irsb_joined;
|
||||
return true;
|
||||
@ -876,8 +878,8 @@ static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure, RSE_GET_
|
||||
if (!get_record(tdbb, full, NULL, mode)) {
|
||||
if (mode == RSE_get_forward)
|
||||
return false;
|
||||
else
|
||||
goto return_to_outer;
|
||||
|
||||
goto return_to_outer;
|
||||
}
|
||||
|
||||
RSE_open(tdbb, rsb->rsb_arg[RSB_LEFT_outer]);
|
||||
@ -885,24 +887,19 @@ static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure, RSE_GET_
|
||||
get_record(tdbb, rsb->rsb_arg[RSB_LEFT_outer],
|
||||
NULL, mode))
|
||||
{
|
||||
if (
|
||||
(!rsb->rsb_arg[RSB_LEFT_boolean]
|
||||
|| EVL_boolean(tdbb,
|
||||
rsb->
|
||||
rsb_arg[RSB_LEFT_boolean]))
|
||||
&& (!rsb->rsb_arg[RSB_LEFT_inner_boolean]
|
||||
|| EVL_boolean(tdbb,
|
||||
rsb->rsb_arg
|
||||
[RSB_LEFT_inner_boolean]))
|
||||
&& (full == rsb->rsb_arg[RSB_LEFT_inner]
|
||||
|| EVL_boolean(tdbb,
|
||||
rsb->
|
||||
rsb_arg
|
||||
[RSB_LEFT_inner]->rsb_arg
|
||||
[0])))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (
|
||||
(!rsb->rsb_arg[RSB_LEFT_boolean]
|
||||
|| EVL_boolean(tdbb,
|
||||
(jrd_nod*) rsb->rsb_arg[RSB_LEFT_boolean]))
|
||||
&& (!rsb->rsb_arg[RSB_LEFT_inner_boolean]
|
||||
|| EVL_boolean(tdbb,
|
||||
(jrd_nod*) rsb->rsb_arg[RSB_LEFT_inner_boolean]))
|
||||
&& (full == rsb->rsb_arg[RSB_LEFT_inner]
|
||||
|| EVL_boolean(tdbb,
|
||||
(jrd_nod*) rsb->rsb_arg[RSB_LEFT_inner]->rsb_arg[0])))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
RSE_close(tdbb, rsb->rsb_arg[RSB_LEFT_outer]);
|
||||
} while (found);
|
||||
@ -911,8 +908,8 @@ static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure, RSE_GET_
|
||||
{
|
||||
if (mode == RSE_get_forward)
|
||||
return false;
|
||||
else
|
||||
goto return_to_outer;
|
||||
|
||||
goto return_to_outer;
|
||||
}
|
||||
|
||||
join_to_nulls(tdbb, rsb, rsb->rsb_left_inner_streams);
|
||||
@ -1311,7 +1308,7 @@ static bool get_merge_join(
|
||||
/* Map data into target records and do comparison */
|
||||
|
||||
map_sort_data(tdbb, request, map, get_merge_data(tdbb, mfb, record));
|
||||
const int result = compare(tdbb, highest_ptr[1], ptr[1]);
|
||||
const int result = compare(tdbb, (jrd_nod*) highest_ptr[1], (jrd_nod*) ptr[1]);
|
||||
if (ptr != highest_ptr)
|
||||
{
|
||||
if (((result > 0) && (impure->irsb_flags & irsb_backwards)) ||
|
||||
@ -1333,7 +1330,7 @@ static bool get_merge_join(
|
||||
if (highest_ptr != ptr)
|
||||
{
|
||||
int result;
|
||||
while (result = compare(tdbb, highest_ptr[1], ptr[1]))
|
||||
while (result = compare(tdbb, (jrd_nod*) highest_ptr[1], (jrd_nod*) ptr[1]))
|
||||
{
|
||||
if (((result > 0)
|
||||
&& (impure->irsb_flags & irsb_backwards))
|
||||
@ -1928,7 +1925,7 @@ static bool get_record(thread_db* tdbb,
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
if (impure->irsb_flags & irsb_bof)
|
||||
{
|
||||
rpb->rpb_number = -1;
|
||||
rpb->rpb_number.setValue(BOF_NUMBER);
|
||||
}
|
||||
#endif
|
||||
if (!NAV_get_record(tdbb, rsb, (IRSB_NAV) impure, rpb, mode))
|
||||
@ -2733,14 +2730,20 @@ static void map_sort_data(thread_db* tdbb, jrd_req* request, SortMap* map, UCHAR
|
||||
const SSHORT id = item->smb_field_id;
|
||||
if (id < 0)
|
||||
{
|
||||
if (id == SMB_TRANS_ID)
|
||||
switch (id)
|
||||
{
|
||||
case SMB_TRANS_ID:
|
||||
rpb->rpb_transaction_nr = *reinterpret_cast<SLONG*>(from.dsc_address);
|
||||
else if (id == SMB_DBKEY)
|
||||
break;
|
||||
case SMB_DBKEY:
|
||||
rpb->rpb_number.setValue(*reinterpret_cast<SINT64*>(from.dsc_address));
|
||||
else if (id == SMB_DBKEY_VALID)
|
||||
break;
|
||||
case SMB_DBKEY_VALID:
|
||||
rpb->rpb_number.setValid(*from.dsc_address != 0);
|
||||
else
|
||||
break;
|
||||
default:
|
||||
fb_assert(false);
|
||||
}
|
||||
rpb->rpb_stream_flags |= RPB_s_refetch;
|
||||
continue;
|
||||
}
|
||||
@ -2969,14 +2972,20 @@ static void open_sort(thread_db* tdbb, RecordSource* rsb, irsb_sort* impure, FB_
|
||||
from = &temp;
|
||||
record_param* rpb = &request->req_rpb[item->smb_stream];
|
||||
if (item->smb_field_id < 0) {
|
||||
if (item->smb_field_id == SMB_TRANS_ID)
|
||||
switch (item->smb_field_id)
|
||||
{
|
||||
case SMB_TRANS_ID:
|
||||
*reinterpret_cast<SLONG*>(to.dsc_address) = rpb->rpb_transaction_nr;
|
||||
else if (item->smb_field_id == SMB_DBKEY)
|
||||
break;
|
||||
case SMB_DBKEY:
|
||||
*reinterpret_cast<SINT64*>(to.dsc_address) = rpb->rpb_number.getValue();
|
||||
else if (item->smb_field_id == SMB_DBKEY_VALID)
|
||||
break;
|
||||
case SMB_DBKEY_VALID:
|
||||
*to.dsc_address = (UCHAR) rpb->rpb_number.isValid();
|
||||
else
|
||||
break;
|
||||
default:
|
||||
fb_assert(false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!EVL_field
|
||||
@ -3702,31 +3711,29 @@ bool RSBRecurse::get(thread_db* tdbb, RecordSource* rsb, irsb_recurse* irsb)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
RSE_close(tdbb, *rsb_ptr);
|
||||
delete[] irsb->irsb_data;
|
||||
|
||||
char* tmp = irsb->irsb_stack;
|
||||
memcpy(irsb, tmp, inner_size);
|
||||
|
||||
char* p = tmp + inner_size;
|
||||
RecordSource** ptr = rsb->rsb_arg + rsb->rsb_count + 1;
|
||||
const RecordSource* const* end = ptr + streams;
|
||||
for (; ptr < end; ptr++)
|
||||
{
|
||||
RSE_close(tdbb, *rsb_ptr);
|
||||
delete[] irsb->irsb_data;
|
||||
record_param* rpb = request->req_rpb + (USHORT)(U_IPTR) *ptr;
|
||||
Record* rec = rpb->rpb_record;
|
||||
memmove(rpb, p, sizeof(record_param));
|
||||
p += sizeof(record_param);
|
||||
|
||||
char* tmp = irsb->irsb_stack;
|
||||
memcpy(irsb, tmp, inner_size);
|
||||
|
||||
char* p = tmp + inner_size;
|
||||
RecordSource** ptr = rsb->rsb_arg + rsb->rsb_count + 1;
|
||||
const RecordSource* const* end = ptr + streams;
|
||||
for (; ptr < end; ptr++)
|
||||
{
|
||||
record_param* rpb = request->req_rpb + (USHORT)(U_IPTR) *ptr;
|
||||
Record* rec = rpb->rpb_record;
|
||||
memmove(rpb, p, sizeof(record_param));
|
||||
p += sizeof(record_param);
|
||||
|
||||
if (!rpb->rpb_record) {
|
||||
rpb->rpb_record = rec;
|
||||
}
|
||||
fb_assert(rpb->rpb_record == rec);
|
||||
if (!rpb->rpb_record) {
|
||||
rpb->rpb_record = rec;
|
||||
}
|
||||
delete[] tmp;
|
||||
fb_assert(rpb->rpb_record == rec);
|
||||
}
|
||||
delete[] tmp;
|
||||
|
||||
if (irsb->irsb_level > 1)
|
||||
{
|
||||
|
632
src/jrd/sch.cpp
632
src/jrd/sch.cpp
@ -28,7 +28,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "../jrd/common.h"
|
||||
#include "../jrd/thd.h"
|
||||
#include "../jrd/ThreadStart.h"
|
||||
#include "../jrd/isc.h"
|
||||
#include "../jrd/ibase.h"
|
||||
#include "../jrd/gds_proto.h"
|
||||
@ -46,84 +46,109 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* must be careful with alignment on structures like this that are
|
||||
not run through the ALL routine */
|
||||
|
||||
struct thread {
|
||||
struct thread *thread_next; /* Next thread to be scheduled */
|
||||
struct thread *thread_prior; /* Prior thread */
|
||||
event_t thread_stall[1]; /* Generic event to stall thread */
|
||||
FB_THREAD_ID thread_id; /* Current thread id */
|
||||
USHORT thread_count; /* AST disable count */
|
||||
USHORT thread_flags; /* Flags */
|
||||
thread* thread_next; // Next thread to be scheduled
|
||||
thread* thread_prior; // Prior thread
|
||||
event_t thread_stall; // Generic event to stall thread
|
||||
FB_THREAD_ID thread_id; // Current thread ID
|
||||
USHORT thread_count; // AST disable count
|
||||
USHORT thread_flags; // Flags
|
||||
};
|
||||
|
||||
typedef thread *THREAD;
|
||||
|
||||
// thread_flags
|
||||
|
||||
const USHORT THREAD_hiber = 1; /* Thread is hibernating */
|
||||
const USHORT THREAD_ast_disabled = 2; /* Disable AST delivery */
|
||||
const USHORT THREAD_ast_active = 4; /* Disable AST preemption while AST active */
|
||||
const USHORT THREAD_ast_pending = 8; /* AST waiting to be delivered */
|
||||
const USHORT THREAD_hiber = 1; // Thread is hibernating
|
||||
const USHORT THREAD_ast_disabled = 2; // Disable AST delivery
|
||||
const USHORT THREAD_ast_active = 4; // Disable AST preemption while AST active
|
||||
const USHORT THREAD_ast_pending = 8; // AST waiting to be delivered
|
||||
|
||||
static THREAD alloc_thread(void);
|
||||
static bool ast_enable(void);
|
||||
static void ast_disable(void);
|
||||
static void cleanup(void *);
|
||||
static THREAD alloc_thread();
|
||||
static bool ast_enable();
|
||||
static void ast_disable();
|
||||
static void mutex_bugcheck(const TEXT*, int);
|
||||
static bool schedule(void);
|
||||
static void schedule();
|
||||
static bool schedule_active(bool);
|
||||
static void stall(THREAD);
|
||||
static void stall_ast(THREAD);
|
||||
static void sch_mutex_lock(Firebird::Mutex&);
|
||||
static void sch_mutex_unlock(Firebird::Mutex&);
|
||||
|
||||
static THREAD free_threads = NULL;
|
||||
static THREAD active_thread = NULL;
|
||||
static THREAD ast_thread = NULL;
|
||||
static Firebird::Mutex thread_mutex;
|
||||
volatile static bool init_flag = false;
|
||||
static USHORT enabled = FALSE;
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef VMS
|
||||
int API_ROUTINE gds__ast_active(void)
|
||||
class SchedulerInit
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* g d s _ $ a s t _ a c t i v e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* An asynchronous operation has completed, wake somebody
|
||||
* up, if necessary.
|
||||
*
|
||||
**************************************/
|
||||
public:
|
||||
SchedulerInit()
|
||||
{}
|
||||
|
||||
return THREAD_ast_active();
|
||||
}
|
||||
~SchedulerInit()
|
||||
{
|
||||
#ifdef SUPERCLIENT
|
||||
// Loop through the list of active threads and free the events
|
||||
|
||||
THREAD temp_thread = active_thread;
|
||||
if (temp_thread) {
|
||||
while (temp_thread != temp_thread->thread_prior)
|
||||
temp_thread = temp_thread->thread_prior;
|
||||
|
||||
void API_ROUTINE gds__completion_ast(int *arg)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* g d s _ $ c o m p l e t i o n _ a s t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* An asynchronous operation has completed, wake somebody
|
||||
* up, if necessary.
|
||||
*
|
||||
**************************************/
|
||||
do {
|
||||
ISC_event_fini(&temp_thread->thread_stall);
|
||||
// the thread structures are freed as a part of the
|
||||
// gds_alloc cleanup, so do not worry about them here
|
||||
} while (temp_thread->thread_next != temp_thread &&
|
||||
(temp_thread = temp_thread->thread_next));
|
||||
}
|
||||
|
||||
THREAD_completion_ast();
|
||||
sys$wake(0, 0);
|
||||
}
|
||||
// Loop through the list of free threads and free the events
|
||||
|
||||
if ( (temp_thread = free_threads) ) {
|
||||
while (temp_thread != temp_thread->thread_prior)
|
||||
temp_thread = temp_thread->thread_prior;
|
||||
|
||||
do {
|
||||
ISC_event_fini(&temp_thread->thread_stall);
|
||||
// the thread structures are freed as a part of the
|
||||
// gds_alloc cleanup, so do not worry about them here
|
||||
} while (temp_thread->thread_next != temp_thread &&
|
||||
(temp_thread = temp_thread->thread_next));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
static SchedulerInit initHolder;
|
||||
|
||||
|
||||
static inline void sch_mutex_lock()
|
||||
{
|
||||
try
|
||||
{
|
||||
thread_mutex.enter();
|
||||
}
|
||||
catch (const Firebird::system_call_failed& e)
|
||||
{
|
||||
mutex_bugcheck("mutex lock", e.getErrorCode());
|
||||
}
|
||||
}
|
||||
|
||||
static inline void sch_mutex_unlock()
|
||||
{
|
||||
try
|
||||
{
|
||||
thread_mutex.leave();
|
||||
}
|
||||
catch (const Firebird::system_call_failed& e)
|
||||
{
|
||||
mutex_bugcheck("mutex unlock", e.getErrorCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int API_ROUTINE gds__thread_enable(int enable_flag)
|
||||
@ -139,16 +164,11 @@ int API_ROUTINE gds__thread_enable(int enable_flag)
|
||||
*
|
||||
**************************************/
|
||||
|
||||
if (enable_flag) {
|
||||
enabled = TRUE;
|
||||
SCH_init();
|
||||
}
|
||||
|
||||
return enabled;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void API_ROUTINE gds__thread_enter(void)
|
||||
void API_ROUTINE gds__thread_enter()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -165,7 +185,7 @@ void API_ROUTINE gds__thread_enter(void)
|
||||
}
|
||||
|
||||
|
||||
void API_ROUTINE gds__thread_exit(void)
|
||||
void API_ROUTINE gds__thread_exit()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -182,74 +202,6 @@ void API_ROUTINE gds__thread_exit(void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef VMS
|
||||
int API_ROUTINE gds__thread_wait(FPTR_INT entrypoint, SLONG arg)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* g d s _ $ t h r e a d _ w a i t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Stall a thread with a callback to determine runnability.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
return thread_wait(entrypoint, arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void SCH_abort(void)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* S C H _ a b o r t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Try to abort the current thread. If the thread is active,
|
||||
* unlink it.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
/* If threading isn't active, don't sweat it */
|
||||
|
||||
if (!active_thread)
|
||||
return;
|
||||
|
||||
/* See if we can find thread. If not, don't worry about it */
|
||||
|
||||
const FB_THREAD_ID id = ThreadData::getId();
|
||||
THREAD thread;
|
||||
for (THREAD* ptr = &active_thread; thread = *ptr; ptr = &thread->thread_next)
|
||||
{
|
||||
if (thread->thread_id == id)
|
||||
break;
|
||||
if (thread->thread_next == active_thread)
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we're the active thread, do a normal thread exit */
|
||||
|
||||
if (thread == active_thread) {
|
||||
SCH_exit();
|
||||
return;
|
||||
}
|
||||
|
||||
/* We're on the list but not active. Remove from list */
|
||||
|
||||
sch_mutex_lock(thread_mutex);
|
||||
thread->thread_prior->thread_next = thread->thread_next;
|
||||
thread->thread_next->thread_prior = thread->thread_prior;
|
||||
thread->thread_next = free_threads;
|
||||
free_threads = thread;
|
||||
sch_mutex_unlock(thread_mutex);
|
||||
}
|
||||
|
||||
|
||||
void SCH_ast(enum ast_t action)
|
||||
{
|
||||
/**************************************
|
||||
@ -266,28 +218,28 @@ void SCH_ast(enum ast_t action)
|
||||
* In case you're wondering: AST = Asynchronous System Trap
|
||||
*
|
||||
**************************************/
|
||||
if (!ast_thread && !(action == AST_alloc || action == AST_disable ||
|
||||
action == AST_enable))
|
||||
if (!ast_thread &&
|
||||
!(action == AST_alloc || action == AST_disable || action == AST_enable))
|
||||
{
|
||||
/* Better be an AST thread before we do anything to it! */
|
||||
fb_assert(FALSE);
|
||||
// Better be an AST thread before we do anything to it!
|
||||
fb_assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ast_thread && action == AST_check)
|
||||
{
|
||||
if (!(ast_thread->thread_flags & THREAD_ast_pending) ||
|
||||
ast_thread->thread_count > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_flag)
|
||||
SCH_init();
|
||||
|
||||
sch_mutex_lock(thread_mutex);
|
||||
sch_mutex_lock();
|
||||
|
||||
switch (action) {
|
||||
/* Check into thread scheduler as AST thread */
|
||||
|
||||
// Check into thread scheduler as AST thread
|
||||
|
||||
case AST_alloc:
|
||||
ast_thread = alloc_thread();
|
||||
@ -296,10 +248,10 @@ void SCH_ast(enum ast_t action)
|
||||
break;
|
||||
|
||||
case AST_init:
|
||||
ast_thread->thread_id = ThreadData::getId();
|
||||
ast_thread->thread_id = getThreadId();
|
||||
break;
|
||||
|
||||
/* Check out of thread scheduler as AST thread */
|
||||
// Check out of thread scheduler as AST thread
|
||||
|
||||
case AST_fini:
|
||||
ast_thread->thread_next = free_threads;
|
||||
@ -307,20 +259,19 @@ void SCH_ast(enum ast_t action)
|
||||
ast_thread = NULL;
|
||||
break;
|
||||
|
||||
/* Disable AST delivery if not an AST thread */
|
||||
// Disable AST delivery if not an AST thread
|
||||
|
||||
case AST_disable:
|
||||
ast_disable();
|
||||
break;
|
||||
|
||||
/* Reenable AST delivery if not an AST thread */
|
||||
// Reenable AST delivery if not an AST thread
|
||||
|
||||
case AST_enable:
|
||||
ast_enable();
|
||||
break;
|
||||
|
||||
/* Active thread allows a pending AST to be delivered
|
||||
and waits */
|
||||
// Active thread allows a pending AST to be delivered and waits
|
||||
|
||||
case AST_check:
|
||||
if (ast_enable())
|
||||
@ -329,7 +280,7 @@ void SCH_ast(enum ast_t action)
|
||||
ast_disable();
|
||||
break;
|
||||
|
||||
/* Request AST delivery and prevent thread scheduling */
|
||||
// Request AST delivery and prevent thread scheduling
|
||||
|
||||
case AST_enter:
|
||||
if (ast_thread->thread_flags & THREAD_ast_disabled) {
|
||||
@ -339,28 +290,28 @@ void SCH_ast(enum ast_t action)
|
||||
ast_thread->thread_flags |= THREAD_ast_active;
|
||||
break;
|
||||
|
||||
/* AST delivery complete; resume thread scheduling */
|
||||
// AST delivery complete; resume thread scheduling
|
||||
|
||||
case AST_exit:
|
||||
ast_thread->thread_flags &= ~(THREAD_ast_active | THREAD_ast_pending);
|
||||
if (active_thread)
|
||||
ISC_event_post(active_thread->thread_stall);
|
||||
ISC_event_post(&active_thread->thread_stall);
|
||||
|
||||
/* Post non-active threads that have requested AST disabling */
|
||||
// Post non-active threads that have requested AST disabling
|
||||
|
||||
for (THREAD thread = ast_thread->thread_next; thread != ast_thread;
|
||||
thread = thread->thread_next)
|
||||
{
|
||||
ISC_event_post(thread->thread_stall);
|
||||
ISC_event_post(&thread->thread_stall);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
sch_mutex_unlock(thread_mutex);
|
||||
sch_mutex_unlock();
|
||||
}
|
||||
|
||||
|
||||
THREAD SCH_current_thread(void)
|
||||
THREAD SCH_current_thread()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -378,7 +329,7 @@ THREAD SCH_current_thread(void)
|
||||
}
|
||||
|
||||
|
||||
void SCH_enter(void)
|
||||
void SCH_enter()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -392,36 +343,20 @@ void SCH_enter(void)
|
||||
*
|
||||
**************************************/
|
||||
|
||||
/* Special case single thread case */
|
||||
|
||||
#ifndef MULTI_THREAD
|
||||
if (free_threads) {
|
||||
THREAD thread = active_thread = free_threads;
|
||||
free_threads = NULL;
|
||||
thread->thread_next = thread->thread_prior = thread;
|
||||
thread->thread_flags = 0;
|
||||
thread->thread_id = ThreadData::getId();
|
||||
if (ast_thread && ast_thread->thread_id == getThreadId())
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!init_flag) {
|
||||
SCH_init();
|
||||
}
|
||||
|
||||
/* Get mutex on scheduler data structures to prevent tragic misunderstandings */
|
||||
|
||||
sch_mutex_lock(thread_mutex);
|
||||
sch_mutex_lock();
|
||||
|
||||
THREAD thread = alloc_thread();
|
||||
thread->thread_id = ThreadData::getId();
|
||||
thread->thread_id = getThreadId();
|
||||
|
||||
/* Link thread block into circular list of active threads */
|
||||
// Link thread block into circular list of active threads
|
||||
|
||||
if (active_thread)
|
||||
{
|
||||
/* The calling thread should NOT be the active_thread
|
||||
This is to prevent deadlock by the same thread */
|
||||
// The calling thread should NOT be the active_thread.
|
||||
// This is to prevent deadlock by the same thread.
|
||||
fb_assert(thread->thread_id != active_thread->thread_id);
|
||||
|
||||
thread->thread_next = active_thread;
|
||||
@ -442,11 +377,11 @@ void SCH_enter(void)
|
||||
}
|
||||
|
||||
stall(thread);
|
||||
sch_mutex_unlock(thread_mutex);
|
||||
sch_mutex_unlock();
|
||||
}
|
||||
|
||||
|
||||
void SCH_exit(void)
|
||||
void SCH_exit()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -459,16 +394,24 @@ void SCH_exit(void)
|
||||
* scheduler, and release thread block.
|
||||
*
|
||||
**************************************/
|
||||
SCH_validate();
|
||||
|
||||
#ifndef MULTI_THREAD
|
||||
free_threads = active_thread;
|
||||
active_thread = NULL;
|
||||
free_threads->thread_next = NULL;
|
||||
#else
|
||||
sch_mutex_lock(thread_mutex);
|
||||
if (ast_thread && ast_thread->thread_id == getThreadId())
|
||||
return;
|
||||
|
||||
ast_enable(); /* Reenable AST delivery */
|
||||
// Validate thread
|
||||
|
||||
if (!active_thread) {
|
||||
gds__log("Thread validation: not entered");
|
||||
fb_assert(false);
|
||||
}
|
||||
else if (active_thread->thread_id != getThreadId()) {
|
||||
gds__log("Thread validation: wrong thread");
|
||||
fb_assert(false);
|
||||
}
|
||||
|
||||
sch_mutex_lock();
|
||||
|
||||
ast_enable(); // Reenable AST delivery
|
||||
|
||||
THREAD thread = active_thread;
|
||||
|
||||
@ -477,7 +420,7 @@ void SCH_exit(void)
|
||||
// handler there calls THREAD_EXIT without preceding THREAD_ENTER
|
||||
// in this case (during shutdown of CACHE_WRITER or CACHE_READER)
|
||||
if (!thread) {
|
||||
sch_mutex_unlock(thread_mutex);
|
||||
sch_mutex_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -496,12 +439,11 @@ void SCH_exit(void)
|
||||
free_threads = thread;
|
||||
schedule();
|
||||
|
||||
sch_mutex_unlock(thread_mutex);
|
||||
#endif
|
||||
sch_mutex_unlock();
|
||||
}
|
||||
|
||||
|
||||
void SCH_hiber(void)
|
||||
void SCH_hiber()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -518,46 +460,7 @@ void SCH_hiber(void)
|
||||
schedule_active(true);
|
||||
}
|
||||
|
||||
#ifdef MULTI_THREAD
|
||||
static Firebird::Mutex scheduler_init_lock;
|
||||
#endif
|
||||
|
||||
void SCH_init(void)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* S C H _ i n i t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Initialize the thread scheduler.
|
||||
*
|
||||
**************************************/
|
||||
if (init_flag)
|
||||
return;
|
||||
|
||||
#ifdef MULTI_THREAD
|
||||
scheduler_init_lock.enter();
|
||||
|
||||
try {
|
||||
if (!init_flag) {
|
||||
#endif
|
||||
gds__register_cleanup(cleanup, 0);
|
||||
init_flag = true;
|
||||
#ifdef MULTI_THREAD
|
||||
}
|
||||
}
|
||||
catch (const Firebird::Exception&) {
|
||||
scheduler_init_lock.leave();
|
||||
throw;
|
||||
}
|
||||
scheduler_init_lock.leave();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool SCH_schedule(void)
|
||||
bool SCH_schedule()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -570,11 +473,12 @@ bool SCH_schedule(void)
|
||||
* If a context switch actually happened, return true.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
return schedule_active(false);
|
||||
}
|
||||
|
||||
|
||||
bool SCH_thread_enter_check(void)
|
||||
bool SCH_thread_enter_check()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -588,8 +492,9 @@ bool SCH_thread_enter_check(void)
|
||||
*
|
||||
**************************************/
|
||||
|
||||
/* if active thread is not null and thread_id matches the we are the
|
||||
active thread */
|
||||
// If active thread is not null and thread_id matches
|
||||
// then we are the active thread
|
||||
|
||||
sch_mutex_lock(thread_mutex);
|
||||
const bool ret = ((active_thread) && (active_thread->thread_id == ThreadData::getId()));
|
||||
sch_mutex_unlock(thread_mutex);
|
||||
@ -598,38 +503,6 @@ bool SCH_thread_enter_check(void)
|
||||
}
|
||||
|
||||
|
||||
bool SCH_validate(void)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* S C H _ v a l i d a t e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Check integrity of thread system (assume thread is entered).
|
||||
*
|
||||
**************************************/
|
||||
|
||||
if (!init_flag || !active_thread) {
|
||||
gds__log("SCH_validate -- not entered");
|
||||
// CVC: No need to replace by fb_utils::readenv() I think.
|
||||
if (getenv("ISC_PUNT"))
|
||||
abort();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MULTI_THREAD
|
||||
if (active_thread->thread_id != ThreadData::getId()) {
|
||||
gds__log("SCH_validate -- wrong thread");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SCH_wake(THREAD thread)
|
||||
{
|
||||
/**************************************
|
||||
@ -643,11 +516,11 @@ void SCH_wake(THREAD thread)
|
||||
*
|
||||
**************************************/
|
||||
thread->thread_flags &= ~THREAD_hiber;
|
||||
ISC_event_post(thread->thread_stall);
|
||||
ISC_event_post(&thread->thread_stall);
|
||||
}
|
||||
|
||||
|
||||
static THREAD alloc_thread(void)
|
||||
static THREAD alloc_thread()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -660,31 +533,31 @@ static THREAD alloc_thread(void)
|
||||
*
|
||||
**************************************/
|
||||
|
||||
/* Find a useable thread block. If there isn't one, allocate one */
|
||||
// Find a useable thread block. If there isn't one, allocate one.
|
||||
|
||||
THREAD thread = free_threads;
|
||||
if (thread)
|
||||
free_threads = thread->thread_next;
|
||||
else {
|
||||
thread = (THREAD) gds__alloc((SLONG) sizeof(struct thread));
|
||||
/* FREE: unknown */
|
||||
if (!thread) /* NOMEM: bugcheck */
|
||||
mutex_bugcheck("Out of memory", 0); /* no real error handling */
|
||||
if (!thread)
|
||||
mutex_bugcheck("Out of memory", 0); // no real error handling
|
||||
#ifdef DEBUG_GDS_ALLOC
|
||||
/* There is one thread structure allocated per thread, and this
|
||||
* is never freed except by process exit
|
||||
*/
|
||||
// There is one thread structure allocated per thread, and this
|
||||
// is never freed except by process exit
|
||||
gds_alloc_flag_unfreed((void *) thread);
|
||||
#endif
|
||||
ISC_event_init(thread->thread_stall, 0, 0);
|
||||
ISC_event_init(&thread->thread_stall, 0, 0);
|
||||
}
|
||||
|
||||
thread->thread_flags = thread->thread_count = 0;
|
||||
thread->thread_flags = 0;
|
||||
thread->thread_count = 0;
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
|
||||
static bool ast_enable(void)
|
||||
static bool ast_enable()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -701,7 +574,7 @@ static bool ast_enable(void)
|
||||
return false;
|
||||
|
||||
if (ast_thread->thread_flags & THREAD_ast_active &&
|
||||
ast_thread->thread_id == ThreadData::getId())
|
||||
ast_thread->thread_id == getThreadId())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -710,7 +583,7 @@ static bool ast_enable(void)
|
||||
ast_thread->thread_flags &= ~THREAD_ast_disabled;
|
||||
if (ast_thread->thread_flags & THREAD_ast_pending) {
|
||||
ast_thread->thread_flags |= THREAD_ast_active;
|
||||
ISC_event_post(ast_thread->thread_stall);
|
||||
ISC_event_post(&ast_thread->thread_stall);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -719,7 +592,7 @@ static bool ast_enable(void)
|
||||
}
|
||||
|
||||
|
||||
static void ast_disable(void)
|
||||
static void ast_disable()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -737,11 +610,11 @@ static void ast_disable(void)
|
||||
return;
|
||||
|
||||
if (ast_thread->thread_flags & THREAD_ast_active) {
|
||||
if (ast_thread->thread_id == ThreadData::getId())
|
||||
if (ast_thread->thread_id == getThreadId())
|
||||
return;
|
||||
else {
|
||||
if (active_thread
|
||||
&& active_thread->thread_id == ThreadData::getId())
|
||||
if (active_thread &&
|
||||
active_thread->thread_id == getThreadId())
|
||||
{
|
||||
stall(active_thread);
|
||||
return;
|
||||
@ -760,75 +633,6 @@ static void ast_disable(void)
|
||||
}
|
||||
|
||||
|
||||
static void cleanup(void *arg)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* c l e a n u p
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Exit handler for image exit.
|
||||
*
|
||||
**************************************/
|
||||
if (!init_flag)
|
||||
return;
|
||||
|
||||
/* this is added to make sure that we release the memory
|
||||
* we have allocated for the thread event handler through
|
||||
* ISC_event_handle () (CreateEvent) */
|
||||
|
||||
#ifdef SUPERCLIENT
|
||||
/* use locks */
|
||||
thread_mutex.enter();
|
||||
|
||||
if (!init_flag)
|
||||
return;
|
||||
|
||||
/* loop through the list of active threads and free the events */
|
||||
THREAD temp_thread = active_thread;
|
||||
if (temp_thread) {
|
||||
/* reach to the starting of the list */
|
||||
while (temp_thread != temp_thread->thread_prior)
|
||||
temp_thread = temp_thread->thread_prior;
|
||||
/* now we are at the begining of the list. Now start freeing the
|
||||
* EVENT structures and move to the next */
|
||||
do {
|
||||
ISC_event_fini(temp_thread->thread_stall);
|
||||
/* the thread structures are freed as a part of the
|
||||
* gds_alloc cleanup, so do not worry about them here
|
||||
*/
|
||||
} while (temp_thread->thread_next != temp_thread
|
||||
&& (temp_thread = temp_thread->thread_next));
|
||||
|
||||
}
|
||||
|
||||
/* loop through the list of free threads and free the events */
|
||||
if (temp_thread = free_threads) {
|
||||
/* reach to the starting of the list */
|
||||
while (temp_thread != temp_thread->thread_prior)
|
||||
temp_thread = temp_thread->thread_prior;
|
||||
/* now we are at the begining of the list. Now start freeing the
|
||||
* EVENT structures and move to the next */
|
||||
do {
|
||||
ISC_event_fini(temp_thread->thread_stall);
|
||||
/* the thread structures are freed as a part of the
|
||||
* gds_alloc cleanup, so do not worry about them here
|
||||
*/
|
||||
} while (temp_thread->thread_next != temp_thread
|
||||
&& (temp_thread = temp_thread->thread_next));
|
||||
|
||||
|
||||
}
|
||||
|
||||
thread_mutex.leave();
|
||||
#endif /* SUPERCLIENT */
|
||||
|
||||
init_flag = false;
|
||||
}
|
||||
|
||||
|
||||
static void mutex_bugcheck(const TEXT* string, int mutex_state)
|
||||
{
|
||||
/**************************************
|
||||
@ -852,8 +656,7 @@ static void mutex_bugcheck(const TEXT* string, int mutex_state)
|
||||
}
|
||||
|
||||
|
||||
// CVC: Nobody checks the result from this function.
|
||||
static bool schedule(void)
|
||||
static void schedule()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -868,22 +671,20 @@ static bool schedule(void)
|
||||
*
|
||||
**************************************/
|
||||
if (!active_thread)
|
||||
return false;
|
||||
return;
|
||||
|
||||
THREAD thread = active_thread;
|
||||
|
||||
for (;;) {
|
||||
while (true) {
|
||||
thread = thread->thread_next;
|
||||
if (!(thread->thread_flags & THREAD_hiber))
|
||||
break;
|
||||
if (thread == active_thread)
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
active_thread = thread;
|
||||
ISC_event_post(active_thread->thread_stall);
|
||||
|
||||
return true;
|
||||
ISC_event_post(&active_thread->thread_stall);
|
||||
}
|
||||
|
||||
|
||||
@ -900,16 +701,13 @@ static bool schedule_active(bool hiber_flag)
|
||||
* If a context switch actually happened, return true.
|
||||
*
|
||||
**************************************/
|
||||
#ifndef MULTI_THREAD
|
||||
return false;
|
||||
#else
|
||||
if (!active_thread)
|
||||
return false;
|
||||
|
||||
sch_mutex_lock(thread_mutex);
|
||||
sch_mutex_lock();
|
||||
|
||||
/* Take this opportunity to check for pending ASTs
|
||||
and deliver them. */
|
||||
// Take this opportunity to check for pending ASTs
|
||||
// and deliver them
|
||||
|
||||
if (ast_enable())
|
||||
stall(active_thread);
|
||||
@ -929,10 +727,9 @@ static bool schedule_active(bool hiber_flag)
|
||||
ret = true;
|
||||
}
|
||||
|
||||
sch_mutex_unlock(thread_mutex);
|
||||
sch_mutex_unlock();
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -951,23 +748,23 @@ static void stall(THREAD thread)
|
||||
if (thread != active_thread || thread->thread_flags & THREAD_hiber ||
|
||||
(ast_thread && ast_thread->thread_flags & THREAD_ast_active))
|
||||
{
|
||||
for (;;) {
|
||||
SLONG value = ISC_event_clear(thread->thread_stall);
|
||||
if (thread == active_thread
|
||||
&& !(thread->thread_flags & THREAD_hiber)
|
||||
&& (!ast_thread
|
||||
|| !(ast_thread->thread_flags & THREAD_ast_active)))
|
||||
while (true) {
|
||||
const SLONG value = ISC_event_clear(&thread->thread_stall);
|
||||
if (thread == active_thread &&
|
||||
!(thread->thread_flags & THREAD_hiber) &&
|
||||
(!ast_thread ||
|
||||
!(ast_thread->thread_flags & THREAD_ast_active)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
sch_mutex_unlock(thread_mutex);
|
||||
event_t* ptr = thread->thread_stall;
|
||||
ISC_event_wait(1, &ptr, &value, 0, 0, 0);
|
||||
sch_mutex_lock(thread_mutex);
|
||||
sch_mutex_unlock();
|
||||
event_t* ptr = &thread->thread_stall;
|
||||
ISC_event_wait(1, &ptr, &value, 0);
|
||||
sch_mutex_lock();
|
||||
}
|
||||
}
|
||||
|
||||
/* Explicitly disable AST delivery for active thread */
|
||||
// Explicitly disable AST delivery for active thread
|
||||
|
||||
ast_disable();
|
||||
}
|
||||
@ -990,85 +787,42 @@ static void stall_ast(THREAD thread)
|
||||
**************************************/
|
||||
if (thread == ast_thread) {
|
||||
if (ast_thread->thread_flags & THREAD_ast_disabled)
|
||||
for (;;) {
|
||||
SLONG value = ISC_event_clear(thread->thread_stall);
|
||||
while (true) {
|
||||
const SLONG value = ISC_event_clear(&thread->thread_stall);
|
||||
if (!(ast_thread->thread_flags & THREAD_ast_disabled))
|
||||
break;
|
||||
sch_mutex_unlock(thread_mutex);
|
||||
event_t* ptr = thread->thread_stall;
|
||||
ISC_event_wait(1, &ptr, &value, 0, 0, 0);
|
||||
sch_mutex_lock(thread_mutex);
|
||||
sch_mutex_unlock();
|
||||
event_t* ptr = &thread->thread_stall;
|
||||
ISC_event_wait(1, &ptr, &value, 0);
|
||||
sch_mutex_lock();
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Link thread block into ast thread queue */
|
||||
// Link thread block into ast thread queue
|
||||
|
||||
thread->thread_next = ast_thread->thread_next;
|
||||
thread->thread_prior = ast_thread;
|
||||
ast_thread->thread_next->thread_prior = thread;
|
||||
ast_thread->thread_next = thread;
|
||||
|
||||
/* Wait for AST delivery to complete */
|
||||
// Wait for AST delivery to complete
|
||||
|
||||
if (ast_thread->thread_flags & THREAD_ast_active)
|
||||
for (;;) {
|
||||
SLONG value = ISC_event_clear(thread->thread_stall);
|
||||
{
|
||||
while (true) {
|
||||
const SLONG value = ISC_event_clear(&thread->thread_stall);
|
||||
if (!(ast_thread->thread_flags & THREAD_ast_active))
|
||||
break;
|
||||
sch_mutex_unlock(thread_mutex);
|
||||
event_t* ptr = thread->thread_stall;
|
||||
ISC_event_wait(1, &ptr, &value, 0, 0, 0);
|
||||
sch_mutex_lock(thread_mutex);
|
||||
sch_mutex_unlock();
|
||||
event_t* ptr = &thread->thread_stall;
|
||||
ISC_event_wait(1, &ptr, &value, 0);
|
||||
sch_mutex_lock();
|
||||
}
|
||||
/* Unlink thread block from ast thread queue */
|
||||
}
|
||||
|
||||
// Unlink thread block from ast thread queue
|
||||
|
||||
thread->thread_prior->thread_next = thread->thread_next;
|
||||
thread->thread_next->thread_prior = thread->thread_prior;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void sch_mutex_lock(Firebird::Mutex& mtx)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* s c h _ m u t e x _ l o c k
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Enters mutex, on error bugcheks.
|
||||
*
|
||||
**************************************/
|
||||
try
|
||||
{
|
||||
mtx.enter();
|
||||
}
|
||||
catch (const Firebird::system_call_failed& e)
|
||||
{
|
||||
mutex_bugcheck("mutex lock", e.getErrorCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void sch_mutex_unlock(Firebird::Mutex& mtx)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* s c h _ m u t e x _ u n l o c k
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Leaves mutex, on error bugcheks.
|
||||
*
|
||||
**************************************/
|
||||
try
|
||||
{
|
||||
mtx.leave();
|
||||
}
|
||||
catch (const Firebird::system_call_failed& e)
|
||||
{
|
||||
mutex_bugcheck("mutex unlock", e.getErrorCode());
|
||||
}
|
||||
}
|
||||
|
@ -43,31 +43,20 @@ enum ast_t
|
||||
};
|
||||
|
||||
int API_ROUTINE gds__thread_enable(int);
|
||||
void API_ROUTINE gds__thread_enter(void);
|
||||
void API_ROUTINE gds__thread_exit(void);
|
||||
#ifdef VMS
|
||||
int API_ROUTINE gds__ast_active(void);
|
||||
void API_ROUTINE gds__completion_ast(void);
|
||||
int API_ROUTINE gds__thread_wait(int (*)(), SLONG);
|
||||
#endif // VMS
|
||||
void API_ROUTINE gds__thread_enter();
|
||||
void API_ROUTINE gds__thread_exit();
|
||||
|
||||
} // extern "C"
|
||||
|
||||
struct thread;
|
||||
|
||||
void SCH_abort(void);
|
||||
|
||||
extern "C"
|
||||
void SCH_ast(enum ast_t);
|
||||
|
||||
thread* SCH_current_thread(void);
|
||||
void SCH_enter(void);
|
||||
void SCH_exit(void);
|
||||
void SCH_hiber(void);
|
||||
void SCH_init(void);
|
||||
bool SCH_schedule(void);
|
||||
bool SCH_thread_enter_check(void);
|
||||
bool SCH_validate(void);
|
||||
thread* SCH_current_thread();
|
||||
void SCH_enter();
|
||||
void SCH_exit();
|
||||
void SCH_hiber();
|
||||
bool SCH_schedule();
|
||||
bool SCH_thread_enter_check();
|
||||
void SCH_wake(thread*);
|
||||
|
||||
|
||||
|
104
src/jrd/scl.epp
104
src/jrd/scl.epp
@ -66,11 +66,7 @@
|
||||
#include "../common/config/config.h"
|
||||
|
||||
|
||||
#ifdef VMS
|
||||
const int UIC_BASE = 8;
|
||||
#else
|
||||
const int UIC_BASE = 10;
|
||||
#endif
|
||||
|
||||
const SLONG BLOB_BUFFER_SIZE = 4096; /* used to read in acl blob */
|
||||
|
||||
@ -125,7 +121,7 @@ void SCL_check_access(const SecurityClass* s_class,
|
||||
const Firebird::MetaName& prc_name,
|
||||
SecurityClass::flags_t mask,
|
||||
const TEXT* type,
|
||||
const Firebird::MetaName& name)
|
||||
const char* name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -149,12 +145,6 @@ void SCL_check_access(const SecurityClass* s_class,
|
||||
0);
|
||||
}
|
||||
|
||||
// Don't run internal handles thru the security gauntlet.
|
||||
if (JRD_get_thread_security_disabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Attachment* const attachment = tdbb->getAttachment();
|
||||
|
||||
// Allow the database owner to back up a database even if he does not have
|
||||
@ -165,6 +155,13 @@ void SCL_check_access(const SecurityClass* s_class,
|
||||
return;
|
||||
}
|
||||
|
||||
// Allow the locksmith any access to database
|
||||
|
||||
if (attachment->locksmith())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool denied_db = false;
|
||||
|
||||
const SecurityClass* const att_class = attachment->att_security_class;
|
||||
@ -208,12 +205,45 @@ void SCL_check_access(const SecurityClass* s_class,
|
||||
ERR_post(isc_no_priv,
|
||||
isc_arg_string, names->p_names_string,
|
||||
isc_arg_string, type,
|
||||
isc_arg_string, ERR_cstring(name.c_str()),
|
||||
isc_arg_string, ERR_cstring(name),
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SCL_check_access(const SecurityClass* s_class,
|
||||
SLONG view_id,
|
||||
const Firebird::MetaName& trg_name,
|
||||
const Firebird::MetaName& prc_name,
|
||||
SecurityClass::flags_t mask,
|
||||
const TEXT* type,
|
||||
const Firebird::MetaName& name,
|
||||
const Firebird::MetaName& r_name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* S C L _ c h e c k _ a c c e s s
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Check security class for desired permission.
|
||||
* Alternate entrypoint.
|
||||
*
|
||||
**************************************/
|
||||
Firebird::string fullFieldName(name.c_str());
|
||||
if (r_name.hasData())
|
||||
{
|
||||
fullFieldName = r_name.c_str();
|
||||
fullFieldName += '.';
|
||||
fullFieldName += name.c_str();
|
||||
}
|
||||
|
||||
SCL_check_access(s_class, view_id, trg_name, prc_name,
|
||||
mask, type, fullFieldName.c_str());
|
||||
}
|
||||
|
||||
|
||||
void SCL_check_index(thread_db* tdbb, const Firebird::MetaName& index_name, UCHAR index_id,
|
||||
SecurityClass::flags_t mask)
|
||||
{
|
||||
@ -318,14 +348,18 @@ void SCL_check_index(thread_db* tdbb, const Firebird::MetaName& index_name, UCHA
|
||||
WITH RF.RDB$RELATION_NAME EQ reln_name.c_str()
|
||||
AND ISEG.RDB$INDEX_NAME EQ idx_name_ptr->c_str()
|
||||
|
||||
Firebird::string fullFieldName(reln_name.c_str());
|
||||
fullFieldName += '.';
|
||||
fullFieldName += RF.RDB$FIELD_NAME;
|
||||
fullFieldName.rtrim();
|
||||
if (!RF.RDB$SECURITY_CLASS.NULL) {
|
||||
s_class = SCL_get_class(RF.RDB$SECURITY_CLASS);
|
||||
SCL_check_access(s_class, 0, NULL, NULL, mask,
|
||||
object_column, RF.RDB$FIELD_NAME);
|
||||
SCL_check_access(s_class, 0, NULL, NULL, mask,
|
||||
object_column, fullFieldName);
|
||||
}
|
||||
else {
|
||||
SCL_check_access(default_s_class, 0, NULL, NULL, mask,
|
||||
object_column, RF.RDB$FIELD_NAME);
|
||||
object_column, fullFieldName);
|
||||
}
|
||||
|
||||
END_FOR;
|
||||
@ -634,7 +668,7 @@ void SCL_init(bool create,
|
||||
AND RR.RDB$ROLE_NAME EQ UU.RDB$RELATION_NAME
|
||||
AND UU.RDB$OBJECT_TYPE EQ obj_sql_role
|
||||
AND (UU.RDB$USER EQ login_name
|
||||
OR UU.RDB$USER EQ "PUBLIC")
|
||||
OR UU.RDB$USER EQ "PUBLIC")
|
||||
AND UU.RDB$USER_TYPE EQ obj_user
|
||||
AND UU.RDB$PRIVILEGE EQ "M"
|
||||
|
||||
@ -649,6 +683,26 @@ void SCL_init(bool create,
|
||||
if (!REQUEST (irq_verify_role_name))
|
||||
REQUEST (irq_verify_role_name) = request;
|
||||
|
||||
if (!found && (tempId.usr_flags & USR_trole))
|
||||
{
|
||||
jrd_req* request = CMP_find_request (tdbb, irq_verify_trusted_role, IRQ_REQUESTS);
|
||||
|
||||
FOR (REQUEST_HANDLE request) FIRST 1 RR IN RDB$ROLES
|
||||
WITH RR.RDB$ROLE_NAME EQ sql_role
|
||||
AND RR.RDB$SYSTEM_FLAG NOT MISSING
|
||||
|
||||
if (!REQUEST (irq_verify_trusted_role))
|
||||
REQUEST (irq_verify_trusted_role) = request;
|
||||
|
||||
if (RR.RDB$SYSTEM_FLAG & ROLE_FLAG_MAY_TRUST)
|
||||
found = true;
|
||||
|
||||
END_FOR;
|
||||
|
||||
if (!REQUEST (irq_verify_trusted_role))
|
||||
REQUEST (irq_verify_trusted_role) = request;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
role_name = NULL_ROLE;
|
||||
@ -669,10 +723,11 @@ void SCL_init(bool create,
|
||||
user->usr_sql_role_name = role_name.c_str();
|
||||
tdbb->getAttachment()->att_user = user;
|
||||
|
||||
jrd_req* handle = NULL;
|
||||
jrd_req* handle1 = NULL;
|
||||
|
||||
if (!create) {
|
||||
jrd_req* handle = NULL;
|
||||
jrd_req* handle1 = NULL;
|
||||
jrd_req* handle2 = NULL;
|
||||
|
||||
FOR(REQUEST_HANDLE handle) X IN RDB$DATABASE
|
||||
|
||||
if (!X.RDB$SECURITY_CLASS.NULL)
|
||||
@ -698,6 +753,17 @@ void SCL_init(bool create,
|
||||
}
|
||||
END_FOR;
|
||||
CMP_release(tdbb, handle1);
|
||||
|
||||
FOR(REQUEST_HANDLE handle2) R IN RDB$ROLES
|
||||
WITH R.RDB$ROLE_NAME EQ role_name.c_str()
|
||||
|
||||
if (!R.RDB$SYSTEM_FLAG.NULL)
|
||||
{
|
||||
if (R.RDB$SYSTEM_FLAG & ROLE_FLAG_DBO)
|
||||
user->usr_flags |= USR_dba;
|
||||
}
|
||||
END_FOR;
|
||||
CMP_release(tdbb, handle2);
|
||||
}
|
||||
else {
|
||||
user->usr_flags |= USR_owner;
|
||||
|
@ -59,6 +59,8 @@ const SecurityClass::flags_t SCL_execute = 8192;
|
||||
const USHORT USR_locksmith = 1; /* User has great karma */
|
||||
const USHORT USR_dba = 2; /* User has DBA privileges */
|
||||
const USHORT USR_owner = 4; /* User owns database */
|
||||
const USHORT USR_trole = 8; /* Role was set by trusted auth */
|
||||
|
||||
|
||||
class UserId
|
||||
{
|
||||
@ -75,7 +77,7 @@ public:
|
||||
|
||||
bool locksmith() const
|
||||
{
|
||||
return usr_flags & (USR_locksmith | USR_owner);
|
||||
return usr_flags & (USR_locksmith | USR_owner | USR_dba);
|
||||
}
|
||||
|
||||
UserId() : usr_user_id(0), usr_group_id(0),
|
||||
|
@ -35,7 +35,31 @@ struct dsc;
|
||||
|
||||
void SCL_check_access(const Jrd::SecurityClass*, SLONG, const Firebird::MetaName&,
|
||||
const Firebird::MetaName&, Jrd::SecurityClass::flags_t,
|
||||
const TEXT*, const Firebird::MetaName&);
|
||||
const TEXT*, const char*);
|
||||
void SCL_check_access(const Jrd::SecurityClass*, SLONG, const Firebird::MetaName&,
|
||||
const Firebird::MetaName&, Jrd::SecurityClass::flags_t,
|
||||
const TEXT*, const Firebird::MetaName&, const Firebird::MetaName&);
|
||||
inline void SCL_check_access(const Jrd::SecurityClass* s_class,
|
||||
SLONG view_id,
|
||||
const Firebird::MetaName& trg_name,
|
||||
const Firebird::MetaName& prc_name,
|
||||
Jrd::SecurityClass::flags_t mask,
|
||||
const TEXT* type,
|
||||
const Firebird::string& name)
|
||||
{
|
||||
SCL_check_access(s_class, view_id, trg_name, prc_name, mask, type, name.c_str());
|
||||
}
|
||||
inline void SCL_check_access(const Jrd::SecurityClass* s_class,
|
||||
SLONG view_id,
|
||||
const Firebird::MetaName& trg_name,
|
||||
const Firebird::MetaName& prc_name,
|
||||
Jrd::SecurityClass::flags_t mask,
|
||||
const TEXT* type,
|
||||
const Firebird::MetaName& name)
|
||||
{
|
||||
SCL_check_access(s_class, view_id, trg_name, prc_name, mask, type, name.c_str());
|
||||
}
|
||||
|
||||
void SCL_check_index(Jrd::thread_db*, const Firebird::MetaName&, UCHAR, Jrd::SecurityClass::flags_t);
|
||||
void SCL_check_procedure(const dsc*, Jrd::SecurityClass::flags_t);
|
||||
void SCL_check_relation(const dsc*, Jrd::SecurityClass::flags_t);
|
||||
|
@ -25,9 +25,7 @@
|
||||
#include <string.h>
|
||||
#include "../jrd/common.h"
|
||||
#include <stdarg.h>
|
||||
#ifndef REQUESTER
|
||||
#include "../jrd/jrd.h"
|
||||
#endif
|
||||
#include "../jrd/ibase.h"
|
||||
#include "../jrd/val.h"
|
||||
#include "../jrd/sdl.h"
|
||||
@ -979,20 +977,11 @@ static const UCHAR* sdl_desc(const UCHAR* ptr, DSC* desc)
|
||||
break;
|
||||
|
||||
case blr_double:
|
||||
#ifndef VMS
|
||||
case blr_d_float:
|
||||
#endif
|
||||
desc->dsc_dtype = dtype_double;
|
||||
desc->dsc_length = sizeof(double);
|
||||
break;
|
||||
|
||||
#ifdef VMS
|
||||
case blr_d_float:
|
||||
desc->dsc_dtype = dtype_d_float;
|
||||
desc->dsc_length = sizeof(double);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case blr_timestamp:
|
||||
desc->dsc_dtype = dtype_timestamp;
|
||||
desc->dsc_length = sizeof(ISC_QUAD);
|
||||
|
@ -346,7 +346,6 @@ void SDW_check(void)
|
||||
lock->lck_owner_handle =
|
||||
LCK_get_owner_handle(tdbb, lock->lck_type);
|
||||
lock->lck_parent = dbb->dbb_lock;
|
||||
lock->lck_owner = tdbb->getAttachment();
|
||||
|
||||
LCK_lock(tdbb, lock, LCK_EX, LCK_NO_WAIT);
|
||||
if (lock->lck_physical == LCK_EX) {
|
||||
@ -652,10 +651,7 @@ bool SDW_lck_update(SLONG sdw_update_flags)
|
||||
}
|
||||
|
||||
if (!sdw_update_flags) {
|
||||
if (LCK_read_data(lock))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
return !LCK_read_data(lock);
|
||||
}
|
||||
|
||||
if (LCK_read_data(lock))
|
||||
@ -750,7 +746,6 @@ bool SDW_rollover_to_shadow(jrd_file* file, const bool inAst)
|
||||
update_lock->lck_owner_handle =
|
||||
LCK_get_owner_handle(tdbb, update_lock->lck_type);
|
||||
update_lock->lck_parent = dbb->dbb_lock;
|
||||
update_lock->lck_owner = tdbb->getAttachment();
|
||||
|
||||
SLONG sdw_update_flags = SDW_rollover;
|
||||
|
||||
@ -952,8 +947,8 @@ void SDW_start(const TEXT* file_name,
|
||||
{
|
||||
if (shadow && (shadow->sdw_flags & SDW_rollover))
|
||||
return;
|
||||
else
|
||||
ERR_post(isc_shadow_accessed, 0);
|
||||
|
||||
ERR_post(isc_shadow_accessed, 0);
|
||||
}
|
||||
|
||||
// Verify shadow file path against DatabaseAccess entry of firebird.conf
|
||||
@ -1118,12 +1113,9 @@ int SDW_start_shadowing(void* ast_object)
|
||||
if (lock->lck_physical != LCK_SR)
|
||||
return 0;
|
||||
|
||||
ISC_ast_enter();
|
||||
|
||||
/* 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);
|
||||
ThreadContextHolder tdbb;
|
||||
|
||||
tdbb->setDatabase(new_dbb);
|
||||
tdbb->tdbb_quantum = QUANTUM;
|
||||
@ -1136,11 +1128,6 @@ int SDW_start_shadowing(void* ast_object)
|
||||
|
||||
LCK_release(tdbb, lock);
|
||||
|
||||
/* Restore the prior thread context */
|
||||
|
||||
JRD_restore_thread_data();
|
||||
|
||||
ISC_ast_exit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,7 @@ void sha_final(unsigned char [SHA_DIGESTSIZE], SHA_INFO *);
|
||||
#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
|
||||
#define f4(x,y,z) (x ^ y ^ z)
|
||||
|
||||
|
||||
/* SHA constants */
|
||||
|
||||
#define CONST1 0x5a827999L
|
||||
@ -133,7 +134,7 @@ void sha_final(unsigned char [SHA_DIGESTSIZE], SHA_INFO *);
|
||||
static void sha_transform(SHA_INFO *sha_info)
|
||||
{
|
||||
int i;
|
||||
LONG T, W[80];
|
||||
LONG W[80];
|
||||
|
||||
const BYTE* dp = sha_info->data;
|
||||
|
||||
@ -148,17 +149,17 @@ nether regions of the anatomy...
|
||||
#if (SHA_BYTE_ORDER == 1234)
|
||||
#define SWAP_DONE
|
||||
for (i = 0; i < 16; ++i) {
|
||||
T = *((LONG *) dp);
|
||||
dp += 4;
|
||||
W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
|
||||
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
|
||||
const LONG T = *((LONG *) dp);
|
||||
dp += 4;
|
||||
W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
|
||||
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
|
||||
}
|
||||
#endif /* SHA_BYTE_ORDER == 1234 */
|
||||
|
||||
#if (SHA_BYTE_ORDER == 4321)
|
||||
#define SWAP_DONE
|
||||
for (i = 0; i < 16; ++i) {
|
||||
T = *((LONG *) dp);
|
||||
const LONG T = *((LONG *) dp);
|
||||
dp += 4;
|
||||
W[i] = T32(T);
|
||||
}
|
||||
@ -167,7 +168,7 @@ nether regions of the anatomy...
|
||||
#if (SHA_BYTE_ORDER == 12345678)
|
||||
#define SWAP_DONE
|
||||
for (i = 0; i < 16; i += 2) {
|
||||
T = *((LONG *) dp);
|
||||
LONG T = *((LONG *) dp);
|
||||
dp += 8;
|
||||
W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
|
||||
((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
|
||||
@ -180,7 +181,7 @@ nether regions of the anatomy...
|
||||
#if (SHA_BYTE_ORDER == 87654321)
|
||||
#define SWAP_DONE
|
||||
for (i = 0; i < 16; i += 2) {
|
||||
T = *((LONG *) dp);
|
||||
const LONG T = *((LONG *) dp);
|
||||
dp += 8;
|
||||
W[i] = T32(T >> 32);
|
||||
W[i + 1] = T32(T);
|
||||
@ -203,6 +204,7 @@ nether regions of the anatomy...
|
||||
LONG D = sha_info->digest[3];
|
||||
LONG E = sha_info->digest[4];
|
||||
const LONG* WP = W;
|
||||
LONG T;
|
||||
#ifdef UNRAVEL
|
||||
FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
|
||||
FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
|
||||
@ -338,7 +340,7 @@ void sha_final(unsigned char digest[SHA_DIGESTSIZE], SHA_INFO *sha_info)
|
||||
digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
|
||||
}
|
||||
|
||||
char conv_bin2ascii(ULONG l)
|
||||
inline char conv_bin2ascii(ULONG l)
|
||||
{
|
||||
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[l & 0x3f];
|
||||
}
|
||||
|
@ -118,16 +118,15 @@ bool SHUT_blocking_ast(Database* dbb)
|
||||
|
||||
if ((flag & isc_dpb_shut_force) && !delay)
|
||||
return shutdown_locks(dbb, flag);
|
||||
else {
|
||||
if (flag & isc_dpb_shut_attachment)
|
||||
dbb->dbb_ast_flags |= DBB_shut_attach;
|
||||
if (flag & isc_dpb_shut_force)
|
||||
dbb->dbb_ast_flags |= DBB_shut_force;
|
||||
if (flag & isc_dpb_shut_transaction)
|
||||
dbb->dbb_ast_flags |= DBB_shut_tran;
|
||||
dbb->dbb_shutdown_delay = delay; // not tested anywhere
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flag & isc_dpb_shut_attachment)
|
||||
dbb->dbb_ast_flags |= DBB_shut_attach;
|
||||
if (flag & isc_dpb_shut_force)
|
||||
dbb->dbb_ast_flags |= DBB_shut_force;
|
||||
if (flag & isc_dpb_shut_transaction)
|
||||
dbb->dbb_ast_flags |= DBB_shut_tran;
|
||||
dbb->dbb_shutdown_delay = delay; // not tested anywhere
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
246
src/jrd/sort.cpp
246
src/jrd/sort.cpp
@ -74,10 +74,6 @@ const ULONG IO_RETRY = 20;
|
||||
const USHORT RUN_GROUP = 8;
|
||||
const USHORT MAX_MERGE_LEVEL = 2;
|
||||
|
||||
#ifdef VMS
|
||||
double MTH$CVT_D_G(), MTH$CVT_G_D();
|
||||
#endif
|
||||
|
||||
using namespace Jrd;
|
||||
|
||||
// The sort buffer size should be just under a multiple of the
|
||||
@ -96,7 +92,7 @@ const ULONG MAX_SORT_BUFFER_SIZE = SORT_BUFFER_CHUNK_SIZE * 32;
|
||||
// offset in array of pointers to back record pointer (sr_bckptr)
|
||||
#define BACK_OFFSET (-static_cast<signed>(SIZEOF_SR_BCKPTR / sizeof(SLONG*)))
|
||||
|
||||
#define DIFF_LONGS(a, b) ((a) - (b))
|
||||
//#define DIFF_LONGS(a, b) ((a) - (b))
|
||||
#define SWAP_LONGS(a, b, t) {t = a; a = b; b = t;}
|
||||
|
||||
// Compare p and q both SORTP pointers for l 32-bit longwords
|
||||
@ -126,7 +122,7 @@ static ULONG high_key[] = {
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
static sort_record* get_merge(merge_control*, sort_context*, RSE_GET_MODE);
|
||||
#else
|
||||
static void diddle_key(UCHAR *, sort_context*, bool);
|
||||
static void diddle_key(UCHAR*, sort_context*, bool);
|
||||
static sort_record* get_merge(merge_control*, sort_context*);
|
||||
#endif
|
||||
|
||||
@ -195,17 +191,18 @@ void SORT_diddle_key(UCHAR* record, sort_context* scb, bool direction)
|
||||
|
||||
case SKD_varying:
|
||||
if (direction) {
|
||||
if (!(scb->scb_flags & scb_sorted)) {
|
||||
*((USHORT *) (record + key->skd_vary_offset)) =
|
||||
((vary*) p)->vary_length;
|
||||
USHORT& vlen = ((vary*) p)->vary_length;
|
||||
if (!(scb->scb_flags & scb_sorted))
|
||||
{
|
||||
*((USHORT *) (record + key->skd_vary_offset)) = vlen;
|
||||
const UCHAR fill_char =
|
||||
(key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE;
|
||||
UCHAR* fill_pos = p + sizeof(USHORT) + ((vary*) p)->vary_length;
|
||||
const USHORT fill = n - sizeof(USHORT) - ((vary*) p)->vary_length;
|
||||
UCHAR* fill_pos = p + sizeof(USHORT) + vlen;
|
||||
const USHORT fill = n - sizeof(USHORT) - vlen;
|
||||
if (fill)
|
||||
memset(fill_pos, fill_char, fill);
|
||||
}
|
||||
((vary*) p)->vary_length = 0;
|
||||
vlen = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -213,7 +210,7 @@ void SORT_diddle_key(UCHAR* record, sort_context* scb, bool direction)
|
||||
if (direction) {
|
||||
const UCHAR fill_char = (key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE;
|
||||
if (!(scb->scb_flags & scb_sorted)) {
|
||||
const USHORT l = strlen(p);
|
||||
const USHORT l = strlen(reinterpret_cast<char*>(p));
|
||||
*((USHORT *) (record + key->skd_vary_offset)) = l;
|
||||
UCHAR* fill_pos = p + l;
|
||||
const USHORT fill = n - l;
|
||||
@ -294,13 +291,10 @@ void SORT_diddle_key(UCHAR* record, sort_context* scb, bool direction)
|
||||
* direction - true for SORT_put() and false for SORT_get()
|
||||
*
|
||||
**************************************/
|
||||
UCHAR c1, c2, fill_char, *fill_pos;
|
||||
USHORT w, l, fill;
|
||||
UCHAR c1, fill_char, *fill_pos;
|
||||
USHORT fill;
|
||||
SSHORT longs, flag;
|
||||
ULONG lw;
|
||||
#ifdef VMS
|
||||
double *dp;
|
||||
#endif
|
||||
|
||||
const sort_key_def* key = scb->scb_description;
|
||||
for (const sort_key_def* const end = key + scb->scb_keys; key < end; key++)
|
||||
@ -332,31 +326,31 @@ void SORT_diddle_key(UCHAR* record, sort_context* scb, bool direction)
|
||||
// record and zap it so that it doesn't interfere with collation
|
||||
|
||||
if (key->skd_dtype == SKD_varying && direction) {
|
||||
USHORT& vlen = ((vary*) p)->vary_length;
|
||||
if (!(scb->scb_flags & scb_sorted)) {
|
||||
*((USHORT *) (record + key->skd_vary_offset)) = l =
|
||||
((vary*) p)->vary_length;
|
||||
*((USHORT*) (record + key->skd_vary_offset)) = vlen;
|
||||
fill_char =
|
||||
(key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE;
|
||||
fill_pos = p + sizeof(USHORT) + l;
|
||||
fill = n - sizeof(USHORT) - l;
|
||||
fill_pos = p + sizeof(USHORT) + vlen;
|
||||
fill = n - sizeof(USHORT) - vlen;
|
||||
if (fill)
|
||||
memset(fill_pos, fill_char, fill);
|
||||
}
|
||||
((vary*) p)->vary_length = 0;
|
||||
vlen = 0;
|
||||
}
|
||||
|
||||
if (key->skd_dtype == SKD_cstring && direction) {
|
||||
fill_char = (key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE;
|
||||
if (!(scb->scb_flags & scb_sorted)) {
|
||||
*((USHORT *) (record + key->skd_vary_offset)) = l =
|
||||
strlen(p);
|
||||
const USHORT l = strlen(reinterpret_cast<char*>(p));
|
||||
*((USHORT*) (record + key->skd_vary_offset)) = l;
|
||||
fill_pos = p + l;
|
||||
fill = n - l;
|
||||
if (fill)
|
||||
memset(fill_pos, fill_char, fill);
|
||||
}
|
||||
else {
|
||||
l = *((USHORT *) (record + key->skd_vary_offset));
|
||||
USHORT l = *((USHORT*) (record + key->skd_vary_offset));
|
||||
*(p + l) = fill_char;
|
||||
}
|
||||
}
|
||||
@ -428,47 +422,40 @@ void SORT_diddle_key(UCHAR* record, sort_context* scb, bool direction)
|
||||
break;
|
||||
|
||||
#else // IEEE
|
||||
#ifdef VMS
|
||||
case SKD_d_float:
|
||||
dp = (double *) p;
|
||||
if (direction)
|
||||
*dp = MTH$CVT_D_G(dp);
|
||||
|
||||
#endif
|
||||
case SKD_double:
|
||||
w = wp[2];
|
||||
wp[2] = wp[3];
|
||||
wp[3] = w;
|
||||
|
||||
#ifndef VMS
|
||||
case SKD_d_float:
|
||||
#endif
|
||||
case SKD_float:
|
||||
if (!direction)
|
||||
if (complement) {
|
||||
{
|
||||
if (complement)
|
||||
{
|
||||
if (p[3] & 1 << 7)
|
||||
complement = !complement;
|
||||
else
|
||||
p[3] ^= 1 << 7;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
if (p[3] & 1 << 7)
|
||||
p[3] ^= 1 << 7;
|
||||
else
|
||||
complement = !complement;
|
||||
}
|
||||
}
|
||||
w = wp[0];
|
||||
wp[0] = wp[1];
|
||||
wp[1] = w;
|
||||
if (direction)
|
||||
{
|
||||
if (p[3] & 1 << 7)
|
||||
complement = !complement;
|
||||
else
|
||||
p[3] ^= 1 << 7;
|
||||
#ifdef VMS
|
||||
else if (key->skd_dtype == SKD_d_float)
|
||||
*dp = MTH$CVT_G_D(dp);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#endif // IEEE
|
||||
|
||||
@ -476,10 +463,13 @@ void SORT_diddle_key(UCHAR* record, sort_context* scb, bool direction)
|
||||
fb_assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (complement && n)
|
||||
do
|
||||
{
|
||||
do {
|
||||
*p++ ^= -1;
|
||||
while (--n);
|
||||
} while (--n);
|
||||
}
|
||||
|
||||
// Flatter but don't complement control info for non-fixed
|
||||
// data types when restoring the data
|
||||
@ -491,7 +481,7 @@ void SORT_diddle_key(UCHAR* record, sort_context* scb, bool direction)
|
||||
|
||||
if (key->skd_dtype == SKD_cstring && !direction) {
|
||||
p = (BLOB_PTR *) record + key->skd_offset;
|
||||
l = *((USHORT *) (record + key->skd_vary_offset));
|
||||
USHORT l = *((USHORT *) (record + key->skd_vary_offset));
|
||||
*(p + l) = 0;
|
||||
}
|
||||
}
|
||||
@ -601,7 +591,7 @@ void SORT_get(thread_db* tdbb,
|
||||
}
|
||||
|
||||
if (record)
|
||||
SORT_diddle_key((UCHAR *) record->sort_record_key, scb, false);
|
||||
SORT_diddle_key((UCHAR*) record->sort_record_key, scb, false);
|
||||
|
||||
*record_address = (ULONG *) record;
|
||||
|
||||
@ -646,7 +636,7 @@ void SORT_get(thread_db* tdbb,
|
||||
*record_address = (ULONG *) record;
|
||||
|
||||
if (record) {
|
||||
diddle_key((UCHAR *) record->sort_record_key, scb, false);
|
||||
diddle_key((UCHAR*) record->sort_record_key, scb, false);
|
||||
}
|
||||
|
||||
tdbb->bumpStats(RuntimeStatistics::SORT_GETS);
|
||||
@ -819,10 +809,10 @@ void SORT_put(thread_db* tdbb, sort_context* scb, ULONG ** record_address)
|
||||
if (record != (SR *) scb->scb_end_memory)
|
||||
{
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
SORT_diddle_key((UCHAR *) (record->sr_sort_record.sort_record_key),
|
||||
SORT_diddle_key((UCHAR*) (record->sr_sort_record.sort_record_key),
|
||||
scb, true);
|
||||
#else
|
||||
diddle_key((UCHAR *) (record->sr_sort_record.sort_record_key), scb,
|
||||
diddle_key((UCHAR*) (record->sr_sort_record.sort_record_key), scb,
|
||||
true);
|
||||
#endif
|
||||
}
|
||||
@ -958,9 +948,9 @@ void SORT_sort(thread_db* tdbb, sort_context* scb)
|
||||
if (scb->scb_last_record != (SR *) scb->scb_end_memory)
|
||||
{
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
SORT_diddle_key((UCHAR *) KEYOF(scb->scb_last_record), scb, true);
|
||||
SORT_diddle_key((UCHAR*) KEYOF(scb->scb_last_record), scb, true);
|
||||
#else
|
||||
diddle_key((UCHAR *) KEYOF(scb->scb_last_record), scb, true);
|
||||
diddle_key((UCHAR*) KEYOF(scb->scb_last_record), scb, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1213,7 +1203,7 @@ FB_UINT64 SORT_write_block(ISC_STATUS* status_vector,
|
||||
|
||||
#ifndef SCROLLABLE_CURSORS
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
static void diddle_key(UCHAR* record, sort_context* scb, bool direction)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1229,7 +1219,7 @@ static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
*
|
||||
**************************************/
|
||||
UCHAR *fill_pos, fill_char;
|
||||
USHORT l, fill, flag;
|
||||
USHORT fill, flag;
|
||||
|
||||
for (sort_key_def* key = scb->scb_description, *end = key + scb->scb_keys;
|
||||
key < end; key++)
|
||||
@ -1249,18 +1239,19 @@ static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
// record and zap it so that it doesn't interfere with collation
|
||||
|
||||
case SKD_varying:
|
||||
if (direction) {
|
||||
if (!(scb->scb_flags & scb_sorted)) {
|
||||
*((USHORT *) (record + key->skd_vary_offset)) =
|
||||
((vary*) p)->vary_length;
|
||||
fill_char =
|
||||
(key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE;
|
||||
fill_pos = p + sizeof(USHORT) + ((vary*) p)->vary_length;
|
||||
fill = n - sizeof(USHORT) - ((vary*) p)->vary_length;
|
||||
if (direction)
|
||||
{
|
||||
USHORT& vlen = ((vary*) p)->vary_length;
|
||||
if (!(scb->scb_flags & scb_sorted))
|
||||
{
|
||||
*((USHORT *) (record + key->skd_vary_offset)) = vlen;
|
||||
fill_char = (key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE;
|
||||
fill_pos = p + sizeof(USHORT) + vlen;
|
||||
fill = n - sizeof(USHORT) - vlen;
|
||||
if (fill)
|
||||
memset(fill_pos, fill_char, fill);
|
||||
}
|
||||
((vary*) p)->vary_length = 0;
|
||||
vlen = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1268,15 +1259,15 @@ static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
if (direction) {
|
||||
fill_char = (key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE;
|
||||
if (!(scb->scb_flags & scb_sorted)) {
|
||||
*((USHORT *) (record + key->skd_vary_offset)) = l =
|
||||
strlen((char*)p);
|
||||
const USHORT l = strlen(reinterpret_cast<char*>(p));
|
||||
*((USHORT *) (record + key->skd_vary_offset)) = l;
|
||||
fill_pos = p + l;
|
||||
fill = n - l;
|
||||
if (fill)
|
||||
memset(fill_pos, fill_char, fill);
|
||||
}
|
||||
else {
|
||||
l = *((USHORT *) (record + key->skd_vary_offset));
|
||||
USHORT l = *((USHORT *) (record + key->skd_vary_offset));
|
||||
*(p + l) = fill_char;
|
||||
}
|
||||
}
|
||||
@ -1285,12 +1276,7 @@ static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
case SKD_text:
|
||||
break;
|
||||
|
||||
#ifndef VMS
|
||||
case SKD_d_float:
|
||||
#else
|
||||
Deliberate_compile_error++;
|
||||
Fix for any VMS port.
|
||||
#endif
|
||||
case SKD_float:
|
||||
case SKD_double:
|
||||
flag = (direction || !complement)
|
||||
@ -1330,7 +1316,7 @@ static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
|
||||
if (key->skd_dtype == SKD_cstring && !direction) {
|
||||
p = record + key->skd_offset;
|
||||
l = *((USHORT *) (record + key->skd_vary_offset));
|
||||
USHORT l = *((USHORT *) (record + key->skd_vary_offset));
|
||||
*(p + l) = 0;
|
||||
}
|
||||
}
|
||||
@ -1338,7 +1324,7 @@ static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
|
||||
|
||||
#else
|
||||
static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
static void diddle_key(UCHAR* record, sort_context* scb, bool direction)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1354,12 +1340,9 @@ static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
*
|
||||
**************************************/
|
||||
UCHAR c1, fill_char, *fill_pos;
|
||||
USHORT l, fill;
|
||||
USHORT fill;
|
||||
SSHORT longs, flag;
|
||||
ULONG lw;
|
||||
#ifdef VMS
|
||||
double *dp;
|
||||
#endif
|
||||
#ifndef IEEE
|
||||
USHORT w;
|
||||
#endif
|
||||
@ -1394,31 +1377,31 @@ static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
// record and zap it so that it doesn't interfere with collation
|
||||
|
||||
if (key->skd_dtype == SKD_varying && direction) {
|
||||
USHORT& vlen = ((vary*) p)->vary_length;
|
||||
if (!(scb->scb_flags & scb_sorted)) {
|
||||
*((USHORT *) (record + key->skd_vary_offset)) = l =
|
||||
((vary*) p)->vary_length;
|
||||
*((USHORT *) (record + key->skd_vary_offset)) = vlen;
|
||||
fill_char =
|
||||
(key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE;
|
||||
fill_pos = p + sizeof(USHORT) + l;
|
||||
fill = n - sizeof(USHORT) - l;
|
||||
fill_pos = p + sizeof(USHORT) + vlen;
|
||||
fill = n - sizeof(USHORT) - vlen;
|
||||
if (fill)
|
||||
memset(fill_pos, fill_char, fill);
|
||||
}
|
||||
((vary*) p)->vary_length = 0;
|
||||
vlen = 0;
|
||||
}
|
||||
|
||||
if (key->skd_dtype == SKD_cstring && direction) {
|
||||
fill_char = (key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE;
|
||||
if (!(scb->scb_flags & scb_sorted)) {
|
||||
*((USHORT *) (record + key->skd_vary_offset)) = l =
|
||||
strlen(reinterpret_cast<const char*>(p));
|
||||
const USHORT l = strlen(reinterpret_cast<char*>(p));
|
||||
*((USHORT *) (record + key->skd_vary_offset)) = l;
|
||||
fill_pos = p + l;
|
||||
fill = n - l;
|
||||
if (fill)
|
||||
memset(fill_pos, fill_char, fill);
|
||||
}
|
||||
else {
|
||||
l = *((USHORT *) (record + key->skd_vary_offset));
|
||||
USHORT l = *((USHORT *) (record + key->skd_vary_offset));
|
||||
*(p + l) = fill_char;
|
||||
}
|
||||
}
|
||||
@ -1488,47 +1471,40 @@ static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
break;
|
||||
|
||||
#else // IEEE
|
||||
#ifdef VMS
|
||||
case SKD_d_float:
|
||||
dp = (double *) p;
|
||||
if (direction)
|
||||
*dp = MTH$CVT_D_G(dp);
|
||||
|
||||
#endif
|
||||
case SKD_double:
|
||||
w = wp[2];
|
||||
wp[2] = wp[3];
|
||||
wp[3] = w;
|
||||
|
||||
#ifndef VMS
|
||||
case SKD_d_float:
|
||||
#endif
|
||||
case SKD_float:
|
||||
if (!direction)
|
||||
if (complement) {
|
||||
{
|
||||
if (complement)
|
||||
{
|
||||
if (p[3] & 1 << 7)
|
||||
complement = !complement;
|
||||
else
|
||||
p[3] ^= 1 << 7;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
if (p[3] & 1 << 7)
|
||||
p[3] ^= 1 << 7;
|
||||
else
|
||||
complement = !complement;
|
||||
}
|
||||
}
|
||||
w = wp[0];
|
||||
wp[0] = wp[1];
|
||||
wp[1] = w;
|
||||
if (direction)
|
||||
{
|
||||
if (p[3] & 1 << 7)
|
||||
complement = !complement;
|
||||
else
|
||||
p[3] ^= 1 << 7;
|
||||
#ifdef VMS
|
||||
else if (key->skd_dtype == SKD_d_float)
|
||||
*dp = MTH$CVT_G_D(dp);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#endif // IEEE
|
||||
|
||||
@ -1546,12 +1522,12 @@ static void diddle_key(UCHAR * record, sort_context* scb, bool direction)
|
||||
|
||||
if (key->skd_dtype == SKD_varying && !direction) {
|
||||
p = (BLOB_PTR *) record + key->skd_offset;
|
||||
((vary*) p)->vary_length = *((USHORT *) (record + key->skd_vary_offset));
|
||||
((vary*) p)->vary_length = *((USHORT*) (record + key->skd_vary_offset));
|
||||
}
|
||||
|
||||
if (key->skd_dtype == SKD_cstring && !direction) {
|
||||
p = (BLOB_PTR *) record + key->skd_offset;
|
||||
l = *((USHORT *) (record + key->skd_vary_offset));
|
||||
USHORT l = *((USHORT *) (record + key->skd_vary_offset));
|
||||
*(p + l) = 0;
|
||||
}
|
||||
}
|
||||
@ -1682,7 +1658,8 @@ static sort_record* get_merge(merge_control* merge, sort_context* scb
|
||||
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
if (mode == RSE_get_forward) {
|
||||
run->run_record = NEXT_RUN_RECORD(run->run_record);
|
||||
run->run_record =
|
||||
reinterpret_cast<sort_record*>(NEXT_RUN_RECORD(run->run_record));
|
||||
#endif
|
||||
|
||||
if ((record = (sort_record*) run->run_record) <
|
||||
@ -1710,9 +1687,10 @@ static sort_record* get_merge(merge_control* merge, sort_context* scb
|
||||
#else
|
||||
}
|
||||
else {
|
||||
run->run_record = PREV_RUN_RECORD(run->run_record);
|
||||
run->run_record =
|
||||
reinterpret_cast<sort_record*>(PREV_RUN_RECORD(run->run_record));
|
||||
if ((record = (sort_record*) run->run_record) >=
|
||||
run->run_buffer)
|
||||
reinterpret_cast<sort_record*>(run->run_buffer))
|
||||
{
|
||||
++run->run_records;
|
||||
continue;
|
||||
@ -1742,7 +1720,7 @@ static sort_record* get_merge(merge_control* merge, sort_context* scb
|
||||
else
|
||||
run->run_seek -= l;
|
||||
|
||||
SORT_read_block(scb->scb_status_vector, run->run_sfb,
|
||||
SORT_read_block(scb->scb_status_vector, scb->scb_space,
|
||||
run->run_seek, (UCHAR*) run->run_buffer, l);
|
||||
run->run_cached = l;
|
||||
|
||||
@ -1757,7 +1735,7 @@ static sort_record* get_merge(merge_control* merge, sort_context* scb
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
}
|
||||
else {
|
||||
record = PREV_RUN_RECORD(run->run_end_buffer);
|
||||
record = reinterpret_cast<sort_record*>(PREV_RUN_RECORD(run->run_end_buffer));
|
||||
++run->run_records;
|
||||
}
|
||||
|
||||
@ -1828,11 +1806,11 @@ static sort_record* get_merge(merge_control* merge, sort_context* scb
|
||||
|
||||
if (l == 0 && scb->scb_dup_callback) {
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
SORT_diddle_key((UCHAR *) merge->mrg_record_a, scb, false);
|
||||
SORT_diddle_key((UCHAR *) merge->mrg_record_b, scb, false);
|
||||
SORT_diddle_key((UCHAR*) merge->mrg_record_a, scb, false);
|
||||
SORT_diddle_key((UCHAR*) merge->mrg_record_b, scb, false);
|
||||
#else
|
||||
diddle_key((UCHAR *) merge->mrg_record_a, scb, false);
|
||||
diddle_key((UCHAR *) merge->mrg_record_b, scb, false);
|
||||
diddle_key((UCHAR*) merge->mrg_record_a, scb, false);
|
||||
diddle_key((UCHAR*) merge->mrg_record_b, scb, false);
|
||||
#endif
|
||||
if ((*scb->scb_dup_callback) ((const UCHAR*) merge->mrg_record_a,
|
||||
(const UCHAR*) merge->mrg_record_b,
|
||||
@ -1840,18 +1818,18 @@ static sort_record* get_merge(merge_control* merge, sort_context* scb
|
||||
{
|
||||
merge->mrg_record_a = NULL;
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
SORT_diddle_key((UCHAR *) merge->mrg_record_b, scb, true);
|
||||
SORT_diddle_key((UCHAR*) merge->mrg_record_b, scb, true);
|
||||
#else
|
||||
diddle_key((UCHAR *) merge->mrg_record_b, scb, true);
|
||||
diddle_key((UCHAR*) merge->mrg_record_b, scb, true);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
SORT_diddle_key((UCHAR *) merge->mrg_record_a, scb, true);
|
||||
SORT_diddle_key((UCHAR *) merge->mrg_record_b, scb, true);
|
||||
SORT_diddle_key((UCHAR*) merge->mrg_record_a, scb, true);
|
||||
SORT_diddle_key((UCHAR*) merge->mrg_record_b, scb, true);
|
||||
#else
|
||||
diddle_key((UCHAR *) merge->mrg_record_a, scb, true);
|
||||
diddle_key((UCHAR *) merge->mrg_record_b, scb, true);
|
||||
diddle_key((UCHAR*) merge->mrg_record_a, scb, true);
|
||||
diddle_key((UCHAR*) merge->mrg_record_b, scb, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1951,9 +1929,6 @@ static bool local_fini(sort_context* scb, Attachment* att)
|
||||
* Finish sort, and release all resources.
|
||||
*
|
||||
**************************************/
|
||||
ULONG** merge_buf;
|
||||
sort_context** ptr;
|
||||
|
||||
bool found_it = true;
|
||||
|
||||
if (att) {
|
||||
@ -1968,12 +1943,16 @@ static bool local_fini(sort_context* scb, Attachment* att)
|
||||
// Start by unlinking from que, if present
|
||||
|
||||
if (att)
|
||||
for (ptr = &att->att_active_sorts; *ptr; ptr = &(*ptr)->scb_next)
|
||||
{
|
||||
for (sort_context** ptr = &att->att_active_sorts; *ptr; ptr = &(*ptr)->scb_next)
|
||||
{
|
||||
if (*ptr == scb) {
|
||||
*ptr = scb->scb_next;
|
||||
found_it = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *NO*. I won't free it if it's not in
|
||||
// the pointer list that has been passed
|
||||
@ -1988,6 +1967,7 @@ static bool local_fini(sort_context* scb, Attachment* att)
|
||||
|
||||
// Get rid of extra merge space
|
||||
|
||||
ULONG** merge_buf;
|
||||
while ( (merge_buf = (ULONG **) scb->scb_merge_space) ) {
|
||||
scb->scb_merge_space = *merge_buf;
|
||||
delete merge_buf;
|
||||
@ -2537,7 +2517,8 @@ static ULONG order(sort_context* scb)
|
||||
|
||||
// scb_next_pointer points to the end of pointer memory or the beginning of
|
||||
// records
|
||||
while (ptr < scb->scb_next_pointer) {
|
||||
while (ptr < scb->scb_next_pointer)
|
||||
{
|
||||
// If the next pointer is null, it's record has been eliminated as a
|
||||
// duplicate. This is the only easy case.
|
||||
|
||||
@ -2796,7 +2777,8 @@ static void sort(sort_context* scb)
|
||||
|
||||
// Scream through and correct any out of order pairs
|
||||
// hvlad: don't compare user keys against high_key
|
||||
while (j < (SORTP **) scb->scb_next_pointer - 1) {
|
||||
while (j < (SORTP **) scb->scb_next_pointer - 1)
|
||||
{
|
||||
SORTP** i = j;
|
||||
j++;
|
||||
if (**i >= **j) {
|
||||
@ -2831,7 +2813,8 @@ static void sort(sort_context* scb)
|
||||
j = reinterpret_cast<SORTP**>(scb->scb_first_pointer + 1);
|
||||
|
||||
// hvlad: don't compare user keys against high_key
|
||||
while (j < ((SORTP **) scb->scb_next_pointer) - 1) {
|
||||
while (j < ((SORTP **) scb->scb_next_pointer) - 1)
|
||||
{
|
||||
SORTP** i = j;
|
||||
j++;
|
||||
if (**i != **j)
|
||||
@ -2841,13 +2824,14 @@ static void sort(sort_context* scb)
|
||||
|
||||
ULONG l = scb->scb_unique_length;
|
||||
DO_32_COMPARE(p, q, l);
|
||||
if (l == 0) {
|
||||
if (l == 0)
|
||||
{
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
SORT_diddle_key((UCHAR *) * i, scb, false);
|
||||
SORT_diddle_key((UCHAR *) * j, scb, false);
|
||||
SORT_diddle_key((UCHAR*) *i, scb, false);
|
||||
SORT_diddle_key((UCHAR*) *j, scb, false);
|
||||
#else
|
||||
diddle_key((UCHAR *) * i, scb, false);
|
||||
diddle_key((UCHAR *) * j, scb, false);
|
||||
diddle_key((UCHAR*) *i, scb, false);
|
||||
diddle_key((UCHAR*) *j, scb, false);
|
||||
#endif
|
||||
if ((*scb->scb_dup_callback) ((const UCHAR*) *i, (const UCHAR*) *j, scb->scb_dup_callback_arg))
|
||||
{
|
||||
@ -2856,11 +2840,11 @@ static void sort(sort_context* scb)
|
||||
}
|
||||
else
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
SORT_diddle_key((UCHAR *) * i, scb, true);
|
||||
SORT_diddle_key((UCHAR *) * j, scb, true);
|
||||
SORT_diddle_key((UCHAR*) *i, scb, true);
|
||||
SORT_diddle_key((UCHAR*) *j, scb, true);
|
||||
#else
|
||||
diddle_key((UCHAR *) * i, scb, true);
|
||||
diddle_key((UCHAR *) * j, scb, true);
|
||||
diddle_key((UCHAR*) *i, scb, true);
|
||||
diddle_key((UCHAR*) *j, scb, true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ struct sort_context
|
||||
sort_record** scb_first_pointer; /* Memory for sort */
|
||||
sort_record** scb_next_pointer; /* Address for next pointer */
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
SORTP **scb_last_pointer; /* Address for last pointer in block */
|
||||
sort_record** scb_last_pointer; /* Address for last pointer in block */
|
||||
#endif
|
||||
//USHORT scb_length; // Record length. Unused.
|
||||
USHORT scb_longs; /* Length of record in longwords */
|
||||
|
@ -33,7 +33,7 @@ namespace Jrd {
|
||||
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
void SORT_diddle_key(UCHAR *, Jrd::sort_context*, bool);
|
||||
void SORT_get(Jrd::thread_db*, Jrd::sort_context*, ULONG **, RSE_GET_MODE);
|
||||
void SORT_get(Jrd::thread_db*, Jrd::sort_context*, ULONG **, Jrd::rse_get_mode);
|
||||
void SORT_read_block(ISC_STATUS*, TempSpace*, FB_UINT64, BLOB_PTR *, ULONG);
|
||||
#else
|
||||
void SORT_get(Jrd::thread_db*, Jrd::sort_context*, ULONG **);
|
||||
|
@ -171,6 +171,7 @@ USHORT SQZ_compress_length(DataComprControl* dcc, const SCHAR* input, int space)
|
||||
while (true) {
|
||||
const SCHAR* control = dcc->dcc_string;
|
||||
while (control < dcc->dcc_end)
|
||||
{
|
||||
if (--space <= 0)
|
||||
return input - start;
|
||||
else if ((length = *control++) & 128) {
|
||||
@ -185,6 +186,7 @@ USHORT SQZ_compress_length(DataComprControl* dcc, const SCHAR* input, int space)
|
||||
}
|
||||
input += length;
|
||||
}
|
||||
}
|
||||
if (!(dcc = dcc->dcc_next))
|
||||
BUGCHECK(178); /* msg 178 record length inconsistent */
|
||||
}
|
||||
|
1068
src/jrd/svc.cpp
1068
src/jrd/svc.cpp
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,7 @@
|
||||
#include "../include/fb_blk.h"
|
||||
#include "../common/classes/array.h"
|
||||
#include "../common/classes/SafeArg.h"
|
||||
#include "../common/UtilSvc.h"
|
||||
|
||||
void SVC_STATUS_ARG(ISC_STATUS*& status, const MsgFormat::safe_cell& value);
|
||||
void SVC_STATUS_ARG(ISC_STATUS*& status, const char* value);
|
||||
@ -74,20 +75,6 @@ const USHORT isc_action_max = 14;
|
||||
//define isc_info_max 67
|
||||
|
||||
|
||||
/* switches for username and password used when a username and/or password
|
||||
* is specified by the client application
|
||||
*/
|
||||
#define USERNAME_SWITCH "-USER"
|
||||
#define PASSWORD_SWITCH "-PASSWORD"
|
||||
#ifdef SERVICE_THREAD
|
||||
#define SERVICE_THD_PARAM "-svc_thd"
|
||||
#else
|
||||
#define SERVICE_THD_PARAM "-svc"
|
||||
#endif
|
||||
#ifdef TRUSTED_SERVICES
|
||||
#define TRUSTED_USER_SWITCH "-TRUSTED_SVC"
|
||||
#endif
|
||||
|
||||
/* Macro used to store services thread specific data */
|
||||
/* Currently we store empty string, see bug #10394 */
|
||||
// BRS 01/07/2004 commented
|
||||
@ -105,11 +92,11 @@ const USHORT isc_action_max = 14;
|
||||
struct serv_entry; // forward decl.
|
||||
|
||||
/* Service manager block */
|
||||
class Service : public pool_alloc<type_svc>
|
||||
class Service : public Firebird::UtilSvc, public LocalType<type_svc>
|
||||
{
|
||||
private:
|
||||
ISC_STATUS_ARRAY svc_status_array;
|
||||
Firebird::string svc_parsed_sw; // Here point elements of svc_argv
|
||||
Firebird::string svc_parsed_sw; // Here point elements of argv
|
||||
|
||||
public:
|
||||
Service(serv_entry *se, Firebird::MemoryPool& p);
|
||||
@ -122,8 +109,6 @@ public:
|
||||
ULONG svc_stdout_head;
|
||||
ULONG svc_stdout_tail;
|
||||
UCHAR* svc_stdout;
|
||||
Firebird::HalfStaticArray<const char*, 20> svc_argv;
|
||||
ULONG svc_argc;
|
||||
Firebird::Semaphore svcStart;
|
||||
serv_entry* svc_service;
|
||||
UCHAR* svc_resp_buf;
|
||||
@ -136,40 +121,42 @@ public:
|
||||
bool svc_do_shutdown;
|
||||
Firebird::string svc_username;
|
||||
Firebird::string svc_enc_password;
|
||||
#ifdef TRUSTED_SERVICES
|
||||
Firebird::string svc_trusted_login;
|
||||
#endif
|
||||
bool svc_trusted_role;
|
||||
Firebird::string svc_switches; // Full set of switches
|
||||
Firebird::string svc_perm_sw; // Switches, taken from services table
|
||||
// and/or passed using spb_command_line
|
||||
|
||||
void svc_started();
|
||||
void parseSwitches(); // Create svc_argv, svc_argc and svc_parsed_sw
|
||||
void parseSwitches(); // Create argv, argc and svc_parsed_sw
|
||||
|
||||
// utilities interface with service
|
||||
public:
|
||||
virtual void printf(const SCHAR* format, ...);
|
||||
virtual bool isService();
|
||||
virtual void started();
|
||||
virtual void finish();
|
||||
virtual void putLine(char, const char*);
|
||||
virtual void putSLong(char, SLONG);
|
||||
virtual void putChar(char, char);
|
||||
virtual void stuffStatus(const ISC_STATUS*);
|
||||
virtual void stuffStatus(const USHORT, const USHORT, const MsgFormat::SafeArg&);
|
||||
virtual void hidePasswd(ArgvType&, int);
|
||||
virtual ISC_STATUS* getStatus();
|
||||
virtual void checkService();
|
||||
};
|
||||
|
||||
/* Bitmask values for the svc_flags variable */
|
||||
|
||||
//const int SVC_eof = 1;
|
||||
const int SVC_timeout = 2;
|
||||
const int SVC_forked = 4;
|
||||
//const int SVC_forked = 4;
|
||||
const int SVC_detached = 8;
|
||||
const int SVC_finished = 16;
|
||||
const int SVC_thd_running = 32;
|
||||
const int SVC_evnt_fired = 64;
|
||||
const int SVC_cmd_line = 128;
|
||||
|
||||
// Method used to signify that the service started has done basic
|
||||
// initialization and can be considered a successful startup.
|
||||
|
||||
#ifndef SERVICE_THREAD
|
||||
|
||||
inline void Service::svc_started()
|
||||
{
|
||||
// null definition, no overhead.
|
||||
}
|
||||
|
||||
#endif /* SERVICE_THREAD */
|
||||
|
||||
typedef int (*pfn_svc_output)(Service*, const UCHAR*);
|
||||
|
||||
struct serv_entry
|
||||
@ -177,9 +164,7 @@ struct serv_entry
|
||||
USHORT serv_action;
|
||||
const TEXT* serv_name;
|
||||
const TEXT* serv_std_switches;
|
||||
const TEXT* serv_executable;
|
||||
ThreadEntryPoint* serv_thd;
|
||||
bool* serv_in_use;
|
||||
};
|
||||
|
||||
} //namespace Jrd
|
||||
|
@ -24,7 +24,7 @@
|
||||
#ifndef JRD_SVC_PROTO_H
|
||||
#define JRD_SVC_PROTO_H
|
||||
|
||||
#include "../jrd/thd.h"
|
||||
#include "../jrd/ThreadStart.h"
|
||||
|
||||
namespace Jrd {
|
||||
class Service;
|
||||
@ -34,7 +34,6 @@ namespace Jrd {
|
||||
extern "C" {
|
||||
Jrd::Service* SVC_attach(USHORT, const TEXT*, USHORT, const SCHAR*);
|
||||
void SVC_detach(Jrd::Service*);
|
||||
void SVC_fprintf(Jrd::Service*, const SCHAR*, ...);
|
||||
void SVC_putc(Jrd::Service*, const UCHAR);
|
||||
void SVC_query(Jrd::Service*, USHORT, const SCHAR*, USHORT, const SCHAR*,
|
||||
USHORT, SCHAR*);
|
||||
@ -43,7 +42,6 @@ ISC_STATUS SVC_query2(Jrd::Service*, Jrd::thread_db*, USHORT, const SCHAR*,
|
||||
void* SVC_start(Jrd::Service*, USHORT, const SCHAR*);
|
||||
void SVC_finish(Jrd::Service*, USHORT);
|
||||
THREAD_ENTRY_DECLARE SVC_read_fb_log(THREAD_ENTRY_PARAM);
|
||||
int SVC_output(Jrd::Service*, const UCHAR*);
|
||||
|
||||
#ifdef SERVER_SHUTDOWN
|
||||
typedef void (*shutdown_fct_t) (ULONG);
|
||||
|
170
src/jrd/sym.cpp
170
src/jrd/sym.cpp
@ -1,170 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD access method
|
||||
* MODULE: hsh.cpp
|
||||
* DESCRIPTION: Hash table and symbol manager
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include "../jrd/common.h"
|
||||
#include "../jrd/jrd.h"
|
||||
#include "../jrd/val.h"
|
||||
#include "../jrd/err_proto.h"
|
||||
#include "../jrd/sym.h"
|
||||
#include "../jrd/thd.h"
|
||||
|
||||
|
||||
using namespace Jrd;
|
||||
|
||||
namespace {
|
||||
SSHORT hash_func(const Firebird::MetaName&);
|
||||
}
|
||||
|
||||
void Symbol::insert()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* S Y M _ i n s e r t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Insert a symbol into the hash table.
|
||||
*
|
||||
**************************************/
|
||||
Database* dbb = GET_DBB();
|
||||
|
||||
const int h = hash_func(sym_string);
|
||||
|
||||
for (Symbol* old = dbb->dbb_hash_table[h]; old; old = old->sym_collision)
|
||||
{
|
||||
if (sym_string == old->sym_string)
|
||||
{
|
||||
sym_homonym = old->sym_homonym;
|
||||
old->sym_homonym = this;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sym_collision = dbb->dbb_hash_table[h];
|
||||
dbb->dbb_hash_table[h] = this;
|
||||
}
|
||||
|
||||
|
||||
Symbol* Symbol::lookup(const Firebird::MetaName& string)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* S Y M _ l o o k u p
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Perform a string lookup against hash table.
|
||||
*
|
||||
**************************************/
|
||||
Database* dbb = GET_DBB();
|
||||
|
||||
for (Symbol* symbol = dbb->dbb_hash_table[hash_func(string)]; symbol;
|
||||
symbol = symbol->sym_collision)
|
||||
{
|
||||
if (string == symbol->sym_string)
|
||||
return symbol;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void Symbol::remove()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* S Y M _ r e m o v e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Remove a symbol from the hash table.
|
||||
*
|
||||
**************************************/
|
||||
Database* dbb = GET_DBB();
|
||||
|
||||
const int h = hash_func(sym_string);
|
||||
|
||||
for (Symbol** next = &dbb->dbb_hash_table[h]; *next;
|
||||
next = &(*next)->sym_collision)
|
||||
{
|
||||
if (this == *next) {
|
||||
Symbol* homonym = sym_homonym;
|
||||
if (homonym) {
|
||||
homonym->sym_collision = sym_collision;
|
||||
*next = homonym;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
*next = sym_collision;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (Symbol** ptr = &(*next)->sym_homonym; *ptr;
|
||||
ptr = &(*ptr)->sym_homonym)
|
||||
{
|
||||
if (this == *ptr) {
|
||||
*ptr = sym_homonym;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BUGCHECK(164); /* msg 164 failed to remove symbol from hash table */
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
SSHORT hash_func(const Firebird::MetaName& str)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* h a s h
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Returns the hash function of a string.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
/* It is OK to not Internationalize this function as it is for
|
||||
internal optimization of symbol lookup */
|
||||
|
||||
int value = 0;
|
||||
|
||||
for (const char *s = str.c_str(); *s; s++)
|
||||
{
|
||||
value = (value << 1) + UPPER7(*s);
|
||||
}
|
||||
|
||||
return ((value >= 0) ? value : -value) % HASH_SIZE;
|
||||
}
|
||||
|
||||
} //noname namespace
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Access Method
|
||||
* MODULE: sym.h
|
||||
* DESCRIPTION: Header file for sym.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_SYM_H
|
||||
#define JRD_SYM_H
|
||||
|
||||
#include "../common/classes/MetaName.h"
|
||||
|
||||
namespace Jrd {
|
||||
/* symbol definitions */
|
||||
|
||||
class UserFunction;
|
||||
|
||||
// This "Symbol" became a mere container for UDFs. DSQL has another Symbol class.
|
||||
|
||||
class Symbol : public pool_alloc<type_sym>
|
||||
{
|
||||
private:
|
||||
Symbol* sym_collision; // collision pointer
|
||||
|
||||
public:
|
||||
//enum sym_t {
|
||||
//rel, // relation block
|
||||
//fld, // field block
|
||||
//fun // UDF function block
|
||||
//prc, // stored procedure block
|
||||
//sql, // SQL request cache block
|
||||
//blr, // BLR request cache block
|
||||
//label // CVC: I need to track labels if LEAVE is implemented.
|
||||
//};
|
||||
Firebird::MetaName sym_string; // symbol value
|
||||
//sym_t sym_type; // symbol type
|
||||
UserFunction* sym_object; // pointer to UDF object
|
||||
Symbol* sym_homonym; // homonym pointer
|
||||
|
||||
public:
|
||||
explicit Symbol(MemoryPool& p, const Firebird::MetaName& val, //sym_t type,
|
||||
UserFunction* object)
|
||||
: sym_collision(0), sym_string(p, val), //sym_type(type),
|
||||
sym_object(object), sym_homonym(0) { }
|
||||
void insert();
|
||||
static Symbol* lookup(const Firebird::MetaName&);
|
||||
void remove();
|
||||
};
|
||||
|
||||
} //namespace Jrd
|
||||
|
||||
|
||||
#endif // JRD_SYM_H
|
||||
|
Loading…
Reference in New Issue
Block a user