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

The merge continued.

This commit is contained in:
dimitr 2008-01-16 09:29:37 +00:00
parent e053607b22
commit d1e8f67a5d
13 changed files with 769 additions and 1643 deletions

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,7 @@
#include "../jrd/btn.h"
#include "../jrd/all.h"
#include "../jrd/jrd_proto.h"
#include "../jrd/val.h"
#if defined(UNIX) && defined(SUPERSERVER)
#include <setjmp.h>
#endif
@ -88,9 +89,12 @@
// Thread data block / IPC related data blocks
#include "../jrd/thd.h"
#include "../jrd/ThreadData.h"
#include "../jrd/isc.h"
// recursive mutexes
#include "../jrd/thd.h"
// Definition of block types for data allocation in JRD
#include "../jrd/jrd_blks.h"
#include "../include/fb_blk.h"
@ -104,6 +108,9 @@
#include "../jrd/RuntimeStatistics.h"
// Error codes
#include "../include/gen/iberror.h"
class str;
class CharSetContainer;
struct dsc;
@ -316,7 +323,8 @@ public:
vcl* dbb_pc_transactions; // active precommitted transactions
BackupManager *dbb_backup_manager; // physical backup manager
Firebird::TimeStamp dbb_creation_date; // creation date
Symbol* dbb_hash_table[HASH_SIZE]; // keep this at the end
Firebird::GenericMap<Firebird::Pair<Firebird::Left<
Firebird::MetaName, UserFunction*> > > dbb_functions; // User defined functions
ULONG generateId()
{
@ -334,7 +342,8 @@ private:
dbb_database_name(p),
dbb_encrypt_key(p),
dbb_pools(p, 4),
dbb_charsets(p)
dbb_charsets(p),
dbb_functions(p)
{
dbb_pools.resize(1);
}
@ -357,10 +366,11 @@ private:
JrdMemoryPool::deletePool(dbb_bufferpool);
}
// temporal measure to avoid unstable state of lock file -
// this is anyway called in ~Database(), and in theory should be private
public:
// temporary measure to avoid unstable state of lock file -
// this is anyway called in ~Database(), and in theory should be private
void destroyIntlObjects(); // defined in intl.cpp
private:
// The delete operators are no-oped because the Database memory is allocated from the
@ -377,37 +387,28 @@ private:
//
// bit values for dbb_flags
//
//const ULONG DBB_no_garbage_collect = 0x1L; // Obsolete.
const ULONG DBB_damaged = 0x2L;
const ULONG DBB_exclusive = 0x4L; // Database is accessed in exclusive mode
const ULONG DBB_bugcheck = 0x8L; // Bugcheck has occurred
const ULONG DBB_damaged = 0x1L;
const ULONG DBB_exclusive = 0x2L; // Database is accessed in exclusive mode
const ULONG DBB_bugcheck = 0x4L; // Bugcheck has occurred
#ifdef GARBAGE_THREAD
const ULONG DBB_garbage_collector = 0x10L; // garbage collector thread exists
const ULONG DBB_gc_active = 0x20L; // ... and is actively working.
const ULONG DBB_gc_pending = 0x40L; // garbage collection requested
#endif
const ULONG DBB_force_write = 0x80L; // Database is forced write
const ULONG DBB_no_reserve = 0x100L; // No reserve space for versions
const ULONG DBB_no_fs_cache = 0x200L; // Not using file system cache
//const ULONG DBB_add_log = 0x200L; // write ahead log has been added
//const ULONG DBB_delete_log = 0x400L; // write ahead log has been deleted
//const ULONG DBB_cache_manager = 0x800L; // Shared cache manager
const ULONG DBB_DB_SQL_dialect_3 = 0x1000L; // database SQL dialect 3
const ULONG DBB_read_only = 0x2000L; // DB is ReadOnly (RO). If not set, DB is RW
const ULONG DBB_being_opened_read_only = 0x4000L; // DB is being opened RO. If unset, opened as RW
const ULONG DBB_not_in_use = 0x8000L; // Database to be ignored while attaching
const ULONG DBB_lck_init_done = 0x10000L; // LCK_init() called for the database
const ULONG DBB_sp_rec_mutex_init = 0x20000L; // Stored procedure mutex initialized
const ULONG DBB_sweep_in_progress = 0x40000L; // A database sweep operation is in progress
const ULONG DBB_security_db = 0x80000L; // ISC security database
//const ULONG DBB_sweep_thread_started = 0x100000L; // A database sweep thread has been started
const ULONG DBB_suspend_bgio = 0x200000L; // Suspend I/O by background threads
const ULONG DBB_being_opened = 0x400000L; // database is being attached to
const ULONG DBB_gc_cooperative = 0x0800000L; // cooperative garbage collection
const ULONG DBB_gc_background = 0x1000000L; // background garbage collection by gc_thread
#if (defined DEV_BUILD && !defined MULTI_THREAD)
const ULONG DBB_exec_statement = 0x2000000L; // execute statement runs against database
const ULONG DBB_garbage_collector = 0x8L; // garbage collector thread exists
const ULONG DBB_gc_active = 0x10L; // ... and is actively working.
const ULONG DBB_gc_pending = 0x20L; // garbage collection requested
#endif
const ULONG DBB_force_write = 0x40L; // Database is forced write
const ULONG DBB_no_reserve = 0x80L; // No reserve space for versions
const ULONG DBB_DB_SQL_dialect_3 = 0x100L; // database SQL dialect 3
const ULONG DBB_read_only = 0x200L; // DB is ReadOnly (RO). If not set, DB is RW
const ULONG DBB_being_opened_read_only = 0x400L; // DB is being opened RO. If unset, opened as RW
const ULONG DBB_not_in_use = 0x800L; // Database to be ignored while attaching
const ULONG DBB_lck_init_done = 0x1000L; // LCK_init() called for the database
const ULONG DBB_sweep_in_progress = 0x2000L; // A database sweep operation is in progress
const ULONG DBB_security_db = 0x4000L; // ISC security database
const ULONG DBB_suspend_bgio = 0x8000L; // Suspend I/O by background threads
const ULONG DBB_being_opened = 0x10000L; // database is being attached to
const ULONG DBB_gc_cooperative = 0x20000L; // cooperative garbage collection
const ULONG DBB_gc_background = 0x40000L; // background garbage collection by gc_thread
//
// dbb_ast_flags
//
@ -439,15 +440,11 @@ const int DBB_max_count = 8;
//
// Database mutexes
//
const int DBB_MUTX_init_fini = 0; // During startup and shutdown
//const int DBB_MUTX_statistics = 1; // Memory size and counts
//const int DBB_MUTX_replay = 2; // Replay logging
const int DBB_MUTX_dyn = 3; // Dynamic ddl
//const int DBB_MUTX_cache = 4; // Process-private cache management
const int DBB_MUTX_clone = 5; // Request cloning
const int DBB_MUTX_cmp_clone = 6; // Compiled request cloning
const int DBB_MUTX_flush_count = 7; // flush count/time
const int DBB_MUTX_max = 8;
const int DBB_MUTX_dyn = 0; // Dynamic ddl
const int DBB_MUTX_clone = 1; // Request cloning
const int DBB_MUTX_cmp_clone = 2; // Compiled request cloning
const int DBB_MUTX_flush_count = 3; // flush count/time
const int DBB_MUTX_max = 4;
//
// Flags to indicate normal internal requests vs. dyn internal requests
@ -602,9 +599,6 @@ const ULONG ATT_exclusive = 32; // attachment wants exclusive database access
const ULONG ATT_attach_pending = 64; // Indicate attachment is only pending
const ULONG ATT_exclusive_pending = 128; // Indicate exclusive attachment pending
const ULONG ATT_gbak_attachment = 256; // Indicate GBAK attachment
#ifdef GOVERNOR
const ULONG ATT_security_db = 512; // Indicates an implicit attachment to the security db
#endif
#ifdef GARBAGE_THREAD
const ULONG ATT_notify_gc = 1024; // Notify garbage collector to expunge, purge ..
@ -884,7 +878,7 @@ private:
RuntimeStatistics *reqStat, *traStat, *attStat, *dbbStat;
public:
thread_db()
explicit thread_db(ISC_STATUS* status)
: ThreadData(ThreadData::tddDBB)
{
tdbb_default = 0;
@ -892,17 +886,19 @@ public:
attachment = 0;
transaction = 0;
request = 0;
tdbb_status_vector = 0;
tdbb_quantum = 0;
tdbb_flags = 0;
tdbb_temp_attid = tdbb_temp_traid = 0;
JRD_inuse_clear(this);
reqStat = traStat = attStat = dbbStat = RuntimeStatistics::getDummy();
tdbb_status_vector = status;
tdbb_status_vector[0] = isc_arg_gds;
tdbb_status_vector[1] = FB_SUCCESS;
tdbb_status_vector[2] = isc_arg_end;
}
ISC_STATUS* tdbb_status_vector;
SSHORT tdbb_quantum; // Cycles remaining until voluntary schedule
USHORT tdbb_flags;
struct iuo tdbb_mutexes;
SLONG tdbb_temp_attid; // current temporary table scope
SLONG tdbb_temp_traid; // current temporary table scope
@ -993,6 +989,41 @@ const USHORT TDBB_deferred = 64; // deferred work performed now
const USHORT TDBB_sys_error = 128; // error shouldn't be handled by the looper
const USHORT TDBB_verb_cleanup = 256; // verb cleanup is in progress
class ThreadContextHolder
{
public:
explicit ThreadContextHolder(ISC_STATUS* status = NULL)
: context(status ? status : local_status)
{
context.putSpecific();
}
~ThreadContextHolder()
{
ThreadData::restoreSpecific();
}
thread_db* operator->()
{
return &context;
}
operator thread_db*()
{
return &context;
}
private:
// copying is prohibited
ThreadContextHolder(const ThreadContextHolder&);
ThreadContextHolder& operator= (const ThreadContextHolder&);
ISC_STATUS_ARRAY local_status;
thread_db context;
};
// duplicate context of firebird string to store in jrd_nod::nod_arg
inline char* stringDup(MemoryPool& p, const Firebird::string& s)
{
@ -1087,8 +1118,8 @@ inline void CHECK_DBB(const Jrd::Database* dbb) {
fb_assert(dbb && MemoryPool::blk_type(dbb) == type_dbb);
}
#else
// PROD_BUILD
#else // PROD_BUILD
inline Jrd::thread_db* JRD_get_thread_data() {
return (Jrd::thread_db*) ThreadData::getSpecific();
}
@ -1119,41 +1150,11 @@ inline void SET_DBB(Jrd::Database* &dbb) {
CHECK_DBB(dbb);
}
#ifdef MULTI_THREAD
#define THD_JRD_MUTEX_LOCK(mutx) JRD_mutex_lock(mutx)
#define THD_JRD_MUTEX_UNLOCK(mutx) JRD_mutex_unlock(mutx)
#else
#define THD_JRD_MUTEX_LOCK(mutx)
#define THD_JRD_MUTEX_UNLOCK(mutx)
#endif
// global variables for engine
#if !defined(REQUESTER)
extern int debug;
#endif // REQUESTER
/* Define the xxx_thread_data macros. These are needed in the whole
component, but they are defined differently for use in jrd.cpp (JRD_MAIN)
Here we have a function which sets some flags, and then calls THD_put_specific
so in this case we define the macro as calling that function. */
// CVC: This may be obsolete now that different subsystems use different macro/function names.
inline static void JRD_set_thread_data(Jrd::thread_db* &tdbb, Jrd::thread_db& thd_context)
{
tdbb = &thd_context;
tdbb->putSpecific();
}
inline void JRD_restore_thread_data() {
ThreadData::restoreSpecific();
}
namespace Jrd {
typedef Firebird::SubsystemContextPoolHolder <Jrd::thread_db, JrdMemoryPool>
ContextPoolHolder;

View File

@ -160,17 +160,9 @@ void JRD_process_close();
void JRD_database_close(Jrd::Attachment**, Jrd::Attachment**);
#endif /* SERVER_SHUTDOWN */
void JRD_set_cache_default(ULONG *);
void JRD_blocked(Jrd::Attachment*, Jrd::BlockingThread**);
void JRD_mutex_lock(Firebird::Mutex&);
void JRD_mutex_unlock(Firebird::Mutex&);
bool JRD_reschedule(Jrd::thread_db*, SLONG, bool);
void JRD_restore_context(void);
void JRD_set_context(Jrd::thread_db*);
void JRD_inuse_clear(Jrd::thread_db* tdbb);
void JRD_unblock(Jrd::BlockingThread**);
void JRD_thread_security_disable(bool disable);
bool JRD_get_thread_security_disabled();
// Call this function from the debugger if desired
void JRD_print_pools(const char* filename);

View File

@ -40,6 +40,8 @@ const size_t MAX_PASSWORD_LENGTH = 64; // used to store passwords internally
static const char* PASSWORD_SALT = "9z"; // for old ENC_crypt()
const size_t SALT_LENGTH = 12; // measured after base64 coding
namespace Jrd {
class SecurityDatabase
{
struct user_record {
@ -50,16 +52,9 @@ class SecurityDatabase
};
public:
static void getPath(TEXT* path_buffer)
{
static const char* USER_INFO_NAME =
#ifdef VMS
"[sysmgr]security2.fdb";
#else
"security2.fdb";
#endif
static const char* USER_INFO_NAME = "security2.fdb";
gds__prefix(path_buffer, USER_INFO_NAME);
}
@ -92,7 +87,6 @@ public:
}
private:
static const UCHAR PWD_REQUEST[256];
static const UCHAR TPB[4];
@ -120,4 +114,21 @@ private:
}
};
class DelayFailedLogin : public Firebird::Exception
{
private:
int seconds;
public:
DelayFailedLogin(int sec) throw() : Exception(), seconds(sec) { }
virtual ISC_STATUS stuff_exception(ISC_STATUS* const status_vector, Firebird::StringsBuffer* sb = NULL) const throw();
virtual const char* what() const throw() { return "Jrd::DelayFailedLogin"; }
static void raise(int sec);
void sleep() const;
};
} // namespace Jrd
#endif /* JRD_PWD_H */

View File

@ -38,11 +38,7 @@
#include "../jrd/jrd_proto.h"
#include "../jrd/lck_proto.h"
#ifndef VMS
#include "../lock/lock_proto.h"
#else
#include "../jrd/vmslo_proto.h"
#endif
#include "../jrd/sch_proto.h"
#include "../jrd/thd.h"
#include "../jrd/gdsassert.h"
@ -63,15 +59,11 @@
using namespace Jrd;
static void bug_lck(const TEXT*);
#ifdef MULTI_THREAD
static void check_lock(Lock*, USHORT);
#endif
static bool compatible(const Lock*, const Lock*, USHORT);
static void enqueue(thread_db*, Lock*, USHORT, SSHORT);
static int external_ast(void*);
#ifdef MULTI_THREAD
static Lock* find_block(Lock*, USHORT);
#endif
static USHORT hash_func(const UCHAR*, USHORT);
static void hash_allocate(Lock*);
static Lock* hash_get_lock(Lock*, USHORT*, Lock***);
@ -88,79 +80,60 @@ static void set_lock_attachment(Lock*, Attachment*);
/* globals and macros */
static SLONG process_lck_owner_handle = 0;
#ifdef SUPERSERVER
inline LOCK_OWNER_T LCK_OWNER_ID_PROCESS() {
return getpid();
inline LOCK_OWNER_T LCK_OWNER_ID_DBB(thread_db* tdbb) {
return (LOCK_OWNER_T) tdbb->tdbb_database;
}
inline LOCK_OWNER_T LCK_OWNER_ID_DBB(Database* dbb) {
return (LOCK_OWNER_T) dbb;
}
inline LOCK_OWNER_T LCK_OWNER_ID_ATT(Attachment* attachment) {
return (LOCK_OWNER_T) attachment;
inline LOCK_OWNER_T LCK_OWNER_ID_ATT(thread_db* tdbb) {
return (LOCK_OWNER_T) tdbb->tdbb_attachment;
}
const lck_owner_t LCK_OWNER_TYPE_PROCESS = LCK_OWNER_process;
const lck_owner_t LCK_OWNER_TYPE_DBB = LCK_OWNER_database;
const lck_owner_t LCK_OWNER_TYPE_ATT = LCK_OWNER_attachment;
inline SLONG* LCK_OWNER_HANDLE_PROCESS() {
return &process_lck_owner_handle;
inline SLONG* LCK_OWNER_HANDLE_DBB(thread_db* tdbb) {
return &tdbb->tdbb_database->dbb_lock_owner_handle;
}
inline SLONG* LCK_OWNER_HANDLE_DBB(Database* dbb) {
return &dbb->dbb_lock_owner_handle;
}
inline SLONG* LCK_OWNER_HANDLE_ATT(Attachment* attachment) {
return &attachment->att_lock_owner_handle;
inline SLONG* LCK_OWNER_HANDLE_ATT(thread_db* tdbb) {
return &tdbb->tdbb_attachment->att_lock_owner_handle;
}
#else /* SUPERSERVER */
/* This is not a SUPERSERVER build */
inline LOCK_OWNER_T LCK_OWNER_ID_PROCESS() {
static SLONG process_lck_owner_handle = 0;
inline LOCK_OWNER_T LCK_OWNER_ID_DBB(thread_db* tdbb) {
return getpid();
}
inline LOCK_OWNER_T LCK_OWNER_ID_DBB(Database* dbb) {
return getpid();
}
inline LOCK_OWNER_T LCK_OWNER_ID_ATT(Attachment* attachment) {
inline LOCK_OWNER_T LCK_OWNER_ID_ATT(thread_db* tdbb) {
return getpid();
}
const lck_owner_t LCK_OWNER_TYPE_PROCESS = LCK_OWNER_process;
const lck_owner_t LCK_OWNER_TYPE_DBB = LCK_OWNER_process;
const lck_owner_t LCK_OWNER_TYPE_ATT = LCK_OWNER_process;
inline SLONG* LCK_OWNER_HANDLE_PROCESS() {
inline SLONG* LCK_OWNER_HANDLE_DBB(thread_db* tdbb) {
return &process_lck_owner_handle;
}
inline SLONG* LCK_OWNER_HANDLE_DBB(Database* dbb) {
return &process_lck_owner_handle;
}
inline SLONG* LCK_OWNER_HANDLE_ATT(Attachment* attachment) {
inline SLONG* LCK_OWNER_HANDLE_ATT(thread_db* tdbb) {
return &process_lck_owner_handle;
}
#endif /* SUPERSERVER */
static const UCHAR compatibility[] = {
static const bool compatibility[LCK_max][LCK_max] =
{
/* Shared Prot Shared Prot
none null Read Read Write Write Exclusive */
/* none */ 1, 1, 1, 1, 1, 1, 1,
/* null */ 1, 1, 1, 1, 1, 1, 1,
/* SR */ 1, 1, 1, 1, 1, 1, 0,
/* PR */ 1, 1, 1, 1, 0, 0, 0,
/* SW */ 1, 1, 1, 0, 1, 0, 0,
/* PW */ 1, 1, 1, 0, 0, 0, 0,
/* EX */ 1, 1, 0, 0, 0, 0, 0
/* none */ {true, true, true, true, true, true, true},
/* null */ {true, true, true, true, true, true, true},
/* SR */ {true, true, true, true, true, true, false},
/* PR */ {true, true, true, true, false, false, false},
/* SW */ {true, true, true, false, true, false, false},
/* PW */ {true, true, true, false, false, false, false},
/* EX */ {true, true, false, false, false, false, false}
};
#define COMPATIBLE(st1, st2) compatibility [st1 * LCK_max + st2]
//#define COMPATIBLE(st1, st2) compatibility [st1 * LCK_max + st2]
const int LOCK_HASH_SIZE = 19;
inline void ENQUEUE(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
@ -290,13 +263,16 @@ bool LCK_convert(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
if (!result) {
set_lock_attachment(lock, old_attachment);
if (status[1] == isc_deadlock ||
status[1] == isc_lock_conflict || status[1] == isc_lock_timeout)
switch (status[1])
{
case isc_deadlock:
case isc_lock_conflict:
case isc_lock_timeout:
return false;
}
if (status[1] == isc_lockmanerr)
case isc_lockmanerr:
dbb->dbb_flags |= DBB_bugcheck;
break;
}
ERR_punt();
}
@ -308,12 +284,11 @@ bool LCK_convert(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
}
#ifdef MULTI_THREAD
int LCK_convert_non_blocking(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
{
/**************************************
*
* L C K _ c o n v e r t _ n o n _ b l o c k i n g ( m u l t i _ t h r e a d )
* L C K _ c o n v e r t _ n o n _ b l o c k i n g
*
**************************************
*
@ -326,7 +301,7 @@ int LCK_convert_non_blocking(thread_db* tdbb, Lock* lock, USHORT level, SSHORT w
Database* dbb = lock->lck_dbb;
if (!wait || !gds__thread_enable(FALSE))
if (!wait)
return LCK_convert(tdbb, lock, level, wait);
Attachment* old_attachment = lock->lck_attachment;
@ -360,13 +335,16 @@ int LCK_convert_non_blocking(thread_db* tdbb, Lock* lock, USHORT level, SSHORT w
if (!result) {
set_lock_attachment(lock, old_attachment);
if (status[1] == isc_deadlock ||
status[1] == isc_lock_conflict || status[1] == isc_lock_timeout)
switch (status[1])
{
case isc_deadlock:
case isc_lock_conflict:
case isc_lock_timeout:
return FALSE;
}
if (status[1] == isc_lockmanerr)
case isc_lockmanerr:
dbb->dbb_flags |= DBB_bugcheck;
break;
}
ERR_punt();
}
@ -378,29 +356,6 @@ int LCK_convert_non_blocking(thread_db* tdbb, Lock* lock, USHORT level, SSHORT w
}
#else
int LCK_convert_non_blocking(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
{
/**************************************
*
* L C K _ c o n v e r t _ n o n _ b l o c k i n g ( s i n g l e _
* t h r e a d )
*
**************************************
*
* Functional description
* Convert and existing lock. If successful, return 0, otherwise
* return error code.
*
**************************************/
fb_assert(LCK_CHECK_LOCK(lock));
SET_TDBB(tdbb);
return LCK_convert(tdbb, lock, level, wait);
}
#endif
int LCK_convert_opt(thread_db* tdbb, Lock* lock, USHORT level)
{
/**************************************
@ -429,7 +384,6 @@ int LCK_convert_opt(thread_db* tdbb, Lock* lock, USHORT level)
}
#ifndef VMS
int LCK_downgrade(thread_db* tdbb, Lock* lock)
{
/**************************************
@ -463,7 +417,6 @@ int LCK_downgrade(thread_db* tdbb, Lock* lock)
fb_assert(LCK_CHECK_LOCK(lock));
return TRUE;
}
#endif
void LCK_fini(thread_db* tdbb, enum lck_owner_t owner_type)
@ -481,20 +434,14 @@ void LCK_fini(thread_db* tdbb, enum lck_owner_t owner_type)
SLONG* owner_handle_ptr = 0;
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Attachment* attachment = tdbb->getAttachment();
switch (owner_type) {
case LCK_OWNER_process:
owner_handle_ptr = LCK_OWNER_HANDLE_PROCESS();
break;
case LCK_OWNER_database:
owner_handle_ptr = LCK_OWNER_HANDLE_DBB(dbb);
owner_handle_ptr = LCK_OWNER_HANDLE_DBB(tdbb);
break;
case LCK_OWNER_attachment:
owner_handle_ptr = LCK_OWNER_HANDLE_ATT(attachment);
owner_handle_ptr = LCK_OWNER_HANDLE_ATT(tdbb);
break;
default:
@ -520,13 +467,7 @@ SLONG LCK_get_owner_handle(thread_db* tdbb, enum lck_t lock_type)
**************************************/
SET_TDBB(tdbb);
#ifdef SUPERSERVER
Database* dbb = tdbb->getDatabase();
Attachment* attachment = tdbb->getAttachment();
#else
Database* dbb = NULL;
Attachment* attachment = NULL;
#endif
switch (lock_type) {
case LCK_database:
case LCK_instance:
@ -539,12 +480,11 @@ SLONG LCK_get_owner_handle(thread_db* tdbb, enum lck_t lock_type)
case LCK_expression:
case LCK_record_locking:
case LCK_prc_exist:
//case LCK_range_relation: // PC_ENGINE
case LCK_backup_alloc:
case LCK_backup_database:
case LCK_monitor:
case LCK_tt_exist:
return *LCK_OWNER_HANDLE_DBB(dbb);
return *LCK_OWNER_HANDLE_DBB(tdbb);
case LCK_attachment:
case LCK_page_space:
case LCK_relation:
@ -556,7 +496,7 @@ SLONG LCK_get_owner_handle(thread_db* tdbb, enum lck_t lock_type)
case LCK_dsql_cache:
case LCK_backup_end:
case LCK_cancel:
return *LCK_OWNER_HANDLE_ATT(attachment);
return *LCK_OWNER_HANDLE_ATT(tdbb);
default:
bug_lck("Invalid lock type in LCK_get_owner_handle ()");
/* Not Reached - bug_lck calls ERR_post */
@ -581,12 +521,10 @@ SLONG LCK_get_owner_handle_by_type(thread_db* tdbb, lck_owner_t lck_owner_type)
switch(lck_owner_type)
{
case LCK_OWNER_process:
return *LCK_OWNER_HANDLE_PROCESS();
case LCK_OWNER_database:
return *LCK_OWNER_HANDLE_DBB(tdbb->getDatabase());;
return *LCK_OWNER_HANDLE_DBB(tdbb);
case LCK_OWNER_attachment:
return *LCK_OWNER_HANDLE_ATT(tdbb->getAttachment());
return *LCK_OWNER_HANDLE_ATT(tdbb);
default:
bug_lck("Invalid lock owner type in LCK_get_owner_handle_by_type ()");
return 0;
@ -634,23 +572,16 @@ void LCK_init(thread_db* tdbb, enum lck_owner_t owner_type)
SLONG* owner_handle_ptr = 0;
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Attachment* attachment = tdbb->getAttachment();
switch (owner_type) {
case LCK_OWNER_process:
owner_id = LCK_OWNER_ID_PROCESS();
owner_handle_ptr = LCK_OWNER_HANDLE_PROCESS();
break;
case LCK_OWNER_database:
owner_id = LCK_OWNER_ID_DBB(dbb);
owner_handle_ptr = LCK_OWNER_HANDLE_DBB(dbb);
owner_id = LCK_OWNER_ID_DBB(tdbb);
owner_handle_ptr = LCK_OWNER_HANDLE_DBB(tdbb);
break;
case LCK_OWNER_attachment:
owner_id = LCK_OWNER_ID_ATT(attachment);
owner_handle_ptr = LCK_OWNER_HANDLE_ATT(attachment);
owner_id = LCK_OWNER_ID_ATT(tdbb);
owner_handle_ptr = LCK_OWNER_HANDLE_ATT(tdbb);
break;
default:
@ -658,11 +589,11 @@ void LCK_init(thread_db* tdbb, enum lck_owner_t owner_type)
break;
}
if (LOCK_init(tdbb->tdbb_status_vector, true,
if (LOCK_init(tdbb->tdbb_status_vector,
owner_id, owner_type, owner_handle_ptr))
{
if (tdbb->tdbb_status_vector[1] == isc_lockmanerr)
dbb->dbb_flags |= DBB_bugcheck;
tdbb->tdbb_database->dbb_flags |= DBB_bugcheck;
ERR_punt();
}
}
@ -693,17 +624,20 @@ int LCK_lock(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
if (!lock->lck_id)
{
set_lock_attachment(lock, NULL);
if (!wait ||
status[1] == isc_deadlock ||
status[1] == isc_lock_conflict || status[1] == isc_lock_timeout)
{
if (!wait)
return FALSE;
}
else {
if (status[1] == isc_lockmanerr)
switch (status[1])
{
case isc_deadlock:
case isc_lock_conflict:
case isc_lock_timeout:
return FALSE;
case isc_lockmanerr:
dbb->dbb_flags |= DBB_bugcheck;
ERR_punt();
break;
}
ERR_punt();
}
if (!lock->lck_compatible)
@ -727,15 +661,14 @@ int LCK_lock_non_blocking(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait
* threads to be scheduled.
*
**************************************/
#ifdef MULTI_THREAD
fb_assert(LCK_CHECK_LOCK(lock));
SET_TDBB(tdbb);
Database* dbb = lock->lck_dbb;
/* Don't bother for the non-wait or non-multi-threading case */
/* Don't bother for the non-wait case */
if (!wait || !gds__thread_enable(FALSE))
if (!wait)
return LCK_lock(tdbb, lock, level, wait);
set_lock_attachment(lock, tdbb->getAttachment());
@ -782,17 +715,17 @@ int LCK_lock_non_blocking(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait
if (!lock->lck_id) {
set_lock_attachment(lock, NULL);
if (status[1] == isc_deadlock ||
status[1] == isc_lock_conflict ||
status[1] == isc_lock_timeout)
switch (status[1])
{
case isc_deadlock:
case isc_lock_conflict:
case isc_lock_timeout:
return FALSE;
}
else {
if (status[1] == isc_lockmanerr)
case isc_lockmanerr:
dbb->dbb_flags |= DBB_bugcheck;
ERR_punt();
break;
}
ERR_punt();
}
}
@ -801,14 +734,6 @@ int LCK_lock_non_blocking(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait
fb_assert(LCK_CHECK_LOCK(lock));
return TRUE;
#else
SET_TDBB(tdbb);
fb_assert(LCK_CHECK_LOCK(lock));
return LCK_lock(tdbb, lock, level, wait);
#endif
}
@ -840,7 +765,6 @@ int LCK_lock_opt(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
}
#ifndef VMS
SLONG LCK_query_data(Lock* parent, enum lck_t lock_type, USHORT aggregate)
{
/**************************************
@ -859,7 +783,6 @@ SLONG LCK_query_data(Lock* parent, enum lck_t lock_type, USHORT aggregate)
fb_assert(LCK_CHECK_LOCK(parent));
return LOCK_query_data(parent->lck_id, lock_type, aggregate);
}
#endif
SLONG LCK_read_data(Lock* lock)
@ -919,10 +842,8 @@ void LCK_release(thread_db* tdbb, Lock* lock)
lock->lck_id = lock->lck_data = 0;
set_lock_attachment(lock, NULL);
#ifdef MULTI_THREAD
if (lock->lck_blocked_threads)
JRD_unblock(&lock->lck_blocked_threads);
#endif
fb_assert(LCK_CHECK_LOCK(lock));
}
@ -996,7 +917,6 @@ static void bug_lck(const TEXT* string)
}
#ifdef MULTI_THREAD
static void check_lock(Lock* lock, USHORT level)
{
/**************************************
@ -1017,7 +937,6 @@ static void check_lock(Lock* lock, USHORT level)
while (next = find_block(lock, level))
JRD_blocked(next->lck_attachment, &next->lck_blocked_threads);
}
#endif
static bool compatible(const Lock* lock1, const Lock* lock2, USHORT level2)
@ -1057,10 +976,7 @@ static bool compatible(const Lock* lock1, const Lock* lock2, USHORT level2)
}
}
if (COMPATIBLE(lock1->lck_logical, level2))
return true;
return false;
return compatibility[lock1->lck_logical][level2];
}
@ -1128,7 +1044,6 @@ static int external_ast(void* lock_void)
#ifdef MULTI_THREAD
static Lock* find_block(Lock* lock, USHORT level)
{
/**************************************
@ -1165,7 +1080,6 @@ static Lock* find_block(Lock* lock, USHORT level)
return NULL;
}
#endif
static USHORT hash_func(const UCHAR* value, USHORT length)
@ -1358,20 +1272,23 @@ static bool hash_remove_lock(Lock* lock, Lock** match)
/* special case if our lock is the first one in the identical list */
if (next == lock)
{
if (lock->lck_identical) {
lock->lck_identical->lck_collision = lock->lck_collision;
*prior = lock->lck_identical;
return false;
}
else {
*prior = lock->lck_collision;
return true;
}
Lock* last = 0;
for (; next; last = next, next = next->lck_identical)
{
if (next == lock)
break;
}
if (!next) {
lock->lck_compatible = NULL;
@ -1449,8 +1366,10 @@ static bool internal_compatible(Lock* match, const Lock* lock, USHORT level)
lock */
for (next = match; next; next = next->lck_identical)
{
if (!next->lck_ast && !compatible(next, lock, level))
return false;
}
/* now deliver the blocking asts, attempting to gain
compatibility by getting everybody to downgrade */
@ -1459,8 +1378,10 @@ static bool internal_compatible(Lock* match, const Lock* lock, USHORT level)
/* make one more pass to see if all locks were downgraded */
for (next = match; next; next = next->lck_identical)
{
if (!compatible(next, match, level))
return false;
}
return true;
}

View File

@ -50,7 +50,6 @@ enum lck_t {
LCK_record_locking, /* Lock on existence of record locking for this database */
LCK_record, /* Record Lock */
LCK_prc_exist, /* Procedure existence lock */
LCK_range_relation_obsolete, // Relation refresh range lock, PC_ENGINE
LCK_update_shadow, /* shadow update sync lock */
LCK_backup_alloc, /* Lock for page allocation table in backup spare file */
LCK_backup_database, /* Lock to protect writing to database file */
@ -64,8 +63,12 @@ enum lck_t {
LCK_cancel /* Cancellation lock */
};
// This is defined in dbt.cpp and nobody calls it.
void MP_GDB_print(MemoryPool*);
/* Lock owner types */
enum lck_owner_t {
LCK_OWNER_database = 1, // A database is the owner of the lock
LCK_OWNER_attachment // An attachment is the owner of the lock
};
class Lock : public pool_alloc_rpt<UCHAR, type_lck>
{
@ -74,13 +77,11 @@ public:
: lck_test_field(666),
lck_parent(0),
lck_next(0),
lck_att_next(0),
lck_prior(0),
lck_collision(0),
lck_identical(0),
lck_dbb(0),
lck_object(0),
lck_owner(0),
lck_compatible(0),
lck_compatible2(0),
lck_attachment(0),
@ -88,7 +89,6 @@ public:
lck_ast(0),
lck_id(0),
lck_owner_handle(0),
lck_count(0),
lck_length(0),
lck_logical(0),
lck_physical(0),
@ -101,14 +101,12 @@ public:
int lck_test_field;
Lock* lck_parent;
Lock* lck_next; /* lck_next and lck_prior form a doubly linked list of locks
bound to attachment. Used in MULTI_THREAD builds only */
Lock* lck_att_next; /* Next in chain owned by attachment (RLCK, currently unused) */
bound to attachment */
Lock* lck_prior;
Lock* lck_collision; /* collisions in compatibility table */
Lock* lck_identical; /* identical locks in compatibility table */
Database* lck_dbb; /* database object is contained in */
blk* lck_object; /* argument to be passed to ast */
blk* lck_owner; /* Logical owner block (transaction, etc.) */
blk* lck_compatible; /* Enter into internal_enqueue() and treat as compatible */
blk* lck_compatible2; /* Sub-level for internal compatibility */
Attachment* lck_attachment; /* Attachment that owns lock, set only using set_lock_attachment */
@ -116,7 +114,6 @@ public:
lock_ast_t lck_ast; /* Blocking AST routine */
SLONG lck_id; /* Lock id from lock manager */
SLONG lck_owner_handle; /* Lock owner handle from the lock manager's point of view */
USHORT lck_count; /* count of locks taken out by attachment */
SSHORT lck_length; /* Length of lock string */
UCHAR lck_logical; /* Logical lock level */
UCHAR lck_physical; /* Physical lock level */

View File

@ -92,14 +92,6 @@
#endif
#endif /* sun */
#ifdef VMS
#ifdef __ALPHA
#define FB_PLATFORM "AV"
#else
#define FB_PLATFORM "VM"
#endif
#endif
#ifdef AIX
#define FB_PLATFORM "IA"
#endif
@ -120,10 +112,6 @@
#define FB_PLATFORM "LI" /* Linux on Intel */
#endif
#ifdef SINIXZ
#define FB_PLATFORM "SZ" /* SINIX for PC */
#endif
#ifdef FREEBSD
#define FB_PLATFORM "FB" /* FreeBSD/i386 */
#endif

View File

@ -105,9 +105,7 @@ static const SCHAR arg_types1[log_max][10] = {
/* this is the replay log filename definition */
#ifdef VMS
static const char* LOG_FILE_NAME = "[SYSMGR]replay.log";
#elif defined (WIN_NT)
#ifdef WIN_NT
static const char* LOG_FILE_NAME = "replay.log";
#else
static const char* LOG_FILE_NAME = FB_PREFIX "/replay.log";

View File

@ -50,7 +50,6 @@
#include "../jrd/ibase.h"
#include "../jrd/jrd.h"
#include "../jrd/sym.h"
#include "../jrd/val.h"
#include "../jrd/irq.h"
#include "../jrd/tra.h"
@ -124,6 +123,7 @@ static void get_trigger(thread_db*, jrd_rel*, bid*, bid*, trig_vec**, const TEXT
static bool get_type(thread_db*, USHORT*, const UCHAR*, const TEXT*);
static void lookup_view_contexts(thread_db*, jrd_rel*);
static void make_relation_scope_name(const TEXT*, const USHORT, Firebird::string& str);
static jrd_nod* parse_field_blr(thread_db* tdbb, bid* blob_id, const Firebird::MetaName name = Firebird::MetaName());
static jrd_nod* parse_param_blr(thread_db*, jrd_prc*, bid*, CompilerScratch*);
static jrd_nod* parse_procedure_blr(thread_db*, jrd_prc*, bid*, CompilerScratch*);
static bool par_messages(thread_db*, const UCHAR*, USHORT, jrd_prc*, CompilerScratch*);
@ -232,40 +232,12 @@ void MET_get_domain(thread_db* tdbb, const Firebird::MetaName& name, dsc* desc,
if (FLD.RDB$DEFAULT_VALUE.NULL)
fieldInfo->defaultValue = NULL;
else
{
CompilerScratch* csb = CompilerScratch::newCsb(*tdbb->getDefaultPool(), 5);
blb* blob = BLB_open(tdbb, dbb->dbb_sys_trans, &FLD.RDB$DEFAULT_VALUE);
SLONG length = blob->blb_length + 10;
Firebird::HalfStaticArray<UCHAR, 512> temp;
BLB_get_data(tdbb, blob, temp.getBuffer(length), length);
csb->csb_blr = temp.begin();
fieldInfo->defaultValue = PAR_blr(tdbb, NULL, temp.begin(), NULL, &csb, NULL, false, 0);
csb->csb_blr = 0;
delete csb;
}
fieldInfo->defaultValue = parse_field_blr(tdbb, &FLD.RDB$DEFAULT_VALUE);
if (FLD.RDB$VALIDATION_BLR.NULL)
fieldInfo->validation = NULL;
else
{
CompilerScratch* csb = CompilerScratch::newCsb(*tdbb->getDefaultPool(), 5, name);
blb* blob = BLB_open(tdbb, dbb->dbb_sys_trans, &FLD.RDB$VALIDATION_BLR);
SLONG length = blob->blb_length + 10;
Firebird::HalfStaticArray<UCHAR, 512> temp;
BLB_get_data(tdbb, blob, temp.getBuffer(length), length);
csb->csb_blr = temp.begin();
fieldInfo->validation = PAR_blr(tdbb, NULL, temp.begin(), NULL, &csb, NULL, false, 0);
csb->csb_blr = 0;
delete csb;
}
fieldInfo->validation = parse_field_blr(tdbb, &FLD.RDB$VALIDATION_BLR, name);
}
catch (const Firebird::Exception&)
{
@ -289,6 +261,100 @@ void MET_get_domain(thread_db* tdbb, const Firebird::MetaName& name, dsc* desc,
}
Firebird::MetaName MET_get_relation_field(thread_db* tdbb, const Firebird::MetaName& relationName,
const Firebird::MetaName& fieldName, dsc* desc, FieldInfo* fieldInfo)
{
/**************************************
*
* M E T _ g e t _ r e l a t i o n _ f i e l d
*
**************************************
*
* Functional description
* Get relation field descriptor and informations.
* Returns field source name.
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->tdbb_database;
bool found = false;
Firebird::MetaName sourceName;
jrd_req* handle = CMP_find_request(tdbb, irq_l_relfield, IRQ_REQUESTS);
FOR(REQUEST_HANDLE handle)
RFL IN RDB$RELATION_FIELDS CROSS
FLD IN RDB$FIELDS WITH
RFL.RDB$RELATION_NAME EQ relationName.c_str() AND
RFL.RDB$FIELD_NAME EQ fieldName.c_str() AND
FLD.RDB$FIELD_NAME EQ RFL.RDB$FIELD_SOURCE
if (!REQUEST(irq_l_relfield))
REQUEST(irq_l_relfield) = handle;
if (DSC_make_descriptor(desc,
FLD.RDB$FIELD_TYPE,
FLD.RDB$FIELD_SCALE,
FLD.RDB$FIELD_LENGTH,
FLD.RDB$FIELD_SUB_TYPE,
FLD.RDB$CHARACTER_SET_ID,
FLD.RDB$COLLATION_ID))
{
found = true;
sourceName = RFL.RDB$FIELD_SOURCE;
if (fieldInfo)
{
fieldInfo->nullable = RFL.RDB$NULL_FLAG.NULL ?
(FLD.RDB$NULL_FLAG.NULL || FLD.RDB$NULL_FLAG == 0) :
RFL.RDB$NULL_FLAG == 0;
JrdMemoryPool* csb_pool = JrdMemoryPool::createPool();
Jrd::ContextPoolHolder context(tdbb, csb_pool);
try
{
bid* defaultId = NULL;
if (!RFL.RDB$DEFAULT_VALUE.NULL)
defaultId = &RFL.RDB$DEFAULT_VALUE;
else if (!FLD.RDB$DEFAULT_VALUE.NULL)
defaultId = &FLD.RDB$DEFAULT_VALUE;
if (defaultId)
fieldInfo->defaultValue = parse_field_blr(tdbb, defaultId);
else
fieldInfo->defaultValue = NULL;
if (!FLD.RDB$VALIDATION_BLR.NULL)
fieldInfo->validation = parse_field_blr(tdbb, &FLD.RDB$VALIDATION_BLR, RFL.RDB$FIELD_SOURCE);
else
fieldInfo->validation = NULL;
}
catch (const Firebird::Exception&)
{
JrdMemoryPool::deletePool(csb_pool);
throw;
}
}
}
END_FOR;
if (!REQUEST(irq_l_relfield))
REQUEST(irq_l_relfield) = handle;
if (!found)
{
ERR_post(isc_dyn_column_does_not_exist,
isc_arg_string, ERR_cstring(fieldName.c_str()),
isc_arg_string, ERR_cstring(relationName.c_str()),
0);
}
return sourceName;
}
void MET_update_partners(thread_db* tdbb)
{
/**************************************
@ -833,6 +899,8 @@ DeferredWork* MET_change_fields(thread_db* tdbb, jrd_tra* transaction, const dsc
DeferredWork* dw2 =
DFW_post_work(transaction, dfw_modify_trigger, &desc, 0);
DFW_post_work_arg(transaction, dw2, NULL,
TRG.RDB$TRIGGER_TYPE)->dfw_type = dfw_arg_trg_type;
desc.dsc_length = trigger_relation_name.length();
desc.dsc_address = (UCHAR*) trigger_relation_name.c_str();
@ -841,6 +909,76 @@ DeferredWork* MET_change_fields(thread_db* tdbb, jrd_tra* transaction, const dsc
if (!REQUEST(irq_m_fields3))
REQUEST(irq_m_fields3) = request;
request = CMP_find_request(tdbb, irq_m_fields4, IRQ_REQUESTS);
FOR(REQUEST_HANDLE request)
RFL IN RDB$RELATION_FIELDS CROSS
DEP IN RDB$DEPENDENCIES CROSS
PRC IN RDB$PROCEDURES
WITH RFL.RDB$FIELD_SOURCE EQ field_source->dsc_address AND
DEP.RDB$DEPENDED_ON_NAME EQ RFL.RDB$RELATION_NAME AND
DEP.RDB$FIELD_NAME EQ RFL.RDB$FIELD_NAME AND
DEP.RDB$DEPENDED_ON_TYPE EQ obj_relation AND
DEP.RDB$DEPENDENT_TYPE EQ obj_procedure AND
DEP.RDB$DEPENDENT_NAME EQ PRC.RDB$PROCEDURE_NAME
if (!REQUEST(irq_m_fields4))
REQUEST(irq_m_fields4) = request;
Firebird::MetaName proc_name(PRC.RDB$PROCEDURE_NAME);
dsc desc;
desc.dsc_dtype = dtype_text;
INTL_ASSIGN_DSC(&desc, CS_METADATA, COLLATE_NONE);
desc.dsc_length = proc_name.length();
desc.dsc_address = (UCHAR*) proc_name.c_str();
DeferredWork* dw2 =
DFW_post_work(transaction, dfw_modify_procedure, &desc, PRC.RDB$PROCEDURE_ID);
DFW_post_work_arg(transaction, dw2, NULL, 0)->dfw_type = dfw_arg_check_blr;
END_FOR;
if (!REQUEST(irq_m_fields4))
REQUEST(irq_m_fields4) = request;
request = CMP_find_request(tdbb, irq_m_fields5, IRQ_REQUESTS);
FOR(REQUEST_HANDLE request)
RFL IN RDB$RELATION_FIELDS CROSS
DEP IN RDB$DEPENDENCIES CROSS
TRG IN RDB$TRIGGERS
WITH RFL.RDB$FIELD_SOURCE EQ field_source->dsc_address AND
DEP.RDB$DEPENDED_ON_NAME EQ RFL.RDB$RELATION_NAME AND
DEP.RDB$FIELD_NAME EQ RFL.RDB$FIELD_NAME AND
DEP.RDB$DEPENDED_ON_TYPE EQ obj_relation AND
DEP.RDB$DEPENDENT_TYPE EQ obj_trigger AND
DEP.RDB$DEPENDENT_NAME EQ TRG.RDB$TRIGGER_NAME
if (!REQUEST(irq_m_fields5))
REQUEST(irq_m_fields5) = request;
Firebird::MetaName trigger_name(TRG.RDB$TRIGGER_NAME);
Firebird::MetaName trigger_relation_name(TRG.RDB$RELATION_NAME);
dsc desc;
desc.dsc_dtype = dtype_text;
INTL_ASSIGN_DSC(&desc, CS_METADATA, COLLATE_NONE);
desc.dsc_length = trigger_name.length();
desc.dsc_address = (UCHAR*) trigger_name.c_str();
DeferredWork* dw2 =
DFW_post_work(transaction, dfw_modify_trigger, &desc, 0);
DFW_post_work_arg(transaction, dw2, NULL,
TRG.RDB$TRIGGER_TYPE)->dfw_type = dfw_arg_trg_type;
desc.dsc_length = trigger_relation_name.length();
desc.dsc_address = (UCHAR*) trigger_relation_name.c_str();
DFW_post_work_arg(transaction, dw2, &desc, 0)->dfw_type = dfw_arg_check_blr;
END_FOR;
if (!REQUEST(irq_m_fields5))
REQUEST(irq_m_fields5) = request;
}
return dw;
@ -1120,7 +1258,7 @@ bool MET_get_char_coll_subtype(thread_db* tdbb,
*period = 0;
return resolve_charset_and_collation(tdbb, id, period + 1, buffer);
}
else {
/* Is it a character set name (implying charset default collation sequence) */
bool res = resolve_charset_and_collation(tdbb, id, buffer, NULL);
@ -1130,7 +1268,6 @@ bool MET_get_char_coll_subtype(thread_db* tdbb,
}
return res;
}
}
bool MET_get_char_coll_subtype_info(thread_db* tdbb, USHORT id, SubtypeInfo* info)
@ -1760,7 +1897,7 @@ int MET_lookup_field(thread_db* tdbb,
*
* Functional description
* Look up a field name.
* Additinally, if security_name is a not null pointer,
* Additionally, if security_name is a not null pointer,
* it's used to include the condition that it should match
* the field's security class name, too.
*
@ -2332,13 +2469,12 @@ jrd_prc* MET_lookup_procedure(thread_db* tdbb, const Firebird::MetaName& name, b
LCK_SR, LCK_WAIT);
break;
}
else {
return procedure;
}
}
}
}
}
/* We need to look up the procedure name in RDB$PROCEDURES */
@ -2485,6 +2621,7 @@ jrd_rel* MET_lookup_relation(thread_db* tdbb, const Firebird::MetaName& name)
LCK_lock(tdbb, relation->rel_partners_lock,
LCK_SR, LCK_WAIT);
}
if (relation->rel_flags & REL_check_existence)
{
check_relation = relation;
@ -2492,13 +2629,11 @@ jrd_rel* MET_lookup_relation(thread_db* tdbb, const Firebird::MetaName& name)
LCK_SR, LCK_WAIT);
break;
}
else
{
return relation;
}
}
}
}
/* We need to look up the relation name in RDB$RELATIONS */
@ -2571,16 +2706,14 @@ jrd_rel* MET_lookup_relation_id(thread_db* tdbb, SLONG id, bool return_deleted)
{
if (relation->rel_flags & REL_deleted)
{
if (return_deleted)
return relation;
return NULL;
return return_deleted ? relation : NULL;
}
else
{
if (relation->rel_flags & REL_check_partners)
{
LCK_lock(tdbb, relation->rel_partners_lock, LCK_SR, LCK_WAIT);
}
if (relation->rel_flags & REL_check_existence)
{
check_relation = relation;
@ -2591,7 +2724,6 @@ jrd_rel* MET_lookup_relation_id(thread_db* tdbb, SLONG id, bool return_deleted)
return relation;
}
}
}
/* We need to look up the relation id in RDB$RELATIONS */
@ -2874,13 +3006,6 @@ jrd_prc* MET_procedure(thread_db* tdbb, int id, bool noscan, USHORT flags)
vector->resize(id + 10);
}
#ifdef SUPERSERVER
if (!(dbb->dbb_flags & DBB_sp_rec_mutex_init))
{
THD_rec_mutex_init(&dbb->dbb_sp_rec_mutex);
dbb->dbb_flags |= DBB_sp_rec_mutex_init;
}
THREAD_EXIT();
if (THD_rec_mutex_lock(&dbb->dbb_sp_rec_mutex))
@ -2891,8 +3016,6 @@ jrd_prc* MET_procedure(thread_db* tdbb, int id, bool noscan, USHORT flags)
THREAD_ENTER();
#endif /* SUPERSERVER */
jrd_prc* procedure = (*vector)[id];
if (procedure)
{
@ -2925,10 +3048,7 @@ jrd_prc* MET_procedure(thread_db* tdbb, int id, bool noscan, USHORT flags)
if ((procedure->prc_flags & PRC_being_scanned) ||
(procedure->prc_flags & PRC_scanned))
{
#ifdef SUPERSERVER
THD_rec_mutex_unlock(&dbb->dbb_sp_rec_mutex);
#endif
return procedure;
}
}
@ -3227,17 +3347,12 @@ jrd_prc* MET_procedure(thread_db* tdbb, int id, bool noscan, USHORT flags)
fb_assert(procedure->prc_flags & PRC_being_scanned);
procedure->prc_flags &= ~PRC_being_scanned;
#ifdef SUPERSERVER
THD_rec_mutex_unlock(&dbb->dbb_sp_rec_mutex);
#endif
} // try
catch (const Firebird::Exception&) {
procedure->prc_flags &= ~(PRC_being_scanned | PRC_scanned);
#ifdef SUPERSERVER
THD_rec_mutex_unlock(&dbb->dbb_sp_rec_mutex);
#endif
if (procedure->prc_existence_lock)
{
LCK_release(tdbb, procedure->prc_existence_lock);
@ -3601,25 +3716,17 @@ void MET_scan_relation( thread_db* tdbb, jrd_rel* relation)
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
#ifdef SUPERSERVER
if (!(dbb->dbb_flags & DBB_sp_rec_mutex_init)) {
THD_rec_mutex_init(&dbb->dbb_sp_rec_mutex);
dbb->dbb_flags |= DBB_sp_rec_mutex_init;
}
THREAD_EXIT();
if (THD_rec_mutex_lock(&dbb->dbb_sp_rec_mutex)) {
THREAD_ENTER();
return;
}
THREAD_ENTER();
#endif /* SUPERSERVER */
if (relation->rel_flags & REL_scanned
|| relation->rel_flags & REL_deleted)
{
#ifdef SUPERSERVER
THD_rec_mutex_unlock(&dbb->dbb_sp_rec_mutex);
#endif
return;
}
@ -3957,9 +4064,8 @@ void MET_scan_relation( thread_db* tdbb, jrd_rel* relation)
}
relation->rel_flags &= ~REL_being_scanned;
#ifdef SUPERSERVER
THD_rec_mutex_unlock(&dbb->dbb_sp_rec_mutex);
#endif
relation->rel_current_format = NULL;
} // try
@ -3973,9 +4079,9 @@ void MET_scan_relation( thread_db* tdbb, jrd_rel* relation)
}
if (blob)
BLB_close(tdbb, blob);
#ifdef SUPERSERVER
THD_rec_mutex_unlock(&dbb->dbb_sp_rec_mutex);
#endif
// Some functions inside FOR loop may throw, in which case request
// remained active forever. AP: 13-may-05.
if (request && request->req_flags & req_active)
@ -4108,12 +4214,11 @@ static int blocking_ast_procedure(void* ast_object)
*
**************************************/
jrd_prc* procedure = static_cast<jrd_prc*>(ast_object);
thread_db thd_context, *tdbb;
/* Since this routine will be called asynchronously, we must establish
a thread context. */
JRD_set_thread_data(tdbb, thd_context);
ThreadContextHolder tdbb;
tdbb->setDatabase(procedure->prc_existence_lock->lck_dbb);
tdbb->setAttachment(procedure->prc_existence_lock->lck_attachment);
@ -4127,9 +4232,6 @@ static int blocking_ast_procedure(void* ast_object)
}
procedure->prc_flags |= PRC_obsolete;
/* Restore the prior thread context */
JRD_restore_thread_data();
return 0;
}
@ -4151,12 +4253,11 @@ static int blocking_ast_relation(void* ast_object)
*
**************************************/
jrd_rel* relation = static_cast<jrd_rel*>(ast_object);
thread_db thd_context, *tdbb;
/* Since this routine will be called asynchronously, we must establish
a thread context. */
JRD_set_thread_data(tdbb, thd_context);
ThreadContextHolder tdbb;
tdbb->setDatabase(relation->rel_existence_lock->lck_dbb);
tdbb->setAttachment(relation->rel_existence_lock->lck_attachment);
@ -4175,9 +4276,6 @@ static int blocking_ast_relation(void* ast_object)
LCK_release(tdbb, relation->rel_existence_lock);
}
/* Restore the prior thread context */
JRD_restore_thread_data();
return 0;
}
@ -4185,12 +4283,11 @@ static int blocking_ast_relation(void* ast_object)
static int partners_ast_relation(void* ast_object)
{
jrd_rel* relation = static_cast<jrd_rel*>(ast_object);
thread_db thd_context, *tdbb;
/* Since this routine will be called asynchronously, we must establish
a thread context. */
JRD_set_thread_data(tdbb, thd_context);
ThreadContextHolder tdbb;
fb_assert(relation->rel_partners_lock);
@ -4204,9 +4301,6 @@ static int partners_ast_relation(void* ast_object)
relation->rel_flags |= REL_check_partners;
LCK_release(tdbb, relation->rel_partners_lock);
/* Restore the prior thread context */
JRD_restore_thread_data();
return 0;
}
@ -4355,6 +4449,33 @@ static void make_relation_scope_name(const TEXT* rel_name,
}
// ***********************************************************
// * p a r s e _ f i e l d _ b l r
// ***********************************************************
// Parses default BLR and validation BLR for a field.
static jrd_nod* parse_field_blr(thread_db* tdbb, bid* blob_id, const Firebird::MetaName name)
{
SET_TDBB(tdbb);
Database* dbb = tdbb->tdbb_database;
CompilerScratch* csb = CompilerScratch::newCsb(*tdbb->getDefaultPool(), 5, name);
blb* blob = BLB_open(tdbb, dbb->dbb_sys_trans, blob_id);
SLONG length = blob->blb_length + 10;
Firebird::HalfStaticArray<UCHAR, 512> temp;
BLB_get_data(tdbb, blob, temp.getBuffer(length), length);
csb->csb_blr = temp.begin();
jrd_nod* node = PAR_blr(tdbb, NULL, temp.begin(), NULL, &csb, NULL, false, 0);
csb->csb_blr = 0;
delete csb;
return node;
}
static jrd_nod* parse_param_blr(thread_db* tdbb,
jrd_prc* procedure, bid* blob_id, CompilerScratch* csb)
{
@ -4648,7 +4769,8 @@ static bool resolve_charset_and_collation(
return found;
}
else if (charset == NULL)
if (charset == NULL)
{
FOR(REQUEST_HANDLE handle)
FIRST 1 COL IN RDB$COLLATIONS
@ -4851,7 +4973,7 @@ static void store_dependencies(thread_db* tdbb,
case obj_udf:
{
UserFunction* udf = (UserFunction*) node->nod_arg[e_dep_object];
dpdo_name = &udf->fun_symbol->sym_string;
dpdo_name = &udf->fun_name;
}
break;
case obj_index:

View File

@ -118,6 +118,8 @@ const TEXT* MET_trigger_msg(Jrd::thread_db*, const Firebird::MetaName&, USHORT);
void MET_update_shadow(Jrd::thread_db*, Jrd::Shadow*, USHORT);
void MET_update_transaction(Jrd::thread_db*, Jrd::jrd_tra*, const bool);
void MET_get_domain(Jrd::thread_db*, const Firebird::MetaName&, dsc*, Jrd::FieldInfo*);
Firebird::MetaName MET_get_relation_field(Jrd::thread_db*, const Firebird::MetaName&,
const Firebird::MetaName&, dsc*, Jrd::FieldInfo*);
void MET_update_partners(Jrd::thread_db*);
#endif // JRD_MET_PROTO_H

View File

@ -130,159 +130,6 @@ void MOV_double_to_date(double real, SLONG fixed[2])
}
#ifndef VMS
void MOV_fast(
const SCHAR* from,
SCHAR* to, ULONG length)
{
/**************************************
*
* M O V _ f a s t
*
**************************************
*
* Functional description
* Move a byte string as fast as possible.
*
**************************************/
ULONG l = length >> 4;
if (l)
do {
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
} while (--l);
if (length &= 15)
do {
*to++ = *from++;
} while (--length);
}
void MOV_faster(const SLONG* from, SLONG* to, ULONG length)
{
/**************************************
*
* M O V _ f a s t e r
*
**************************************
*
* Functional description
* Do a long move, already aligned, as quickly as possible.
*
**************************************/
ULONG l;
fb_assert(!((U_IPTR) to & (sizeof(ULONG) - 1))); /* ULONG alignment required */
fb_assert(!((U_IPTR) from & (sizeof(ULONG) - 1))); /* ULONG alignment required */
/* copy by chunks of 8 longwords == 32 bytes == 2**5 bytes */
if (l = (length >> 5)) {
do {
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
*to++ = *from++;
} while (--l);
length &= (8 * sizeof(ULONG) - 1);
}
/* Copy by longwords */
if (l = (length >> 2))
do
*to++ = *from++;
while (--l);
/* Finally, copy any trailing bytes */
if (l = (length & 3)) {
UCHAR* p = (UCHAR *) to;
const UCHAR* q = (UCHAR *) from;
do
*p++ = *q++;
while (--l);
}
}
#endif
void MOV_fill(SLONG* to, ULONG length)
{
/**************************************
*
* M O V _ f i l l
*
**************************************
*
* Functional description
* Clear out a block.
*
**************************************/
ULONG l;
/* If not longword aligned, fill bytewise until it is */
if (l = (((U_IPTR) to) & (sizeof(ULONG) - 1))) {
l = sizeof(ULONG) - l;
if (length < l)
l = length;
length -= l;
UCHAR* p = (UCHAR *) to;
while (l--)
*p++ = 0;
to = (SLONG *) p;
fb_assert(!(((U_IPTR) to) & (sizeof(ULONG) - 1)) /* We're now aligned ULONG */
|| !length); /* Or already completed */
}
/* Fill in chunks of 8 longwords == 32 bytes == 2**5 bytes */
if (l = (length >> 5)) {
do {
*to++ = 0;
*to++ = 0;
*to++ = 0;
*to++ = 0;
*to++ = 0;
*to++ = 0;
*to++ = 0;
*to++ = 0;
} while (--l);
length &= (8 * sizeof(ULONG) - 1);
}
/* Fill by longwords */
if (l = (length >> 2))
do
*to++ = 0;
while (--l);
/* Finally, fill any trailing bytes */
if (l = (length & 3)) {
UCHAR* p = (UCHAR *) to;
do
*p++ = 0;
while (--l);
}
}
double MOV_get_double(const dsc* desc)
{
/**************************************
@ -580,7 +427,7 @@ int MOV_make_string2(Jrd::thread_db* tdbb,
return size;
}
else
return CVT2_make_string2(desc, ttype, address, buffer, ERR_post);
}

View File

@ -34,9 +34,6 @@ struct vary;
int MOV_compare(const dsc*, const dsc*);
double MOV_date_to_double(const dsc*);
void MOV_double_to_date(double, SLONG[2]);
void MOV_fast(const SCHAR*, SCHAR*, ULONG);
void MOV_faster(const SLONG*, SLONG*, ULONG);
void MOV_fill(SLONG*, ULONG);
double MOV_get_double(const dsc*);
SLONG MOV_get_long(const dsc*, SSHORT);
void MOV_get_metadata_str(const dsc*, TEXT*, USHORT);

View File

@ -110,7 +110,7 @@ exp_index_buf* NAV_expand_index(WIN * window, IRSB_NAV impure)
ALL_free(expanded_page);
}
btree_page* page = (btree_page*) window->win_buffer;
Ods::btree_page* page = (Ods::btree_page*) window->win_buffer;
expanded_page = (exp_index_buf*) ALL_malloc(EXP_SIZE + page->btr_prefix_total +
(SLONG) page->btr_length + BTX_SIZE, ERR_jmp);
@ -131,7 +131,7 @@ exp_index_buf* NAV_expand_index(WIN * window, IRSB_NAV impure)
impure->irsb_nav_expanded_offset = -1;
IndexNode node;
Ods::IndexNode node;
while (pointer < endPointer) {
if (pointer == current_pointer) {
impure->irsb_nav_expanded_offset =
@ -344,23 +344,13 @@ bool NAV_get_record(thread_db* tdbb,
// has extra fields to the right, we just need to add some code to check
// when only the first n segment(s) of the key has changed, rather than the whole key
if (rsb->rsb_flags & rsb_project) {
if (page_changed) {
if (node.length != key.key_length) {
if (page_changed)
{
if (node.length != key.key_length || (key.key_length &&
memcmp(key.key_data, node.data, key.key_length)))
{
impure->irsb_flags |= irsb_key_changed;
}
else {
UCHAR* p = key.key_data;
const UCHAR* q = node.data;
USHORT l = key.key_length;
for (; l; l--) {
if (*p++ != *q++) {
break;
}
}
if (l) {
impure->irsb_flags |= irsb_key_changed;
}
}
}
else if (node.length) {
impure->irsb_flags |= irsb_key_changed;
@ -559,10 +549,9 @@ static int compare_keys(
if (flags & irb_descending) {
return (length1 < length2) ? 1 : -1;
}
else {
return (length1 < length2) ? -1 : 1;
}
}
#ifdef SCROLLABLE_CURSORS
@ -582,7 +571,7 @@ static void expand_index(WIN * window)
* the prior node.
*
**************************************/
btree_page* page = (btree_page*) window->win_buffer;
Ods::btree_page* page = (Ods::btree_page*) window->win_buffer;
exp_index_buf* expanded_page = window->win_expanded_buffer;
expanded_page->exp_incarnation = CCH_get_incarnation(window);
@ -593,8 +582,8 @@ static void expand_index(WIN * window)
UCHAR* pointer = BTreeNode::getPointerFirstNode(page);
const UCHAR* const endPointer = ((UCHAR*) page + page->btr_length);
const UCHAR flags = page->pag_flags;
IndexNode node, priorNode;
const UCHAR flags = page->btr_header.pag_flags;
Ods::IndexNode node, priorNode;
while (pointer < endPointer) {
@ -602,7 +591,7 @@ static void expand_index(WIN * window)
pointer = BTreeNode::readNode(&node, pointer, flags, true);
}
memcpy(key.key_data + node.prefix, node.data, node_length);
memcpy(key.key_data + node.prefix, node.data, node.length);
memcpy(expanded_node->btx_data, key.key_data, node.length + node.prefix);
// point back to the prior nodes on the expanded page and the btree page
@ -682,7 +671,7 @@ static bool find_saved_node(RecordSource* rsb, IRSB_NAV impure,
* A page has changed. Find the new position of the
* previously stored node. The node could even be on
* a sibling page if the page has split. If we find
* the actual node, return TRUE.
* the actual node, return true.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
@ -726,12 +715,7 @@ static bool find_saved_node(RecordSource* rsb, IRSB_NAV impure,
// safely returned since their position in the index is arbitrary
if (!result) {
*return_pointer = node.nodePointer;
if (node.recordNumber == impure->irsb_nav_number) {
return true;
}
else {
return false;
}
return node.recordNumber == impure->irsb_nav_number;
}
// if the stored key is less than the current key, then the stored key
@ -1085,6 +1069,10 @@ static UCHAR* nav_open(
// isn't a starting descriptor, walk down the left side of the index (or the
// right side if backwards).
#ifdef SCROLLABLE_CURSORS
exp_index_buf* expanded_page = 0;
#endif
UCHAR* pointer = NULL;
if (limit_ptr) {