1/*
2 * PROGRAM: JRD access method
3 * MODULE: jrd.h
4 * DESCRIPTION: Common descriptions
5 *
6 * The contents of this file are subject to the Interbase Public
7 * License Version 1.0 (the "License"); you may not use this file
8 * except in compliance with the License. You may obtain a copy
9 * of the License at http://www.Inprise.com/IPL.html
10 *
11 * Software distributed under the License is distributed on an
12 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
13 * or implied. See the License for the specific language governing
14 * rights and limitations under the License.
15 *
16 * The Original Code was created by Inprise Corporation
17 * and its predecessors. Portions created by Inprise Corporation are
18 * Copyright (C) Inprise Corporation.
19 *
20 * All Rights Reserved.
21 * Contributor(s): ______________________________________.
22 *
23 * 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "DecOSF" port
24 *
25 * 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
26 * Claudio Valderrama C.
27 * Adriano dos Santos Fernandes
28 *
29 */
30
31#ifndef JRD_JRD_H
32#define JRD_JRD_H
33
34#include "../common/gdsassert.h"
35#include "../common/dsc.h"
36#include "../jrd/err_proto.h"
37#include "../jrd/jrd_proto.h"
38#include "../jrd/obj.h"
39#include "../jrd/val.h"
40
41#include "../common/classes/fb_atomic.h"
42#include "../common/classes/fb_string.h"
43#include "../common/classes/MetaName.h"
44#include "../common/classes/NestConst.h"
45#include "../common/classes/array.h"
46#include "../common/classes/objects_array.h"
47#include "../common/classes/stack.h"
48#include "../common/classes/timestamp.h"
49#include "../common/classes/GenericMap.h"
50#include "../common/classes/Synchronize.h"
51#include "../common/utils_proto.h"
52#include "../common/StatusHolder.h"
53#include "../jrd/RandomGenerator.h"
54#include "../common/os/guid.h"
55#include "../jrd/sbm.h"
56#include "../jrd/scl.h"
57#include "../jrd/Routine.h"
58#include "../jrd/ExtEngineManager.h"
59#include "../jrd/Attachment.h"
60#include "firebird/Provider.h"
61
62#ifdef DEV_BUILD
63//#define DEBUG if (debug) DBG_supervisor(debug);
64#else // PROD
65//#define DEBUG
66#endif
67#define DEBUG
68
69#define BUGCHECK(number) ERR_bugcheck (number, __FILE__, __LINE__)
70#define CORRUPT(number) ERR_corrupt (number)
71#define IBERROR(number) ERR_error (number)
72
73
74#define BLKCHK(blk, type) if (!blk->checkHandle()) BUGCHECK(147)
75
76#define DEV_BLKCHK(blk, type) do { } while (false) // nothing
77
78
79// Thread data block / IPC related data blocks
80#include "../common/ThreadData.h"
81
82// Definition of block types for data allocation in JRD
83#include "../include/fb_blk.h"
84
85#include "../jrd/blb.h"
86
87// Definition of DatabasePlugins
88#include "../jrd/flu.h"
89
90#include "../jrd/pag.h"
91
92#include "../jrd/RuntimeStatistics.h"
93#include "../jrd/Database.h"
94#include "../jrd/lck.h"
95
96// Error codes
97#include "gen/iberror.h"
98
99struct dsc;
100
101namespace EDS {
102 class Connection;
103}
104
105namespace Jrd {
106
107const int QUANTUM = 100; // Default quantum
108const int SWEEP_QUANTUM = 10; // Make sweeps less disruptive
109const unsigned MAX_CALLBACKS = 50;
110
111// fwd. decl.
112class thread_db;
113class Attachment;
114class jrd_tra;
115class jrd_req;
116class JrdStatement;
117class jrd_file;
118class Format;
119class BufferDesc;
120class SparseBitmap;
121class jrd_rel;
122class ExternalFile;
123class ViewContext;
124class IndexBlock;
125class IndexLock;
126class ArrayField;
127struct sort_context;
128class vcl;
129class TextType;
130class Parameter;
131class jrd_fld;
132class dsql_dbb;
133class PreparedStatement;
134class TraceManager;
135class MessageNode;
136
137// The database block, the topmost block in the metadata
138// cache for a database
139
140// Relation trigger definition
141
142class Trigger
143{
144public:
145 Firebird::HalfStaticArray<UCHAR, 128> blr; // BLR code
146 bid dbg_blob_id; // RDB$DEBUG_INFO
147 JrdStatement* statement; // Compiled statement
148 bool compile_in_progress;
149 bool sys_trigger;
150 FB_UINT64 type; // Trigger type
151 USHORT flags; // Flags as they are in RDB$TRIGGERS table
152 jrd_rel* relation; // Trigger parent relation
153 Firebird::MetaName name; // Trigger name
154 Firebird::MetaName engine; // External engine name
155 Firebird::string entryPoint; // External trigger entrypoint
156 Firebird::string extBody; // External trigger body
157 ExtEngineManager::Trigger* extTrigger; // External trigger
158
159 void compile(thread_db*); // Ensure that trigger is compiled
160 void release(thread_db*); // Try to free trigger request
161
162 explicit Trigger(MemoryPool& p)
163 : blr(p),
164 name(p),
165 engine(p),
166 entryPoint(p),
167 extBody(p),
168 extTrigger(NULL)
169 {
170 dbg_blob_id.clear();
171 }
172};
173
174
175//
176// Flags to indicate normal internal requests vs. dyn internal requests
177//
178const int IRQ_REQUESTS = 1;
179const int DYN_REQUESTS = 2;
180
181
182//
183// Errors during validation - will be returned on info calls
184// CVC: It seems they will be better in a header for val.cpp that's not val.h
185//
186const int VAL_PAG_WRONG_TYPE = 0;
187const int VAL_PAG_CHECKSUM_ERR = 1;
188const int VAL_PAG_DOUBLE_ALLOC = 2;
189const int VAL_PAG_IN_USE = 3;
190const int VAL_PAG_ORPHAN = 4;
191const int VAL_BLOB_INCONSISTENT = 5;
192const int VAL_BLOB_CORRUPT = 6;
193const int VAL_BLOB_TRUNCATED = 7;
194const int VAL_REC_CHAIN_BROKEN = 8;
195const int VAL_DATA_PAGE_CONFUSED = 9;
196const int VAL_DATA_PAGE_LINE_ERR = 10;
197const int VAL_INDEX_PAGE_CORRUPT = 11;
198const int VAL_P_PAGE_LOST = 12;
199const int VAL_P_PAGE_INCONSISTENT = 13;
200const int VAL_REC_DAMAGED = 14;
201const int VAL_REC_BAD_TID = 15;
202const int VAL_REC_FRAGMENT_CORRUPT = 16;
203const int VAL_REC_WRONG_LENGTH = 17;
204const int VAL_INDEX_ROOT_MISSING = 18;
205const int VAL_TIP_LOST = 19;
206const int VAL_TIP_LOST_SEQUENCE = 20;
207const int VAL_TIP_CONFUSED = 21;
208const int VAL_REL_CHAIN_ORPHANS = 22;
209const int VAL_INDEX_MISSING_ROWS = 23;
210const int VAL_INDEX_ORPHAN_CHILD = 24;
211const int VAL_INDEX_CYCLE = 25;
212const int VAL_SCNS_PAGE_INCONSISTENT = 26;
213const int VAL_PAG_WRONG_SCN = 27;
214const int VAL_BLOB_UNKNOWN_LEVEL = 28;
215const int VAL_MAX_ERROR = 29;
216
217
218// Procedure block
219
220class jrd_prc : public Routine
221{
222public:
223 ///const MessageNode* prc_output_msg;
224 const Format* prc_record_format;
225 prc_t prc_type; // procedure type
226
227 const ExtEngineManager::Procedure* getExternal() const { return prc_external; }
228 void setExternal(ExtEngineManager::Procedure* value) { prc_external = value; }
229
230private:
231 const ExtEngineManager::Procedure* prc_external;
232
233public:
234 explicit jrd_prc(MemoryPool& p)
235 : Routine(p),
236 ///prc_output_msg(NULL),
237 prc_record_format(NULL),
238 prc_type(prc_legacy),
239 prc_external(NULL)
240 {
241 }
242
243public:
244 virtual int getObjectType() const
245 {
246 return obj_procedure;
247 }
248
249 virtual SLONG getSclType() const
250 {
251 return SCL_object_procedure;
252 }
253
254 virtual void releaseFormat()
255 {
256 delete prc_record_format;
257 prc_record_format = NULL;
258 }
259
260 virtual bool checkCache(thread_db* tdbb) const;
261 virtual void clearCache(thread_db* tdbb);
262};
263
264
265// Parameter block
266
267class Parameter : public pool_alloc<type_prm>
268{
269public:
270 USHORT prm_number;
271 dsc prm_desc;
272 NestConst<ValueExprNode> prm_default_value;
273 bool prm_nullable;
274 prm_mech_t prm_mechanism;
275 Firebird::MetaName prm_name; // asciiz name
276 Firebird::MetaName prm_field_source;
277 FUN_T prm_fun_mechanism;
278
279public:
280 explicit Parameter(MemoryPool& p)
281 : prm_name(p),
282 prm_field_source(p)
283 {
284 }
285};
286
287// Index block to cache index information
288
289class IndexBlock : public pool_alloc<type_idb>
290{
291public:
292 IndexBlock* idb_next;
293 ValueExprNode* idb_expression; // node tree for index expression
294 JrdStatement* idb_expression_statement; // statement for index expression evaluation
295 dsc idb_expression_desc; // descriptor for expression result
296 Lock* idb_lock; // lock to synchronize changes to index
297 USHORT idb_id;
298};
299
300
301//
302// Transaction element block
303//
304struct teb
305{
306 Attachment* teb_database;
307 int teb_tpb_length;
308 const UCHAR* teb_tpb;
309};
310
311typedef teb TEB;
312
313// Window block for loading cached pages into
314// CVC: Apparently, the only possible values are HEADER_PAGE==0 and LOG_PAGE==2
315// and reside in ods.h, although I watched a place with 1 and others with members
316// of a struct.
317
318struct win
319{
320 PageNumber win_page;
321 Ods::pag* win_buffer;
322 class BufferDesc* win_bdb;
323 SSHORT win_scans;
324 USHORT win_flags;
325 explicit win(const PageNumber& wp)
326 : win_page(wp), win_bdb(NULL), win_flags(0)
327 {}
328 win(const USHORT pageSpaceID, const SLONG pageNum)
329 : win_page(pageSpaceID, pageNum), win_bdb(NULL), win_flags(0)
330 {}
331};
332
333typedef win WIN;
334
335// This is a compilation artifact: I wanted to be sure I would pick all old "win"
336// declarations at the top, so "win" was built with a mandatory argument in
337// the constructor. This struct satisfies a single place with an array. The
338// alternative would be to initialize 16 elements of the array with 16 calls
339// to the constructor: win my_array[n] = {win(-1), ... (win-1)};
340// When all places are changed, this class can disappear and win's constructor
341// may get the default value of -1 to "wp".
342struct win_for_array: public win
343{
344 win_for_array()
345 : win(DB_PAGE_SPACE, -1)
346 {}
347};
348
349// win_flags
350
351const USHORT WIN_large_scan = 1; // large sequential scan
352const USHORT WIN_secondary = 2; // secondary stream
353const USHORT WIN_garbage_collector = 4; // garbage collector's window
354const USHORT WIN_garbage_collect = 8; // scan left a page for garbage collector
355
356
357// Thread specific database block
358
359// tdbb_flags
360
361const USHORT TDBB_sweeper = 1; // Thread sweeper or garbage collector
362const USHORT TDBB_no_cache_unwind = 2; // Don't unwind page buffer cache
363const USHORT TDBB_backup_write_locked = 4; // BackupManager has write lock on LCK_backup_database
364const USHORT TDBB_stack_trace_done = 8; // PSQL stack trace is added into status-vector
365const USHORT TDBB_shutdown_manager = 16; // Server shutdown thread
366const USHORT TDBB_dont_post_dfw = 32; // dont post DFW tasks as deferred work is performed now
367const USHORT TDBB_sys_error = 64; // error shouldn't be handled by the looper
368const USHORT TDBB_verb_cleanup = 128; // verb cleanup is in progress
369const USHORT TDBB_use_db_page_space = 256; // use database (not temporary) page space in GTT operations
370const USHORT TDBB_detaching = 512; // detach is in progress
371const USHORT TDBB_wait_cancel_disable = 1024; // don't cancel current waiting operation
372const USHORT TDBB_cache_unwound = 2048; // page cache was unwound
373
374class thread_db : public Firebird::ThreadData
375{
376private:
377 MemoryPool* defaultPool;
378 void setDefaultPool(MemoryPool* p)
379 {
380 defaultPool = p;
381 }
382 friend class Firebird::SubsystemContextPoolHolder <Jrd::thread_db, MemoryPool>;
383 Database* database;
384 Attachment* attachment;
385 jrd_tra* transaction;
386 jrd_req* request;
387 RuntimeStatistics *reqStat, *traStat, *attStat, *dbbStat;
388 thread_db *priorThread, *nextThread;
389
390public:
391 explicit thread_db(ISC_STATUS* status)
392 : ThreadData(ThreadData::tddDBB),
393 defaultPool(NULL),
394 database(NULL),
395 attachment(NULL),
396 transaction(NULL),
397 request(NULL),
398 priorThread(NULL),
399 nextThread(NULL),
400 tdbb_status_vector(status),
401 tdbb_quantum(QUANTUM),
402 tdbb_flags(0),
403 tdbb_temp_traid(0),
404 tdbb_bdbs(*getDefaultMemoryPool()),
405 tdbb_thread(Firebird::ThreadSync::getThread("thread_db"))
406 {
407 reqStat = traStat = attStat = dbbStat = RuntimeStatistics::getDummy();
408 fb_utils::init_status(tdbb_status_vector);
409 }
410
411 ~thread_db()
412 {
413#ifdef DEV_BUILD
414 for (size_t n = 0; n < tdbb_bdbs.getCount(); ++n)
415 {
416 fb_assert(tdbb_bdbs[n] == NULL);
417 }
418#endif
419 }
420
421 ISC_STATUS* tdbb_status_vector;
422 SSHORT tdbb_quantum; // Cycles remaining until voluntary schedule
423 USHORT tdbb_flags;
424
425 TraNumber tdbb_temp_traid; // current temporary table scope
426
427 // BDB's held by thread
428 Firebird::HalfStaticArray<BufferDesc*, 16> tdbb_bdbs;
429 Firebird::ThreadSync* tdbb_thread;
430
431 MemoryPool* getDefaultPool()
432 {
433 return defaultPool;
434 }
435
436 Database* getDatabase()
437 {
438 return database;
439 }
440
441 const Database* getDatabase() const
442 {
443 return database;
444 }
445
446 void setDatabase(Database* val);
447
448 Attachment* getAttachment()
449 {
450 return attachment;
451 }
452
453 const Attachment* getAttachment() const
454 {
455 return attachment;
456 }
457
458 void setAttachment(Attachment* val);
459
460 jrd_tra* getTransaction()
461 {
462 return transaction;
463 }
464
465 const jrd_tra* getTransaction() const
466 {
467 return transaction;
468 }
469
470 void setTransaction(jrd_tra* val);
471
472 jrd_req* getRequest()
473 {
474 return request;
475 }
476
477 const jrd_req* getRequest() const
478 {
479 return request;
480 }
481
482 void setRequest(jrd_req* val);
483
484 SSHORT getCharSet() const;
485
486 void bumpStats(const RuntimeStatistics::StatType index)
487 {
488 reqStat->bumpValue(index);
489 traStat->bumpValue(index);
490 attStat->bumpValue(index);
491 dbbStat->bumpValue(index);
492 }
493
494 void bumpRelStats(const RelStatType index, SLONG relation_id)
495 {
496 reqStat->bumpRelValue(index, relation_id);
497 traStat->bumpRelValue(index, relation_id);
498 attStat->bumpRelValue(index, relation_id);
499 //dbbStat->bumpRelValue(index, relation_id);
500 }
501
502 bool checkCancelState(bool punt);
503
504 void registerBdb(BufferDesc* bdb)
505 {
506 if (tdbb_bdbs.isEmpty()) {
507 tdbb_flags &= ~TDBB_cache_unwound;
508 }
509 fb_assert(!(tdbb_flags & TDBB_cache_unwound));
510
511 size_t pos;
512 if (tdbb_bdbs.find(NULL, pos))
513 tdbb_bdbs[pos] = bdb;
514 else
515 tdbb_bdbs.add(bdb);
516 }
517
518 bool clearBdb(BufferDesc* bdb)
519 {
520 if (tdbb_bdbs.isEmpty())
521 {
522 // hvlad: the only legal case when thread holds no latches but someone
523 // tried to release latch is when CCH_unwind was called (and released
524 // all latches) but caller is unaware about it. See CORE-3034, for example.
525 // Else it is bug and should be BUGCHECK'ed.
526
527 if (tdbb_flags & TDBB_cache_unwound)
528 return false;
529 }
530 fb_assert(!(tdbb_flags & TDBB_cache_unwound));
531
532 size_t pos;
533 if (!tdbb_bdbs.find(bdb, pos))
534 BUGCHECK(300); // can't find shared latch
535
536 tdbb_bdbs[pos] = NULL;
537
538 if (pos == tdbb_bdbs.getCount() - 1)
539 {
540 while (true)
541 {
542 if (tdbb_bdbs[pos] != NULL)
543 {
544 tdbb_bdbs.shrink(pos + 1);
545 break;
546 }
547
548 if (pos == 0)
549 {
550 tdbb_bdbs.shrink(0);
551 break;
552 }
553
554 --pos;
555 }
556 }
557
558 return true;
559 }
560
561 void activate()
562 {
563 fb_assert(!priorThread && !nextThread);
564
565 if (database)
566 {
567 Firebird::SyncLockGuard sync(&database->dbb_threads_sync, Firebird::SYNC_EXCLUSIVE,
568 "thread_db::activate");
569
570 if (database->dbb_active_threads)
571 {
572 fb_assert(!database->dbb_active_threads->priorThread);
573 database->dbb_active_threads->priorThread = this;
574 nextThread = database->dbb_active_threads;
575 }
576
577 database->dbb_active_threads = this;
578 }
579 }
580
581 void deactivate()
582 {
583 if (database)
584 {
585 Firebird::SyncLockGuard sync(&database->dbb_threads_sync, Firebird::SYNC_EXCLUSIVE,
586 "thread_db::deactivate");
587
588 if (nextThread)
589 {
590 fb_assert(nextThread->priorThread == this);
591 nextThread->priorThread = priorThread;
592 }
593
594 if (priorThread)
595 {
596 fb_assert(priorThread->nextThread == this);
597 priorThread->nextThread = nextThread;
598 }
599 else
600 {
601 fb_assert(database->dbb_active_threads == this);
602 database->dbb_active_threads = nextThread;
603 }
604 }
605
606 priorThread = nextThread = NULL;
607 }
608};
609
610
611class ThreadContextHolder
612{
613public:
614 explicit ThreadContextHolder(ISC_STATUS* status = NULL)
615 : context(status ? status : local_status), externStatus(NULL)
616 {
617 context.putSpecific();
618 }
619
620 explicit ThreadContextHolder(Firebird::IStatus* status)
621 : context(local_status), externStatus(status)
622 {
623 context.putSpecific();
624 externStatus->init();
625 }
626
627 ThreadContextHolder(Database* dbb, Jrd::Attachment* att, ISC_STATUS* status = NULL)
628 : context(status ? status : local_status), externStatus(NULL)
629 {
630 context.putSpecific();
631 context.setDatabase(dbb);
632 context.setAttachment(att);
633 }
634
635 ~ThreadContextHolder()
636 {
637 unsigned l = fb_utils::statusLength(context.tdbb_status_vector);
638 if (externStatus && externStatus->isSuccess() && (l > 2 || context.tdbb_status_vector[1]))
639 {
640 externStatus->set(l, context.tdbb_status_vector);
641 }
642 Firebird::ThreadData::restoreSpecific();
643 }
644
645 thread_db* operator->()
646 {
647 return &context;
648 }
649
650 operator thread_db*()
651 {
652 return &context;
653 }
654
655private:
656 // copying is prohibited
657 ThreadContextHolder(const ThreadContextHolder&);
658 ThreadContextHolder& operator= (const ThreadContextHolder&);
659
660 ISC_STATUS_ARRAY local_status;
661 thread_db context;
662 Firebird::IStatus* externStatus;
663};
664
665
666// CVC: This class was designed to restore the thread's default status vector automatically.
667// In several places, tdbb_status_vector is replaced by a local temporary.
668class ThreadStatusGuard
669{
670public:
671 explicit ThreadStatusGuard(thread_db* tdbb)
672 : m_tdbb(tdbb), m_old_status(tdbb->tdbb_status_vector)
673 {
674 fb_utils::init_status(m_local_status);
675 m_tdbb->tdbb_status_vector = m_local_status;
676 }
677
678 ~ThreadStatusGuard()
679 {
680 m_tdbb->tdbb_status_vector = m_old_status;
681 }
682
683 //ISC_STATUS* restore()
684 //{
685 // return m_tdbb->tdbb_status_vector = m_old_status; // copy, not comparison
686 //}
687
688 operator ISC_STATUS*() { return m_local_status; }
689
690 void copyToOriginal()
691 {
692 memcpy(m_old_status, m_local_status, sizeof(ISC_STATUS_ARRAY));
693 }
694
695private:
696 thread_db* const m_tdbb;
697 ISC_STATUS* const m_old_status;
698 ISC_STATUS_ARRAY m_local_status;
699
700 // copying is prohibited
701 ThreadStatusGuard(const ThreadStatusGuard&);
702 ThreadStatusGuard& operator=(const ThreadStatusGuard&);
703};
704
705
706// duplicate context of firebird string
707inline char* stringDup(MemoryPool& p, const Firebird::string& s)
708{
709 char* rc = (char*) p.allocate(s.length() + 1
710#ifdef DEBUG_GDS_ALLOC
711 , __FILE__, __LINE__
712#endif
713 );
714 strcpy(rc, s.c_str());
715 return rc;
716}
717
718inline char* stringDup(MemoryPool& p, const char* s, size_t l)
719{
720 char* rc = (char*) p.allocate(l + 1
721#ifdef DEBUG_GDS_ALLOC
722 , __FILE__, __LINE__
723#endif
724 );
725 memcpy(rc, s, l);
726 rc[l] = 0;
727 return rc;
728}
729
730inline char* stringDup(MemoryPool& p, const char* s)
731{
732 if (! s)
733 {
734 return 0;
735 }
736 return stringDup(p, s, strlen(s));
737}
738
739// Used in string conversion calls
740typedef Firebird::HalfStaticArray<UCHAR, 256> MoveBuffer;
741
742} //namespace Jrd
743
744// Threading macros
745
746/* Define JRD_get_thread_data off the platform specific version.
747 * If we're in DEV mode, also do consistancy checks on the
748 * retrieved memory structure. This was originally done to
749 * track down cases of no "PUT_THREAD_DATA" on the NLM.
750 *
751 * This allows for NULL thread data (which might be an error by itself)
752 * If there is thread data,
753 * AND it is tagged as being a thread_db.
754 * AND it has a non-NULL database field,
755 * THEN we validate that the structure there is a database block.
756 * Otherwise, we return what we got.
757 * We can't always validate the database field, as during initialization
758 * there is no database set up.
759 */
760
761#if defined(DEV_BUILD)
762#include "../jrd/err_proto.h"
763
764inline Jrd::thread_db* JRD_get_thread_data()
765{
766 Firebird::ThreadData* p1 = Firebird::ThreadData::getSpecific();
767 if (p1 && p1->getType() == Firebird::ThreadData::tddDBB)
768 {
769 Jrd::thread_db* p2 = (Jrd::thread_db*) p1;
770 if (p2->getDatabase() && !p2->getDatabase()->checkHandle())
771 {
772 BUGCHECK(147);
773 }
774 }
775 return (Jrd::thread_db*) p1;
776}
777
778inline void CHECK_TDBB(const Jrd::thread_db* tdbb)
779{
780 fb_assert(tdbb && (tdbb->getType() == Firebird::ThreadData::tddDBB) &&
781 (!tdbb->getDatabase() || tdbb->getDatabase()->checkHandle()));
782}
783
784inline void CHECK_DBB(const Jrd::Database* dbb)
785{
786 fb_assert(dbb && dbb->checkHandle());
787}
788
789#else // PROD_BUILD
790
791inline Jrd::thread_db* JRD_get_thread_data()
792{
793 return (Jrd::thread_db*) Firebird::ThreadData::getSpecific();
794}
795
796inline void CHECK_DBB(const Jrd::Database*)
797{
798}
799
800inline void CHECK_TDBB(const Jrd::thread_db*)
801{
802}
803
804#endif
805
806inline Jrd::Database* GET_DBB()
807{
808 return JRD_get_thread_data()->getDatabase();
809}
810
811/*-------------------------------------------------------------------------*
812 * macros used to set thread_db and Database pointers when there are not set already *
813 *-------------------------------------------------------------------------*/
814inline void SET_TDBB(Jrd::thread_db*& tdbb)
815{
816 if (tdbb == NULL) {
817 tdbb = JRD_get_thread_data();
818 }
819 CHECK_TDBB(tdbb);
820}
821
822inline void SET_DBB(Jrd::Database*& dbb)
823{
824 if (dbb == NULL) {
825 dbb = GET_DBB();
826 }
827 CHECK_DBB(dbb);
828}
829
830
831// global variables for engine
832
833extern int debug;
834
835namespace Jrd {
836 typedef Firebird::SubsystemContextPoolHolder <Jrd::thread_db, MemoryPool> ContextPoolHolder;
837
838 class DatabaseContextHolder : public Jrd::ContextPoolHolder
839 {
840 public:
841 explicit DatabaseContextHolder(thread_db* tdbb)
842 : Jrd::ContextPoolHolder(tdbb, tdbb->getDatabase()->dbb_permanent),
843 savedTdbb(tdbb)
844 {
845 savedTdbb->activate();
846 }
847
848 ~DatabaseContextHolder()
849 {
850 savedTdbb->deactivate();
851 }
852
853 private:
854 // copying is prohibited
855 DatabaseContextHolder(const DatabaseContextHolder&);
856 DatabaseContextHolder& operator=(const DatabaseContextHolder&);
857
858 thread_db* const savedTdbb;
859 };
860
861 class BackgroundContextHolder : public ThreadContextHolder, public DatabaseContextHolder,
862 public Jrd::Attachment::SyncGuard
863 {
864 public:
865 BackgroundContextHolder(Database* dbb, Jrd::Attachment* att, ISC_STATUS* status, const char* f)
866 : ThreadContextHolder(dbb, att, status),
867 DatabaseContextHolder(operator thread_db*()),
868 Jrd::Attachment::SyncGuard(att, f)
869 {}
870
871 private:
872 // copying is prohibited
873 BackgroundContextHolder(const BackgroundContextHolder&);
874 BackgroundContextHolder& operator=(const BackgroundContextHolder&);
875 };
876
877 class AstLockHolder : public Firebird::ReadLockGuard
878 {
879 public:
880 AstLockHolder(Database* dbb, const char* f)
881 : Firebird::ReadLockGuard(dbb->dbb_ast_lock, f)
882 {
883 if (dbb->dbb_flags & DBB_no_ast)
884 {
885 // usually to be swallowed by the AST, but it allows to skip its execution
886 Firebird::status_exception::raise(Firebird::Arg::Gds(isc_unavailable));
887 }
888 }
889 };
890
891 class AsyncContextHolder : public AstLockHolder, public Jrd::Attachment::SyncGuard,
892 public ThreadContextHolder, public DatabaseContextHolder
893 {
894 public:
895 AsyncContextHolder(Database* dbb, const char* f, Lock* lck = NULL)
896 : AstLockHolder(dbb, f),
897 Jrd::Attachment::SyncGuard(lck ?
898 lck->getLockInterface() : Firebird::RefPtr<JAttachment>(), f, true),
899 ThreadContextHolder(dbb, lck ? lck->getLockAttachment() : NULL),
900 DatabaseContextHolder(operator thread_db*())
901 {}
902
903 private:
904 // copying is prohibited
905 AsyncContextHolder(const AsyncContextHolder&);
906 AsyncContextHolder& operator=(const AsyncContextHolder&);
907 };
908}
909
910#endif // JRD_JRD_H
911