8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-31 01:23:02 +01:00
firebird-mirror/src/jrd/jrd.h

908 lines
22 KiB
C
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD access method
* MODULE: jrd.h
* DESCRIPTION: Common descriptions
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
* 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "DecOSF" port
*
2002-10-30 07:40:58 +01:00
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
* Claudio Valderrama C.
* Adriano dos Santos Fernandes
2002-10-30 07:40:58 +01:00
*
2001-05-23 15:26:42 +02:00
*/
#ifndef JRD_JRD_H
#define JRD_JRD_H
#include "../common/gdsassert.h"
2010-10-12 10:02:57 +02:00
#include "../common/dsc.h"
#include "../jrd/btn.h"
#include "../jrd/jrd_proto.h"
#include "../jrd/obj.h"
2008-01-16 10:29:37 +01:00
#include "../jrd/val.h"
2001-12-24 03:51:06 +01:00
#include "../common/classes/fb_atomic.h"
#include "../common/classes/fb_string.h"
#include "../common/classes/MetaName.h"
#include "../common/classes/NestConst.h"
#include "../common/classes/array.h"
2004-04-19 17:29:29 +02:00
#include "../common/classes/objects_array.h"
#include "../common/classes/stack.h"
#include "../common/classes/timestamp.h"
#include "../common/classes/GenericMap.h"
2011-05-09 12:15:19 +02:00
#include "../common/classes/Synchronize.h"
#include "../common/utils_proto.h"
2010-10-12 10:02:57 +02:00
#include "../common/StatusHolder.h"
#include "../jrd/RandomGenerator.h"
2010-10-12 10:02:57 +02:00
#include "../common/os/guid.h"
#include "../jrd/sbm.h"
#include "../jrd/scl.h"
#include "../jrd/Routine.h"
#include "../jrd/ExtEngineManager.h"
#include "../jrd/Attachment.h"
#include "firebird/Provider.h"
2001-05-23 15:26:42 +02:00
#ifdef DEV_BUILD
2010-10-12 10:02:57 +02:00
//#define DEBUG if (debug) DBG_supervisor(debug);
//#define VIO_DEBUG // remove this for production build
2006-07-21 03:35:17 +02:00
#else // PROD
2010-10-12 10:02:57 +02:00
//#define DEBUG
2001-05-23 15:26:42 +02:00
#undef VIO_DEBUG
#endif
2010-10-12 10:02:57 +02:00
#define DEBUG
2001-05-23 15:26:42 +02:00
#define BUGCHECK(number) ERR_bugcheck (number, __FILE__, __LINE__)
2001-05-23 15:26:42 +02:00
#define CORRUPT(number) ERR_corrupt (number)
#define IBERROR(number) ERR_error (number)
#define BLKCHK(blk, type) if (!blk->checkHandle()) BUGCHECK(147)
2001-05-23 15:26:42 +02:00
#define DEV_BLKCHK(blk, type) do { } while (false) // nothing
2001-05-23 15:26:42 +02:00
// Thread data block / IPC related data blocks
2010-10-12 10:02:57 +02:00
#include "../common/ThreadData.h"
2001-05-23 15:26:42 +02:00
2008-01-16 10:29:37 +01:00
// recursive mutexes
#include "../common/thd.h"
2008-01-16 10:29:37 +01:00
// Definition of block types for data allocation in JRD
2001-05-23 15:26:42 +02:00
#include "../include/fb_blk.h"
#include "../jrd/blb.h"
// Definition of DatabasePlugins
#include "../jrd/flu.h"
2006-05-22 00:07:35 +02:00
#include "../jrd/pag.h"
#include "../jrd/RuntimeStatistics.h"
#include "../jrd/Database.h"
2008-01-16 10:29:37 +01:00
// Error codes
#include "../include/gen/iberror.h"
2006-05-22 00:07:35 +02:00
class str;
struct dsc;
2004-04-20 07:57:31 +02:00
struct thread;
struct mod;
2001-05-23 15:26:42 +02:00
namespace EDS {
class Connection;
}
namespace Jrd {
2009-12-06 15:13:24 +01:00
const int QUANTUM = 100; // Default quantum
const int SWEEP_QUANTUM = 10; // Make sweeps less disruptive
const unsigned MAX_CALLBACKS = 50;
2001-12-28 07:31:38 +01:00
// fwd. decl.
class thread_db;
class Attachment;
class jrd_tra;
class jrd_req;
class JrdStatement;
class Lock;
class jrd_file;
2004-03-30 06:10:52 +02:00
class Format;
2011-05-09 12:15:19 +02:00
class BufferDesc;
class SparseBitmap;
class jrd_rel;
class ExternalFile;
class ViewContext;
class IndexBlock;
class IndexLock;
class ArrayField;
struct sort_context;
class vcl;
class TextType;
class Parameter;
class jrd_fld;
2008-02-28 14:48:16 +01:00
class dsql_dbb;
class PreparedStatement;
2009-02-01 23:10:12 +01:00
class TraceManager;
class MessageNode;
2001-12-28 07:31:38 +01:00
// The database block, the topmost block in the metadata
// cache for a database
// Relation trigger definition
2008-12-13 10:26:00 +01:00
class Trigger
{
public:
Firebird::HalfStaticArray<UCHAR, 128> blr; // BLR code
2008-12-05 01:56:15 +01:00
bid dbg_blob_id; // RDB$DEBUG_INFO
JrdStatement* statement; // Compiled statement
bool compile_in_progress;
bool sys_trigger;
FB_UINT64 type; // Trigger type
USHORT flags; // Flags as they are in RDB$TRIGGERS table
jrd_rel* relation; // Trigger parent relation
Firebird::MetaName name; // Trigger name
Firebird::MetaName engine; // External engine name
Firebird::string entryPoint; // External trigger entrypoint
Firebird::string extBody; // External trigger body
ExtEngineManager::Trigger* extTrigger; // External trigger
void compile(thread_db*); // Ensure that trigger is compiled
void release(thread_db*); // Try to free trigger request
2008-12-13 10:26:00 +01:00
explicit Trigger(MemoryPool& p)
: blr(p),
name(p),
engine(p),
entryPoint(p),
extBody(p),
extTrigger(NULL)
2008-12-13 10:26:00 +01:00
{
dbg_blob_id.clear();
}
};
2001-12-24 03:51:06 +01:00
//
// Flags to indicate normal internal requests vs. dyn internal requests
//
2004-04-29 16:51:02 +02:00
const int IRQ_REQUESTS = 1;
const int DYN_REQUESTS = 2;
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
//
// Errors during validation - will be returned on info calls
// CVC: It seems they will be better in a header for val.cpp that's not val.h
2001-12-24 03:51:06 +01:00
//
2004-04-29 16:51:02 +02:00
const int VAL_PAG_WRONG_TYPE = 0;
const int VAL_PAG_CHECKSUM_ERR = 1;
const int VAL_PAG_DOUBLE_ALLOC = 2;
const int VAL_PAG_IN_USE = 3;
const int VAL_PAG_ORPHAN = 4;
const int VAL_BLOB_INCONSISTENT = 5;
const int VAL_BLOB_CORRUPT = 6;
const int VAL_BLOB_TRUNCATED = 7;
const int VAL_REC_CHAIN_BROKEN = 8;
const int VAL_DATA_PAGE_CONFUSED = 9;
const int VAL_DATA_PAGE_LINE_ERR = 10;
const int VAL_INDEX_PAGE_CORRUPT = 11;
const int VAL_P_PAGE_LOST = 12;
const int VAL_P_PAGE_INCONSISTENT = 13;
const int VAL_REC_DAMAGED = 14;
const int VAL_REC_BAD_TID = 15;
const int VAL_REC_FRAGMENT_CORRUPT = 16;
const int VAL_REC_WRONG_LENGTH = 17;
const int VAL_INDEX_ROOT_MISSING = 18;
const int VAL_TIP_LOST = 19;
const int VAL_TIP_LOST_SEQUENCE = 20;
const int VAL_TIP_CONFUSED = 21;
const int VAL_REL_CHAIN_ORPHANS = 22;
const int VAL_INDEX_MISSING_ROWS = 23;
const int VAL_INDEX_ORPHAN_CHILD = 24;
const int VAL_INDEX_CYCLE = 25;
const int VAL_SCNS_PAGE_INCONSISTENT = 26;
const int VAL_PAG_WRONG_SCN = 27;
const int VAL_BLOB_UNKNOWN_LEVEL = 28;
const int VAL_MAX_ERROR = 29;
2001-05-23 15:26:42 +02:00
2006-07-21 03:35:17 +02:00
// Procedure block
2001-05-23 15:26:42 +02:00
class jrd_prc : public Routine
2001-12-24 03:51:06 +01:00
{
2006-07-21 03:35:17 +02:00
public:
2001-05-23 15:26:42 +02:00
USHORT prc_flags;
const MessageNode* prc_output_msg;
const Format* prc_format;
2006-07-21 03:35:17 +02:00
prc_t prc_type; // procedure type
USHORT prc_use_count; // requests compiled with procedure
SSHORT prc_int_use_count; // number of procedures compiled with procedure, set and
// used internally in the MET_clear_cache procedure
// no code should rely on value of this field
// (it will usually be 0)
Lock* prc_existence_lock; // existence lock, if any
USHORT prc_alter_count; // No. of times the procedure was altered
const ExtEngineManager::Procedure* getExternal() const { return prc_external; }
void setExternal(ExtEngineManager::Procedure* value) { prc_external = value; }
private:
const ExtEngineManager::Procedure* prc_external;
2006-07-21 03:35:17 +02:00
public:
2009-04-04 18:39:31 +02:00
explicit jrd_prc(MemoryPool& p)
: Routine(p),
prc_flags(0),
prc_output_msg(NULL),
prc_format(NULL),
prc_type(prc_legacy),
prc_use_count(0),
prc_int_use_count(0),
prc_existence_lock(NULL),
prc_alter_count(0),
prc_external(NULL)
{
}
public:
virtual int getObjectType() const
{
return obj_procedure;
}
virtual SLONG getSclType() const
{
return SCL_object_procedure;
}
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
2004-05-04 00:42:47 +02:00
// prc_flags
2006-07-21 03:35:17 +02:00
const USHORT PRC_scanned = 1; // Field expressions scanned
const USHORT PRC_obsolete = 2; // Procedure known gonzo
const USHORT PRC_being_scanned = 4; // New procedure needs dependencies during scan
const USHORT PRC_being_altered = 8; // Procedure is getting altered
2004-04-10 21:46:48 +02:00
// This flag is used to make sure that MET_remove_procedure
// does not delete and remove procedure block from cache
2008-12-05 01:56:15 +01:00
// so dfw.epp:modify_procedure() can flip procedure body without
2004-04-10 21:46:48 +02:00
// invalidating procedure pointers from other parts of metadata cache
const USHORT PRC_check_existence = 16; // Existence lock released
2001-05-23 15:26:42 +02:00
const USHORT MAX_PROC_ALTER = 64; // No. of times an in-cache procedure can be altered
2001-05-23 15:26:42 +02:00
2006-07-21 03:35:17 +02:00
// Parameter block
2001-05-23 15:26:42 +02:00
class Parameter : public pool_alloc<type_prm>
2001-12-24 03:51:06 +01:00
{
public:
USHORT prm_number;
dsc prm_desc;
NestConst<ValueExprNode> prm_default_value;
bool prm_nullable;
prm_mech_t prm_mechanism;
2006-07-21 03:35:17 +02:00
Firebird::MetaName prm_name; // asciiz name
Firebird::MetaName prm_field_source;
FUN_T prm_fun_mechanism;
public:
2009-04-04 18:39:31 +02:00
explicit Parameter(MemoryPool& p)
: prm_name(p),
prm_field_source(p)
{
}
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
2006-07-21 03:35:17 +02:00
// Index block to cache index information
2001-05-23 15:26:42 +02:00
class IndexBlock : public pool_alloc<type_idb>
2001-05-23 15:26:42 +02:00
{
public:
IndexBlock* idb_next;
ValueExprNode* idb_expression; // node tree for index expression
JrdStatement* idb_expression_statement; // statement for index expression evaluation
2006-07-21 03:35:17 +02:00
dsc idb_expression_desc; // descriptor for expression result
Lock* idb_lock; // lock to synchronize changes to index
USHORT idb_id;
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
//
// Transaction element block
//
2008-12-13 10:26:00 +01:00
struct teb
{
2010-10-12 10:02:57 +02:00
Attachment* teb_database;
2001-05-23 15:26:42 +02:00
int teb_tpb_length;
const UCHAR* teb_tpb;
2004-05-24 19:31:47 +02:00
};
typedef teb TEB;
2001-05-23 15:26:42 +02:00
2006-07-21 03:35:17 +02:00
// Window block for loading cached pages into
// CVC: Apparently, the only possible values are HEADER_PAGE==0 and LOG_PAGE==2
// and reside in ods.h, although I watched a place with 1 and others with members
// of a struct.
2001-05-23 15:26:42 +02:00
2008-12-13 10:26:00 +01:00
struct win
{
2006-05-22 00:07:35 +02:00
PageNumber win_page;
Ods::pag* win_buffer;
class BufferDesc* win_bdb;
2001-05-23 15:26:42 +02:00
SSHORT win_scans;
USHORT win_flags;
2009-04-04 18:39:31 +02:00
explicit win(const PageNumber& wp)
: win_page(wp), win_bdb(NULL), win_flags(0)
2008-12-22 10:00:05 +01:00
{}
2009-04-04 18:39:31 +02:00
win(const USHORT pageSpaceID, const SLONG pageNum)
: win_page(pageSpaceID, pageNum), win_bdb(NULL), win_flags(0)
2008-12-22 10:00:05 +01:00
{}
2004-05-24 19:31:47 +02:00
};
typedef win WIN;
2001-05-23 15:26:42 +02:00
// This is a compilation artifact: I wanted to be sure I would pick all old "win"
// declarations at the top, so "win" was built with a mandatory argument in
// the constructor. This struct satisfies a single place with an array. The
// alternative would be to initialize 16 elements of the array with 16 calls
// to the constructor: win my_array[n] = {win(-1), ... (win-1)};
// When all places are changed, this class can disappear and win's constructor
// may get the default value of -1 to "wp".
struct win_for_array: public win
{
2009-04-04 18:39:31 +02:00
win_for_array()
: win(DB_PAGE_SPACE, -1)
2008-12-22 10:00:05 +01:00
{}
};
2004-05-04 00:42:47 +02:00
// win_flags
2006-07-22 05:54:43 +02:00
const USHORT WIN_large_scan = 1; // large sequential scan
2006-07-21 03:35:17 +02:00
const USHORT WIN_secondary = 2; // secondary stream
const USHORT WIN_garbage_collector = 4; // garbage collector's window
const USHORT WIN_garbage_collect = 8; // scan left a page for garbage collector
2001-05-23 15:26:42 +02:00
// Thread specific database block
class thread_db : public ThreadData
2001-05-23 15:26:42 +02:00
{
private:
MemoryPool* defaultPool;
2008-01-29 11:11:52 +01:00
void setDefaultPool(MemoryPool* p)
{
defaultPool = p;
}
2008-01-29 11:11:52 +01:00
friend class Firebird::SubsystemContextPoolHolder <Jrd::thread_db, MemoryPool>;
Database* database;
Attachment* attachment;
jrd_tra* transaction;
jrd_req* request;
RuntimeStatistics *reqStat, *traStat, *attStat, *dbbStat;
thread_db *priorThread, *nextThread;
public:
2008-01-16 10:29:37 +01:00
explicit thread_db(ISC_STATUS* status)
2011-05-09 12:15:19 +02:00
: ThreadData(ThreadData::tddDBB),
defaultPool(NULL),
database(NULL),
attachment(NULL),
transaction(NULL),
request(NULL),
priorThread(NULL),
nextThread(NULL),
tdbb_status_vector(status),
tdbb_quantum(QUANTUM),
tdbb_flags(0),
tdbb_temp_traid(0),
tdbb_bdbs(*getDefaultMemoryPool()),
tdbb_thread(Firebird::ThreadSync::getThread("thread_db"))
{
reqStat = traStat = attStat = dbbStat = RuntimeStatistics::getDummy();
fb_utils::init_status(tdbb_status_vector);
2011-05-09 12:15:19 +02:00
}
~thread_db()
{
#ifdef DEV_BUILD
2011-05-10 03:12:14 +02:00
for (size_t n = 0; n < tdbb_bdbs.getCount(); ++n)
2011-05-09 12:15:19 +02:00
{
fb_assert(tdbb_bdbs[n] == NULL);
}
#endif
}
2011-05-09 12:15:19 +02:00
2003-04-10 08:49:16 +02:00
ISC_STATUS* tdbb_status_vector;
SSHORT tdbb_quantum; // Cycles remaining until voluntary schedule
2001-05-23 15:26:42 +02:00
USHORT tdbb_flags;
2006-05-22 00:07:35 +02:00
SLONG tdbb_temp_traid; // current temporary table scope
2008-12-05 01:56:15 +01:00
2011-05-09 12:15:19 +02:00
// BDB's held by thread
Firebird::HalfStaticArray<BufferDesc*, 16> tdbb_bdbs;
Firebird::ThreadSync* tdbb_thread;
2006-05-22 00:07:35 +02:00
2008-01-29 11:11:52 +01:00
MemoryPool* getDefaultPool()
{
return defaultPool;
}
Database* getDatabase()
{
return database;
}
2007-12-05 01:03:15 +01:00
const Database* getDatabase() const
{
return database;
}
2007-12-05 01:03:15 +01:00
void setDatabase(Database* val);
Attachment* getAttachment()
{
return attachment;
}
2007-12-05 01:03:15 +01:00
const Attachment* getAttachment() const
{
return attachment;
}
2007-12-05 01:03:15 +01:00
void setAttachment(Attachment* val);
jrd_tra* getTransaction()
{
return transaction;
}
2007-12-05 01:03:15 +01:00
const jrd_tra* getTransaction() const
{
return transaction;
}
2007-12-05 01:03:15 +01:00
void setTransaction(jrd_tra* val);
jrd_req* getRequest()
{
return request;
}
2007-12-05 01:03:15 +01:00
const jrd_req* getRequest() const
{
return request;
}
2007-12-05 01:03:15 +01:00
void setRequest(jrd_req* val);
2009-10-30 11:50:59 +01:00
SSHORT getCharSet() const;
void bumpStats(const RuntimeStatistics::StatType index)
{
reqStat->bumpValue(index);
traStat->bumpValue(index);
attStat->bumpValue(index);
dbbStat->bumpValue(index);
}
2009-02-01 23:10:12 +01:00
void bumpRelStats(const RelStatType index, SLONG relation_id)
2009-02-01 23:10:12 +01:00
{
reqStat->bumpRelValue(index, relation_id);
//traStat->bumpRelValue(index, relation_id);
//attStat->bumpRelValue(index, relation_id);
//dbbStat->bumpRelValue(index, relation_id);
2009-02-01 23:10:12 +01:00
}
bool checkCancelState(bool punt);
2011-05-09 12:15:19 +02:00
void registerBdb(BufferDesc* bdb)
{
size_t pos;
if (tdbb_bdbs.find(NULL, pos))
tdbb_bdbs[pos] = bdb;
else
tdbb_bdbs.add(bdb);
}
void clearBdb(BufferDesc* bdb)
{
size_t pos;
if (tdbb_bdbs.find(bdb, pos))
{
tdbb_bdbs[pos] = NULL;
if (pos == tdbb_bdbs.getCount() - 1)
{
while (true)
{
if (tdbb_bdbs[pos] != NULL)
{
tdbb_bdbs.shrink(pos + 1);
break;
}
2011-05-10 03:12:14 +02:00
2011-05-09 12:15:19 +02:00
if (pos == 0)
{
tdbb_bdbs.shrink(0);
break;
}
2011-05-10 03:12:14 +02:00
--pos;
2011-05-09 12:15:19 +02:00
}
}
}
else
fb_assert(false);
}
void activate()
{
fb_assert(!priorThread && !nextThread);
if (database)
{
Firebird::SyncLockGuard sync(&database->dbb_threads_sync, Firebird::SYNC_EXCLUSIVE,
"thread_db::activate");
if (database->dbb_active_threads)
{
fb_assert(!database->dbb_active_threads->priorThread);
database->dbb_active_threads->priorThread = this;
nextThread = database->dbb_active_threads;
}
database->dbb_active_threads = this;
}
}
void deactivate()
{
if (database)
{
Firebird::SyncLockGuard sync(&database->dbb_threads_sync, Firebird::SYNC_EXCLUSIVE,
"thread_db::deactivate");
if (nextThread)
{
fb_assert(nextThread->priorThread == this);
nextThread->priorThread = priorThread;
}
if (priorThread)
{
fb_assert(priorThread->nextThread == this);
priorThread->nextThread = nextThread;
}
else
{
fb_assert(database->dbb_active_threads == this);
database->dbb_active_threads = nextThread;
}
}
priorThread = nextThread = NULL;
}
};
2001-05-23 15:26:42 +02:00
2004-05-04 00:42:47 +02:00
// tdbb_flags
2006-07-21 03:35:17 +02:00
const USHORT TDBB_sweeper = 1; // Thread sweeper or garbage collector
const USHORT TDBB_no_cache_unwind = 2; // Don't unwind page buffer cache
2010-04-14 10:30:29 +02:00
const USHORT TDBB_backup_write_locked = 4; // BackupManager has write lock on LCK_backup_database
const USHORT TDBB_stack_trace_done = 8; // PSQL stack trace is added into status-vector
const USHORT TDBB_shutdown_manager = 16; // Server shutdown thread
const USHORT TDBB_dont_post_dfw = 32; // dont post DFW tasks as deferred work is performed now
const USHORT TDBB_sys_error = 64; // error shouldn't be handled by the looper
const USHORT TDBB_verb_cleanup = 128; // verb cleanup is in progress
const USHORT TDBB_use_db_page_space = 256; // use database (not temporary) page space in GTT operations
const USHORT TDBB_detaching = 512; // detach is in progress
const USHORT TDBB_wait_cancel_disable = 1024; // don't cancel current waiting operation
2001-05-23 15:26:42 +02:00
2008-01-16 10:29:37 +01:00
class ThreadContextHolder
{
public:
explicit ThreadContextHolder(ISC_STATUS* status = NULL)
2010-10-12 10:02:57 +02:00
: context(status ? status : local_status), externStatus(NULL)
{
context.putSpecific();
}
explicit ThreadContextHolder(Firebird::IStatus* status)
2010-10-12 10:02:57 +02:00
: context(local_status), externStatus(status)
2008-01-16 10:29:37 +01:00
{
context.putSpecific();
2010-10-12 10:02:57 +02:00
externStatus->init();
2008-01-16 10:29:37 +01:00
}
ThreadContextHolder(Database* dbb, Jrd::Attachment* att, ISC_STATUS* status = NULL)
: context(status ? status : local_status), externStatus(NULL)
{
context.putSpecific();
context.setDatabase(dbb);
context.setAttachment(att);
}
2008-01-16 10:29:37 +01:00
~ThreadContextHolder()
{
2010-10-12 10:02:57 +02:00
if (externStatus && externStatus->isSuccess())
{
externStatus->set(context.tdbb_status_vector);
}
2008-01-16 10:29:37 +01:00
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;
Firebird::IStatus* externStatus;
2008-01-16 10:29:37 +01:00
};
// CVC: This class was designed to restore the thread's default status vector automatically.
// In several places, tdbb_status_vector is replaced by a local temporary.
class ThreadStatusGuard
{
public:
explicit ThreadStatusGuard(thread_db* tdbb)
: m_tdbb(tdbb), m_old_status(tdbb->tdbb_status_vector)
{
fb_utils::init_status(m_local_status);
m_tdbb->tdbb_status_vector = m_local_status;
}
2008-04-27 04:39:51 +02:00
~ThreadStatusGuard()
{
m_tdbb->tdbb_status_vector = m_old_status;
}
2008-04-27 04:39:51 +02:00
//ISC_STATUS* restore()
//{
// return m_tdbb->tdbb_status_vector = m_old_status; // copy, not comparison
//}
2008-04-27 04:39:51 +02:00
operator ISC_STATUS*() { return m_local_status; }
2008-04-27 04:39:51 +02:00
void copyToOriginal()
{
memcpy(m_old_status, m_local_status, sizeof(ISC_STATUS_ARRAY));
}
2008-04-27 04:39:51 +02:00
private:
thread_db* const m_tdbb;
ISC_STATUS* const m_old_status;
ISC_STATUS_ARRAY m_local_status;
2008-04-27 04:39:51 +02:00
// copying is prohibited
ThreadStatusGuard(const ThreadStatusGuard&);
ThreadStatusGuard& operator=(const ThreadStatusGuard&);
};
// duplicate context of firebird string
2004-03-31 20:03:51 +02:00
inline char* stringDup(MemoryPool& p, const Firebird::string& s)
{
char* rc = (char*) p.allocate(s.length() + 1
#ifdef DEBUG_GDS_ALLOC
2004-03-31 20:03:51 +02:00
, __FILE__, __LINE__
#endif
);
strcpy(rc, s.c_str());
return rc;
}
2004-05-09 07:48:33 +02:00
inline char* stringDup(MemoryPool& p, const char* s, size_t l)
{
char* rc = (char*) p.allocate(l + 1
#ifdef DEBUG_GDS_ALLOC
, __FILE__, __LINE__
#endif
);
memcpy(rc, s, l);
rc[l] = 0;
return rc;
}
2004-05-26 18:12:05 +02:00
inline char* stringDup(MemoryPool& p, const char* s)
{
if (! s)
{
return 0;
}
return stringDup(p, s, strlen(s));
}
2008-06-27 15:31:04 +02:00
// Used in string conversion calls
typedef Firebird::HalfStaticArray<UCHAR, 256> MoveBuffer;
} //namespace Jrd
2006-07-21 03:35:17 +02:00
// Threading macros
2001-05-23 15:26:42 +02:00
/* Define JRD_get_thread_data off the platform specific version.
2001-05-23 15:26:42 +02:00
* If we're in DEV mode, also do consistancy checks on the
* retrieved memory structure. This was originally done to
2008-12-05 01:56:15 +01:00
* track down cases of no "PUT_THREAD_DATA" on the NLM.
2001-05-23 15:26:42 +02:00
*
* This allows for NULL thread data (which might be an error by itself)
2008-12-05 01:56:15 +01:00
* If there is thread data,
* AND it is tagged as being a thread_db.
2008-12-05 01:56:15 +01:00
* AND it has a non-NULL database field,
2001-05-23 15:26:42 +02:00
* THEN we validate that the structure there is a database block.
* Otherwise, we return what we got.
* We can't always validate the database field, as during initialization
* there is no database set up.
2001-05-23 15:26:42 +02:00
*/
#if defined(DEV_BUILD)
#include "../jrd/err_proto.h"
2008-12-13 10:26:00 +01:00
inline Jrd::thread_db* JRD_get_thread_data()
{
ThreadData* p1 = ThreadData::getSpecific();
if (p1 && p1->getType() == ThreadData::tddDBB)
{
2008-12-13 10:26:00 +01:00
Jrd::thread_db* p2 = (Jrd::thread_db*) p1;
if (p2->getDatabase() && !p2->getDatabase()->checkHandle())
{
BUGCHECK(147);
}
}
return (Jrd::thread_db*) p1;
}
2008-12-13 10:26:00 +01:00
inline void CHECK_TDBB(const Jrd::thread_db* tdbb)
{
fb_assert(tdbb && (tdbb->getType() == ThreadData::tddDBB) &&
(!tdbb->getDatabase() || tdbb->getDatabase()->checkHandle()));
}
2008-12-13 10:26:00 +01:00
inline void CHECK_DBB(const Jrd::Database* dbb)
{
fb_assert(dbb && dbb->checkHandle());
}
2008-01-16 10:29:37 +01:00
#else // PROD_BUILD
2008-12-13 10:26:00 +01:00
inline Jrd::thread_db* JRD_get_thread_data()
{
return (Jrd::thread_db*) ThreadData::getSpecific();
}
2008-12-13 10:26:00 +01:00
2009-11-25 09:32:11 +01:00
inline void CHECK_DBB(const Jrd::Database*)
2008-12-13 10:26:00 +01:00
{
}
2008-12-13 10:26:00 +01:00
2009-11-25 09:32:11 +01:00
inline void CHECK_TDBB(const Jrd::thread_db*)
2008-12-13 10:26:00 +01:00
{
}
2001-05-23 15:26:42 +02:00
#endif
2008-12-13 10:26:00 +01:00
inline Jrd::Database* GET_DBB()
{
return JRD_get_thread_data()->getDatabase();
}
2001-05-23 15:26:42 +02:00
/*-------------------------------------------------------------------------*
* macros used to set thread_db and Database pointers when there are not set already *
2001-05-23 15:26:42 +02:00
*-------------------------------------------------------------------------*/
2008-12-13 10:26:00 +01:00
inline void SET_TDBB(Jrd::thread_db* &tdbb)
{
if (tdbb == NULL) {
tdbb = JRD_get_thread_data();
}
CHECK_TDBB(tdbb);
}
2008-12-13 10:26:00 +01:00
inline void SET_DBB(Jrd::Database* &dbb)
{
if (dbb == NULL) {
dbb = GET_DBB();
}
CHECK_DBB(dbb);
}
2001-05-23 15:26:42 +02:00
2006-07-21 03:35:17 +02:00
// global variables for engine
2001-05-23 15:26:42 +02:00
extern int debug;
namespace Jrd {
2008-12-13 10:26:00 +01:00
typedef Firebird::SubsystemContextPoolHolder <Jrd::thread_db, MemoryPool> ContextPoolHolder;
class DatabaseContextHolder : public Jrd::ContextPoolHolder
{
public:
explicit DatabaseContextHolder(thread_db* tdbb)
: Jrd::ContextPoolHolder(tdbb, tdbb->getDatabase()->dbb_permanent),
savedTdbb(tdbb)
{
savedTdbb->activate();
}
~DatabaseContextHolder()
{
savedTdbb->deactivate();
}
private:
// copying is prohibited
DatabaseContextHolder(const DatabaseContextHolder&);
DatabaseContextHolder& operator=(const DatabaseContextHolder&);
thread_db* const savedTdbb;
};
class BackgroundContextHolder : public ThreadContextHolder, public DatabaseContextHolder,
public Jrd::Attachment::SyncGuard
{
public:
explicit BackgroundContextHolder(Database* dbb, Jrd::Attachment* att, ISC_STATUS* status)
: ThreadContextHolder(dbb, att, status),
DatabaseContextHolder(operator thread_db*()),
Jrd::Attachment::SyncGuard(att)
{}
private:
// copying is prohibited
BackgroundContextHolder(const BackgroundContextHolder&);
BackgroundContextHolder& operator=(const BackgroundContextHolder&);
};
class AsyncContextHolder : public ThreadContextHolder, public DatabaseContextHolder,
public Jrd::Attachment::SyncGuard
{
public:
explicit AsyncContextHolder(Database* dbb, Jrd::Attachment* att = NULL)
: ThreadContextHolder(dbb, att),
DatabaseContextHolder(operator thread_db*()),
Jrd::Attachment::SyncGuard(att, true)
{
if (dbb->dbb_flags & DBB_not_in_use)
{
// usually to be swallowed by the AST, but it allows to skip its execution
Firebird::status_exception::raise(Firebird::Arg::Gds(isc_unavailable));
}
}
private:
// copying is prohibited
AsyncContextHolder(const AsyncContextHolder&);
AsyncContextHolder& operator=(const AsyncContextHolder&);
};
}
2001-05-23 15:26:42 +02:00
2006-07-21 03:35:17 +02:00
#endif // JRD_JRD_H