mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 10:43:03 +01:00
The merge continued.
This commit is contained in:
parent
e053607b22
commit
d1e8f67a5d
1366
src/jrd/jrd.cpp
1366
src/jrd/jrd.cpp
File diff suppressed because it is too large
Load Diff
165
src/jrd/jrd.h
165
src/jrd/jrd.h
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
253
src/jrd/lck.cpp
253
src/jrd/lck.cpp
@ -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;
|
||||
|
||||
switch (status[1])
|
||||
{
|
||||
case isc_deadlock:
|
||||
case isc_lock_conflict:
|
||||
case isc_lock_timeout:
|
||||
return FALSE;
|
||||
case isc_lockmanerr:
|
||||
dbb->dbb_flags |= DBB_bugcheck;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (status[1] == isc_lockmanerr)
|
||||
dbb->dbb_flags |= DBB_bugcheck;
|
||||
ERR_punt();
|
||||
}
|
||||
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;
|
||||
case isc_lockmanerr:
|
||||
dbb->dbb_flags |= DBB_bugcheck;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (status[1] == isc_lockmanerr)
|
||||
dbb->dbb_flags |= DBB_bugcheck;
|
||||
ERR_punt();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
*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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
346
src/jrd/met.epp
346
src/jrd/met.epp
@ -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*);
|
||||
@ -219,7 +219,7 @@ void MET_get_domain(thread_db* tdbb, const Firebird::MetaName& name, dsc* desc,
|
||||
FLD.RDB$CHARACTER_SET_ID,
|
||||
FLD.RDB$COLLATION_ID))
|
||||
{
|
||||
found = true;
|
||||
found = true;
|
||||
|
||||
if (fieldInfo)
|
||||
{
|
||||
@ -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,16 +1258,15 @@ 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);
|
||||
if (!res) {
|
||||
/* Is it a collation name (implying implementation-default character set) */
|
||||
res = resolve_charset_and_collation(tdbb, id, NULL, buffer);
|
||||
}
|
||||
return res;
|
||||
/* Is it a character set name (implying charset default collation sequence) */
|
||||
|
||||
bool res = resolve_charset_and_collation(tdbb, id, buffer, NULL);
|
||||
if (!res) {
|
||||
/* Is it a collation name (implying implementation-default character set) */
|
||||
res = resolve_charset_and_collation(tdbb, id, NULL, buffer);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -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,10 +2469,9 @@ jrd_prc* MET_lookup_procedure(thread_db* tdbb, const Firebird::MetaName& name, b
|
||||
LCK_SR, LCK_WAIT);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
return procedure;
|
||||
}
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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,10 +2629,8 @@ jrd_rel* MET_lookup_relation(thread_db* tdbb, const Firebird::MetaName& name)
|
||||
LCK_SR, LCK_WAIT);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
return relation;
|
||||
}
|
||||
|
||||
return relation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2571,25 +2706,22 @@ 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;
|
||||
}
|
||||
|
||||
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;
|
||||
LCK_lock(tdbb, check_relation->rel_existence_lock, LCK_SR, LCK_WAIT);
|
||||
}
|
||||
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;
|
||||
LCK_lock(tdbb, check_relation->rel_existence_lock, LCK_SR, LCK_WAIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
return relation;
|
||||
}
|
||||
return relation;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
@ -4363,7 +4484,7 @@ static jrd_nod* parse_param_blr(thread_db* tdbb,
|
||||
|
||||
blb* blob = BLB_open(tdbb, dbb->dbb_sys_trans, blob_id);
|
||||
SLONG length = blob->blb_length + 10;
|
||||
Firebird::HalfStaticArray<UCHAR, 512> temp;
|
||||
Firebird::HalfStaticArray<UCHAR, 512> temp;
|
||||
|
||||
BLB_get_data(tdbb, blob, temp.getBuffer(length), length);
|
||||
csb->csb_blr = temp.begin();
|
||||
@ -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:
|
||||
|
@ -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
|
||||
|
157
src/jrd/mov.cpp
157
src/jrd/mov.cpp
@ -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,8 +427,8 @@ int MOV_make_string2(Jrd::thread_db* tdbb,
|
||||
|
||||
return size;
|
||||
}
|
||||
else
|
||||
return CVT2_make_string2(desc, ttype, address, buffer, ERR_post);
|
||||
|
||||
return CVT2_make_string2(desc, ttype, address, buffer, ERR_post);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,9 +549,8 @@ static int compare_keys(
|
||||
if (flags & irb_descending) {
|
||||
return (length1 < length2) ? 1 : -1;
|
||||
}
|
||||
else {
|
||||
return (length1 < length2) ? -1 : 1;
|
||||
}
|
||||
|
||||
return (length1 < length2) ? -1 : 1;
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user