1/*
2 * PROGRAM: JRD access method
3 * MODULE: Attachment.h
4 * DESCRIPTION: JRD Attachment class
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 */
24
25#ifndef JRD_ATTACHMENT_H
26#define JRD_ATTACHMENT_H
27
28#include "firebird.h"
29// Definition of block types for data allocation in JRD
30#include "../include/fb_blk.h"
31#include "../jrd/scl.h"
32#include "../jrd/PreparedStatement.h"
33#include "../jrd/RandomGenerator.h"
34#include "../jrd/RuntimeStatistics.h"
35
36#include "../common/classes/ByteChunk.h"
37#include "../common/classes/GenericMap.h"
38#include "../common/classes/SyncObject.h"
39#include "../common/classes/array.h"
40#include "../common/classes/stack.h"
41#include "../common/classes/timestamp.h"
42
43#include "../jrd/EngineInterface.h"
44
45namespace EDS {
46 class Connection;
47}
48
49namespace Firebird {
50 class ICryptKeyCallback;
51}
52
53class CharSetContainer;
54
55namespace Jrd
56{
57 class thread_db;
58 class Database;
59 class jrd_tra;
60 class jrd_req;
61 class Lock;
62 class jrd_file;
63 class Format;
64 class BufferControl;
65 class SparseBitmap;
66 class jrd_rel;
67 class ExternalFile;
68 class ViewContext;
69 class IndexBlock;
70 class IndexLock;
71 class ArrayField;
72 struct sort_context;
73 class vcl;
74 class TextType;
75 class Parameter;
76 class jrd_fld;
77 class dsql_dbb;
78 class PreparedStatement;
79 class TraceManager;
80 template <typename T> class vec;
81 class jrd_rel;
82 class jrd_prc;
83 class Trigger;
84 typedef Firebird::ObjectsArray<Trigger> trig_vec;
85 class Function;
86 class JrdStatement;
87
88struct DSqlCacheItem
89{
90 Lock* lock;
91 bool locked;
92 bool obsolete;
93};
94
95typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<
96 Firebird::string, DSqlCacheItem> > > DSqlCache;
97
98
99struct DdlTriggerContext
100{
101 DdlTriggerContext()
102 : eventType(*getDefaultMemoryPool()),
103 objectType(*getDefaultMemoryPool()),
104 objectName(*getDefaultMemoryPool()),
105 sqlText(*getDefaultMemoryPool())
106 {
107 }
108
109 Firebird::string eventType;
110 Firebird::string objectType;
111 Firebird::MetaName objectName;
112 Firebird::string sqlText;
113};
114
115
116struct bid;
117
118//
119// the attachment block; one is created for each attachment to a database
120//
121class Attachment : public pool_alloc<type_att>
122{
123public:
124 class SyncGuard
125 {
126 public:
127 SyncGuard(JAttachment* ja, const char* f, bool optional = false)
128 : jAtt(ja)
129 {
130 init(f, optional);
131 }
132
133 SyncGuard(Attachment* att, const char* f, bool optional = false)
134 : jAtt(att ? att->att_interface : NULL)
135 {
136 init(f, optional);
137 }
138
139 ~SyncGuard()
140 {
141 if (jAtt)
142 jAtt->getMutex()->leave();
143 }
144
145 private:
146 // copying is prohibited
147 SyncGuard(const SyncGuard&);
148 SyncGuard& operator=(const SyncGuard&);
149
150 void init(const char* f, bool optional);
151
152 Firebird::RefPtr<JAttachment> jAtt;
153 };
154
155 class Checkout
156 {
157 public:
158 Checkout(Attachment* att, const char* f, bool optional = false)
159#ifdef DEV_BUILD
160 : from(f)
161#define FB_LOCKED_FROM from
162#else
163#define FB_LOCKED_FROM NULL
164#endif
165 {
166 if (att && att->att_interface)
167 {
168 m_ref = att->att_interface;
169 }
170
171 fb_assert(optional || m_ref.hasData());
172
173 if (m_ref.hasData())
174 m_ref->getMutex()->leave();
175 }
176
177 ~Checkout()
178 {
179 if (m_ref.hasData())
180 m_ref->getMutex()->enter(FB_LOCKED_FROM);
181 }
182
183 private:
184 // copying is prohibited
185 Checkout(const Checkout&);
186 Checkout& operator=(const Checkout&);
187
188 Firebird::RefPtr<JAttachment> m_ref;
189#ifdef DEV_BUILD
190 const char* from;
191#endif
192 };
193#undef FB_LOCKED_FROM
194
195 class CheckoutLockGuard
196 {
197 public:
198 CheckoutLockGuard(Attachment* att, Firebird::Mutex& mutex, const char* f, bool optional = false)
199 : m_mutex(mutex)
200 {
201 if (!m_mutex.tryEnter(f))
202 {
203 Checkout attCout(att, f, optional);
204 m_mutex.enter(f);
205 }
206 }
207
208 ~CheckoutLockGuard()
209 {
210 m_mutex.leave();
211 }
212
213 private:
214 // copying is prohibited
215 CheckoutLockGuard(const CheckoutLockGuard&);
216 CheckoutLockGuard& operator=(const CheckoutLockGuard&);
217
218 Firebird::Mutex& m_mutex;
219 };
220
221 class CheckoutSyncGuard
222 {
223 public:
224 CheckoutSyncGuard(Attachment* att, Firebird::SyncObject& sync, Firebird::SyncType type, const char* f)
225 : m_sync(&sync, f)
226 {
227 if (!m_sync.lockConditional(type, f))
228 {
229 Checkout attCout(att, f);
230 m_sync.lock(type);
231 }
232 }
233
234 private:
235 // copying is prohibited
236 CheckoutSyncGuard(const CheckoutSyncGuard&);
237 CheckoutSyncGuard& operator=(const CheckoutSyncGuard&);
238
239 Firebird::Sync m_sync;
240 };
241
242public:
243 static Attachment* create(Database* dbb);
244 static void destroy(Attachment* const attachment);
245
246 MemoryPool* const att_pool; // Memory pool
247 Firebird::MemoryStats att_memory_stats;
248
249 Database* att_database; // Parent database block
250 Attachment* att_next; // Next attachment to database
251 UserId* att_user; // User identification
252 jrd_tra* att_transactions; // Transactions belonging to attachment
253 jrd_tra* att_dbkey_trans; // transaction to control db-key scope
254 TraNumber att_oldest_snapshot; // GTT's record versions older than this can be garbage-collected
255
256private:
257 jrd_tra* att_sys_transaction; // system transaction
258
259public:
260 Firebird::SortedArray<jrd_req*> att_requests; // Requests belonging to attachment
261 Lock* att_id_lock; // Attachment lock (if any)
262 SLONG att_attachment_id; // Attachment ID
263 Lock* att_cancel_lock; // Lock to cancel the active request
264 const ULONG att_lock_owner_id; // ID for the lock manager
265 SLONG att_lock_owner_handle; // Handle for the lock manager
266 ULONG att_backup_state_counter; // Counter of backup state locks for attachment
267 SLONG att_event_session; // Event session id, if any
268 SecurityClass* att_security_class; // security class for database
269 SecurityClassList* att_security_classes; // security classes
270 RuntimeStatistics att_stats;
271 ULONG att_flags; // Flags describing the state of the attachment
272 SSHORT att_client_charset; // user's charset specified in dpb
273 SSHORT att_charset; // current (client or external) attachment charset
274 Lock* att_long_locks; // outstanding two phased locks
275 Lock* att_wait_lock; // lock at which attachment waits currently
276 vec<Lock*>* att_compatibility_table; // hash table of compatible locks
277 vcl* att_val_errors;
278 Firebird::PathName att_working_directory; // Current working directory is cached
279 Firebird::PathName att_filename; // alias used to attach the database
280 const Firebird::TimeStamp att_timestamp; // Connection date and time
281 Firebird::StringMap att_context_vars; // Context variables for the connection
282 Firebird::Stack<DdlTriggerContext> ddlTriggersContext; // Context variables for DDL trigger event
283 Firebird::string att_network_protocol; // Network protocol used by client for connection
284 Firebird::string att_remote_address; // Protocol-specific address of remote client
285 SLONG att_remote_pid; // Process id of remote client
286 Firebird::PathName att_remote_process; // Process name of remote client
287 Firebird::string att_client_version; // Version of the client library
288 Firebird::string att_remote_protocol; // Details about the remote protocol
289 Firebird::string att_remote_host; // Host name of remote client
290 Firebird::string att_remote_os_user; // OS user name of remote client
291 RandomGenerator att_random_generator; // Random bytes generator
292 Lock* att_temp_pg_lock; // temporary pagespace ID lock
293 DSqlCache att_dsql_cache; // DSQL cache locks
294 Firebird::SortedArray<void*> att_udf_pointers;
295 dsql_dbb* att_dsql_instance;
296 bool att_in_use; // attachment in use (can't be detached or dropped)
297 int att_use_count; // number of API calls running except of asynchronous ones
298
299 EDS::Connection* att_ext_connection; // external connection executed by this attachment
300 ULONG att_ext_call_depth; // external connection call depth, 0 for user attachment
301 TraceManager* att_trace_manager; // Trace API manager
302
303 JAttachment* att_interface;
304
305 /// former Database members - start
306
307 vec<jrd_rel*>* att_relations; // relation vector
308 Firebird::Array<jrd_prc*> att_procedures; // scanned procedures
309 trig_vec* att_triggers[DB_TRIGGER_MAX];
310 trig_vec* att_ddl_triggers;
311 Firebird::Array<Function*> att_functions; // User defined functions
312
313 Firebird::Array<JrdStatement*> att_internal; // internal statements
314 Firebird::Array<JrdStatement*> att_dyn_req; // internal dyn statements
315 Firebird::ICryptKeyCallback* att_crypt_callback; // callback for DB crypt
316
317 jrd_req* findSystemRequest(thread_db* tdbb, USHORT id, USHORT which);
318
319 Firebird::Array<CharSetContainer*> att_charsets; // intl character set descriptions
320 Firebird::GenericMap<Firebird::Pair<Firebird::Left<
321 Firebird::MetaName, USHORT> > > att_charset_ids; // Character set ids
322
323 void releaseIntlObjects(thread_db* tdbb); // defined in intl.cpp
324 void destroyIntlObjects(thread_db* tdbb); // defined in intl.cpp
325
326 void releaseLocks(thread_db* tdbb);
327
328 Firebird::Array<MemoryPool*> att_pools; // pools
329
330 MemoryPool* createPool();
331 void deletePool(MemoryPool* pool);
332
333 /// former Database members - end
334
335 bool locksmith() const;
336 jrd_tra* getSysTransaction();
337 void setSysTransaction(jrd_tra* trans); // used only by TRA_init
338
339 PreparedStatement* prepareStatement(thread_db* tdbb, jrd_tra* transaction,
340 const Firebird::string& text, Firebird::MemoryPool* pool = NULL);
341 PreparedStatement* prepareStatement(thread_db* tdbb, jrd_tra* transaction,
342 const PreparedStatement::Builder& builder, Firebird::MemoryPool* pool = NULL);
343
344 PreparedStatement* prepareUserStatement(thread_db* tdbb, jrd_tra* transaction,
345 const Firebird::string& text, Firebird::MemoryPool* pool = NULL);
346
347 Firebird::MetaName nameToMetaCharSet(thread_db* tdbb, const Firebird::MetaName& name);
348 Firebird::MetaName nameToUserCharSet(thread_db* tdbb, const Firebird::MetaName& name);
349 Firebird::string stringToMetaCharSet(thread_db* tdbb, const Firebird::string& str,
350 const char* charSet = NULL);
351 Firebird::string stringToUserCharSet(thread_db* tdbb, const Firebird::string& str);
352
353 void storeMetaDataBlob(thread_db* tdbb, jrd_tra* transaction,
354 bid* blobId, const Firebird::string& text, USHORT fromCharSet = CS_METADATA);
355 void storeBinaryBlob(thread_db* tdbb, jrd_tra* transaction, bid* blobId,
356 const Firebird::ByteChunk& chunk);
357
358 void signalCancel();
359 void signalShutdown();
360
361 void detachLocksFromAttachment();
362
363 bool backupStateWriteLock(thread_db* tdbb, SSHORT wait);
364 void backupStateWriteUnLock(thread_db* tdbb);
365 bool backupStateReadLock(thread_db* tdbb, SSHORT wait);
366 void backupStateReadUnLock(thread_db* tdbb);
367
368private:
369 Attachment(MemoryPool* pool, Database* dbb);
370 ~Attachment();
371};
372
373
374// Attachment flags
375
376const ULONG ATT_no_cleanup = 0x00001L; // Don't expunge, purge, or garbage collect
377const ULONG ATT_shutdown = 0x00002L; // attachment has been shutdown
378const ULONG ATT_shutdown_manager = 0x00004L; // attachment requesting shutdown
379const ULONG ATT_exclusive = 0x00008L; // attachment wants exclusive database access
380const ULONG ATT_attach_pending = 0x00010L; // Indicate attachment is only pending
381const ULONG ATT_exclusive_pending = 0x00020L; // Indicate exclusive attachment pending
382const ULONG ATT_gbak_attachment = 0x00040L; // Indicate GBAK attachment
383const ULONG ATT_notify_gc = 0x00080L; // Notify garbage collector to expunge, purge ..
384const ULONG ATT_garbage_collector = 0x00100L; // I'm a garbage collector
385const ULONG ATT_cancel_raise = 0x00200L; // Cancel currently running operation
386const ULONG ATT_cancel_disable = 0x00400L; // Disable cancel operations
387const ULONG ATT_gfix_attachment = 0x00800L; // Indicate a GFIX attachment
388const ULONG ATT_gstat_attachment = 0x01000L; // Indicate a GSTAT attachment
389const ULONG ATT_no_db_triggers = 0x02000L; // Don't execute database triggers
390const ULONG ATT_manual_lock = 0x04000L; // Was locked manually
391const ULONG ATT_async_manual_lock = 0x08000L; // Async mutex was locked manually
392const ULONG ATT_purge_started = 0x10000L; // Purge already started - avoid 2 purges at once
393const ULONG ATT_system = 0x20000L; // Special system attachment
394
395const ULONG ATT_NO_CLEANUP = (ATT_no_cleanup | ATT_notify_gc);
396
397
398inline bool Attachment::locksmith() const
399{
400 return att_user && att_user->locksmith();
401}
402
403inline jrd_tra* Attachment::getSysTransaction()
404{
405 return att_sys_transaction;
406}
407
408inline void Attachment::setSysTransaction(jrd_tra* trans)
409{
410 att_sys_transaction = trans;
411}
412
413// This class holds references to all attachments it contains
414
415class AttachmentsRefHolder
416{
417 friend class Iterator;
418
419public:
420 class Iterator
421 {
422 public:
423 explicit Iterator(AttachmentsRefHolder& list)
424 : m_list(list), m_index(0)
425 {}
426
427 JAttachment* operator*()
428 {
429 if (m_index < m_list.m_attachments.getCount())
430 return m_list.m_attachments[m_index];
431
432 return NULL;
433 }
434
435 void operator++()
436 {
437 m_index++;
438 }
439
440 void remove()
441 {
442 if (m_index < m_list.m_attachments.getCount())
443 {
444 AttachmentsRefHolder::debugHelper(FB_FUNCTION);
445 m_list.m_attachments[m_index]->release();
446 m_list.m_attachments.remove(m_index);
447 }
448 }
449
450 private:
451 // copying is prohibited
452 Iterator(const Iterator&);
453 Iterator& operator=(const Iterator&);
454
455 AttachmentsRefHolder& m_list;
456 size_t m_index;
457 };
458
459 explicit AttachmentsRefHolder(MemoryPool& p)
460 : m_attachments(p)
461 {}
462
463 AttachmentsRefHolder& operator=(const AttachmentsRefHolder& other)
464 {
465 this->~AttachmentsRefHolder();
466
467 for (size_t i = 0; i < other.m_attachments.getCount(); i++)
468 add(other.m_attachments[i]);
469
470 return *this;
471 }
472
473 ~AttachmentsRefHolder()
474 {
475 while (m_attachments.hasData())
476 {
477 debugHelper(FB_FUNCTION);
478 m_attachments.pop()->release();
479 }
480 }
481
482 void add(JAttachment* jAtt)
483 {
484 if (jAtt)
485 {
486 jAtt->addRef();
487 m_attachments.add(jAtt);
488 }
489 }
490
491 void remove(Iterator& iter)
492 {
493 iter.remove();
494 }
495
496private:
497 AttachmentsRefHolder(const AttachmentsRefHolder&);
498
499 static void debugHelper(const char* from);
500
501 Firebird::HalfStaticArray<JAttachment*, 128> m_attachments;
502};
503
504} // namespace Jrd
505
506#endif // JRD_ATTACHMENT_H
507