8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 20:43:04 +01:00
firebird-mirror/src/jrd/tra.h

428 lines
13 KiB
C
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Access Method
* MODULE: tra.h
* DESCRIPTION: Transaction block definitions
*
* 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-07-01 17:07:18 +02:00
* 2001.6.25 Claudio Valderrama: add dfw_delete_generator and dfw_delete_udf
* to the dfw_t enumeration.
* 2002.10.29 Nickolay Samofatov: Added support for savepoints
2001-05-23 15:26:42 +02:00
*/
#ifndef JRD_TRA_H
#define JRD_TRA_H
/*
* TMN: Fix this header! It should include any header it needs
* to define the types this header uses.
2001-05-23 15:26:42 +02:00
*/
2001-12-24 03:51:06 +01:00
#include "../include/fb_blk.h"
#include "../common/classes/tree.h"
#include "../common/classes/GenericMap.h"
#include "../jrd/exe.h"
2008-02-28 14:48:16 +01:00
#include "../jrd/rpb_chain.h"
#include "../jrd/blb.h" // For bid structure
#include "../jrd/sbm.h" // For bid structure
2001-05-23 15:26:42 +02:00
#include "../jrd/DatabaseSnapshot.h"
2008-01-16 11:25:04 +01:00
#include "../jrd/TempSpace.h"
namespace EDS {
class Transaction;
2008-04-10 11:50:17 +02:00
}
namespace Jrd {
class blb;
class Lock;
class jrd_rel;
template <typename T> class vec;
class Savepoint;
class Record;
class VerbAction;
class ArrayField;
class Attachment;
2008-02-28 14:48:16 +01:00
class DeferredWork;
class dsql_opn;
// Blobs active in transaction identified by bli_temp_id. Please keep this
// structure small as there can be huge amount of them floating in memory.
2008-04-19 11:42:01 +02:00
struct BlobIndex
{
ULONG bli_temp_id;
bool bli_materialized;
jrd_req* bli_request;
2008-04-19 11:42:01 +02:00
union
{
bid bli_blob_id; // ID of materialized blob
blb* bli_blob_object; // Blob object
};
2008-04-19 11:42:01 +02:00
static const ULONG& generate(const void *sender, const BlobIndex& item)
{
return item.bli_temp_id;
}
// Empty default constructor to make it behave like POD structure
BlobIndex() {}
BlobIndex(ULONG temp_id, blb* blob_object) :
bli_temp_id(temp_id), bli_materialized(false), bli_request(NULL),
bli_blob_object(blob_object)
{ }
};
typedef Firebird::BePlusTree<BlobIndex, ULONG, MemoryPool, BlobIndex> BlobIndexTree;
2001-05-23 15:26:42 +02:00
/* Transaction block */
2006-10-30 20:04:27 +01:00
const int DEFAULT_LOCK_TIMEOUT = -1; // infinite
2008-01-16 11:25:04 +01:00
const char* const TRA_TEMP_SPACE = "fb_trans_";
2006-10-30 20:04:27 +01:00
class jrd_tra : public pool_alloc<type_tra>
2001-05-23 15:26:42 +02:00
{
2008-01-16 11:25:04 +01:00
public:
enum wait_t {
tra_no_wait,
tra_probe,
tra_wait
};
jrd_tra(MemoryPool* p, Firebird::MemoryStats* parent_stats,
Attachment* attachment, jrd_tra* outer, size_t length = 0)
2008-05-07 13:43:13 +02:00
: tra_attachment(attachment),
tra_pool(p),
tra_memory_stats(parent_stats),
tra_blobs_tree(p),
tra_blobs(&tra_blobs_tree),
tra_deferred_work(0),
2008-01-16 11:25:04 +01:00
tra_resources(*p),
tra_context_vars(*p),
tra_lock_timeout(DEFAULT_LOCK_TIMEOUT),
2008-03-27 10:14:24 +01:00
tra_timestamp(Firebird::TimeStamp::getCurrentTimeStamp()),
tra_open_cursors(*p),
tra_outer(outer),
tra_transactions(*p)
{
if (outer)
{
fb_assert(p == outer->tra_pool);
tra_arrays = outer->tra_arrays;
tra_blobs = outer->tra_blobs;
}
tra_transactions.resize(length);
}
~jrd_tra();
static jrd_tra* create(MemoryPool* pool, Attachment* attachment, jrd_tra* outer, size_t length = 0)
{
jrd_tra* const transaction =
FB_NEW(*pool) jrd_tra(pool, &attachment->att_memory_stats, attachment, outer, length);
if (!outer)
{
pool->setStatsGroup(transaction->tra_memory_stats);
}
return transaction;
}
static void destroy(Database* const dbb, jrd_tra* const transaction)
{
if (transaction)
{
if (transaction->tra_outer)
{
delete transaction;
}
else
{
MemoryPool* const pool = transaction->tra_pool;
Firebird::MemoryStats temp_stats;
pool->setStatsGroup(temp_stats);
delete transaction;
dbb->deletePool(pool);
}
}
2008-01-16 11:25:04 +01:00
}
Attachment* tra_attachment; /* database attachment */
2001-05-23 15:26:42 +02:00
SLONG tra_number; /* transaction number */
SLONG tra_top; /* highest transaction in snapshot */
SLONG tra_oldest; /* oldest interesting transaction */
SLONG tra_oldest_active; /* record versions older than this can be
gargage-collected by this tx */
jrd_tra* tra_next; /* next transaction in database */
jrd_tra* tra_sibling; /* next transaction in group */
2008-04-06 12:31:58 +02:00
MemoryPool* const tra_pool; /* pool for transaction */
Firebird::MemoryStats tra_memory_stats;
BlobIndexTree tra_blobs_tree; // list of active blobs
BlobIndexTree* tra_blobs; // pointer to actual list of active blobs
ArrayField* tra_arrays; /* Linked list of active arrays */
Lock* tra_lock; /* lock for transaction */
Lock* tra_cancel_lock; /* lock to cancel the active request */
vec<Lock*>* tra_relation_locks; /* locks for relations */
UInt32Bitmap* tra_commit_sub_trans; /* commited sub-transactions */
Savepoint* tra_save_point; /* list of savepoints */
Savepoint* tra_save_free; /* free savepoints */
2001-05-23 15:26:42 +02:00
SLONG tra_save_point_number; /* next save point number to use */
ULONG tra_flags;
2008-02-28 14:48:16 +01:00
DeferredWork* tra_deferred_work; /* work deferred to commit time */
ResourceList tra_resources; /* resource existence list */
2004-11-22 21:22:03 +01:00
Firebird::StringMap tra_context_vars; // Context variables for the transaction
traRpbList* tra_rpblist; /* active record_param's of given transaction */
UCHAR tra_use_count; /* use count for safe AST delivery */
UCHAR tra_callback_count; /* callback count for 'execute statement' */
SSHORT tra_lock_timeout; /* in seconds, -1 means infinite, 0 means NOWAIT */
ULONG tra_next_blob_id; // ID of the previous blob or array created in this transaction
2008-03-28 14:32:36 +01:00
const Firebird::TimeStamp tra_timestamp; // transaction start time
jrd_req* tra_requests; // Doubly linked list of requests active in this transaction
DatabaseSnapshot* tra_db_snapshot; // Database state snapshot (for monitoring purposes)
RuntimeStatistics tra_stats;
2008-02-28 14:48:16 +01:00
Firebird::Array<dsql_req*> tra_open_cursors;
2008-04-06 16:45:51 +02:00
jrd_tra* const tra_outer; // outer transaction of an autonomous transaction
jrd_req* tra_callback_caller; // caller request for execute statement
Firebird::Array<UCHAR> tra_transactions;
2008-01-16 11:25:04 +01:00
EDS::Transaction *tra_ext_common;
//Transaction *tra_ext_two_phase;
2008-01-16 11:25:04 +01:00
private:
TempSpace* tra_temp_space; // temp space storage
public:
SSHORT getLockWait() const
{
return -tra_lock_timeout;
}
2008-01-16 11:25:04 +01:00
TempSpace* getTempSpace()
{
if (tra_outer)
return tra_outer->getTempSpace();
2008-01-16 11:25:04 +01:00
if (!tra_temp_space)
tra_temp_space = FB_NEW(*tra_pool) TempSpace(*tra_pool, TRA_TEMP_SPACE);
return tra_temp_space;
}
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
2005-11-06 04:20:18 +01:00
// System transaction is always transaction 0.
const SLONG TRA_system_transaction = 0;
// Flag definitions for tra_flags.
const ULONG TRA_system = 1L; /* system transaction */
//const ULONG TRA_update = 2L; // update is permitted
const ULONG TRA_prepared = 4L; /* transaction is in limbo */
const ULONG TRA_reconnected = 8L; /* reconnect in progress */
//const ULONG TRA_reserving = 16L; // relations explicityly locked
const ULONG TRA_degree3 = 32L; /* serializeable transaction */
//const ULONG TRA_committing = 64L; // commit in progress
const ULONG TRA_write = 128L; /* transaction has written */
const ULONG TRA_readonly = 256L; /* transaction is readonly */
//const ULONG TRA_nowait = 512L; // don't wait on relations, give up
const ULONG TRA_prepare2 = 1024L; /* transaction has updated RDB$TRANSACTIONS */
const ULONG TRA_ignore_limbo = 2048L; /* ignore transactions in limbo */
const ULONG TRA_invalidated = 4096L; /* transaction invalidated by failed write */
const ULONG TRA_deferred_meta = 8192L; /* deferred meta work posted */
2004-10-01 08:21:37 +02:00
//const ULONG TRA_add_log = 16384L; // write ahead log file was added
//const ULONG TRA_delete_log = 32768L; // write ahead log file was deleted
const ULONG TRA_read_committed = 65536L; /* can see latest committed records */
const ULONG TRA_autocommit = 131072L; /* autocommits all updates */
const ULONG TRA_perform_autocommit = 262144L; /* indicates autocommit is necessary */
const ULONG TRA_rec_version = 524288L; /* don't wait for uncommitted versions */
const ULONG TRA_restart_requests = 1048576L; /* restart all requests in attachment */
const ULONG TRA_no_auto_undo = 2097152L; /* don't start a savepoint in TRA_start */
const ULONG TRA_cancel_request = 4194304L; // cancel active request, if any
const ULONG TRA_precommitted = 8388608L; /* transaction committed at startup */
const int TRA_MASK = 3;
//const int TRA_BITS_PER_TRANS = 2;
//const int TRA_TRANS_PER_BYTE = 4;
const int TRA_SHIFT = 2;
2001-05-23 15:26:42 +02:00
#define TRANS_SHIFT(number) (((number) & TRA_MASK) << 1)
#define TRANS_OFFSET(number) ((number) >> TRA_SHIFT)
/* Transaction cleanup. If a database is never quiescent, look
for "dead" active transactions every so often at transaction
startup */
const int TRA_ACTIVE_CLEANUP = 100;
2001-05-23 15:26:42 +02:00
/* Transaction states. The first four are states found
in the transaction inventory page; the last two are
returned internally */
const int tra_active = 0; /* Transaction is active */
const int tra_limbo = 1;
const int tra_dead = 2;
const int tra_committed = 3;
const int tra_us = 4; /* Transaction is us */
const int tra_precommitted = 5; /* Transaction is precommitted */
2001-05-23 15:26:42 +02:00
2004-05-19 00:00:21 +02:00
// The highest transaction number possible. This is 0x7fffffff if SLONG is 32 bits.
//#define MAX_TRA_NUMBER (~(1L << (BITS_PER_LONG - 1)))
2001-05-23 15:26:42 +02:00
/* Savepoint block */
class Savepoint : public pool_alloc<type_sav>
2001-12-24 03:51:06 +01:00
{
2008-04-19 11:42:01 +02:00
public:
VerbAction* sav_verb_actions; /* verb action list */
VerbAction* sav_verb_free; /* free verb actions */
USHORT sav_verb_count; /* Active verb count */
SLONG sav_number; /* save point number */
Savepoint* sav_next;
USHORT sav_flags;
TEXT sav_name[32]; /* Savepoint name */
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
/* Savepoint block flags. */
const int SAV_trans_level = 1; /* savepoint was started by TRA_start */
const int SAV_event_post = 2; /* event posted in the save point */
const int SAV_user = 4; /* named user savepoint as opposed to system ones */
2001-05-23 15:26:42 +02:00
/* Maximum size in bytes of transaction-level savepoint data.
When transaction-level savepoint gets past this size we drop it and use GC
mechanisms to clean out changes done in transaction */
const IPTR SAV_LARGE = 1024 * 32;
2002-11-03 18:29:51 +01:00
2001-05-23 15:26:42 +02:00
/* Deferred work blocks are used by the meta data handler to keep track
of work deferred to commit time. This are usually used to perform
meta data updates */
2003-08-22 12:56:55 +02:00
enum dfw_t {
2001-05-23 15:26:42 +02:00
dfw_null,
dfw_create_relation,
dfw_delete_relation,
dfw_update_format,
dfw_create_index,
dfw_delete_index,
dfw_compute_security,
dfw_add_file,
dfw_add_shadow,
dfw_delete_shadow,
dfw_modify_file,
dfw_erase_file,
dfw_create_field,
dfw_delete_field,
dfw_modify_field,
dfw_delete_global,
dfw_delete_rfr,
dfw_post_event,
dfw_create_trigger,
dfw_delete_trigger,
dfw_modify_trigger,
//dfw_load_triggers,
dfw_grant,
dfw_revoke,
dfw_scan_relation,
dfw_create_expression_index,
dfw_delete_expression_index,
dfw_create_procedure,
dfw_modify_procedure,
dfw_delete_procedure,
dfw_delete_prm,
dfw_create_collation,
dfw_delete_collation,
dfw_delete_exception,
//dfw_unlink_file,
dfw_delete_generator,
dfw_modify_generator,
dfw_delete_udf,
dfw_add_difference,
dfw_delete_difference,
dfw_begin_backup,
dfw_end_backup,
dfw_user_management,
// deferred works argument types
dfw_arg_index_name, // index name for dfw_delete_expression_index, mandatory
dfw_arg_partner_rel_id, // partner relation id for dfw_delete_index if index is FK, optional
dfw_arg_proc_name, // procedure name for dfw_delete_prm, mandatory
dfw_arg_force_computed, // we need to drop dependencies from a field that WAS computed
dfw_arg_check_blr, // check if BLR is still compilable
dfw_arg_rel_name, // relation name of a trigger
dfw_arg_trg_type, // trigger type
dfw_arg_new_name // new name
2002-07-01 17:07:18 +02:00
};
2001-05-23 15:26:42 +02:00
class DeferredWork : public pool_alloc<type_dfw>
2001-12-24 03:51:06 +01:00
{
public:
enum dfw_t dfw_type; /* type of work deferred */
DeferredWork* dfw_next; /* next block in transaction */
Lock* dfw_lock; /* relation creation lock */
DeferredWork* dfw_args; /* arguments */
SLONG dfw_sav_number; /* save point number */
USHORT dfw_id; /* object id, if appropriate */
USHORT dfw_count; /* count of block posts */
Firebird::string dfw_name; /* name of object */
public:
DeferredWork(MemoryPool& p, enum dfw_t t, USHORT id, SLONG sn, const char* string, USHORT length)
: dfw_type(t), dfw_next(NULL), dfw_lock(NULL), dfw_args(NULL),
dfw_sav_number(sn), dfw_id(id), dfw_count(1), dfw_name(p)
{
if (string)
{
dfw_name.assign(string, length);
}
}
~DeferredWork();
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
/* Verb actions */
2008-04-19 11:42:01 +02:00
class UndoItem
{
public:
SINT64 rec_number;
Record* rec_data;
2008-04-19 11:42:01 +02:00
static const SINT64& generate(const void *sender, const UndoItem& item)
{
return item.rec_number;
}
2008-04-19 11:42:01 +02:00
UndoItem() {}
UndoItem(SINT64 rec_numberL, Record* rec_dataL)
{
2004-05-12 21:39:17 +02:00
this->rec_number = rec_numberL;
this->rec_data = rec_dataL;
}
};
typedef Firebird::BePlusTree<UndoItem, SINT64, MemoryPool, UndoItem> UndoItemTree;
class VerbAction : public pool_alloc<type_vct>
2001-12-24 03:51:06 +01:00
{
2008-04-19 11:42:01 +02:00
public:
VerbAction* vct_next; /* Next action within verb */
jrd_rel* vct_relation; /* Relation involved */
RecordBitmap* vct_records; /* Record involved */
UndoItemTree* vct_undo; /* Data for undo records */
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
} //namespace Jrd
2001-05-23 15:26:42 +02:00
#endif // JRD_TRA_H