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 21:20:44 +01:00
|
|
|
* 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
|
2004-02-20 07:43:27 +01:00
|
|
|
* 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"
|
2003-03-02 21:07:32 +01:00
|
|
|
#include "../common/classes/tree.h"
|
2004-11-24 21:48:59 +01:00
|
|
|
#include "../common/classes/GenericMap.h"
|
2004-04-18 04:50:38 +02:00
|
|
|
#include "../jrd/exe.h"
|
2008-02-28 14:48:16 +01:00
|
|
|
#include "../jrd/rpb_chain.h"
|
2004-06-22 22:13:10 +02:00
|
|
|
#include "../jrd/blb.h" // For bid structure
|
2004-09-28 08:28:38 +02:00
|
|
|
#include "../jrd/sbm.h" // For bid structure
|
2009-09-04 08:11:55 +02:00
|
|
|
#include "../jrd/sort.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-17 19:44:18 +02:00
|
|
|
#include "../jrd/DatabaseSnapshot.h"
|
2008-01-16 11:25:04 +01:00
|
|
|
#include "../jrd/TempSpace.h"
|
2006-07-17 19:44:18 +02:00
|
|
|
|
2008-04-09 22:18:47 +02:00
|
|
|
namespace EDS {
|
|
|
|
class Transaction;
|
2008-04-10 11:50:17 +02:00
|
|
|
}
|
2008-04-09 22:18:47 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
namespace Jrd {
|
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
class blb;
|
2004-03-18 06:56:06 +01:00
|
|
|
class Lock;
|
2004-03-11 06:04:26 +01:00
|
|
|
class jrd_rel;
|
2005-12-02 08:35:34 +01:00
|
|
|
template <typename T> class vec;
|
2004-03-18 06:56:06 +01:00
|
|
|
class Savepoint;
|
|
|
|
class Record;
|
|
|
|
class VerbAction;
|
2004-03-19 07:14:53 +01:00
|
|
|
class ArrayField;
|
2004-10-03 06:49:04 +02:00
|
|
|
class Attachment;
|
2008-02-28 14:48:16 +01:00
|
|
|
class DeferredWork;
|
2009-09-29 12:35:16 +02:00
|
|
|
class DeferredJob;
|
2008-02-28 14:48:16 +01:00
|
|
|
class dsql_opn;
|
2009-02-19 13:59:32 +01:00
|
|
|
class UserManagement;
|
|
|
|
class thread_db;
|
2004-03-19 07:14:53 +01:00
|
|
|
|
2009-03-01 11:25:54 +01:00
|
|
|
|
2009-03-01 16:58:24 +01:00
|
|
|
const SLONG MAX_TRA_NUMBER = MAX_SLONG;
|
2009-03-01 11:25:54 +01:00
|
|
|
|
2008-12-05 01:56:15 +01:00
|
|
|
// Blobs active in transaction identified by bli_temp_id. Please keep this
|
2004-06-22 22:13:10 +02:00
|
|
|
// structure small as there can be huge amount of them floating in memory.
|
2008-04-19 11:42:01 +02:00
|
|
|
struct BlobIndex
|
|
|
|
{
|
2004-06-22 22:13:10 +02:00
|
|
|
ULONG bli_temp_id;
|
|
|
|
bool bli_materialized;
|
|
|
|
jrd_req* bli_request;
|
2008-04-19 11:42:01 +02:00
|
|
|
union
|
|
|
|
{
|
2009-07-17 11:02:38 +02:00
|
|
|
bid bli_blob_id; // ID of materialized blob
|
|
|
|
blb* bli_blob_object; // Blob object
|
2004-06-22 22:13:10 +02:00
|
|
|
};
|
2009-04-26 12:24:44 +02:00
|
|
|
static const ULONG& generate(const void* /*sender*/, const BlobIndex& item)
|
2008-04-19 11:42:01 +02:00
|
|
|
{
|
2004-06-22 22:13:10 +02:00
|
|
|
return item.bli_temp_id;
|
|
|
|
}
|
|
|
|
// Empty default constructor to make it behave like POD structure
|
|
|
|
BlobIndex() {}
|
2008-12-05 01:56:15 +01:00
|
|
|
BlobIndex(ULONG temp_id, blb* blob_object) :
|
|
|
|
bli_temp_id(temp_id), bli_materialized(false), bli_request(NULL),
|
|
|
|
bli_blob_object(blob_object)
|
2004-06-22 22:13:10 +02:00
|
|
|
{ }
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef Firebird::BePlusTree<BlobIndex, ULONG, MemoryPool, BlobIndex> BlobIndexTree;
|
2004-02-20 07:43:27 +01:00
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
// Transaction block
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-10-30 20:04:27 +01:00
|
|
|
const int DEFAULT_LOCK_TIMEOUT = -1; // infinite
|
2008-10-14 12:32:54 +02:00
|
|
|
const char* const TRA_BLOB_SPACE = "fb_blob_";
|
|
|
|
const char* const TRA_UNDO_SPACE = "fb_undo_";
|
2006-10-30 20:04:27 +01:00
|
|
|
|
2008-05-06 10:46:39 +02: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:
|
2004-10-07 11:15:32 +02:00
|
|
|
enum wait_t {
|
|
|
|
tra_no_wait,
|
|
|
|
tra_probe,
|
|
|
|
tra_wait
|
|
|
|
};
|
|
|
|
|
2008-05-06 10:46:39 +02:00
|
|
|
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),
|
2008-05-06 10:46:39 +02:00
|
|
|
tra_memory_stats(parent_stats),
|
2008-04-05 21:28:52 +02:00
|
|
|
tra_blobs_tree(p),
|
2013-02-28 17:24:31 +01:00
|
|
|
tra_blobs(outer ? outer->tra_blobs : &tra_blobs_tree),
|
|
|
|
tra_arrays(NULL),
|
2009-09-29 12:35:16 +02:00
|
|
|
tra_deferred_job(NULL),
|
2008-01-16 11:25:04 +01:00
|
|
|
tra_resources(*p),
|
|
|
|
tra_context_vars(*p),
|
2008-02-28 19:42:30 +01:00
|
|
|
tra_lock_timeout(DEFAULT_LOCK_TIMEOUT),
|
2008-03-27 10:14:24 +01:00
|
|
|
tra_timestamp(Firebird::TimeStamp::getCurrentTimeStamp()),
|
2009-02-01 23:10:12 +01:00
|
|
|
tra_stats(*p),
|
2008-04-05 21:28:52 +02:00
|
|
|
tra_open_cursors(*p),
|
2008-05-06 10:46:39 +02:00
|
|
|
tra_outer(outer),
|
2008-10-14 12:32:54 +02:00
|
|
|
tra_transactions(*p),
|
2009-09-05 20:18:24 +02:00
|
|
|
tra_sorts(*p),
|
2008-10-16 12:14:35 +02:00
|
|
|
tra_blob_space(NULL),
|
|
|
|
tra_undo_space(NULL),
|
2009-02-19 13:59:32 +01:00
|
|
|
tra_undo_record(NULL),
|
2013-02-27 15:49:45 +01:00
|
|
|
tra_user_management(NULL),
|
|
|
|
tra_autonomous_pool(NULL),
|
|
|
|
tra_autonomous_cnt(0)
|
2008-04-05 21:28:52 +02:00
|
|
|
{
|
2008-05-06 10:46:39 +02:00
|
|
|
tra_transactions.resize(length);
|
2008-04-05 21:28:52 +02:00
|
|
|
}
|
2006-10-07 12:53:01 +02:00
|
|
|
|
2008-05-21 10:13:20 +02:00
|
|
|
~jrd_tra();
|
2008-05-06 10:46:39 +02:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2013-02-27 15:49:45 +01:00
|
|
|
jrd_tra* outer = transaction->tra_outer;
|
|
|
|
MemoryPool* const pool = transaction->tra_pool;
|
2008-05-06 10:46:39 +02:00
|
|
|
delete transaction;
|
2013-02-27 15:49:45 +01:00
|
|
|
outer->releaseAutonomousPool(pool);
|
2008-05-06 10:46:39 +02:00
|
|
|
}
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
Attachment* tra_attachment; // database attachment
|
|
|
|
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
|
2011-06-24 15:08:59 +02:00
|
|
|
SLONG tra_att_oldest_active; // oldest active transaction in the same attachment
|
2009-07-17 11:02:38 +02:00
|
|
|
jrd_tra* tra_next; // next transaction in database
|
|
|
|
jrd_tra* tra_sibling; // next transaction in group
|
|
|
|
MemoryPool* const tra_pool; // pool for transaction
|
2008-05-06 10:46:39 +02:00
|
|
|
Firebird::MemoryStats tra_memory_stats;
|
2009-07-17 11:02:38 +02:00
|
|
|
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
|
|
|
|
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
|
|
|
|
SLONG tra_save_point_number; // next save point number to use
|
2001-05-23 15:26:42 +02:00
|
|
|
ULONG tra_flags;
|
2009-09-29 12:35:16 +02:00
|
|
|
DeferredJob* tra_deferred_job; // work deferred to commit time
|
2009-07-17 11:02:38 +02:00
|
|
|
ResourceList tra_resources; // resource existence list
|
2004-11-22 21:22:03 +01:00
|
|
|
Firebird::StringMap tra_context_vars; // Context variables for the transaction
|
2009-07-17 11:02:38 +02:00
|
|
|
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
|
2009-07-17 11:02:38 +02:00
|
|
|
jrd_req* tra_requests; // Doubly linked list of requests active in this transaction
|
|
|
|
DatabaseSnapshot* tra_db_snapshot; // Database state snapshot (for monitoring purposes)
|
2006-10-07 12:53:01 +02:00
|
|
|
RuntimeStatistics tra_stats;
|
2008-02-28 14:48:16 +01:00
|
|
|
Firebird::Array<dsql_req*> tra_open_cursors;
|
2009-07-17 11:02:38 +02:00
|
|
|
jrd_tra* const tra_outer; // outer transaction of an autonomous transaction
|
|
|
|
jrd_req* tra_callback_caller; // caller request for execute statement
|
2008-05-06 10:46:39 +02:00
|
|
|
Firebird::Array<UCHAR> tra_transactions;
|
2009-09-04 08:11:55 +02:00
|
|
|
SortOwner tra_sorts;
|
2008-01-16 11:25:04 +01:00
|
|
|
|
2008-04-09 22:18:47 +02:00
|
|
|
EDS::Transaction *tra_ext_common;
|
|
|
|
//Transaction *tra_ext_two_phase;
|
|
|
|
|
2008-01-16 11:25:04 +01:00
|
|
|
private:
|
2008-10-14 12:32:54 +02:00
|
|
|
TempSpace* tra_blob_space; // temp blob storage
|
|
|
|
TempSpace* tra_undo_space; // undo log storage
|
|
|
|
|
|
|
|
Record* tra_undo_record; // temporary record used for the undo purposes
|
2009-02-19 13:59:32 +01:00
|
|
|
UserManagement* tra_user_management;
|
2013-02-27 15:49:45 +01:00
|
|
|
MemoryPool* tra_autonomous_pool;
|
|
|
|
USHORT tra_autonomous_cnt;
|
|
|
|
static const USHORT TRA_AUTONOMOUS_PER_POOL = 64;
|
2008-01-16 11:25:04 +01:00
|
|
|
|
|
|
|
public:
|
2013-02-27 15:49:45 +01:00
|
|
|
MemoryPool* getAutonomousPool();
|
|
|
|
void releaseAutonomousPool(MemoryPool* toRelease);
|
2013-02-28 17:24:31 +01:00
|
|
|
jrd_tra* getOuter();
|
2013-02-27 15:49:45 +01:00
|
|
|
|
2004-10-07 11:15:32 +02:00
|
|
|
SSHORT getLockWait() const
|
|
|
|
{
|
|
|
|
return -tra_lock_timeout;
|
|
|
|
}
|
2008-01-16 11:25:04 +01:00
|
|
|
|
2008-10-14 12:32:54 +02:00
|
|
|
TempSpace* getBlobSpace()
|
2008-01-16 11:25:04 +01:00
|
|
|
{
|
2008-04-05 21:28:52 +02:00
|
|
|
if (tra_outer)
|
2008-10-14 12:32:54 +02:00
|
|
|
return tra_outer->getBlobSpace();
|
2008-04-05 21:28:52 +02:00
|
|
|
|
2008-10-14 12:32:54 +02:00
|
|
|
if (!tra_blob_space)
|
|
|
|
tra_blob_space = FB_NEW(*tra_pool) TempSpace(*tra_pool, TRA_BLOB_SPACE);
|
2008-01-16 11:25:04 +01:00
|
|
|
|
2008-10-14 12:32:54 +02:00
|
|
|
return tra_blob_space;
|
|
|
|
}
|
|
|
|
|
|
|
|
TempSpace* getUndoSpace()
|
|
|
|
{
|
|
|
|
if (!tra_undo_space)
|
2013-02-28 17:24:31 +01:00
|
|
|
{
|
|
|
|
fb_assert(!tra_outer);
|
2008-10-14 12:32:54 +02:00
|
|
|
tra_undo_space = FB_NEW(*tra_pool) TempSpace(*tra_pool, TRA_UNDO_SPACE);
|
2013-02-28 17:24:31 +01:00
|
|
|
}
|
2008-10-14 12:32:54 +02:00
|
|
|
|
|
|
|
return tra_undo_space;
|
|
|
|
}
|
|
|
|
|
|
|
|
Record* getUndoRecord(USHORT length)
|
|
|
|
{
|
|
|
|
if (!tra_undo_record || tra_undo_record->rec_length < length)
|
|
|
|
{
|
|
|
|
delete tra_undo_record;
|
|
|
|
tra_undo_record = FB_NEW_RPT(*tra_pool, length) Record(*tra_pool);
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(tra_undo_record, 0, sizeof(Record) + length);
|
|
|
|
|
|
|
|
return tra_undo_record;
|
2008-01-16 11:25:04 +01:00
|
|
|
}
|
2009-02-19 13:59:32 +01:00
|
|
|
|
|
|
|
UserManagement* getUserManagement();
|
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.
|
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
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
|
|
|
|
//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
|
2012-12-22 17:56:36 +01:00
|
|
|
const ULONG TRA_precommitted = 4194304L; // transaction committed at startup
|
2004-05-01 00:47:16 +02:00
|
|
|
|
2011-06-16 10:44:27 +02:00
|
|
|
// flags derived from TPB, see also transaction_options() at tra.cpp
|
|
|
|
const ULONG TRA_OPTIONS_MASK = (TRA_degree3 | TRA_readonly | TRA_ignore_limbo | TRA_read_committed |
|
|
|
|
TRA_autocommit | TRA_rec_version | TRA_no_auto_undo | TRA_restart_requests);
|
|
|
|
|
2004-05-01 00:47:16 +02:00
|
|
|
const int TRA_MASK = 3;
|
2006-02-23 06:08:26 +01:00
|
|
|
//const int TRA_BITS_PER_TRANS = 2;
|
|
|
|
//const int TRA_TRANS_PER_BYTE = 4;
|
2004-05-01 00:47:16 +02:00
|
|
|
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)
|
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
// Transaction cleanup. If a database is never quiescent, look
|
|
|
|
// for "dead" active transactions every so often at transaction
|
|
|
|
// startup
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-01 00:47:16 +02:00
|
|
|
const int TRA_ACTIVE_CLEANUP = 100;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
// Transaction states. The first four are states found
|
|
|
|
// in the transaction inventory page; the last two are
|
|
|
|
// returned internally
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
const int tra_active = 0; // Transaction is active
|
2004-05-01 00:47:16 +02:00
|
|
|
const int tra_limbo = 1;
|
|
|
|
const int tra_dead = 2;
|
|
|
|
const int tra_committed = 3;
|
2009-07-17 11:02:38 +02:00
|
|
|
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)))
|
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
// Savepoint block
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-18 06:56:06 +01:00
|
|
|
class Savepoint : public pool_alloc<type_sav>
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-04-19 11:42:01 +02:00
|
|
|
public:
|
2012-07-23 11:20:57 +02:00
|
|
|
~Savepoint()
|
|
|
|
{
|
|
|
|
deleteActions(sav_verb_actions);
|
|
|
|
deleteActions(sav_verb_free);
|
|
|
|
}
|
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
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
|
2004-03-18 06:56:06 +01:00
|
|
|
Savepoint* sav_next;
|
|
|
|
USHORT sav_flags;
|
2009-07-17 11:02:38 +02:00
|
|
|
TEXT sav_name[MAX_SQL_IDENTIFIER_SIZE]; // Savepoint name
|
2012-07-23 11:20:57 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
void deleteActions(VerbAction* list);
|
2001-12-24 03:51:06 +01:00
|
|
|
};
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
// Savepoint block flags.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
const int SAV_trans_level = 1; // savepoint was started by TRA_start
|
|
|
|
const int SAV_force_dfw = 2; // DFW is present even if savepoint is empty
|
|
|
|
const int SAV_user = 4; // named user savepoint as opposed to system ones
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-07-17 11:02:38 +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
|
2004-11-25 21:07:20 +01:00
|
|
|
const IPTR SAV_LARGE = 1024 * 32;
|
2002-11-03 18:29:51 +01:00
|
|
|
|
2009-07-17 11:02:38 +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
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-08-22 12:56:55 +02:00
|
|
|
enum dfw_t {
|
2001-05-23 15:26:42 +02:00
|
|
|
dfw_null,
|
2002-12-23 16:49:14 +01:00
|
|
|
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,
|
2007-08-04 04:11:07 +02:00
|
|
|
dfw_create_field,
|
2002-12-23 16:49:14 +01:00
|
|
|
dfw_delete_field,
|
2007-08-04 04:11:07 +02:00
|
|
|
dfw_modify_field,
|
2002-12-23 16:49:14 +01:00
|
|
|
dfw_delete_global,
|
|
|
|
dfw_delete_rfr,
|
|
|
|
dfw_post_event,
|
|
|
|
dfw_create_trigger,
|
|
|
|
dfw_delete_trigger,
|
|
|
|
dfw_modify_trigger,
|
2006-02-23 06:08:26 +01:00
|
|
|
//dfw_load_triggers,
|
2002-12-23 16:49:14 +01:00
|
|
|
dfw_grant,
|
|
|
|
dfw_revoke,
|
|
|
|
dfw_scan_relation,
|
|
|
|
dfw_create_expression_index,
|
|
|
|
dfw_delete_expression_index,
|
|
|
|
dfw_create_procedure,
|
|
|
|
dfw_modify_procedure,
|
|
|
|
dfw_delete_procedure,
|
2008-12-05 01:56:15 +01:00
|
|
|
dfw_delete_prm,
|
2007-04-15 17:57:12 +02:00
|
|
|
dfw_create_collation,
|
2006-08-07 18:39:21 +02:00
|
|
|
dfw_delete_collation,
|
2008-12-05 01:56:15 +01:00
|
|
|
dfw_delete_exception,
|
2006-02-23 06:08:26 +01:00
|
|
|
//dfw_unlink_file,
|
2002-12-23 16:49:14 +01:00
|
|
|
dfw_delete_generator,
|
2004-07-06 07:59:40 +02:00
|
|
|
dfw_modify_generator,
|
2003-08-06 18:30:49 +02:00
|
|
|
dfw_delete_udf,
|
|
|
|
dfw_add_difference,
|
|
|
|
dfw_delete_difference,
|
|
|
|
dfw_begin_backup,
|
2005-08-02 13:41:37 +02:00
|
|
|
dfw_end_backup,
|
2008-05-21 10:13:20 +02:00
|
|
|
dfw_user_management,
|
2011-02-17 07:00:50 +01:00
|
|
|
dfw_create_generator,
|
2005-08-02 13:41:37 +02:00
|
|
|
|
2006-02-23 06:08:26 +01:00
|
|
|
// deferred works argument types
|
2005-08-02 13:41:37 +02:00
|
|
|
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
|
2006-07-11 06:57:28 +02:00
|
|
|
dfw_arg_proc_name, // procedure name for dfw_delete_prm, mandatory
|
2006-08-19 04:52:39 +02:00
|
|
|
dfw_arg_force_computed, // we need to drop dependencies from a field that WAS computed
|
2006-11-05 19:30:36 +01:00
|
|
|
dfw_arg_check_blr, // check if BLR is still compilable
|
|
|
|
dfw_arg_rel_name, // relation name of a trigger
|
2008-07-15 17:41:43 +02:00
|
|
|
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
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
// Verb actions
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-04-19 11:42:01 +02:00
|
|
|
class UndoItem
|
|
|
|
{
|
2003-03-02 21:07:32 +01:00
|
|
|
public:
|
2009-04-26 12:24:44 +02:00
|
|
|
static const SINT64& generate(const void* /*sender*/, const UndoItem& item)
|
2008-04-19 11:42:01 +02:00
|
|
|
{
|
2008-10-14 12:32:54 +02:00
|
|
|
return item.number;
|
2003-03-02 21:07:32 +01:00
|
|
|
}
|
2008-10-14 12:32:54 +02:00
|
|
|
|
2008-04-19 11:42:01 +02:00
|
|
|
UndoItem() {}
|
2008-10-14 12:32:54 +02:00
|
|
|
|
|
|
|
UndoItem(RecordNumber recordNumber, UCHAR recordFlags)
|
|
|
|
: number(recordNumber.getValue()),
|
2008-10-25 04:20:54 +02:00
|
|
|
flags(recordFlags),
|
|
|
|
length(0), offset(0), format(NULL)
|
2008-10-14 12:32:54 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
UndoItem(jrd_tra* transaction, RecordNumber recordNumber, const Record* record, UCHAR recordFlags)
|
|
|
|
: number(recordNumber.getValue()),
|
2008-10-25 04:20:54 +02:00
|
|
|
flags(recordFlags),
|
2008-10-14 12:32:54 +02:00
|
|
|
length(record->rec_length),
|
2008-10-16 12:14:35 +02:00
|
|
|
offset(0),
|
2008-10-25 04:20:54 +02:00
|
|
|
format(record->rec_format)
|
2008-10-14 12:32:54 +02:00
|
|
|
{
|
|
|
|
if (length)
|
|
|
|
{
|
|
|
|
offset = transaction->getUndoSpace()->allocateSpace(length);
|
|
|
|
transaction->getUndoSpace()->write(offset, record->rec_data, length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Record* setupRecord(jrd_tra* transaction, UCHAR newFlags = 0)
|
2008-04-19 11:42:01 +02:00
|
|
|
{
|
2008-10-14 12:32:54 +02:00
|
|
|
flags |= newFlags;
|
|
|
|
|
|
|
|
Record* const record = transaction->getUndoRecord(length);
|
|
|
|
record->rec_number.setValue(number);
|
|
|
|
record->rec_flags = flags;
|
|
|
|
record->rec_length = length;
|
|
|
|
record->rec_format = format;
|
|
|
|
|
|
|
|
if (length)
|
|
|
|
{
|
|
|
|
transaction->getUndoSpace()->read(offset, record->rec_data, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
return record;
|
2003-03-02 21:07:32 +01:00
|
|
|
}
|
2008-10-14 12:32:54 +02:00
|
|
|
|
|
|
|
void release(jrd_tra* transaction)
|
|
|
|
{
|
|
|
|
if (length)
|
|
|
|
{
|
|
|
|
transaction->getUndoSpace()->releaseSpace(offset, length);
|
|
|
|
length = 0;
|
|
|
|
format = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
SINT64 number;
|
|
|
|
UCHAR flags;
|
|
|
|
USHORT length;
|
|
|
|
offset_t offset;
|
|
|
|
const Format* format;
|
2003-03-02 21:07:32 +01:00
|
|
|
};
|
|
|
|
|
2004-09-28 08:28:38 +02:00
|
|
|
typedef Firebird::BePlusTree<UndoItem, SINT64, MemoryPool, UndoItem> UndoItemTree;
|
2003-03-02 21:07:32 +01:00
|
|
|
|
2004-03-18 06:56:06 +01:00
|
|
|
class VerbAction : public pool_alloc<type_vct>
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-04-19 11:42:01 +02:00
|
|
|
public:
|
2012-07-23 11:20:57 +02:00
|
|
|
~VerbAction()
|
|
|
|
{
|
|
|
|
delete vct_records;
|
|
|
|
delete vct_undo;
|
|
|
|
}
|
|
|
|
|
2009-07-17 11:02:38 +02:00
|
|
|
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
|
|
|
|
2012-07-23 11:20:57 +02:00
|
|
|
|
|
|
|
inline void Savepoint::deleteActions(VerbAction* list)
|
|
|
|
{
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
VerbAction* next = list->vct_next;
|
|
|
|
delete list;
|
|
|
|
list = next;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
} //namespace Jrd
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
#endif // JRD_TRA_H
|