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 | |
45 | namespace EDS { |
46 | class Connection; |
47 | } |
48 | |
49 | namespace Firebird { |
50 | class ICryptKeyCallback; |
51 | } |
52 | |
53 | class CharSetContainer; |
54 | |
55 | namespace 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 | |
88 | struct DSqlCacheItem |
89 | { |
90 | Lock* lock; |
91 | bool locked; |
92 | bool obsolete; |
93 | }; |
94 | |
95 | typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left< |
96 | Firebird::string, DSqlCacheItem> > > DSqlCache; |
97 | |
98 | |
99 | struct 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 | |
116 | struct bid; |
117 | |
118 | // |
119 | // the attachment block; one is created for each attachment to a database |
120 | // |
121 | class Attachment : public pool_alloc<type_att> |
122 | { |
123 | public: |
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 | |
242 | public: |
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 | |
256 | private: |
257 | jrd_tra* att_sys_transaction; // system transaction |
258 | |
259 | public: |
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 | |
368 | private: |
369 | Attachment(MemoryPool* pool, Database* dbb); |
370 | ~Attachment(); |
371 | }; |
372 | |
373 | |
374 | // Attachment flags |
375 | |
376 | const ULONG ATT_no_cleanup = 0x00001L; // Don't expunge, purge, or garbage collect |
377 | const ULONG ATT_shutdown = 0x00002L; // attachment has been shutdown |
378 | const ULONG ATT_shutdown_manager = 0x00004L; // attachment requesting shutdown |
379 | const ULONG ATT_exclusive = 0x00008L; // attachment wants exclusive database access |
380 | const ULONG ATT_attach_pending = 0x00010L; // Indicate attachment is only pending |
381 | const ULONG ATT_exclusive_pending = 0x00020L; // Indicate exclusive attachment pending |
382 | const ULONG ATT_gbak_attachment = 0x00040L; // Indicate GBAK attachment |
383 | const ULONG ATT_notify_gc = 0x00080L; // Notify garbage collector to expunge, purge .. |
384 | const ULONG ATT_garbage_collector = 0x00100L; // I'm a garbage collector |
385 | const ULONG ATT_cancel_raise = 0x00200L; // Cancel currently running operation |
386 | const ULONG ATT_cancel_disable = 0x00400L; // Disable cancel operations |
387 | const ULONG ATT_gfix_attachment = 0x00800L; // Indicate a GFIX attachment |
388 | const ULONG ATT_gstat_attachment = 0x01000L; // Indicate a GSTAT attachment |
389 | const ULONG ATT_no_db_triggers = 0x02000L; // Don't execute database triggers |
390 | const ULONG ATT_manual_lock = 0x04000L; // Was locked manually |
391 | const ULONG ATT_async_manual_lock = 0x08000L; // Async mutex was locked manually |
392 | const ULONG ATT_purge_started = 0x10000L; // Purge already started - avoid 2 purges at once |
393 | const ULONG ATT_system = 0x20000L; // Special system attachment |
394 | |
395 | const ULONG ATT_NO_CLEANUP = (ATT_no_cleanup | ATT_notify_gc); |
396 | |
397 | |
398 | inline bool Attachment::locksmith() const |
399 | { |
400 | return att_user && att_user->locksmith(); |
401 | } |
402 | |
403 | inline jrd_tra* Attachment::getSysTransaction() |
404 | { |
405 | return att_sys_transaction; |
406 | } |
407 | |
408 | inline 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 | |
415 | class AttachmentsRefHolder |
416 | { |
417 | friend class Iterator; |
418 | |
419 | public: |
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 | |
496 | private: |
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 | |