8
0
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:
dimitr 2008-01-16 09:48:41 +00:00
parent 6cb91c6433
commit 6666fd1e4a
23 changed files with 2279 additions and 1812 deletions

1317
src/jrd/SimilarToMatcher.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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)
{

View File

@ -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());
}
}

View File

@ -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*);

View File

@ -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;

View File

@ -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),

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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];
}

View File

@ -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;
}

View File

@ -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
}
}

View File

@ -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 */

View File

@ -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 **);

View File

@ -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 */
}

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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