/* * 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.29 Sean Leyne - Removed obsolete "Netware" port * */ #ifndef JRD_JRD_H #define JRD_JRD_H #include "../jrd/gdsassert.h" #include "../jrd/common.h" #include "../jrd/dsc.h" #include "../jrd/all.h" #include "../jrd/nbak.h" #if defined(UNIX) && defined(SUPERSERVER) #include #endif #include "../include/fb_vector.h" #ifdef DEV_BUILD #define DEBUG if (debug) DBG_supervisor(debug); #define VIO_DEBUG /* remove this for production build */ #define WALW_DEBUG /* remove this for production build */ #else /* PROD */ #define DEBUG #undef VIO_DEBUG #undef WALW_DEBUG #endif #define BUGCHECK(number) ERR_bugcheck (number) #define CORRUPT(number) ERR_corrupt (number) #define IBERROR(number) ERR_error (number) #define BLKCHK(blk, type) if (MemoryPool::blk_type(blk) != (USHORT) (type)) BUGCHECK (147) /* 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 * */ #ifdef DEV_BUILD #define DEV_BLKCHK(blk,type) //#define DEV_BLKCHK(blk,type) if (blk) {BLKCHK (blk, type);} #else #define DEV_BLKCHK(blk,type) /* nothing */ #endif /* Thread data block / IPC related data blocks */ #include "../jrd/thd.h" #include "../jrd/isc.h" /* definition of block types for data allocation in JRD */ #include "../jrd/jrd_blks.h" #include "../include/fb_blk.h" /* the database block, the topmost block in the metadata cache for a database */ #define HASH_SIZE 101 // fwd. decl. class vec; class tdbb; class dbb : private pool_alloc { public: typedef int (*crypt_routine) (char*, void*, int, void*); static dbb* newDbb(MemoryPool& p) { return FB_NEW(p) dbb(p); } // The deleteDbb function MUST be used to delete a dbb object. // The function hides some tricky order of operations. Since the // memory for the vectors in the dbb is allocated out of the dbb's // permanent memory pool, the entire delete() operation needs // to complete _before_ the permanent pool is deleted, or else // risk an aborted engine. static void deleteDbb(dbb *toDelete) { if (toDelete == 0) return; JrdMemoryPool *perm = toDelete->dbb_permanent; delete toDelete; JrdMemoryPool::noDbbDeletePool(perm); } class dbb *dbb_next; /* Next database block in system */ class att *dbb_attachments; /* Active attachments */ struct bcb *dbb_bcb; /* Buffer control block */ vec* dbb_relations; /* relation vector */ vec* dbb_procedures; /* scanned procedures */ struct lck *dbb_lock; /* granddaddy lock */ struct jrd_tra *dbb_sys_trans; /* system transaction */ struct fil *dbb_file; /* files for I/O operations */ struct sdw *dbb_shadow; /* shadow control block */ struct lck *dbb_shadow_lock; /* lock for synchronizing addition of shadows */ SLONG dbb_shadow_sync_count; /* to synchronize changes to shadows */ struct lck *dbb_retaining_lock; /* lock for preserving commit retaining snapshot */ struct plc *dbb_connection; /* connection block */ struct pgc *dbb_pcontrol; /* page control */ class vcl *dbb_t_pages; /* pages number for transactions */ class vcl *dbb_gen_id_pages; /* known pages for gen_id */ struct blf *dbb_blob_filters; /* known blob filters */ struct lls *dbb_modules; /* external function/filter modules */ MUTX_T *dbb_mutexes; /* DBB block mutexes */ WLCK_T *dbb_rw_locks; /* DBB block read/write locks */ REC_MUTX_T dbb_sp_rec_mutex; /* Recursive mutex for accessing/updating stored procedure metadata */ SLONG dbb_sort_size; /* Size of sort space per sort */ UATOM dbb_ast_flags; /* flags modified at AST level */ ULONG dbb_flags; USHORT dbb_ods_version; /* major ODS version number */ USHORT dbb_minor_version; /* minor ODS version number */ USHORT dbb_minor_original; /* minor ODS version at creation */ USHORT dbb_page_size; /* page size */ USHORT dbb_dp_per_pp; /* data pages per pointer page */ USHORT dbb_max_records; /* max record per data page */ USHORT dbb_max_idx; /* max number of indexes on a root page */ USHORT dbb_use_count; /* active count of threads */ USHORT dbb_shutdown_delay; /* seconds until forced shutdown */ USHORT dbb_refresh_ranges; /* active count of refresh ranges */ USHORT dbb_prefetch_sequence; /* sequence to pace frequency of prefetch requests */ USHORT dbb_prefetch_pages; /* prefetch pages per request */ class str *dbb_spare_string; /* random buffer */ class str *dbb_filename; /* filename string */ class str *dbb_encrypt_key; /* encryption key */ JrdMemoryPool* dbb_permanent; JrdMemoryPool* dbb_bufferpool; typedef JrdMemoryPool* pool_ptr; typedef Firebird::vector pool_vec_type; pool_vec_type dbb_pools; /* pools */ USHORT dbb_next_pool_id; vec* dbb_internal; /* internal requests */ vec* dbb_dyn_req; /* internal dyn requests */ struct jrn *dbb_journal; /* journal block */ SLONG dbb_oldest_active; /* Cached "oldest active" transaction */ SLONG dbb_oldest_transaction; /* Cached "oldest interesting" transaction */ SLONG dbb_oldest_snapshot; /* Cached "oldest snapshot" of all active transactions */ SLONG dbb_next_transaction; /* Next transaction id used by NETWARE */ SLONG dbb_attachment_id; /* Next attachment id for ReadOnly DB's */ SLONG dbb_page_incarnation; /* Cache page incarnation counter */ ULONG dbb_page_buffers; /* Page buffers from header page */ EVENT_T dbb_writer_event[1]; /* Event to wake up cache writer */ EVENT_T dbb_writer_event_init[1]; /* Event for initialization cache writer */ EVENT_T dbb_writer_event_fini[1]; /* Event for finalization cache writer */ EVENT_T dbb_reader_event[1]; /* Event to wake up cache reader */ #ifdef GARBAGE_THREAD EVENT_T dbb_gc_event[1]; /* Event to wake up garbage collector */ EVENT_T dbb_gc_event_init[1]; /* Event for initialization garbage collector */ EVENT_T dbb_gc_event_fini[1]; /* Event for finalization garbage collector */ #endif class att *dbb_update_attachment; /* Attachment with update in process */ class btb *dbb_update_que; /* Attachments waiting for update */ class btb *dbb_free_btbs; /* Unused btb blocks */ SLONG dbb_current_memory; SLONG dbb_max_memory; SLONG dbb_reads; SLONG dbb_writes; SLONG dbb_fetches; SLONG dbb_marks; SLONG dbb_last_header_write; /* Transaction id of last header page physical write */ SLONG dbb_flush_cycle; /* Current flush cycle */ SLONG dbb_sweep_interval; /* Transactions between sweep */ SLONG dbb_lock_owner_handle; /* Handle for the lock manager */ USHORT unflushed_writes; /* unflushed writes */ time_t last_flushed_write; /* last flushed write time */ crypt_routine dbb_encrypt; /* External encryption routine */ crypt_routine dbb_decrypt; /* External decryption routine */ class map *dbb_blob_map; /* mapping of blobs for REPLAY */ struct log *dbb_log; /* log file for REPLAY */ Firebird::vector dbb_text_objects; /* intl text type descriptions */ Firebird::vector dbb_charsets; /* intl character set descriptions */ struct wal *dbb_wal; /* WAL handle for WAL API */ struct tpc *dbb_tip_cache; /* cache of latest known state of all transactions in system */ class vcl *dbb_pc_transactions; /* active precommitted transactions */ class BackupManager *backup_manager; /* physical backup manager */ class sym *dbb_hash_table[HASH_SIZE]; /* keep this at the end */ private: dbb(MemoryPool& p) : dbb_pools(1, p, type_dbb), dbb_text_objects(p), dbb_charsets(p) { } ~dbb() { pool_vec_type::iterator itr = dbb_pools.begin(); while (itr != dbb_pools.end()) { if (*itr && *itr == dbb_bufferpool) dbb_bufferpool = 0; if (*itr && *itr != dbb_permanent) JrdMemoryPool::deletePool(*itr); else itr++; } if (dbb_bufferpool) JrdMemoryPool::deletePool(dbb_bufferpool); } // The delete operators are no-oped because the dbb memory is allocated from the // dbb's own permanent pool. That pool has already been released by the dbb // destructor, so the memory has already been released. Hence the operator // delete no-op. void operator delete(void *mem) {} void operator delete[](void *mem) {} dbb(const dbb&); // no impl. const dbb& operator =(const dbb&) { return *this; } }; typedef dbb* DBB; // // bit values for dbb_flags // #define DBB_no_garbage_collect 0x1L #define DBB_damaged 0x2L #define DBB_exclusive 0x4L /* Database is accessed in exclusive mode */ #define DBB_bugcheck 0x8L /* Bugcheck has occurred */ #ifdef GARBAGE_THREAD #define DBB_garbage_collector 0x10L /* garbage collector thread exists */ #define DBB_gc_active 0x20L /* ... and is actively working. */ #define DBB_gc_pending 0x40L /* garbage collection requested */ #endif #define DBB_force_write 0x80L /* Database is forced write */ #define DBB_no_reserve 0x100L /* No reserve space for versions */ #define DBB_add_log 0x200L /* write ahead log has been added */ #define DBB_delete_log 0x400L /* write ahead log has been deleted */ #define DBB_cache_manager 0x800L /* Shared cache manager */ #define DBB_DB_SQL_dialect_3 0x1000L /* database SQL dialect 3 */ #define DBB_read_only 0x2000L /* DB is ReadOnly (RO). If not set, DB is RW */ #define DBB_being_opened_read_only 0x4000L /* DB is being opened RO. If unset, opened as RW */ #define DBB_not_in_use 0x8000L /* DBB to be ignored while attaching */ #define DBB_lck_init_done 0x10000L /* LCK_init() called for the database */ #define DBB_sp_rec_mutex_init 0x20000L /* Stored procedure mutex initialized */ #define DBB_sweep_in_progress 0x40000L /* A database sweep operation is in progress */ #define DBB_security_db 0x80000L /* ISC security database */ #define DBB_sweep_thread_started 0x100000L /* A database sweep thread has been started */ #define DBB_suspend_bgio 0x200000L /* Suspend I/O by background threads */ #define DBB_being_opened 0x400000L /* database is being attached to */ // // dbb_ast_flags // #define DBB_blocking 0x1L // Exclusive mode is blocking #define DBB_get_shadows 0x2L // Signal received to check for new shadows #define DBB_assert_locks 0x4L // Locks are to be asserted #define DBB_shutdown 0x8L // Database is shutdown #define DBB_shut_attach 0x10L // no new attachments accepted #define DBB_shut_tran 0x20L // no new transactions accepted #define DBB_shut_force 0x40L // forced shutdown in progress #define DBB_shutdown_locks 0x80L // Database locks release by shutdown // // Database attachments // #define DBB_read_seq_count 0 #define DBB_read_idx_count 1 #define DBB_update_count 2 #define DBB_insert_count 3 #define DBB_delete_count 4 #define DBB_backout_count 5 #define DBB_purge_count 6 #define DBB_expunge_count 7 #define DBB_max_count 8 // // Database mutexes and read/write locks // #define DBB_MUTX_init_fini 0 // During startup and shutdown #define DBB_MUTX_statistics 1 // Memory size and counts #define DBB_MUTX_replay 2 // Replay logging #define DBB_MUTX_dyn 3 // Dynamic ddl #define DBB_MUTX_cache 4 // Process-private cache management #define DBB_MUTX_clone 5 // Request cloning #define DBB_MUTX_cmp_clone 6 // Compiled request cloning #define DBB_MUTX_flush_count 7 // flush count/time #define DBB_MUTX_max 8 #define DBB_WLCK_pools 0 // Pool manipulation #define DBB_WLCK_files 1 // DB and shadow file manipulation #define DBB_WLCK_max 2 // // Flags to indicate normal internal requests vs. dyn internal requests // #define IRQ_REQUESTS 1 #define DYN_REQUESTS 2 // // Errors during validation - will be returned on info calls // #define VAL_PAG_WRONG_TYPE 0 #define VAL_PAG_CHECKSUM_ERR 1 #define VAL_PAG_DOUBLE_ALLOC 2 #define VAL_PAG_IN_USE 3 #define VAL_PAG_ORPHAN 4 #define VAL_BLOB_INCONSISTENT 5 #define VAL_BLOB_CORRUPT 6 #define VAL_BLOB_TRUNCATED 7 #define VAL_REC_CHAIN_BROKEN 8 #define VAL_DATA_PAGE_CONFUSED 9 #define VAL_DATA_PAGE_LINE_ERR 10 #define VAL_INDEX_PAGE_CORRUPT 11 #define VAL_P_PAGE_LOST 12 #define VAL_P_PAGE_INCONSISTENT 13 #define VAL_REC_DAMAGED 14 #define VAL_REC_BAD_TID 15 #define VAL_REC_FRAGMENT_CORRUPT 16 #define VAL_REC_WRONG_LENGTH 17 #define VAL_INDEX_ROOT_MISSING 18 #define VAL_TIP_LOST 19 #define VAL_TIP_LOST_SEQUENCE 20 #define VAL_TIP_CONFUSED 21 #define VAL_REL_CHAIN_ORPHANS 22 #define VAL_INDEX_MISSING_ROWS 23 #define VAL_INDEX_ORPHAN_CHILD 24 #define VAL_MAX_ERROR 25 // // the attachment block; one is created for each attachment to a database // class att : public pool_alloc { public: /* att() : 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_relation_locks(0), att_bookmarks(0), att_record_locks(0), att_bkm_quick_ref(0), att_lck_quick_ref(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; }*/ class dbb* att_database; // Parent databasea block att* att_next; // Next attachment to database att* att_blocking; // Blocking attachment, if any class usr* att_user; // User identification struct jrd_tra* att_transactions; // Transactions belonging to attachment struct jrd_tra* att_dbkey_trans; // transaction to control db-key scope struct jrd_req* att_requests; // Requests belonging to attachment struct scb* att_active_sorts; // Active sorts struct lck* att_id_lock; // Attachment lock (if any) SLONG att_attachment_id; // Attachment ID SLONG att_lock_owner_handle; // Handle for the lock manager SLONG att_event_session; // Event session id, if any class scl* att_security_class; // security class for database class scl* att_security_classes; // security classes class vcl* att_counts[DBB_max_count]; vec* att_relation_locks; // explicit persistent locks for relations struct bkm* att_bookmarks; // list of bookmarks taken out using this attachment struct lck* att_record_locks; // explicit or implicit record locks taken out during attachment vec* att_bkm_quick_ref; // correspondence table of bookmarks vec* att_lck_quick_ref; // correspondence table of locks ULONG att_flags; // Flags describing the state of the attachment SSHORT att_charset; // user's charset specified in dpb class str* att_lc_messages; // attachment's preference for message natural language struct lck* att_long_locks; // outstanding two phased locks vec* att_compatibility_table; // hash table of compatible locks class vcl* att_val_errors; class str* att_working_directory; // Current working directory is cached class str* att_filename; // alias used to attach the database GDS_TIMESTAMP att_timestamp; // connection date and time }; typedef att* ATT; /* Attachment flags */ #define ATT_no_cleanup 1 // Don't expunge, purge, or garbage collect #define ATT_shutdown 2 // attachment has been shutdown #define ATT_shutdown_notify 4 // attachment has notified client of shutdown #define ATT_shutdown_manager 8 // attachment requesting shutdown #define ATT_lck_init_done 16 // LCK_init() called for the attachment #define ATT_exclusive 32 // attachment wants exclusive database access #define ATT_attach_pending 64 // Indicate attachment is only pending #define ATT_exclusive_pending 128 // Indicate exclusive attachment pending #define ATT_gbak_attachment 256 // Indicate GBAK attachment #define ATT_security_db 512 // Indicates an implicit attachment to the security db #ifdef GARBAGE_THREAD #define ATT_notify_gc 1024 // Notify garbage collector to expunge, purge .. #define ATT_disable_notify_gc 2048 // Temporarily perform own garbage collection #define ATT_garbage_collector 4096 // I'm a garbage collector #define ATT_NO_CLEANUP (ATT_no_cleanup | ATT_notify_gc) #else #define ATT_NO_CLEANUP ATT_no_cleanup #endif #ifdef CANCEL_OPERATION #define ATT_cancel_raise 8192 // Cancel currently running operation #define ATT_cancel_disable 16384 // Disable cancel operations #endif #define ATT_gfix_attachment 32768 // Indicate a GFIX attachment #define ATT_gstat_attachment 65536 // Indicate a GSTAT attachment /* Procedure block */ class jrd_prc : public pool_alloc_rpt { public: USHORT prc_id; // Should be first field because MET_remove_procedure relies on that USHORT prc_flags; USHORT prc_inputs; USHORT prc_outputs; struct jrd_nod *prc_input_msg; struct jrd_nod *prc_output_msg; struct fmt *prc_input_fmt; struct fmt *prc_output_fmt; struct fmt *prc_format; vec* prc_input_fields; /* vector of field blocks */ vec* prc_output_fields; /* vector of field blocks */ struct jrd_req *prc_request; /* compiled procedure request */ class str *prc_security_name; /* pointer to security class name for procedure */ 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) */ struct lck *prc_existence_lock; /* existence lock, if any */ class str *prc_name; /* pointer to ascic name */ USHORT prc_alter_count; /* No. of times the procedure was altered */ }; typedef jrd_prc* JRD_PRC; #define PRC_scanned 1 /* Field expressions scanned */ #define PRC_system 2 #define PRC_obsolete 4 /* Procedure known gonzo */ #define PRC_being_scanned 8 /* New procedure needs dependencies during scan */ #define PRC_blocking 16 /* Blocking someone from dropping procedure */ #define PRC_create 32 /* Newly created */ #define PRC_being_altered 64 /* Procedure is getting altered */ #define PRC_check_existence 128 /* Existence lock released */ #define MAX_PROC_ALTER 64 /* No. of times an in-cache procedure can be altered */ /* Parameter block */ class prm : public pool_alloc_rpt { public: USHORT prm_number; struct dsc prm_desc; TEXT *prm_name; /* pointer to asciiz name */ TEXT prm_string[2]; /* one byte for ALLOC and one for the terminating null */ }; typedef prm* PRM; /* Primary dependencies from all foreign references to relation's primary/unique keys */ typedef struct prim { vec* prim_reference_ids; vec* prim_relations; vec* prim_indexes; } *PRIM; /* Foreign references to other relations' primary/unique keys */ typedef struct frgn { vec* frgn_reference_ids; vec* frgn_relations; vec* frgn_indexes; } *FRGN; // Relation trigger definition typedef struct trig { class str* blr; // BLR code jrd_req* request; // Compiled request. Gets filled on first invocation BOOLEAN compile_in_progress; BOOLEAN sys_trigger; USHORT flags; // Flags as they are in RDB$TRIGGERS table class jrd_rel* relation; // Trigger parent relation class str* name; // Trigger name void compile(tdbb* _tdbb); // Ensure that trigger is compiled BOOLEAN release(tdbb* _tdbb); // Try to free trigger request } *TRIG; typedef Firebird::vector trig_vec; typedef trig_vec* TRIG_VEC; /* Relation block; one is created for each relation referenced in the database, though it is not really filled out until the relation is scanned */ class jrd_rel : public pool_alloc { public: USHORT rel_id; USHORT rel_flags; USHORT rel_current_fmt; /* Current format number */ UCHAR rel_length; /* length of ascii relation name */ struct fmt *rel_current_format; /* Current record format */ TEXT* rel_name; /* pointer to ascii relation name */ vec* rel_formats; /* Known record formats */ TEXT *rel_owner_name; /* pointer to ascii owner */ class vcl *rel_pages; /* vector of pointer page numbers */ vec* rel_fields; /* vector of field blocks */ struct rse *rel_view_rse; /* view record select expression */ class vcx *rel_view_contexts; /* linked list of view contexts */ TEXT *rel_security_name; /* pointer to security class name for relation */ struct ext *rel_file; /* external file name */ SLONG rel_index_root; /* index root page number */ SLONG rel_data_pages; /* count of relation data pages */ vec* rel_gc_rec; /* vector of records for garbage collection */ #ifdef GARBAGE_THREAD struct sbm *rel_gc_bitmap; /* garbage collect bitmap of data page sequences */ #endif USHORT rel_slot_space; /* lowest pointer page with slot space */ USHORT rel_data_space; /* lowest pointer page with data page space */ USHORT rel_use_count; /* requests compiled with relation */ USHORT rel_sweep_count; /* sweep and/or garbage collector threads active */ SSHORT rel_scan_count; /* concurrent sequential scan count */ struct lck *rel_existence_lock; /* existence lock, if any */ struct lck *rel_interest_lock; /* interest lock to ensure compatibility of relation and record locks */ struct lck *rel_record_locking; /* lock to start record locking on relation */ ULONG rel_explicit_locks; /* count of records explicitly locked in relation */ ULONG rel_read_locks; /* count of records read locked in relation (implicit or explicit) */ ULONG rel_write_locks; /* count of records write locked in relation (implicit or explicit) */ ULONG rel_lock_total; /* count of records locked since database first attached */ struct idl *rel_index_locks; /* index existence locks */ struct idb *rel_index_blocks; /* index blocks for caching index info */ trig_vec *rel_pre_erase; /* Pre-operation erase trigger */ trig_vec *rel_post_erase; /* Post-operation erase trigger */ trig_vec *rel_pre_modify; /* Pre-operation modify trigger */ trig_vec *rel_post_modify; /* Post-operation modify trigger */ trig_vec *rel_pre_store; /* Pre-operation store trigger */ trig_vec *rel_post_store; /* Post-operation store trigger */ struct prim rel_primary_dpnds; /* foreign dependencies on this relation's primary key */ struct frgn rel_foreign_refs; /* foreign references to other relations' primary keys */ }; typedef jrd_rel* JRD_REL; #define REL_scanned 1 /* Field expressions scanned (or being scanned) */ #define REL_system 2 #define REL_deleted 4 /* Relation known gonzo */ #define REL_get_dependencies 8 /* New relation needs dependencies during scan */ #define REL_force_scan 16 /* system relation has been updated since ODS change, force a scan */ #define REL_check_existence 32 /* Existence lock released pending drop of relation */ #define REL_blocking 64 /* Blocking someone from dropping relation */ #define REL_sys_triggers 128 /* The relation has system triggers to compile */ #define REL_sql_relation 256 /* Relation defined as sql table */ #define REL_check_partners 512 /* Rescan primary dependencies and foreign references */ #define REL_being_scanned 1024 /* relation scan in progress */ #define REL_sys_trigs_being_loaded 2048 /* System triggers being loaded */ #define REL_deleting 4096 /* relation delete in progress */ /* Field block, one for each field in a scanned relation */ class jrd_fld : public pool_alloc_rpt { public: struct jrd_nod* fld_validation; /* validation clause, if any */ struct jrd_nod* fld_not_null; /* if field cannot be NULL */ struct jrd_nod* fld_missing_value; /* missing value, if any */ struct jrd_nod* fld_computation; /* computation for virtual field */ struct jrd_nod* fld_source; /* source for view fields */ struct jrd_nod* fld_default_value; /* default value, if any */ TEXT * fld_security_name; /* pointer to security class name for field */ struct arr* fld_array; /* array description, if array */ const TEXT* fld_name; /* Field name */ UCHAR fld_length; /* Field name length */ UCHAR fld_string[2]; /* one byte for ALLOC and one for the terminating null */ }; typedef jrd_fld *JRD_FLD; /* Index block to cache index information */ class idb : public pool_alloc { public: struct idb* idb_next; struct jrd_nod* idb_expression; /* node tree for index expression */ struct jrd_req* idb_expression_request; /* request in which index expression is evaluated */ struct dsc idb_expression_desc; /* descriptor for expression result */ struct lck* idb_lock; /* lock to synchronize changes to index */ UCHAR idb_id; }; typedef idb *IDB; /* view context block to cache view aliases */ class vcx: public pool_alloc { public: class vcx *vcx_next; class str *vcx_context_name; class str *vcx_relation_name; USHORT vcx_context; }; typedef vcx *VCX; /* general purpose vector */ template class vec_base : protected pool_alloc { public: typedef typename Firebird::vector::iterator iterator; static vec_base* newVector(MemoryPool& p, int len) { return FB_NEW(p) vec_base(p, len); } static vec_base* newVector(MemoryPool& p, const vec_base& base) { return FB_NEW(p) vec_base(p, base); } ULONG count() const { return vector.size(); } T& operator[](size_t index) { return vector[index]; } const T& operator[](size_t index) const { return vector[index]; } iterator begin() { return vector.begin(); } iterator end() { return vector.end(); } void clear() { vector.clear(); } void prepend(int n) { vector.insert(vector.begin(), n); } // T* memPtr() { return &*(vector.begin()); } T* memPtr() { return &vector[0]; } void resize(size_t n, T val = T()) { vector.resize(n, val); } void operator delete(void *mem) { MemoryPool::globalFree(mem); } protected: vec_base(MemoryPool& p, int len) : vector(len, p, TYPE) {} vec_base(MemoryPool& p, const vec_base& base) : vector(p, TYPE) { vector = base.vector; } private: Firebird::vector vector; }; class vec : public vec_base { public: static vec* newVector(MemoryPool& p, int len) { return FB_NEW(p) vec(p, len); } static vec* newVector(MemoryPool& p, const vec& base) { return FB_NEW(p) vec(p, base); } static vec* newVector(MemoryPool& p, vec* base, int len) { if (!base) base = FB_NEW(p) vec(p, len); else if (len > (int) base->count()) base->resize(len); return base; } private: vec(MemoryPool& p, int len) : vec_base(p, len) {} vec(MemoryPool& p, const vec& base) : vec_base(p, base) {} }; typedef vec* VEC; class vcl : public vec_base { public: static vcl* newVector(MemoryPool& p, int len) { return FB_NEW(p) vcl(p, len); } 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; } private: vcl(MemoryPool& p, int len) : vec_base(p, len) {} vcl(MemoryPool& p, const vcl& base) : vec_base(p, base) {} }; typedef vcl* VCL; #define TEST_VECTOR(vector,number) ((vector && number < vector->vec_count) ? \ vector->vec_object [number] : NULL) // // general purpose queue // typedef struct que { struct que* que_forward; struct que* que_backward; } *QUE; /* symbol definitions */ typedef enum sym_t { SYM_rel, /* relation block */ SYM_fld, /* field block */ SYM_fun, /* UDF function block */ SYM_prc, /* stored procedure block */ SYM_sql, /* SQL request cache block */ SYM_blr, /* BLR request cache block */ SYM_label /* CVC: I need to track labels if LEAVE is implemented. */ } SYM_T; class sym : public pool_alloc { public: TEXT *sym_string; /* address of asciz string */ /* USHORT sym_length; *//* length of asciz string */ SYM_T sym_type; /* symbol type */ BLK sym_object; /* general pointer to object */ sym *sym_collision; /* collision pointer */ sym *sym_homonym; /* homonym pointer */ }; typedef sym *SYM; /* Random string block -- jack of all kludges */ class str : public pool_alloc_rpt { public: USHORT str_length; UCHAR str_data[2]; /* one byte for ALLOC and one for the NULL */ static bool extend(str*& s, size_t new_len) { fb_assert(s); MemoryPool* pPool = MemoryPool::blk_pool(s); fb_assert(pPool); if (!pPool) { return false; // runtime safety } // TMN: Note that this violates "common sense" and should be fixed. str* res = FB_NEW_RPT(*pPool, new_len+1) str; res->str_length = new_len; memcpy(res->str_data, s->str_data, s->str_length+1); str* old = s; s = res; delete old; return s != 0; } }; typedef str *STR; // // Transaction element block // typedef struct teb { ATT *teb_database; int teb_tpb_length; UCHAR *teb_tpb; } TEB; /* Blocking Thread Block */ class btb : public pool_alloc { public: btb *btb_next; SLONG btb_thread_id; }; typedef btb *BTB; /* Lock levels */ #define LCK_none 0 #define LCK_null 1 #define LCK_SR 2 #define LCK_PR 3 #define LCK_SW 4 #define LCK_PW 5 #define LCK_EX 6 #define LCK_read LCK_PR #define LCK_write LCK_EX #define LCK_WAIT TRUE #define LCK_NO_WAIT FALSE /* Lock query data aggregates */ #define LCK_MIN 1 #define LCK_MAX 2 #define LCK_CNT 3 #define LCK_SUM 4 #define LCK_AVG 5 #define LCK_ANY 6 /* Window block for loading cached pages into */ typedef struct win { SLONG win_page; struct pag* win_buffer; struct jrd_exp* win_expanded_buffer; struct bdb* win_bdb; SSHORT win_scans; USHORT win_flags; } WIN; #define WIN_large_scan 1 /* large sequential scan */ #define WIN_secondary 2 /* secondary stream */ #define WIN_garbage_collector 4 /* garbage collector's window */ #define WIN_garbage_collect 8 /* scan left a page for garbage collector */ /* define used for journaling start transaction */ #define MOD_START_TRAN 100 /* Thread specific database block */ typedef struct tdbb { struct thdd tdbb_thd_data; dbb* tdbb_database; att* tdbb_attachment; struct jrd_tra* tdbb_transaction; struct jrd_req* tdbb_request; JrdMemoryPool* tdbb_default; ISC_STATUS* tdbb_status_vector; void* tdbb_setjmp; USHORT tdbb_inhibit; /* Inhibit context switch if non-zero */ SSHORT tdbb_quantum; /* Cycles remaining until voluntary schedule */ USHORT tdbb_flags; struct iuo tdbb_mutexes; struct iuo tdbb_rw_locks; struct iuo tdbb_pages; #if defined(UNIX) && defined(SUPERSERVER) #if defined(FREEBSD) sigjmp_buf tdbb_sigsetjmp; #else jmp_buf tdbb_sigsetjmp; #endif #endif } *TDBB; #define TDBB_sweeper 1 /* Thread sweeper or garbage collector */ #define TDBB_no_cache_unwind 2 /* Don't unwind page buffer cache */ #define TDBB_prc_being_dropped 4 /* Dropping a procedure */ #define TDBB_set_backup_state 8 /* Setting state for backup lock */ #define TDBB_backup_merge 16 /* Merging changes from difference file */ /* List of internal database handles */ typedef struct ihndl { struct ihndl* ihndl_next; void* ihndl_object; } *IHNDL; /* Threading macros */ #ifdef GET_THREAD_DATA #undef GET_THREAD_DATA #endif #ifdef V4_THREADING #define PLATFORM_GET_THREAD_DATA ((TDBB) THD_get_specific()) #endif /* RITTER - changed HP10 to HPUX in the expression below */ #ifdef MULTI_THREAD #if (defined SOLARIS_MT || defined WIN_NT || \ defined HPUX || defined LINUX || defined DARWIN || defined FREEBSD ) #define PLATFORM_GET_THREAD_DATA ((TDBB) THD_get_specific()) #endif #endif #ifndef PLATFORM_GET_THREAD_DATA extern TDBB gdbb; #define PLATFORM_GET_THREAD_DATA (gdbb) #endif /* Define GET_THREAD_DATA off the platform specific version. * 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 TDBB. * AND it has a non-NULL tdbb_database field, * 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 tdbb_database set up. */ #ifdef DEV_BUILD #define GET_THREAD_DATA (((PLATFORM_GET_THREAD_DATA) && \ (((THDD)(PLATFORM_GET_THREAD_DATA))->thdd_type == THDD_TYPE_TDBB) && \ (((TDBB)(PLATFORM_GET_THREAD_DATA))->tdbb_database)) \ ? ((MemoryPool::blk_type(((TDBB)(PLATFORM_GET_THREAD_DATA))->tdbb_database) == type_dbb) \ ? (PLATFORM_GET_THREAD_DATA) \ : (BUGCHECK (147), (PLATFORM_GET_THREAD_DATA))) \ : (PLATFORM_GET_THREAD_DATA)) #define CHECK_DBB(dbb) fb_assert ((dbb) && (MemoryPool::blk_type(dbb) == type_dbb) && ((dbb)->dbb_permanent->verify_pool())) #define CHECK_TDBB(tdbb) fb_assert ((tdbb) && \ (((THDD)(tdbb))->thdd_type == THDD_TYPE_TDBB) && \ ((!(tdbb)->tdbb_database)||MemoryPool::blk_type((tdbb)->tdbb_database) == type_dbb)) #else /* PROD_BUILD */ #define GET_THREAD_DATA (PLATFORM_GET_THREAD_DATA) #define CHECK_TDBB(tdbb) /* nothing */ #define CHECK_DBB(dbb) /* nothing */ #endif #define GET_DBB (((TDBB) (GET_THREAD_DATA))->tdbb_database) /*-------------------------------------------------------------------------* * macros used to set tdbb and dbb pointers when there are not set already * *-------------------------------------------------------------------------*/ #define SET_TDBB(tdbb) if ((tdbb) == NULL) { (tdbb) = GET_THREAD_DATA; }; CHECK_TDBB (tdbb) #define SET_DBB(dbb) if ((dbb) == NULL) { (dbb) = GET_DBB; }; CHECK_DBB(dbb); #ifdef V4_THREADING #define V4_JRD_MUTEX_LOCK(mutx) JRD_mutex_lock (mutx) #define V4_JRD_MUTEX_UNLOCK(mutx) JRD_mutex_unlock (mutx) #define V4_JRD_RW_LOCK_LOCK(wlck,type) JRD_wlck_lock (wlck, type) #define V4_JRD_RW_LOCK_UNLOCK(wlck) JRD_wlck_unlock (wlck) // BRS. 03/23/2003 // Those empty defines was substituted with #ifdef V4_THREADING //#else //#define V4_JRD_MUTEX_LOCK(mutx) //#define V4_JRD_MUTEX_UNLOCK(mutx) //#define V4_JRD_RW_LOCK_LOCK(wlck,type) //#define V4_JRD_RW_LOCK_UNLOCK(wlck) #endif #ifdef ANY_THREADING #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; extern IHNDL internal_db_handles; #endif /* REQUESTER */ /* Define the xxx_THREAD_DATA macros. These are needed in the whole component, but they are defined differently for use in jrd.c (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. */ #ifndef JRD_MAIN #ifdef __cplusplus #define SET_THREAD_DATA tdbb = &thd_context;\ MOVE_CLEAR (tdbb, sizeof (*tdbb));\ THD_put_specific (reinterpret_cast(tdbb));\ tdbb->tdbb_thd_data.thdd_type = THDD_TYPE_TDBB #else #define SET_THREAD_DATA tdbb = &thd_context;\ MOVE_CLEAR (tdbb, sizeof (*tdbb));\ THD_put_specific((struct thdd*)tdbb);\ tdbb->tdbb_thd_data.thdd_type = THDD_TYPE_TDBB #endif /* __cplusplus */ #define RESTORE_THREAD_DATA THD_restore_specific() #endif /* !JRD_MAIN */ #endif /* JRD_JRD_H */