8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-27 20:03:03 +01:00
firebird-mirror/src/jrd/jrd.h

894 lines
25 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.
2002-10-30 07:40:58 +01:00
*
2001-05-23 15:26:42 +02:00
*/
#ifndef JRD_JRD_H
#define JRD_JRD_H
2004-03-24 12:06:22 +01:00
#include "../jrd/gdsassert.h"
#include "../jrd/common.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/dsc.h"
2001-12-24 03:51:06 +01:00
#include "../jrd/all.h"
#include "../jrd/btn.h"
#include "../jrd/all.h"
#include "../jrd/jrd_proto.h"
2008-01-16 10:29:37 +01:00
#include "../jrd/val.h"
2003-11-18 14:46:27 +01:00
#if defined(UNIX) && defined(SUPERSERVER)
#include <setjmp.h>
#endif
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/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"
#include "../jrd/RandomGenerator.h"
#include "../jrd/os/guid.h"
#include "../jrd/sbm.h"
2001-05-23 15:26:42 +02:00
#ifdef DEV_BUILD
#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
2001-05-23 15:26:42 +02:00
#define DEBUG
#undef VIO_DEBUG
#endif
#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)
2001-12-24 03:51:06 +01:00
#define BLKCHK(blk, type) if (MemoryPool::blk_type(blk) != (USHORT) (type)) BUGCHECK (147)
2001-05-23 15:26:42 +02:00
/* DEV_BLKCHK is used for internal consistency checking - where
* the performance hit in production build isn't desired.
* (eg: scatter this everywhere)
*
* This causes me a problem DEV_BLKCHK fails when the data seems valid
* After talking to John this could be because the memory is from the local
* stack rather than the heap. However I found to continue I needed to
* turn it off by dfining the macro to be empty. But In thinking about
* it I think that it would be more helful for a mode where these extra
* DEV checks just gave warnings rather than being fatal.
* MOD 29-July-2002
*
2001-05-23 15:26:42 +02:00
*/
#ifdef DEV_BUILD
#define DEV_BLKCHK(blk,type)
2004-11-24 10:22:07 +01:00
//#define DEV_BLKCHK(blk, type) if (blk) {BLKCHK (blk, type);}
2001-05-23 15:26:42 +02:00
#else
#define DEV_BLKCHK(blk, type) // nothing
2001-05-23 15:26:42 +02:00
#endif
// Thread data block / IPC related data blocks
2008-01-16 10:29:37 +01:00
#include "../jrd/ThreadData.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/isc.h"
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-12-24 03:51:06 +01:00
#include "../jrd/jrd_blks.h"
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 Jrd {
//const int HASH_SIZE = 509;
2001-12-28 07:31:38 +01:00
// fwd. decl.
//class vec;
class thread_db;
class Attachment;
class jrd_tra;
class jrd_req;
class Lock;
class jrd_file;
2004-03-30 06:10:52 +02:00
class Format;
class jrd_nod;
class BufferControl;
class SparseBitmap;
class jrd_rel;
class ExternalFile;
class ViewContext;
class IndexBlock;
class IndexLock;
class ArrayField;
//class PageControl;
class Symbol;
class UserId;
struct sort_context;
class RecordSelExpr;
class SecurityClass;
class vcl;
class TextType;
//class jrd_prc;
class Parameter;
class jrd_fld;
2008-02-28 14:48:16 +01:00
class dsql_dbb;
2001-12-28 07:31:38 +01:00
// The database block, the topmost block in the metadata
// cache for a database
// Relation trigger definition
class Trigger {
public:
Firebird::HalfStaticArray<UCHAR, 128> blr; // BLR code
bid dbg_blob_id; // RDB$DEBUG_INFO
jrd_req* request; // Compiled request. Gets filled on first invocation
bool compile_in_progress;
bool sys_trigger;
UCHAR type; // Trigger type
USHORT flags; // Flags as they are in RDB$TRIGGERS table
jrd_rel* relation; // Trigger parent relation
Firebird::MetaName name; // Trigger name
void compile(thread_db*); // Ensure that trigger is compiled
void release(thread_db*); // Try to free trigger request
explicit Trigger(MemoryPool& p) : blr(p), name(p)
{ dbg_blob_id.clear(); }
};
2001-12-24 03:51:06 +01:00
//
// Database attachments
//
2004-04-29 16:51:02 +02:00
const int DBB_read_seq_count = 0;
const int DBB_read_idx_count = 1;
const int DBB_update_count = 2;
const int DBB_insert_count = 3;
const int DBB_delete_count = 4;
const int DBB_backout_count = 5;
const int DBB_purge_count = 6;
const int DBB_expunge_count = 7;
const int DBB_max_count = 8;
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
//
2006-05-01 06:42:10 +02:00
// Database mutexes
2001-12-24 03:51:06 +01:00
//
2008-01-16 10:29:37 +01:00
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;
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_MAX_ERROR = 26;
2001-05-23 15:26:42 +02:00
struct DSqlCacheItem
{
Lock* lock;
bool locked;
bool obsolete;
};
2001-12-24 03:51:06 +01:00
//
// the attachment block; one is created for each attachment to a database
//
class Attachment : public pool_alloc<type_att>
2001-12-24 03:51:06 +01:00
{
public:
explicit Attachment(Database* dbb);
2007-06-15 11:28:56 +02:00
~Attachment();
/* Attachment()
2001-12-24 03:51:06 +01:00
: att_database(0),
att_next(0),
att_blocking(0),
att_user(0),
att_transactions(0),
att_dbkey_trans(0),
att_requests(0),
att_active_sorts(0),
att_id_lock(0),
att_attachment_id(0),
att_lock_owner_handle(0),
att_event_session(0),
att_security_class(0),
att_security_classes(0),
att_flags(0),
att_charset(0),
att_lc_messages(0),
att_long_locks(0),
att_compatibility_table(0),
att_val_errors(0),
att_working_directory(0)
{
att_counts[0] = 0;
}*/
2001-12-24 03:51:06 +01:00
2006-07-21 03:35:17 +02:00
Database* att_database; // Parent databasea block
Attachment* att_next; // Next attachment to database
Attachment* att_blocking; // Blocking attachment, if any
UserId* att_user; // User identification
jrd_tra* att_transactions; // Transactions belonging to attachment
jrd_tra* att_dbkey_trans; // transaction to control db-key scope
jrd_req* att_requests; // Requests belonging to attachment
sort_context* att_active_sorts; // Active sorts
Lock* att_id_lock; // Attachment lock (if any)
SLONG att_attachment_id; // Attachment ID
const ULONG att_lock_owner_id; // ID for the lock manager
2006-07-21 03:35:17 +02:00
SLONG att_lock_owner_handle; // Handle for the lock manager
SLONG att_event_session; // Event session id, if any
SecurityClass* att_security_class; // security class for database
SecurityClass* att_security_classes; // security classes
vcl* att_counts[DBB_max_count];
RuntimeStatistics att_stats;
2006-07-21 03:35:17 +02:00
ULONG att_flags; // Flags describing the state of the attachment
SSHORT att_charset; // user's charset specified in dpb
// The following data member is set but never used, so the DPB to set the location of a
// customized firebird.msg file doesn't work; the only way is to use an env var.
Firebird::PathName att_lc_messages; // attachment's preference for message natural language
2006-07-21 03:35:17 +02:00
Lock* att_long_locks; // outstanding two phased locks
vec<Lock*>* att_compatibility_table; // hash table of compatible locks
vcl* att_val_errors;
Firebird::PathName att_working_directory; // Current working directory is cached
Firebird::PathName att_filename; // alias used to attach the database
2006-07-21 03:35:17 +02:00
Firebird::TimeStamp att_timestamp; // Connection date and time
Firebird::StringMap att_context_vars; // Context variables for the connection
Firebird::string att_network_protocol; // Network protocol used by client for connection
Firebird::string att_remote_address; // Protocol-specific addess of remote client
SLONG att_remote_pid; // Process id of remote client
Firebird::PathName att_remote_process; // Process name of remote client
RandomGenerator att_random_generator; // Random bytes generator
2006-07-12 17:13:22 +02:00
#ifndef SUPERSERVER
2006-07-21 03:35:17 +02:00
Lock* att_temp_pg_lock; // temporary pagespace ID lock
#endif
2006-07-12 17:13:22 +02:00
Firebird::GenericMap<Firebird::Pair<Firebird::Left<
Firebird::string, DSqlCacheItem> > > att_dsql_cache; // DSQL cache locks
2008-02-28 14:48:16 +01:00
dsql_dbb* att_dsql_instance;
bool locksmith() const;
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
2006-07-21 03:35:17 +02:00
// Attachment flags
2001-05-23 15:26:42 +02:00
2004-05-04 00:42:47 +02:00
const ULONG ATT_no_cleanup = 1; // Don't expunge, purge, or garbage collect
const ULONG ATT_shutdown = 2; // attachment has been shutdown
//const ULONG ATT_shutdown_notify = 4; // attachment has notified client of shutdown
2004-05-04 00:42:47 +02:00
const ULONG ATT_shutdown_manager = 8; // attachment requesting shutdown
const ULONG ATT_lck_init_done = 16; // LCK_init() called for the attachment
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
2007-04-09 18:15:29 +02:00
2001-05-23 15:26:42 +02:00
#ifdef GARBAGE_THREAD
2004-05-04 00:42:47 +02:00
const ULONG ATT_notify_gc = 1024; // Notify garbage collector to expunge, purge ..
const ULONG ATT_disable_notify_gc = 2048; // Temporarily perform own garbage collection
const ULONG ATT_garbage_collector = 4096; // I'm a garbage collector
2001-05-23 15:26:42 +02:00
2004-05-04 00:42:47 +02:00
const ULONG ATT_NO_CLEANUP = (ATT_no_cleanup | ATT_notify_gc);
2001-05-23 15:26:42 +02:00
#else
2004-05-04 00:42:47 +02:00
const ULONG ATT_NO_CLEANUP = ATT_no_cleanup;
2001-05-23 15:26:42 +02:00
#endif
2004-05-04 00:42:47 +02:00
const ULONG ATT_cancel_raise = 8192; // Cancel currently running operation
const ULONG ATT_cancel_disable = 16384; // Disable cancel operations
const ULONG ATT_gfix_attachment = 32768; // Indicate a GFIX attachment
const ULONG ATT_gstat_attachment = 65536; // Indicate a GSTAT attachment
const ULONG ATT_no_db_triggers = 131072; // Don't execute database triggers
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 pool_alloc<type_prc>
2001-12-24 03:51:06 +01:00
{
2006-07-21 03:35:17 +02:00
public:
USHORT prc_id;
2001-05-23 15:26:42 +02:00
USHORT prc_flags;
USHORT prc_inputs;
2004-01-16 13:59:16 +01:00
USHORT prc_defaults;
2001-05-23 15:26:42 +02:00
USHORT prc_outputs;
2008-02-14 13:21:35 +01:00
//jrd_nod* prc_input_msg; // It's set once by met.epp and never used.
jrd_nod* prc_output_msg;
2004-03-30 06:10:52 +02:00
Format* prc_input_fmt;
Format* prc_output_fmt;
Format* prc_format;
2006-07-21 03:35:17 +02:00
vec<Parameter*>* prc_input_fields; // vector of field blocks
vec<Parameter*>* prc_output_fields; // vector of field blocks
prc_t prc_type; // procedure type
jrd_req* prc_request; // compiled procedure request
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
Firebird::MetaName prc_security_name; // security class name for procedure
Firebird::MetaName prc_name; // ascic name
USHORT prc_alter_count; // No. of times the procedure was altered
2006-07-21 03:35:17 +02:00
public:
2004-03-31 20:03:51 +02:00
explicit jrd_prc(MemoryPool& p) : prc_security_name(p), prc_name(p) {}
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_system = 2; // Set in met.epp, never tested.
2006-07-21 03:35:17 +02:00
const USHORT PRC_obsolete = 4; // Procedure known gonzo
const USHORT PRC_being_scanned = 8; // New procedure needs dependencies during scan
//const USHORT PRC_blocking = 16; // Blocking someone from dropping procedure
const USHORT PRC_create = 32; // Newly created. Set in met.epp, never tested or disabled.
2006-07-21 03:35:17 +02:00
const USHORT PRC_being_altered = 64; // 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
// so dfw.epp:modify_procedure() can flip procedure body without
// invalidating procedure pointers from other parts of metadata cache
2006-07-21 03:35:17 +02:00
const USHORT PRC_check_existence = 128; // 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;
jrd_nod* prm_default_value;
2006-07-21 03:35:17 +02:00
Firebird::MetaName prm_name; // asciiz name
//public:
explicit Parameter(MemoryPool& p) : prm_name(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;
2006-07-21 03:35:17 +02:00
jrd_nod* idb_expression; // node tree for index expression
jrd_req* idb_expression_request; // request in which index expression is evaluated
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
2006-07-21 03:35:17 +02:00
// general purpose vector
2001-12-24 03:51:06 +01:00
template <class T, USHORT TYPE = type_vec>
class vec_base : protected pool_alloc<TYPE>
{
public:
typedef typename Firebird::Array<T>::iterator iterator;
typedef typename Firebird::Array<T>::const_iterator const_iterator;
/*
2001-12-24 03:51:06 +01:00
static vec_base* newVector(MemoryPool& p, int len)
{
return FB_NEW(p) vec_base<T, TYPE>(p, len);
}
2001-12-24 03:51:06 +01:00
static vec_base* newVector(MemoryPool& p, const vec_base& base)
{
return FB_NEW(p) vec_base<T, TYPE>(p, base);
}
*/
2001-12-24 03:51:06 +01:00
// CVC: This should be size_t instead of ULONG for maximum portability.
ULONG count() const { return v.getCount(); }
T& operator[](size_t index) { return v[index]; }
const T& operator[](size_t index) const { return v[index]; }
2001-12-24 03:51:06 +01:00
iterator begin() { return v.begin(); }
iterator end() { return v.end(); }
const_iterator begin() const { return v.begin(); }
const_iterator end() const { return v.end(); }
2001-12-24 03:51:06 +01:00
void clear() { v.clear(); }
//void prepend(int n) { v.insert(v.begin(), n); }
2001-12-24 03:51:06 +01:00
// T* memPtr() { return &*(v.begin()); }
T* memPtr() { return &v[0]; }
2001-12-24 03:51:06 +01:00
void resize(size_t n, T val = T()) { v.resize(n, val); }
2001-12-24 03:51:06 +01:00
2003-12-22 11:00:59 +01:00
void operator delete(void* mem) { MemoryPool::globalFree(mem); }
2001-12-24 03:51:06 +01:00
protected:
vec_base(MemoryPool& p, int len)
: v(p, len) { v.resize(len); }
2001-12-24 03:51:06 +01:00
vec_base(MemoryPool& p, const vec_base& base)
: v(p) { v = base.v; }
2001-12-24 03:51:06 +01:00
private:
Firebird::Array<T> v;
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
template <typename T>
class vec : public vec_base<T, type_vec>
2001-12-24 03:51:06 +01:00
{
public:
2006-07-21 03:35:17 +02:00
static vec* newVector(MemoryPool& p, int len)
{
return FB_NEW(p) vec<T>(p, len);
}
2006-07-21 03:35:17 +02:00
static vec* newVector(MemoryPool& p, const vec& base)
{
return FB_NEW(p) vec<T>(p, base);
}
static vec* newVector(MemoryPool& p, vec* base, int len)
{
if (!base)
base = FB_NEW(p) vec<T>(p, len);
else if (len > (int) base->count())
base->resize(len);
return base;
}
2001-12-24 03:51:06 +01:00
private:
2006-07-21 03:35:17 +02:00
vec(MemoryPool& p, int len) : vec_base<T, type_vec>(p, len) {}
vec(MemoryPool& p, const vec& base) : vec_base<T, type_vec>(p, base) {}
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
class vcl : public vec_base<SLONG, type_vcl>
{
public:
2006-07-21 03:35:17 +02:00
static vcl* newVector(MemoryPool& p, int len)
{
return FB_NEW(p) vcl(p, len);
}
2006-07-21 03:35:17 +02:00
static vcl* newVector(MemoryPool& p, const vcl& base)
{
return FB_NEW(p) vcl(p, base);
}
static vcl* newVector(MemoryPool& p, vcl* base, int len)
{
if (!base)
base = FB_NEW(p) vcl(p, len);
else if (len > (int) base->count())
base->resize(len);
return base;
}
2001-12-24 03:51:06 +01:00
private:
2006-07-21 03:35:17 +02:00
vcl(MemoryPool& p, int len) : vec_base<SLONG, type_vcl>(p, len) {}
vcl(MemoryPool& p, const vcl& base) : vec_base<SLONG, type_vcl>(p, base) {}
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
//#define TEST_VECTOR(vector, number) ((vector && number < vector->count()) ?
// (*vector)[number] : NULL)
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
//
// Transaction element block
//
2004-05-24 19:31:47 +02:00
struct teb {
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
2004-05-24 19:31:47 +02:00
struct win {
2006-05-22 00:07:35 +02:00
PageNumber win_page;
Ods::pag* win_buffer;
exp_index_buf* win_expanded_buffer;
class BufferDesc* win_bdb;
2001-05-23 15:26:42 +02:00
SSHORT win_scans;
USHORT win_flags;
2006-05-22 00:07:35 +02:00
// explicit win(SLONG wp) : win_page(wp), win_flags(0) {}
explicit win(const PageNumber& wp) : win_page(wp), win_flags(0) {}
win(const USHORT pageSpaceID, const SLONG pageNum) :
win_page(pageSpaceID, pageNum), win_flags(0) {}
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
{
2006-05-22 00:07:35 +02:00
win_for_array() : win(DB_PAGE_SPACE, -1) {}
};
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:
2008-01-29 11:11:52 +01:00
MemoryPool* tdbb_default;
void setDefaultPool(MemoryPool* p)
{
tdbb_default = 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;
public:
2008-01-16 10:29:37 +01:00
explicit thread_db(ISC_STATUS* status)
: ThreadData(ThreadData::tddDBB)
{
tdbb_default = NULL;
database = NULL;
attachment = NULL;
transaction = NULL;
request = NULL;
tdbb_quantum = QUANTUM;
tdbb_flags = 0;
2006-05-22 00:07:35 +02:00
tdbb_temp_attid = tdbb_temp_traid = 0;
reqStat = traStat = attStat = dbbStat = RuntimeStatistics::getDummy();
2008-01-16 10:29:37 +01:00
tdbb_status_vector = status;
tdbb_status_vector[0] = isc_arg_gds;
tdbb_status_vector[1] = FB_SUCCESS;
tdbb_status_vector[2] = isc_arg_end;
}
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_attid; // current temporary table scope
SLONG tdbb_temp_traid; // current temporary table scope
2003-10-03 12:14:05 +02:00
#if defined(UNIX) && defined(SUPERSERVER)
2006-07-21 03:35:17 +02:00
sigjmp_buf tdbb_sigsetjmp;
#endif
2008-01-29 11:11:52 +01:00
MemoryPool* getDefaultPool()
{
return tdbb_default;
}
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)
{
database = val;
dbbStat = val ? &val->dbb_stats : RuntimeStatistics::getDummy();
}
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)
{
attachment = val;
attStat = val ? &val->att_stats : RuntimeStatistics::getDummy();
}
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);
void bumpStats(const RuntimeStatistics::StatType index)
{
reqStat->bumpValue(index);
traStat->bumpValue(index);
attStat->bumpValue(index);
dbbStat->bumpValue(index);
}
};
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
const USHORT TDBB_prc_being_dropped = 4; // Dropping a procedure
const USHORT TDBB_backup_write_locked = 8; // BackupManager has write lock on LCK_backup_database
2007-05-02 08:57:18 +02:00
const USHORT TDBB_stack_trace_done = 16; // PSQL stack trace is added into status-vector
const USHORT TDBB_shutdown_manager = 32; // Server shutdown thread
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
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)
: 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;
};
2004-05-09 07:48:33 +02:00
// duplicate context of firebird string to store in jrd_nod::nod_arg
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, 0
#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, 0
#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));
}
// Used in string convsersion calls
typedef Firebird::HalfStaticArray<UCHAR, 256> MoveBuffer;
} //namespace Jrd
2006-07-21 03:35:17 +02:00
// Lock levels
#include "../lock/lock.h"
2006-07-21 03:35:17 +02:00
// Random string block -- as long as impure areas don't have
// constructors and destructors, the need this varying string
class VaryingString : public pool_alloc_rpt<SCHAR, type_str>
{
public:
USHORT str_length;
UCHAR str_data[2]; // one byte for ALLOC and one for the NULL
};
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
* track down cases of no "PUT_THREAD_DATA" on the NLM.
*
* This allows for NULL thread data (which might be an error by itself)
* If there is thread data,
* AND it is tagged as being a thread_db.
* 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"
inline Jrd::thread_db* JRD_get_thread_data() {
ThreadData* p1 = ThreadData::getSpecific();
if (p1 && p1->getType() == ThreadData::tddDBB)
{
Jrd::thread_db* p2 = (Jrd::thread_db*)p1;
if (p2->getDatabase() && MemoryPool::blk_type(p2->getDatabase()) != type_dbb)
{
BUGCHECK(147);
}
}
return (Jrd::thread_db*) p1;
}
inline void CHECK_TDBB(const Jrd::thread_db* tdbb) {
fb_assert(tdbb && (tdbb->getType() == ThreadData::tddDBB) &&
(!tdbb->getDatabase() ||
MemoryPool::blk_type(tdbb->getDatabase()) == type_dbb));
}
inline void CHECK_DBB(const Jrd::Database* dbb) {
fb_assert(dbb && MemoryPool::blk_type(dbb) == type_dbb);
}
2008-01-16 10:29:37 +01:00
#else // PROD_BUILD
inline Jrd::thread_db* JRD_get_thread_data() {
return (Jrd::thread_db*) ThreadData::getSpecific();
}
inline void CHECK_DBB(const Jrd::Database* dbb) {
}
inline void CHECK_TDBB(const Jrd::thread_db* tdbb) {
}
2001-05-23 15:26:42 +02:00
#endif
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
*-------------------------------------------------------------------------*/
inline void SET_TDBB(Jrd::thread_db* &tdbb) {
if (tdbb == NULL) {
tdbb = JRD_get_thread_data();
}
CHECK_TDBB(tdbb);
}
2004-05-24 19:31:47 +02: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-01-29 11:11:52 +01:00
typedef Firebird::SubsystemContextPoolHolder <Jrd::thread_db, MemoryPool>
ContextPoolHolder;
}
2001-05-23 15:26:42 +02:00
2006-07-21 03:35:17 +02:00
#endif // JRD_JRD_H