8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 04:43:03 +01:00

CORE-4965: Extend the transaction ID space beyond 2^32 transactions. Initially developed in the v2.5 custom branch, then reworked and now merged into v3.0.

This commit is contained in:
dimitr 2015-10-19 13:32:02 +00:00
parent ae3b91aef3
commit 4e4d8002e5
67 changed files with 1237 additions and 917 deletions

View File

@ -308,7 +308,7 @@ int alice(Firebird::UtilSvc* uSvc)
ALICE_error(10); // msg 10: transaction number or "all" required
}
ALICE_upper_case(*argv++, string, sizeof(string));
if (!(tdgbl->ALICE_data.ua_transaction = atoi(string)))
if (!sscanf(string, "%"SQUADFORMAT, &tdgbl->ALICE_data.ua_transaction))
{
if (strcmp(string, "ALL")) {
ALICE_error(10); // msg 10: transaction number or "all" required

View File

@ -79,7 +79,7 @@ struct user_action
bool ua_read_only;
SLONG ua_shutdown_delay;
SLONG ua_sweep_interval;
SLONG ua_transaction;
TraNumber ua_transaction;
SLONG ua_page_buffers;
USHORT ua_debug;
ULONG ua_val_errors[MAX_VAL_ERRORS];
@ -100,19 +100,19 @@ public:
UCHAR str_data[2];
};
// Transaction block: used to store info about a multidatabase transaction.
// Transaction block: used to store info about a multi-database transaction.
// Transaction Description Record
struct tdr : public pool_alloc<alice_type_tdr>
{
tdr* tdr_next; // next subtransaction
SLONG tdr_id; // database-specific transaction id
tdr* tdr_next; // next sub-transaction
TraNumber tdr_id; // database-specific transaction id
alice_str* tdr_fullpath; // full (possibly) remote pathname
const TEXT* tdr_filename; // filename within full pathname
alice_str* tdr_host_site; // host for transaction
alice_str* tdr_remote_site; // site for remote transaction
FB_API_HANDLE tdr_handle; // reconnected transaction handle
FB_API_HANDLE tdr_db_handle; // reattached database handle
FB_API_HANDLE tdr_db_handle; // re-attached database handle
USHORT tdr_db_caps; // capabilities of database
USHORT tdr_state; // see flags below
};

View File

@ -164,7 +164,7 @@ void MET_get_state(ISC_STATUS* user_status, tdr* trans)
* in other databases.
*/
tdr* MET_get_transaction(ISC_STATUS* user_status, isc_db_handle handle, SLONG id)
tdr* MET_get_transaction(ISC_STATUS* user_status, isc_db_handle handle, TraNumber id)
{
FB_API_HANDLE request = 0;
tdr* trans = NULL;
@ -328,7 +328,8 @@ static tdr* get_description(ISC_QUAD* blob_id)
++p;
tdr* ptr = NULL; // silence uninitialized warning
SLONG id_length, id;
SLONG id_length;
TraNumber id;
while (*p)
{
@ -344,7 +345,7 @@ static tdr* get_description(ISC_QUAD* blob_id)
case TDR_TRANSACTION_ID:
id_length = *p++;
id = gds__vax_integer(reinterpret_cast<const UCHAR*>(p), id_length);
id = isc_portable_integer(reinterpret_cast<const UCHAR*>(p), id_length);
p += id_length;
if (!trans) {
trans = ptr = FB_NEW_POOL(*tdgbl->getDefaultPool()) tdr;

View File

@ -26,7 +26,7 @@
void MET_disable_wal(ISC_STATUS*, isc_db_handle);
void MET_get_state(ISC_STATUS*, tdr*);
tdr* MET_get_transaction(ISC_STATUS*, isc_db_handle, SLONG);
tdr* MET_get_transaction(ISC_STATUS*, isc_db_handle, TraNumber);
void MET_set_capabilities(ISC_STATUS*, tdr*);
#endif // ALICE_ALICE_META_H

View File

@ -53,7 +53,7 @@ static SINT64 ask();
static void print_description(const tdr*);
static void reattach_database(tdr*);
static void reattach_databases(tdr*);
static bool reconnect(FB_API_HANDLE, SLONG, const TEXT*, SINT64);
static bool reconnect(FB_API_HANDLE, TraNumber, const TEXT*, SINT64);
static const UCHAR limbo_info[] = { isc_info_limbo, isc_info_end };
@ -285,7 +285,7 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche
return;
}
SLONG id;
TraNumber id;
tdr* trans;
UCHAR* ptr = buffer;
bool flag = true;
@ -298,7 +298,7 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche
switch (item)
{
case isc_info_limbo:
id = gds__vax_integer(ptr, length);
id = isc_portable_integer(ptr, length);
if (switches & (sw_commit | sw_rollback | sw_two_phase | sw_prompt))
{
TDR_reconnect_multiple(handle, id, name, switches);
@ -312,16 +312,19 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche
}
if (trans = MET_get_transaction(status_vector, handle, id))
{
tdgbl->uSvc->putSLong(isc_spb_multi_tra_id, id);
if (id > TraNumber(MAX_SLONG))
tdgbl->uSvc->putSInt64(isc_spb_multi_tra_id_64, id);
else
tdgbl->uSvc->putSLong(isc_spb_multi_tra_id, (SLONG) id);
reattach_databases(trans);
TDR_get_states(trans);
TDR_shutdown_databases(trans);
print_description(trans);
}
else if (id > TraNumber(MAX_SLONG))
tdgbl->uSvc->putSInt64(isc_spb_single_tra_id_64, id);
else
{
tdgbl->uSvc->putSLong(isc_spb_single_tra_id, id);
}
tdgbl->uSvc->putSLong(isc_spb_single_tra_id, (SLONG) id);
ptr += length;
break;
@ -362,7 +365,7 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche
// gfix user.
//
bool TDR_reconnect_multiple(FB_API_HANDLE handle, SLONG id, const TEXT* name, SINT64 switches)
bool TDR_reconnect_multiple(FB_API_HANDLE handle, TraNumber id, const TEXT* name, SINT64 switches)
{
ISC_STATUS_ARRAY status_vector;
@ -531,7 +534,10 @@ static void print_description(const tdr* trans)
// msg 94: Transaction %ld
ALICE_print(94, SafeArg() << ptr->tdr_id);
}
tdgbl->uSvc->putSLong(isc_spb_tra_id, ptr->tdr_id);
if (ptr->tdr_id > TraNumber(MAX_SLONG))
tdgbl->uSvc->putSInt64(isc_spb_tra_id_64, ptr->tdr_id);
else
tdgbl->uSvc->putSLong(isc_spb_tra_id, (SLONG) ptr->tdr_id);
}
switch (ptr->tdr_state)
@ -808,14 +814,13 @@ static void reattach_databases(tdr* trans)
// Commit or rollback a named transaction.
//
static bool reconnect(FB_API_HANDLE handle, SLONG number, const TEXT* name, SINT64 switches)
static bool reconnect(FB_API_HANDLE handle, TraNumber number, const TEXT* name, SINT64 switches)
{
ISC_STATUS_ARRAY status_vector;
const SLONG id = gds__vax_integer(reinterpret_cast<const UCHAR*>(&number), 4);
FB_API_HANDLE transaction = 0;
if (isc_reconnect_transaction(status_vector, &handle, &transaction,
sizeof(id), reinterpret_cast<const char*>(&id)))
sizeof(number), reinterpret_cast<const char*>(&number)))
{
ALICE_print(90, SafeArg() << name);
// msg 90: failed to reconnect to a transaction in database %s

View File

@ -25,7 +25,7 @@
#define ALICE_TDR_PROTO_H
void TDR_list_limbo(FB_API_HANDLE, const TEXT*, const SINT64);
bool TDR_reconnect_multiple(FB_API_HANDLE, SLONG, const TEXT*, SINT64);
bool TDR_reconnect_multiple(FB_API_HANDLE, TraNumber, const TEXT*, SINT64);
void TDR_shutdown_databases(tdr*);
USHORT TDR_analyze(const tdr*);
bool TDR_attach_database(ISC_STATUS*, tdr*, const TEXT*);

View File

@ -134,6 +134,7 @@ public:
virtual void started() { }
virtual void putLine(char, const char*) { }
virtual void putSLong(char, SLONG) { }
virtual void putSInt64(char, SINT64) { }
virtual void putChar(char, char) { }
virtual void putBytes(const UCHAR*, FB_SIZE_T) { }
virtual ULONG getBytes(UCHAR*, ULONG) { return 0; }

View File

@ -60,6 +60,7 @@ public:
virtual void printf(bool err, const SCHAR* format, ...) = 0;
virtual void putLine(char, const char*) = 0;
virtual void putSLong(char, SLONG) = 0;
virtual void putSInt64(char, SINT64) = 0;
virtual void putChar(char, char) = 0;
virtual void putBytes(const UCHAR*, FB_SIZE_T) = 0;
virtual ULONG getBytes(UCHAR*, ULONG) = 0;

View File

@ -6055,12 +6055,29 @@ void InternalInfoNode::genBlr(DsqlCompilerScratch* dsqlScratch)
void InternalInfoNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc)
{
InfoType infoType = static_cast<InfoType>(arg->as<LiteralNode>()->getSlong());
const InfoType infoType = static_cast<InfoType>(arg->as<LiteralNode>()->getSlong());
if (infoType == INFO_TYPE_SQLSTATE)
desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii);
else
desc->makeLong(0);
switch (infoType)
{
case INFO_TYPE_SQLSTATE:
desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii);
break;
case INFO_TYPE_CONNECTION_ID:
case INFO_TYPE_TRANSACTION_ID:
case INFO_TYPE_ROWS_AFFECTED:
desc->makeInt64(0);
break;
case INFO_TYPE_GDSCODE:
case INFO_TYPE_SQLCODE:
case INFO_TYPE_TRIGGER_ACTION:
desc->makeLong(0);
break;
default:
fb_assert(false);
}
}
void InternalInfoNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
@ -6071,12 +6088,29 @@ void InternalInfoNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
arg->getDesc(tdbb, csb, &argDesc);
fb_assert(argDesc.dsc_dtype == dtype_long);
InfoType infoType = static_cast<InfoType>(*reinterpret_cast<SLONG*>(argDesc.dsc_address));
const InfoType infoType = static_cast<InfoType>(*reinterpret_cast<SLONG*>(argDesc.dsc_address));
if (infoType == INFO_TYPE_SQLSTATE)
desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii);
else
desc->makeLong(0);
switch (infoType)
{
case INFO_TYPE_SQLSTATE:
desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii);
break;
case INFO_TYPE_CONNECTION_ID:
case INFO_TYPE_TRANSACTION_ID:
case INFO_TYPE_ROWS_AFFECTED:
desc->makeInt64(0);
break;
case INFO_TYPE_GDSCODE:
case INFO_TYPE_SQLCODE:
case INFO_TYPE_TRIGGER_ACTION:
desc->makeLong(0);
break;
default:
fb_assert(false);
}
}
ValueExprNode* InternalInfoNode::copy(thread_db* tdbb, NodeCopier& copier) const
@ -6108,53 +6142,53 @@ dsc* InternalInfoNode::execute(thread_db* tdbb, jrd_req* request) const
return NULL;
fb_assert(value->dsc_dtype == dtype_long);
InfoType infoType = static_cast<InfoType>(*reinterpret_cast<SLONG*>(value->dsc_address));
const InfoType infoType = static_cast<InfoType>(*reinterpret_cast<SLONG*>(value->dsc_address));
dsc desc;
if (infoType == INFO_TYPE_SQLSTATE)
{
FB_SQLSTATE_STRING sqlstate;
request->req_last_xcp.as_sqlstate(sqlstate);
dsc desc;
desc.makeText(FB_SQLSTATE_LENGTH, ttype_ascii, (UCHAR*) sqlstate);
EVL_make_value(tdbb, &desc, impure);
return &impure->vlu_desc;
}
SLONG result = 0;
switch (infoType)
else
{
case INFO_TYPE_CONNECTION_ID:
result = PAG_attachment_id(tdbb);
break;
case INFO_TYPE_TRANSACTION_ID:
//fb_assert(sizeof(result) == sizeof(tdbb->getTransaction()->tra_number));
// Conversion from unsigned to SLONG, big values will be reported as negative.
result = tdbb->getTransaction()->tra_number;
break;
case INFO_TYPE_GDSCODE:
result = request->req_last_xcp.as_gdscode();
break;
case INFO_TYPE_SQLCODE:
result = request->req_last_xcp.as_sqlcode();
break;
case INFO_TYPE_ROWS_AFFECTED:
// CVC: Not sure if this counter can overflow in extreme cases
result = request->req_records_affected.getCount();
break;
case INFO_TYPE_TRIGGER_ACTION:
result = request->req_trigger_action;
break;
default:
BUGCHECK(232); // msg 232 EVL_expr: invalid operation
SLONG int32_result = 0;
SINT64 int64_result = 0;
switch (infoType)
{
case INFO_TYPE_CONNECTION_ID:
int64_result = PAG_attachment_id(tdbb);
break;
case INFO_TYPE_TRANSACTION_ID:
int64_result = tdbb->getTransaction()->tra_number;
break;
case INFO_TYPE_GDSCODE:
int32_result = request->req_last_xcp.as_gdscode();
break;
case INFO_TYPE_SQLCODE:
int32_result = request->req_last_xcp.as_sqlcode();
break;
case INFO_TYPE_ROWS_AFFECTED:
int64_result = request->req_records_affected.getCount();
break;
case INFO_TYPE_TRIGGER_ACTION:
int32_result = request->req_trigger_action;
break;
default:
BUGCHECK(232); // msg 232 EVL_expr: invalid operation
}
if (int64_result)
desc.makeInt64(0, &int64_result);
else
desc.makeLong(0, &int32_result);
}
dsc desc;
desc.makeLong(0, &result);
EVL_make_value(tdbb, &desc, impure);
return &impure->vlu_desc;
}
@ -8130,7 +8164,7 @@ void RecordKeyNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc)
{
if (dbKeyLength == 8)
{
desc->makeLong(0);
desc->makeInt64(0);
desc->setNullable(true);
}
else
@ -8181,13 +8215,13 @@ void RecordKeyNode::getDesc(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, dsc*
case blr_record_version:
desc->dsc_dtype = dtype_text;
desc->dsc_ttype() = ttype_binary;
desc->dsc_length = sizeof(SLONG);
desc->dsc_length = sizeof(SINT64);
desc->dsc_scale = 0;
desc->dsc_flags = 0;
break;
case blr_record_version2:
desc->makeLong(0);
desc->makeInt64(0);
break;
}
}
@ -8433,10 +8467,10 @@ dsc* RecordKeyNode::execute(thread_db* /*tdbb*/, jrd_req* request) const
// Initialize descriptor
impure->vlu_misc.vlu_long = rpb->rpb_transaction_nr;
impure->vlu_desc.dsc_address = (UCHAR*) &impure->vlu_misc.vlu_long;
impure->vlu_misc.vlu_int64 = rpb->rpb_transaction_nr;
impure->vlu_desc.dsc_address = (UCHAR*) &impure->vlu_misc.vlu_int64;
impure->vlu_desc.dsc_dtype = dtype_text;
impure->vlu_desc.dsc_length = 4;
impure->vlu_desc.dsc_length = sizeof(SINT64);
impure->vlu_desc.dsc_ttype() = ttype_binary;
}
else if (blrOp == blr_record_version2)
@ -8450,8 +8484,8 @@ dsc* RecordKeyNode::execute(thread_db* /*tdbb*/, jrd_req* request) const
return NULL;
}
impure->vlu_misc.vlu_long = rpb->rpb_transaction_nr;
impure->vlu_desc.makeLong(0, &impure->vlu_misc.vlu_long);
impure->vlu_misc.vlu_int64 = rpb->rpb_transaction_nr;
impure->vlu_desc.makeInt64(0, &impure->vlu_misc.vlu_int64);
}
return &impure->vlu_desc;

View File

@ -60,11 +60,6 @@ const StreamType STREAM_MAP_LENGTH = MAX_STREAMS + 2;
// New formula is simply MAX_STREAMS / BITS_PER_LONG
const int OPT_STREAM_BITS = MAX_STREAMS / BITS_PER_LONG; // 128 with 4096 streams
// Number of streams, conjuncts, indices that will be statically allocated
// in various arrays. Larger numbers will have to be allocated dynamically
// CVC: I think we need to have a special, higher value for streams.
const int OPT_STATIC_ITEMS = 64;
typedef Firebird::HalfStaticArray<StreamType, OPT_STATIC_ITEMS> StreamList;
typedef Firebird::SortedArray<StreamType> SortedStreamList;

View File

@ -7358,7 +7358,7 @@ void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
parameter->par_desc.dsc_dtype = dtype_text;
parameter->par_desc.dsc_ttype() = ttype_binary;
parameter->par_desc.dsc_length = relation->rel_dbkey_length / 2;
parameter->par_desc.dsc_length = sizeof(SINT64);
}
}
}

View File

@ -468,6 +468,9 @@
#define isc_spb_tra_advise_commit 30
#define isc_spb_tra_advise_rollback 31
#define isc_spb_tra_advise_unknown 33
#define isc_spb_tra_id_64 46
#define isc_spb_single_tra_id_64 47
#define isc_spb_multi_tra_id_64 48
#define isc_spb_rpr_validate_db 0x01
#define isc_spb_rpr_sweep_db 0x02

View File

@ -142,9 +142,6 @@ typedef USHORT TTYPE_ID;
// Stream type, had to move it from dsql/Nodes.h due to circular dependencies.
typedef ULONG StreamType;
// The type of Jrd's transaction.
typedef ULONG TraNumber;
// Alignment rule
template <typename T>
inline T FB_ALIGN(T n, uintptr_t b)
@ -152,4 +149,10 @@ inline T FB_ALIGN(T n, uintptr_t b)
return (T) ((((uintptr_t) n) + b - 1) & ~(b - 1));
}
// Various object IDs (longer-than-32-bit)
typedef SINT64 AttNumber;
typedef SINT64 TraNumber;
typedef SINT64 StmtNumber;
#endif /* INCLUDE_FB_TYPES_H */

View File

@ -983,7 +983,7 @@ interface TraceConnection : Versioned
interface TraceDatabaseConnection : TraceConnection
{
int getConnectionID();
int64 getConnectionID();
const string getDatabaseName();
}
@ -994,7 +994,7 @@ interface TraceTransaction : Versioned
const uint ISOLATION_READ_COMMITTED_RECVER = 3;
const uint ISOLATION_READ_COMMITTED_NORECVER = 4;
uint getTransactionID();
int64 getTransactionID();
boolean getReadOnly();
int getWait();
uint getIsolation();
@ -1009,7 +1009,7 @@ interface TraceParams : Versioned
interface TraceStatement : Versioned
{
int getStmtID();
int64 getStmtID();
PerformanceInfo* getPerf();
}
@ -1092,10 +1092,10 @@ interface TraceStatusVector : Versioned
interface TraceSweepInfo : Versioned
{
uint64 getOIT();
uint64 getOST();
uint64 getOAT();
uint64 getNext();
int64 getOIT();
int64 getOST();
int64 getOAT();
int64 getNext();
PerformanceInfo* getPerf();
}

View File

@ -3829,7 +3829,7 @@ namespace Firebird
public:
struct VTable : public ITraceConnection::VTable
{
int (CLOOP_CARG *getConnectionID)(ITraceDatabaseConnection* self) throw();
ISC_INT64 (CLOOP_CARG *getConnectionID)(ITraceDatabaseConnection* self) throw();
const char* (CLOOP_CARG *getDatabaseName)(ITraceDatabaseConnection* self) throw();
};
@ -3846,9 +3846,9 @@ namespace Firebird
public:
static const unsigned VERSION = 3;
int getConnectionID()
ISC_INT64 getConnectionID()
{
int ret = static_cast<VTable*>(this->cloopVTable)->getConnectionID(this);
ISC_INT64 ret = static_cast<VTable*>(this->cloopVTable)->getConnectionID(this);
return ret;
}
@ -3864,7 +3864,7 @@ namespace Firebird
public:
struct VTable : public IVersioned::VTable
{
unsigned (CLOOP_CARG *getTransactionID)(ITraceTransaction* self) throw();
ISC_INT64 (CLOOP_CARG *getTransactionID)(ITraceTransaction* self) throw();
FB_BOOLEAN (CLOOP_CARG *getReadOnly)(ITraceTransaction* self) throw();
int (CLOOP_CARG *getWait)(ITraceTransaction* self) throw();
unsigned (CLOOP_CARG *getIsolation)(ITraceTransaction* self) throw();
@ -3889,9 +3889,9 @@ namespace Firebird
static const unsigned ISOLATION_READ_COMMITTED_RECVER = 3;
static const unsigned ISOLATION_READ_COMMITTED_NORECVER = 4;
unsigned getTransactionID()
ISC_INT64 getTransactionID()
{
unsigned ret = static_cast<VTable*>(this->cloopVTable)->getTransactionID(this);
ISC_INT64 ret = static_cast<VTable*>(this->cloopVTable)->getTransactionID(this);
return ret;
}
@ -3960,7 +3960,7 @@ namespace Firebird
public:
struct VTable : public IVersioned::VTable
{
int (CLOOP_CARG *getStmtID)(ITraceStatement* self) throw();
ISC_INT64 (CLOOP_CARG *getStmtID)(ITraceStatement* self) throw();
PerformanceInfo* (CLOOP_CARG *getPerf)(ITraceStatement* self) throw();
};
@ -3977,9 +3977,9 @@ namespace Firebird
public:
static const unsigned VERSION = 2;
int getStmtID()
ISC_INT64 getStmtID()
{
int ret = static_cast<VTable*>(this->cloopVTable)->getStmtID(this);
ISC_INT64 ret = static_cast<VTable*>(this->cloopVTable)->getStmtID(this);
return ret;
}
@ -4419,10 +4419,10 @@ namespace Firebird
public:
struct VTable : public IVersioned::VTable
{
ISC_UINT64 (CLOOP_CARG *getOIT)(ITraceSweepInfo* self) throw();
ISC_UINT64 (CLOOP_CARG *getOST)(ITraceSweepInfo* self) throw();
ISC_UINT64 (CLOOP_CARG *getOAT)(ITraceSweepInfo* self) throw();
ISC_UINT64 (CLOOP_CARG *getNext)(ITraceSweepInfo* self) throw();
ISC_INT64 (CLOOP_CARG *getOIT)(ITraceSweepInfo* self) throw();
ISC_INT64 (CLOOP_CARG *getOST)(ITraceSweepInfo* self) throw();
ISC_INT64 (CLOOP_CARG *getOAT)(ITraceSweepInfo* self) throw();
ISC_INT64 (CLOOP_CARG *getNext)(ITraceSweepInfo* self) throw();
PerformanceInfo* (CLOOP_CARG *getPerf)(ITraceSweepInfo* self) throw();
};
@ -4439,27 +4439,27 @@ namespace Firebird
public:
static const unsigned VERSION = 2;
ISC_UINT64 getOIT()
ISC_INT64 getOIT()
{
ISC_UINT64 ret = static_cast<VTable*>(this->cloopVTable)->getOIT(this);
ISC_INT64 ret = static_cast<VTable*>(this->cloopVTable)->getOIT(this);
return ret;
}
ISC_UINT64 getOST()
ISC_INT64 getOST()
{
ISC_UINT64 ret = static_cast<VTable*>(this->cloopVTable)->getOST(this);
ISC_INT64 ret = static_cast<VTable*>(this->cloopVTable)->getOST(this);
return ret;
}
ISC_UINT64 getOAT()
ISC_INT64 getOAT()
{
ISC_UINT64 ret = static_cast<VTable*>(this->cloopVTable)->getOAT(this);
ISC_INT64 ret = static_cast<VTable*>(this->cloopVTable)->getOAT(this);
return ret;
}
ISC_UINT64 getNext()
ISC_INT64 getNext()
{
ISC_UINT64 ret = static_cast<VTable*>(this->cloopVTable)->getNext(this);
ISC_INT64 ret = static_cast<VTable*>(this->cloopVTable)->getNext(this);
return ret;
}
@ -13032,7 +13032,7 @@ namespace Firebird
this->cloopVTable = &vTable;
}
static int CLOOP_CARG cloopgetConnectionIDDispatcher(ITraceDatabaseConnection* self) throw()
static ISC_INT64 CLOOP_CARG cloopgetConnectionIDDispatcher(ITraceDatabaseConnection* self) throw()
{
try
{
@ -13041,7 +13041,7 @@ namespace Firebird
catch (...)
{
StatusType::catchException(0);
return static_cast<int>(0);
return static_cast<ISC_INT64>(0);
}
}
@ -13189,7 +13189,7 @@ namespace Firebird
{
}
virtual int getConnectionID() = 0;
virtual ISC_INT64 getConnectionID() = 0;
virtual const char* getDatabaseName() = 0;
};
@ -13217,7 +13217,7 @@ namespace Firebird
this->cloopVTable = &vTable;
}
static unsigned CLOOP_CARG cloopgetTransactionIDDispatcher(ITraceTransaction* self) throw()
static ISC_INT64 CLOOP_CARG cloopgetTransactionIDDispatcher(ITraceTransaction* self) throw()
{
try
{
@ -13226,7 +13226,7 @@ namespace Firebird
catch (...)
{
StatusType::catchException(0);
return static_cast<unsigned>(0);
return static_cast<ISC_INT64>(0);
}
}
@ -13296,7 +13296,7 @@ namespace Firebird
{
}
virtual unsigned getTransactionID() = 0;
virtual ISC_INT64 getTransactionID() = 0;
virtual FB_BOOLEAN getReadOnly() = 0;
virtual int getWait() = 0;
virtual unsigned getIsolation() = 0;
@ -13389,7 +13389,7 @@ namespace Firebird
this->cloopVTable = &vTable;
}
static int CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw()
static ISC_INT64 CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw()
{
try
{
@ -13398,7 +13398,7 @@ namespace Firebird
catch (...)
{
StatusType::catchException(0);
return static_cast<int>(0);
return static_cast<ISC_INT64>(0);
}
}
@ -13429,7 +13429,7 @@ namespace Firebird
{
}
virtual int getStmtID() = 0;
virtual ISC_INT64 getStmtID() = 0;
virtual PerformanceInfo* getPerf() = 0;
};
@ -13524,7 +13524,7 @@ namespace Firebird
}
}
static int CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw()
static ISC_INT64 CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw()
{
try
{
@ -13533,7 +13533,7 @@ namespace Firebird
catch (...)
{
StatusType::catchException(0);
return static_cast<int>(0);
return static_cast<ISC_INT64>(0);
}
}
@ -13634,7 +13634,7 @@ namespace Firebird
}
}
static int CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw()
static ISC_INT64 CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw()
{
try
{
@ -13643,7 +13643,7 @@ namespace Firebird
catch (...)
{
StatusType::catchException(0);
return static_cast<int>(0);
return static_cast<ISC_INT64>(0);
}
}
@ -14449,7 +14449,7 @@ namespace Firebird
this->cloopVTable = &vTable;
}
static ISC_UINT64 CLOOP_CARG cloopgetOITDispatcher(ITraceSweepInfo* self) throw()
static ISC_INT64 CLOOP_CARG cloopgetOITDispatcher(ITraceSweepInfo* self) throw()
{
try
{
@ -14458,11 +14458,11 @@ namespace Firebird
catch (...)
{
StatusType::catchException(0);
return static_cast<ISC_UINT64>(0);
return static_cast<ISC_INT64>(0);
}
}
static ISC_UINT64 CLOOP_CARG cloopgetOSTDispatcher(ITraceSweepInfo* self) throw()
static ISC_INT64 CLOOP_CARG cloopgetOSTDispatcher(ITraceSweepInfo* self) throw()
{
try
{
@ -14471,11 +14471,11 @@ namespace Firebird
catch (...)
{
StatusType::catchException(0);
return static_cast<ISC_UINT64>(0);
return static_cast<ISC_INT64>(0);
}
}
static ISC_UINT64 CLOOP_CARG cloopgetOATDispatcher(ITraceSweepInfo* self) throw()
static ISC_INT64 CLOOP_CARG cloopgetOATDispatcher(ITraceSweepInfo* self) throw()
{
try
{
@ -14484,11 +14484,11 @@ namespace Firebird
catch (...)
{
StatusType::catchException(0);
return static_cast<ISC_UINT64>(0);
return static_cast<ISC_INT64>(0);
}
}
static ISC_UINT64 CLOOP_CARG cloopgetNextDispatcher(ITraceSweepInfo* self) throw()
static ISC_INT64 CLOOP_CARG cloopgetNextDispatcher(ITraceSweepInfo* self) throw()
{
try
{
@ -14497,7 +14497,7 @@ namespace Firebird
catch (...)
{
StatusType::catchException(0);
return static_cast<ISC_UINT64>(0);
return static_cast<ISC_INT64>(0);
}
}
@ -14528,10 +14528,10 @@ namespace Firebird
{
}
virtual ISC_UINT64 getOIT() = 0;
virtual ISC_UINT64 getOST() = 0;
virtual ISC_UINT64 getOAT() = 0;
virtual ISC_UINT64 getNext() = 0;
virtual ISC_INT64 getOIT() = 0;
virtual ISC_INT64 getOST() = 0;
virtual ISC_INT64 getOAT() = 0;
virtual ISC_INT64 getNext() = 0;
virtual PerformanceInfo* getPerf() = 0;
};

View File

@ -37,6 +37,7 @@
#include "../jrd/ext_proto.h"
#include "../jrd/intl_proto.h"
#include "../jrd/met_proto.h"
#include "../jrd/tra_proto.h"
#include "../jrd/extds/ExtDS.h"
@ -423,16 +424,16 @@ void Jrd::Attachment::initLocks(thread_db* tdbb)
const lock_ast_t ast = (att_flags & ATT_system) ? NULL : blockingAstShutdown;
Lock* lock = FB_NEW_RPT(*att_pool, sizeof(SLONG))
Lock(tdbb, sizeof(SLONG), LCK_attachment, this, ast);
Lock* lock = FB_NEW_RPT(*att_pool, 0)
Lock(tdbb, sizeof(AttNumber), LCK_attachment, this, ast);
att_id_lock = lock;
lock->lck_key.lck_long = lock->lck_data = att_attachment_id;
lock->lck_key.lck_long = att_attachment_id;
LCK_lock(tdbb, lock, LCK_EX, LCK_WAIT);
// Allocate and take the monitoring lock
lock = FB_NEW_RPT(*att_pool, sizeof(SLONG))
Lock(tdbb, sizeof(SLONG), LCK_monitor, this, blockingAstMonitor);
lock = FB_NEW_RPT(*att_pool, 0)
Lock(tdbb, sizeof(AttNumber), LCK_monitor, this, blockingAstMonitor);
att_monitor_lock = lock;
lock->lck_key.lck_long = att_attachment_id;
LCK_lock(tdbb, lock, LCK_EX, LCK_WAIT);
@ -441,8 +442,8 @@ void Jrd::Attachment::initLocks(thread_db* tdbb)
if (!(att_flags & ATT_system))
{
lock = FB_NEW_RPT(*att_pool, sizeof(SLONG))
Lock(tdbb, sizeof(SLONG), LCK_cancel, this, blockingAstCancel);
lock = FB_NEW_RPT(*att_pool, 0)
Lock(tdbb, sizeof(AttNumber), LCK_cancel, this, blockingAstCancel);
att_cancel_lock = lock;
lock->lck_key.lck_long = att_attachment_id;
}
@ -620,7 +621,6 @@ void Jrd::Attachment::releaseRelations(thread_db* tdbb)
}
}
}
}
int Jrd::Attachment::blockingAstShutdown(void* ast_object)

View File

@ -327,7 +327,7 @@ private:
public:
Firebird::SortedArray<jrd_req*> att_requests; // Requests belonging to attachment
Lock* att_id_lock; // Attachment lock (if any)
SLONG att_attachment_id; // Attachment ID
AttNumber att_attachment_id; // Attachment ID
Lock* att_cancel_lock; // Lock to cancel the active request
Lock* att_monitor_lock; // Lock for monitoring purposes
const ULONG att_lock_owner_id; // ID for the lock manager

View File

@ -237,7 +237,6 @@ namespace Jrd
dbb_flags &= ~(DBB_sweep_in_progress | DBB_sweep_starting);
}
void Database::SharedCounter::shutdown(thread_db* tdbb)
{
for (size_t i = 0; i < TOTAL_ITEMS; i++)
@ -247,36 +246,28 @@ namespace Jrd
}
}
SLONG Database::SharedCounter::generate(thread_db* tdbb, ULONG space, ULONG prefetch)
SINT64 Database::SharedCounter::generate(thread_db* tdbb, ULONG space, ULONG prefetch)
{
fb_assert(space < TOTAL_ITEMS);
ValueCache* const counter = &m_counters[space];
if (m_localOnly)
{
SLONG result = 0;
while ( !(result = (SLONG) ++counter->curVal) )
;
return result;
}
Database* const dbb = tdbb->getDatabase();
SyncLockGuard guard(&dbb->dbb_sh_counter_sync, SYNC_EXCLUSIVE, "Database::SharedCounter::generate");
if (!counter->lock)
{
Lock* const lock =
FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock(tdbb, sizeof(SLONG), LCK_shared_counter);
counter->lock = lock;
lock->lck_key.lck_long = space;
LCK_lock(tdbb, lock, LCK_PW, LCK_WAIT);
}
SINT64 result = ++counter->curVal;
SLONG result = (SLONG) ++counter->curVal;
if (result > counter->maxVal)
if (!m_localOnly && result > counter->maxVal)
{
LCK_convert(tdbb, counter->lock, LCK_PW, LCK_WAIT);
if (!counter->lock)
{
counter->lock =
FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock(tdbb, sizeof(SLONG), LCK_shared_counter);
counter->lock->lck_key.lck_long = space;
LCK_lock(tdbb, counter->lock, LCK_PW, LCK_WAIT);
}
else
LCK_convert(tdbb, counter->lock, LCK_PW, LCK_WAIT);
result = LCK_read_data(tdbb, counter->lock);
// zero IDs are somewhat special, so let's better skip them

View File

@ -243,8 +243,8 @@ public:
struct ValueCache
{
Lock* lock; // lock which holds shared counter value
Firebird::AtomicCounter curVal; // current value of shared counter lock
SLONG maxVal; // maximum cached value of shared counter lock
SINT64 curVal; // current value of shared counter lock
SINT64 maxVal; // maximum cached value of shared counter lock
};
public:
@ -266,7 +266,7 @@ public:
delete m_counters[i].lock;
}
SLONG generate(thread_db* tdbb, ULONG space, ULONG prefetch = DEFAULT_CACHE_SIZE);
SINT64 generate(thread_db* tdbb, ULONG space, ULONG prefetch = DEFAULT_CACHE_SIZE);
void shutdown(thread_db* tdbb);
private:
@ -438,7 +438,7 @@ public:
TraNumber dbb_oldest_transaction; // Cached "oldest interesting" transaction
TraNumber dbb_oldest_snapshot; // Cached "oldest snapshot" of all active transactions
TraNumber dbb_next_transaction; // Next transaction id used by NETWARE
SLONG dbb_attachment_id; // Next attachment id for ReadOnly DB's
AttNumber dbb_attachment_id; // Next attachment id for ReadOnly DB's
ULONG dbb_page_buffers; // Page buffers from header page
GarbageCollector* dbb_garbage_collector; // GarbageCollector class
@ -531,17 +531,17 @@ private:
~Database();
public:
SLONG generateAttachmentId(thread_db* tdbb)
AttNumber generateAttachmentId(thread_db* tdbb)
{
return dbb_shared_counter.generate(tdbb, SharedCounter::ATTACHMENT_ID_SPACE, 1);
}
SLONG generateTransactionId(thread_db* tdbb)
TraNumber generateTransactionId(thread_db* tdbb)
{
return dbb_shared_counter.generate(tdbb, SharedCounter::TRANSACTION_ID_SPACE, 1);
}
SLONG generateStatementId(thread_db* tdbb)
StmtNumber generateStatementId(thread_db* tdbb)
{
return dbb_shared_counter.generate(tdbb, SharedCounter::STATEMENT_ID_SPACE);
}

View File

@ -135,7 +135,7 @@ void MonitoringData::release()
}
void MonitoringData::read(SLONG att_id, TempSpace& temp)
void MonitoringData::read(AttNumber att_id, TempSpace& temp)
{
offset_t position = 0;
@ -177,7 +177,7 @@ void MonitoringData::read(SLONG att_id, TempSpace& temp)
}
ULONG MonitoringData::setup(SLONG att_id)
ULONG MonitoringData::setup(AttNumber att_id)
{
ensureSpace(sizeof(Element));
@ -209,7 +209,7 @@ void MonitoringData::write(ULONG offset, ULONG length, const void* buffer)
}
void MonitoringData::cleanup(SLONG att_id)
void MonitoringData::cleanup(AttNumber att_id)
{
// Remove information about the given session
@ -337,7 +337,7 @@ MonitoringSnapshot::MonitoringSnapshot(thread_db* tdbb, MemoryPool& pool)
Attachment* const attachment = tdbb->getAttachment();
fb_assert(attachment);
const SLONG self_att_id = attachment->att_attachment_id;
const AttNumber self_att_id = attachment->att_attachment_id;
// Initialize record buffers
RecordBuffer* const dbb_buffer = allocBuffer(tdbb, pool, rel_mon_database);
@ -379,7 +379,7 @@ MonitoringSnapshot::MonitoringSnapshot(thread_db* tdbb, MemoryPool& pool)
ThreadStatusGuard temp_status(tdbb);
for (SLONG* iter = sessions.begin(); iter != sessions.end(); iter++)
for (AttNumber* iter = sessions.begin(); iter != sessions.end(); iter++)
{
if (*iter != self_att_id)
{
@ -403,7 +403,7 @@ MonitoringSnapshot::MonitoringSnapshot(thread_db* tdbb, MemoryPool& pool)
ThreadStatusGuard temp_status(tdbb);
lock->lck_type = LCK_attachment;
for (SLONG* iter = sessions.begin(); iter != sessions.end(); iter++)
for (AttNumber* iter = sessions.begin(); iter != sessions.end(); iter++)
{
if (*iter != self_att_id)
{
@ -1172,7 +1172,8 @@ void Monitoring::putStatistics(SnapshotData::DumpRecord& record, const RuntimeSt
}
void Monitoring::putContextVars(SnapshotData::DumpRecord& record, const StringMap& variables,
MonitoringData::Writer& writer, int object_id, bool is_attachment)
MonitoringData::Writer& writer, SINT64 object_id,
bool is_attachment)
{
StringMap::ConstAccessor accessor(&variables);
@ -1180,10 +1181,8 @@ void Monitoring::putContextVars(SnapshotData::DumpRecord& record, const StringMa
{
record.reset(rel_mon_ctx_vars);
if (is_attachment)
record.storeInteger(f_mon_ctx_var_att_id, object_id);
else
record.storeInteger(f_mon_ctx_var_tra_id, object_id);
const int field_id = is_attachment ? f_mon_ctx_var_att_id : f_mon_ctx_var_tra_id;
record.storeInteger(field_id, object_id);
record.storeString(f_mon_ctx_var_name, accessor.current()->first);
record.storeString(f_mon_ctx_var_value, accessor.current()->second);

View File

@ -242,7 +242,7 @@ class MonitoringData FB_FINAL : public Firebird::IpcObject
struct Element
{
SLONG attId;
AttNumber attId;
ULONG length;
};
@ -273,7 +273,7 @@ public:
class Writer
{
public:
Writer(MonitoringData* data, SLONG att_id)
Writer(MonitoringData* data, AttNumber att_id)
: dump(data)
{
fb_assert(dump);
@ -325,7 +325,7 @@ public:
Firebird::UCharBuffer buffer;
};
typedef Firebird::HalfStaticArray<SLONG, 64> SessionList;
typedef Firebird::HalfStaticArray<AttNumber, 64> SessionList;
explicit MonitoringData(const Database*);
~MonitoringData();
@ -336,11 +336,11 @@ public:
void acquire();
void release();
void read(SLONG, TempSpace&);
ULONG setup(SLONG);
void read(AttNumber, TempSpace&);
ULONG setup(AttNumber);
void write(ULONG, ULONG, const void*);
void cleanup(SLONG);
void cleanup(AttNumber);
void enumerate(SessionList&);
private:
@ -405,7 +405,7 @@ private:
static void putStatistics(SnapshotData::DumpRecord&, const RuntimeStatistics&,
MonitoringData::Writer&, int, int);
static void putContextVars(SnapshotData::DumpRecord&, const Firebird::StringMap&,
MonitoringData::Writer&, int, bool);
MonitoringData::Writer&, SINT64, bool);
static void putMemoryUsage(SnapshotData::DumpRecord&, const Firebird::MemoryStats&,
MonitoringData::Writer&, int, int);
};

View File

@ -44,9 +44,10 @@ RelationPages* jrd_rel::getPagesInternal(thread_db* tdbb, TraNumber tran, bool a
Jrd::Attachment* attachment = tdbb->getAttachment();
Database* dbb = tdbb->getDatabase();
ULONG inst_id;
SINT64 inst_id;
// Vlad asked for this compile-time check to make sure we can contain a txn number here
typedef int RangeCheck[sizeof(inst_id) >= sizeof(TraNumber)];
typedef int RangeCheck1[sizeof(inst_id) >= sizeof(TraNumber)];
typedef int RangeCheck2[sizeof(inst_id) >= sizeof(AttNumber)];
if (rel_flags & REL_temp_tran)
{
@ -136,7 +137,7 @@ RelationPages* jrd_rel::getPagesInternal(thread_db* tdbb, TraNumber tran, bool a
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES,
"jrd_rel::getPages inst %"ULONGFORMAT", irp %"SLONGFORMAT", idx %u, idx_root %"SLONGFORMAT", addr 0x%x\n",
"jrd_rel::getPages inst %"SQUADFORMAT", irp %"SLONGFORMAT", idx %u, idx_root %"SLONGFORMAT", addr 0x%x\n",
newPages->rel_instance_id,
newPages->rel_index_root,
idx->idx_id,
@ -190,13 +191,11 @@ bool jrd_rel::delPages(thread_db* tdbb, TraNumber tran, RelationPages* aPages)
rel_pages_inst->remove(pos);
if (pages->rel_index_root) {
if (pages->rel_index_root)
IDX_delete_indices(tdbb, this, pages);
}
if (pages->rel_pages) {
if (pages->rel_pages)
DPM_delete_relation_pages(tdbb, this, pages);
}
pages->free(rel_pages_free);
return true;
@ -208,13 +207,13 @@ void jrd_rel::getRelLockKey(thread_db* tdbb, UCHAR* key)
memcpy(key, &val, sizeof(ULONG));
key += sizeof(ULONG);
const ULONG inst_id = getPages(tdbb)->rel_instance_id;
memcpy(key, &inst_id, sizeof(ULONG));
const SINT64 inst_id = getPages(tdbb)->rel_instance_id;
memcpy(key, &inst_id, sizeof(SINT64));
}
USHORT jrd_rel::getRelLockKeyLength() const
{
return sizeof(ULONG) + sizeof(SLONG);
return sizeof(ULONG) + sizeof(SINT64);
}
void jrd_rel::cleanUp()
@ -238,7 +237,7 @@ void jrd_rel::fillPagesSnapshot(RelPagesSnapshot& snapshot, const bool attachmen
relPages->addRef();
}
else if ((rel_flags & REL_temp_conn) &&
(ULONG) PAG_attachment_id(snapshot.spt_tdbb) == relPages->rel_instance_id)
PAG_attachment_id(snapshot.spt_tdbb) == relPages->rel_instance_id)
{
snapshot.add(relPages);
relPages->addRef();

View File

@ -23,6 +23,7 @@
#define JRD_RELATION_H
#include "../jrd/jrd.h"
#include "../jrd/btr.h"
#include "../jrd/lck.h"
#include "../jrd/pag.h"
#include "../jrd/val.h"
@ -68,29 +69,27 @@ typedef Firebird::SortedArray<ViewContext*, Firebird::EmptyStorage<ViewContext*>
class RelationPages
{
public:
typedef ULONG RP_INSTANCE_ID;
vcl* rel_pages; // vector of pointer page numbers
RP_INSTANCE_ID rel_instance_id; // 0 or att_attachment_id or tra_number
typedef SINT64 RP_INSTANCE_ID;
vcl* rel_pages; // vector of pointer page numbers
RP_INSTANCE_ID rel_instance_id; // 0 or att_attachment_id or tra_number
// Vlad asked for this compile-time check to make sure we can contain a txn number here
typedef int RangeCheck[sizeof(RP_INSTANCE_ID) >= sizeof(TraNumber)];
typedef int RangeCheck1[sizeof(RP_INSTANCE_ID) >= sizeof(TraNumber)];
typedef int RangeCheck2[sizeof(RP_INSTANCE_ID) >= sizeof(AttNumber)];
SLONG rel_index_root; // index root page number
SLONG rel_data_pages; // count of relation data pages
ULONG rel_slot_space; // lowest pointer page with slot space
ULONG rel_pri_data_space; // lowest pointer page with primary data page space
ULONG rel_sec_data_space; // lowest pointer page with secondary data page space
USHORT rel_pg_space_id;
SLONG rel_index_root; // index root page number
SLONG rel_data_pages; // count of relation data pages
ULONG rel_slot_space; // lowest pointer page with slot space
ULONG rel_pri_data_space; // lowest pointer page with primary data page space
ULONG rel_sec_data_space; // lowest pointer page with secondary data page space
USHORT rel_pg_space_id;
RelationPages()
{
rel_pages = 0;
rel_index_root = rel_data_pages = 0;
rel_instance_id = 0;
rel_slot_space = rel_pri_data_space = rel_sec_data_space = 0;
rel_pg_space_id = DB_PAGE_SPACE;
rel_next_free = 0;
useCount = 0;
}
explicit RelationPages()
: rel_pages(NULL), rel_instance_id(0),
rel_index_root(0), rel_data_pages(0), rel_slot_space(0),
rel_pri_data_space(0), rel_sec_data_space(0),
rel_pg_space_id(DB_PAGE_SPACE), rel_next_free(NULL),
useCount(0)
{}
inline SLONG addRef()
{
@ -99,7 +98,7 @@ public:
void free(RelationPages*& nextFree);
static inline ULONG generate(const RelationPages* item)
static inline RP_INSTANCE_ID generate(const RelationPages* item)
{
return item->rel_instance_id;
}
@ -132,7 +131,6 @@ struct frgn
vec<int>* frgn_indexes;
};
// Relation block; one is created for each relation referenced
// in the database, though it is not really filled out until
// the relation is scanned
@ -147,15 +145,17 @@ public:
USHORT rel_current_fmt; // Current format number
ULONG rel_flags;
Format* rel_current_format; // Current record format
Firebird::MetaName rel_name; // ascii relation name
vec<Format*>* rel_formats; // Known record formats
Firebird::MetaName rel_owner_name; // ascii owner
Firebird::MetaName rel_security_name; // security class name for relation
vec<Format*>* rel_formats; // Known record formats
vec<jrd_fld*>* rel_fields; // vector of field blocks
RseNode* rel_view_rse; // view record select expression
ViewContexts rel_view_contexts; // sorted array of view contexts
Firebird::MetaName rel_security_name; // security class name for relation
ExternalFile* rel_file; // external file name
GCRecordList rel_gc_records; // records for garbage collection
@ -228,12 +228,13 @@ private:
typedef Firebird::SortedArray<
RelationPages*,
Firebird::EmptyStorage<RelationPages*>,
ULONG, // This type should be able to hold a TraNumber value
SINT64,
RelationPages>
RelationPagesInstances;
// Vlad asked for this compile-time check to make sure we can contain a txn number here
typedef int RangeCheck[sizeof(ULONG) >= sizeof(TraNumber)];
typedef int RangeCheck1[sizeof(SINT64) >= sizeof(TraNumber)];
typedef int RangeCheck2[sizeof(SINT64) >= sizeof(AttNumber)];
RelationPagesInstances* rel_pages_inst;
RelationPages rel_pages_base;
@ -316,8 +317,9 @@ const ULONG REL_gc_lockneed = 0x80000; // gc lock should be acquired
/// class jrd_rel
inline jrd_rel::jrd_rel(MemoryPool& p)
: rel_pool(&p), rel_flags(REL_gc_lockneed), rel_name(p), rel_owner_name(p),
rel_view_contexts(p), rel_security_name(p), rel_gc_records(p)
: rel_pool(&p), rel_flags(REL_gc_lockneed),
rel_name(p), rel_owner_name(p), rel_security_name(p),
rel_view_contexts(p), rel_gc_records(p)
{
}

View File

@ -105,17 +105,19 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att,
const RelCounters::const_iterator end = new_stat.rel_counts.end();
for (; new_cnts != end; ++new_cnts)
{
if (base_found && base_cnts->getRelationId() == new_cnts->getRelationId())
const SLONG rel_id = new_cnts->getRelationId();
if (base_found && base_cnts->getRelationId() == rel_id)
{
// Point TraceCounts to counts array from baseline object
if (base_cnts->setToDiff(*new_cnts))
{
jrd_rel* const relation =
new_cnts->getRelationId() < static_cast<SLONG>(att->att_relations->count()) ?
(*att->att_relations)[new_cnts->getRelationId()] : NULL;
rel_id < static_cast<SLONG>(att->att_relations->count()) ?
(*att->att_relations)[rel_id] : NULL;
TraceCounts traceCounts;
traceCounts.trc_relation_id = new_cnts->getRelationId();
traceCounts.trc_relation_id = rel_id;
traceCounts.trc_counters = base_cnts->getCounterVector();
traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL;
temp.add(traceCounts);
@ -127,12 +129,12 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att,
else
{
jrd_rel* const relation =
new_cnts->getRelationId() < static_cast<SLONG>(att->att_relations->count()) ?
(*att->att_relations)[new_cnts->getRelationId()] : NULL;
rel_id < static_cast<SLONG>(att->att_relations->count()) ?
(*att->att_relations)[rel_id] : NULL;
// Point TraceCounts to counts array from object with updated counters
TraceCounts traceCounts;
traceCounts.trc_relation_id = new_cnts->getRelationId();
traceCounts.trc_relation_id = rel_id;
traceCounts.trc_counters = new_cnts->getCounterVector();
traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL;
temp.add(traceCounts);

View File

@ -2164,7 +2164,7 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
else if (nameStr == DATABASE_NAME)
resultStr = dbb->dbb_database_name.ToString();
else if (nameStr == SESSION_ID_NAME)
resultStr.printf("%d", PAG_attachment_id(tdbb));
resultStr.printf("%"SQUADFORMAT, PAG_attachment_id(tdbb));
else if (nameStr == NETWORK_PROTOCOL_NAME)
{
if (attachment->att_network_protocol.isEmpty())
@ -2184,7 +2184,7 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
if (!attachment->att_remote_pid)
return NULL;
resultStr.printf("%d", attachment->att_remote_pid);
resultStr.printf("%"SLONGFORMAT, attachment->att_remote_pid);
}
else if (nameStr == CLIENT_PROCESS_NAME)
{
@ -2208,7 +2208,7 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
resultStr = attachment->att_user->usr_sql_role_name;
}
else if (nameStr == TRANSACTION_ID_NAME)
resultStr.printf("%lu", transaction->tra_number);
resultStr.printf("%"SQUADFORMAT, transaction->tra_number);
else if (nameStr == ISOLATION_LEVEL_NAME)
{
if (transaction->tra_flags & TRA_read_committed)
@ -2219,7 +2219,7 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
resultStr = SNAPSHOT_VALUE;
}
else if (nameStr == LOCK_TIMEOUT_NAME)
resultStr.printf("%d", transaction->tra_lock_timeout);
resultStr.printf("%"SLONGFORMAT, transaction->tra_lock_timeout);
else if (nameStr == READ_ONLY_NAME)
resultStr = (transaction->tra_flags & TRA_readonly) ? TRUE_VALUE : FALSE_VALUE;
else

View File

@ -90,10 +90,10 @@ void VirtualTable::erase(thread_db* tdbb, record_param* rpb)
return;
}
const SLONG id = MOV_get_long(&desc, 0);
const SINT64 id = MOV_get_int64(&desc, 0);
// Post a blocking request
Lock temp_lock(tdbb, sizeof(SLONG), lock_type);
Lock temp_lock(tdbb, sizeof(SINT64), lock_type);
temp_lock.lck_key.lck_long = id;
ThreadStatusGuard temp_status(tdbb);

View File

@ -170,7 +170,7 @@ static void copy_key(const temporary_key*, temporary_key*);
static contents delete_node(thread_db*, WIN*, UCHAR*);
static void delete_tree(thread_db*, USHORT, USHORT, PageNumber, PageNumber);
static DSC* eval(thread_db*, const ValueExprNode*, DSC*, bool*);
static ULONG fast_load(thread_db*, jrd_rel*, index_desc*, USHORT, AutoPtr<Sort>&, SelectivityList&);
static ULONG fast_load(thread_db*, IndexCreation&, SelectivityList&);
static index_root_page* fetch_root(thread_db*, WIN*, const jrd_rel*, const RelationPages*);
static UCHAR* find_node_start_point(btree_page*, temporary_key*, UCHAR*, USHORT*,
@ -378,10 +378,7 @@ void BTR_complement_key(temporary_key* key)
void BTR_create(thread_db* tdbb,
jrd_rel* relation,
index_desc* idx,
USHORT key_length,
AutoPtr<Sort>& scb,
IndexCreation& creation,
SelectivityList& selectivity)
{
/**************************************
@ -396,22 +393,27 @@ void BTR_create(thread_db* tdbb,
**************************************/
SET_TDBB(tdbb);
const Database* dbb = tdbb->getDatabase();
const Database* const dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
jrd_rel* const relation = creation.relation;
index_desc* const idx = creation.index;
// Now that the index id has been checked out, create the index.
idx->idx_root = fast_load(tdbb, relation, idx, key_length, scb, selectivity);
idx->idx_root = fast_load(tdbb, creation, selectivity);
// Index is created. Go back to the index root page and update it to
// point to the index.
RelationPages* relPages = relation->getPages(tdbb);
RelationPages* const relPages = relation->getPages(tdbb);
WIN window(relPages->rel_pg_space_id, relPages->rel_index_root);
index_root_page* root = (index_root_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_root);
index_root_page* const root = (index_root_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_root);
CCH_MARK(tdbb, &window);
root->irt_rpt[idx->idx_id].irt_root = idx->idx_root;
root->irt_rpt[idx->idx_id].irt_flags &= ~irt_in_progress;
update_selectivity(root, idx->idx_id, selectivity);
LCK_release(tdbb, creation.lock);
CCH_RELEASE(tdbb, &window);
}
@ -1450,18 +1452,14 @@ bool BTR_lookup(thread_db* tdbb, jrd_rel* relation, USHORT id, index_desc* buffe
SET_TDBB(tdbb);
WIN window(relPages->rel_pg_space_id, -1);
index_root_page* root = fetch_root(tdbb, &window, relation, relPages);
if (!root) {
return false;
}
index_root_page* const root = fetch_root(tdbb, &window, relation, relPages);
if (id >= root->irt_count || !BTR_description(tdbb, relation, root, buffer, id))
{
CCH_RELEASE(tdbb, &window);
if (!root)
return false;
}
const bool result = (id < root->irt_count && BTR_description(tdbb, relation, root, buffer, id));
CCH_RELEASE(tdbb, &window);
return true;
return result;
}
@ -1697,8 +1695,7 @@ void BTR_make_null_key(thread_db* tdbb, const index_desc* idx, temporary_key* ke
}
bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, index_desc* idx,
WIN* window)
bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, index_desc* idx, WIN* window)
{
/**************************************
*
@ -1729,16 +1726,11 @@ bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, in
}
else
{
RelationPages* relPages;
if (transaction)
relPages = relation->getPages(tdbb, transaction->tra_number);
else
relPages = relation->getPages(tdbb);
RelationPages* const relPages = transaction ?
relation->getPages(tdbb, transaction->tra_number) : relation->getPages(tdbb);
if (!(root = fetch_root(tdbb, window, relation, relPages)))
{
return false;
}
}
for (; id < root->irt_count; ++id)
@ -1746,31 +1738,49 @@ bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, in
const index_root_page::irt_repeat* irt_desc = root->irt_rpt + id;
if (!irt_desc->irt_root && (irt_desc->irt_flags & irt_in_progress) && transaction)
{
const TraNumber trans = irt_desc->irt_transaction;
CCH_RELEASE(tdbb, window);
const int trans_state = TRA_wait(tdbb, transaction, trans, jrd_tra::tra_wait);
if ((trans_state == tra_dead) || (trans_state == tra_committed))
Lock temp_lock(tdbb, sizeof(SLONG), LCK_idx_reserve);
temp_lock.lck_key.lck_long = (relation->rel_id << 16) | id;
while (true)
{
// clean up this left-over index
const ULONG tra_mask = irt_desc->irt_transaction;
CCH_RELEASE(tdbb, window);
if (!LCK_lock(tdbb, &temp_lock, LCK_SR, LCK_WAIT))
ERR_punt();
LCK_release(tdbb, &temp_lock);
// attempt to clean up this left-over index
root = (index_root_page*) CCH_FETCH(tdbb, window, LCK_write, pag_root);
if (id >= root->irt_count)
return false;
irt_desc = root->irt_rpt + id;
if (!irt_desc->irt_root && irt_desc->irt_transaction == trans &&
(irt_desc->irt_flags & irt_in_progress))
if (!irt_desc->irt_root && (irt_desc->irt_flags & irt_in_progress))
{
BTR_delete_index(tdbb, window, id);
if (irt_desc->irt_transaction == tra_mask)
{
BTR_delete_index(tdbb, window, id);
break;
}
}
else {
else
{
CCH_RELEASE(tdbb, window);
break;
}
root = (index_root_page*) CCH_FETCH(tdbb, window, LCK_read, pag_root);
continue;
}
root = (index_root_page*) CCH_FETCH(tdbb, window, LCK_read, pag_root);
}
if (BTR_description(tdbb, relation, root, idx, id)) {
if (BTR_description(tdbb, relation, root, idx, id))
return true;
}
}
CCH_RELEASE(tdbb, window);
@ -1865,7 +1875,7 @@ void BTR_remove(thread_db* tdbb, WIN* root_window, index_insertion* insertion)
}
void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, index_desc* idx)
void BTR_reserve_slot(thread_db* tdbb, IndexCreation& creation)
{
/**************************************
*
@ -1880,11 +1890,15 @@ void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction,
**************************************/
SET_TDBB(tdbb);
const Database* dbb = tdbb->getDatabase();
const Database* const dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
jrd_rel* const relation = creation.relation;
index_desc* const idx = creation.index;
jrd_tra* const transaction = creation.transaction;
fb_assert(relation);
RelationPages* relPages = relation->getPages(tdbb);
RelationPages* const relPages = relation->getPages(tdbb);
fb_assert(relPages && relPages->rel_index_root);
fb_assert(transaction);
@ -1894,9 +1908,8 @@ void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction,
// Index id for temporary index instance of global temporary table is
// already assigned, use it.
const bool use_idx_id = (relPages->rel_instance_id != 0);
if (use_idx_id) {
if (use_idx_id)
fb_assert(idx->idx_id <= dbb->dbb_max_idx);
}
WIN window(relPages->rel_pg_space_id, relPages->rel_index_root);
index_root_page* root = (index_root_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_root);
@ -1935,15 +1948,13 @@ void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction,
end = root->irt_rpt + root->irt_count;
for (index_root_page::irt_repeat* root_idx = root->irt_rpt; root_idx < end; root_idx++)
{
if (root_idx->irt_root || (root_idx->irt_flags & irt_in_progress)) {
if (root_idx->irt_root || (root_idx->irt_flags & irt_in_progress))
space = MIN(space, root_idx->irt_desc);
}
if (!root_idx->irt_root && !slot && !(root_idx->irt_flags & irt_in_progress))
{
if (!use_idx_id || (root_idx - root->irt_rpt) == idx->idx_id)
{
slot = root_idx;
}
}
}
@ -1980,14 +1991,21 @@ void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction,
fb_assert(idx->idx_count <= MAX_UCHAR);
slot->irt_keys = (UCHAR) idx->idx_count;
slot->irt_flags = idx->idx_flags | irt_in_progress;
slot->irt_transaction = transaction->tra_number;
slot->irt_transaction = (ULONG) transaction->tra_number;
slot->irt_root = 0;
// Exploit the fact idx_repeat structure matches ODS IRTD one
memcpy(desc, idx->idx_rpt, len);
fb_assert(!creation.lock);
creation.lock = FB_NEW_RPT(*transaction->tra_pool, 0) IndexReserveLock(tdbb, relation, idx);
const bool error = !LCK_lock(tdbb, creation.lock, LCK_EX, LCK_WAIT);
CCH_RELEASE(tdbb, &window);
if (error)
ERR_punt();
}
@ -3259,10 +3277,7 @@ static DSC* eval(thread_db* tdbb, const ValueExprNode* node, DSC* temp, bool* is
static ULONG fast_load(thread_db* tdbb,
jrd_rel* relation,
index_desc* idx,
USHORT key_length,
AutoPtr<Sort>& scb,
IndexCreation& creation,
SelectivityList& selectivity)
{
/**************************************
@ -3291,9 +3306,14 @@ static ULONG fast_load(thread_db* tdbb,
#endif
SET_TDBB(tdbb);
const Database* dbb = tdbb->getDatabase();
const Database* const dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
jrd_rel* const relation = creation.relation;
index_desc* const idx = creation.index;
const USHORT key_length = creation.key_length;
Sort* const scb = creation.sort;
const USHORT pageSpaceID = relation->getPages(tdbb)->rel_pg_space_id;
// Variable initialization
for (int i = 0; i < MAX_LEVELS; i++)
@ -3974,7 +3994,7 @@ static ULONG fast_load(thread_db* tdbb,
// do some final housekeeping
scb.reset();
creation.sort.reset();
// If index flush fails, try to delete the index tree.
// If the index delete fails, just go ahead and punt.

View File

@ -47,6 +47,7 @@ class JrdStatement;
struct temporary_key;
class jrd_tra;
class BtrPageGCLock;
class Sort;
// Index descriptor block -- used to hold info from index root page
@ -252,6 +253,27 @@ public:
static bool isPageGCAllowed(thread_db* tdbb, const PageNumber& page);
};
class IndexReserveLock : public Lock
{
public:
IndexReserveLock(thread_db* tdbb, const jrd_rel* relation, const index_desc* idx);
~IndexReserveLock();
private:
thread_db* const m_tdbb;
};
// Struct used for index creation
struct IndexCreation
{
jrd_rel* relation;
index_desc* index;
jrd_tra* transaction;
USHORT key_length;
Firebird::AutoPtr<IndexReserveLock> lock;
Firebird::AutoPtr<Sort> sort;
};
// Class used to report any index related errors

View File

@ -31,7 +31,7 @@
USHORT BTR_all(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::IndexDescAlloc**, Jrd::RelationPages*);
void BTR_complement_key(Jrd::temporary_key*);
void BTR_create(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::index_desc*, USHORT, Firebird::AutoPtr<Jrd::Sort>&, Jrd::SelectivityList&);
void BTR_create(Jrd::thread_db*, Jrd::IndexCreation&, Jrd::SelectivityList&);
bool BTR_delete_index(Jrd::thread_db*, Jrd::win*, USHORT);
bool BTR_description(Jrd::thread_db*, Jrd::jrd_rel*, Ods::index_root_page*, Jrd::index_desc*, USHORT);
DSC* BTR_eval_expression(Jrd::thread_db*, Jrd::index_desc*, Jrd::Record*, bool&);
@ -50,7 +50,7 @@ Jrd::idx_e BTR_make_key(Jrd::thread_db*, USHORT, const Jrd::ValueExprNode* const
void BTR_make_null_key(Jrd::thread_db*, const Jrd::index_desc*, Jrd::temporary_key*);
bool BTR_next_index(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::jrd_tra*, Jrd::index_desc*, Jrd::win*);
void BTR_remove(Jrd::thread_db*, Jrd::win*, Jrd::index_insertion*);
void BTR_reserve_slot(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::jrd_tra*, Jrd::index_desc*);
void BTR_reserve_slot(Jrd::thread_db*, Jrd::IndexCreation&);
void BTR_selectivity(Jrd::thread_db*, Jrd::jrd_rel*, USHORT, Jrd::SelectivityList&);
bool BTR_types_comparable(const dsc& target, const dsc& source);

View File

@ -51,6 +51,7 @@
#include "../jrd/jrd_proto.h"
#include "../jrd/lck_proto.h"
#include "../jrd/pag_proto.h"
#include "../jrd/ods_proto.h"
#include "../jrd/os/pio_proto.h"
#include "../jrd/sdw_proto.h"
#include "../jrd/shut_proto.h"
@ -2412,8 +2413,8 @@ static Lock* alloc_page_lock(thread_db* tdbb, BufferDesc* bdb)
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
BufferControl *bcb = bdb->bdb_bcb;
Database* const dbb = tdbb->getDatabase();
BufferControl* const bcb = bdb->bdb_bcb;
const USHORT lockLen = PageNumber::getLockLen();
@ -4805,13 +4806,18 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s
// the next_transaction > oldest_active transaction
if (bdb->bdb_page == HEADER_PAGE_NUMBER)
{
const header_page* header = (header_page*) page;
if (header->hdr_next_transaction)
const header_page* const header = (header_page*) page;
const TraNumber next_transaction = Ods::getNT(header);
const TraNumber oldest_active = Ods::getOAT(header);
const TraNumber oldest_transaction = Ods::getOIT(header);
if (next_transaction)
{
if (header->hdr_oldest_active > header->hdr_next_transaction)
if (oldest_active > next_transaction)
BUGCHECK(266); // next transaction older than oldest active
if (header->hdr_oldest_transaction > header->hdr_next_transaction)
if (oldest_transaction > next_transaction)
BUGCHECK(267); // next transaction older than oldest transaction
}
}
@ -4887,7 +4893,7 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s
{
// We finished. Adjust transaction accounting and get ready for exit
if (bdb->bdb_page == HEADER_PAGE_NUMBER)
dbb->dbb_last_header_write = ((header_page*) page)->hdr_next_transaction;
dbb->dbb_last_header_write = Ods::getNT((header_page*) page);
}
else
{
@ -4916,7 +4922,7 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s
}
if (bdb->bdb_page == HEADER_PAGE_NUMBER)
dbb->dbb_last_header_write = ((header_page*) page)->hdr_next_transaction;
dbb->dbb_last_header_write = Ods::getNT((header_page*) page);
if (dbb->dbb_shadow && !isTempPage)
result = CCH_write_all_shadows(tdbb, 0, bdb, status, inAst);
@ -4945,7 +4951,8 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s
// Destination difference page number is only valid between MARK and
// write_page so clean it now to avoid confusion
bdb->bdb_difference_page = 0;
bdb->bdb_transactions = bdb->bdb_mark_transaction = 0;
bdb->bdb_transactions = 0;
bdb->bdb_mark_transaction = 0;
if (!(bdb->bdb_bcb->bcb_flags & BCB_keep_pages))
removeDirty(bdb->bdb_bcb, bdb);

View File

@ -441,7 +441,13 @@ const int DDL_TRIGGER_DROP_MAPPING = 47;
#define USERNAME_SWITCH "USER"
#define PASSWORD_SWITCH "PASSWORD"
const TraNumber MAX_TRA_NUMBER = ~TraNumber(0);
// The highest transaction number possible
const TraNumber MAX_TRA_NUMBER = 0x0000FFFFFFFFFFFF; // ~2.8 * 10^14
// Number of streams, conjuncts, indices that will be statically allocated
// in various arrays. Larger numbers will have to be allocated dynamically
// CVC: I think we need to have a special, higher value for streams.
const int OPT_STATIC_ITEMS = 64;
#define CURRENT_ENGINE "Engine12"

View File

@ -56,8 +56,10 @@
#include "../jrd/dpm_proto.h"
#include "../jrd/err_proto.h"
#include "../jrd/exe_proto.h"
#include "../jrd/lck_proto.h"
#include "../jrd/met_proto.h"
#include "../jrd/mov_proto.h"
#include "../jrd/ods_proto.h"
#include "../jrd/pag_proto.h"
#include "../common/StatusArg.h"
@ -84,6 +86,50 @@ static rhd* locate_space(thread_db*, record_param*, SSHORT, PageStack&, Record*,
static void mark_full(thread_db*, record_param*);
static void store_big_record(thread_db*, record_param*, PageStack&, const UCHAR*, ULONG, const Jrd::RecordStorageType type);
namespace
{
void lock_gc_active(thread_db* tdbb, const jrd_tra* transaction, record_param* rpb)
{
if (rpb->rpb_gc_lock)
{
fb_assert(rpb->rpb_gc_lock->lck_id);
fb_assert(rpb->rpb_gc_lock->lck_logical == LCK_EX);
fb_assert(rpb->rpb_gc_lock->lck_data == transaction->tra_number);
}
else
{
AutoPtr<Lock> lock(FB_NEW_RPT(*tdbb->getDefaultPool(), 0)
Lock(tdbb, sizeof(SINT64), LCK_record_gc));
lock->lck_key.lck_long = ((SINT64) rpb->rpb_page << 16) | rpb->rpb_line;
lock->lck_data = transaction->tra_number;
ThreadStatusGuard temp_status(tdbb);
if (!LCK_lock(tdbb, lock, LCK_EX, LCK_NO_WAIT))
{
fb_assert(false);
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
ERR_punt();
}
rpb->rpb_gc_lock = lock.release();
}
}
void release_gc_active(thread_db* tdbb, record_param* rpb)
{
if (rpb->rpb_gc_lock)
{
fb_assert(rpb->rpb_gc_lock->lck_id);
fb_assert(rpb->rpb_gc_lock->lck_logical == LCK_EX);
LCK_release(tdbb, rpb->rpb_gc_lock);
delete rpb->rpb_gc_lock;
rpb->rpb_gc_lock = NULL;
}
}
}
PAG DPM_allocate(thread_db* tdbb, WIN* window)
{
@ -103,7 +149,7 @@ PAG DPM_allocate(thread_db* tdbb, WIN* window)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
"DPM_allocate (window page %"SLONGFORMAT")\n",
"DPM_allocate (window page %"ULONGFORMAT")\n",
window ? window->win_page.getPageNum() : 0);
#endif
@ -135,8 +181,8 @@ void DPM_backout( thread_db* tdbb, record_param* rpb)
"DPM_backout (record_param %"QUADFORMAT"d)\n", rpb->rpb_number.getValue());
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %"
SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %"
ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
rpb->rpb_f_line, rpb->rpb_flags);
@ -152,9 +198,11 @@ void DPM_backout( thread_db* tdbb, record_param* rpb)
rhd* header = (rhd*) ((SCHAR *) page + index1->dpg_offset);
header->rhd_flags &= ~(rhd_chain | rhd_gc_active);
release_gc_active(tdbb, rpb);
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
" old record %"SLONGFORMAT":%d, new record %"SLONGFORMAT
" old record %"ULONGFORMAT":%d, new record %"ULONGFORMAT
":%d, old dpg_count %d, ",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_b_page,
rpb->rpb_b_line, page->dpg_count);
@ -195,10 +243,9 @@ void DPM_backout_mark(thread_db* tdbb, record_param* rpb, const jrd_tra* transac
rhd* header = (rhd*) ((SCHAR*) page + index->dpg_offset);
header->rhd_flags |= rhd_gc_active;
header->rhd_transaction = transaction->tra_number;
rpb->rpb_flags |= rpb_gc_active;
rpb->rpb_transaction_nr = transaction->tra_number;
lock_gc_active(tdbb, transaction, rpb);
CCH_RELEASE(tdbb, window);
}
@ -300,8 +347,8 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb)
new_rpb ? new_rpb->rpb_number.getValue() : 0);
VIO_trace(DEBUG_WRITES_INFO,
" org record %"SLONGFORMAT":%d transaction %"ULONGFORMAT
" back %"SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
" org record %"ULONGFORMAT":%d transaction %"ULONGFORMAT
" back %"ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
org_rpb->rpb_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr,
org_rpb->rpb_b_page, org_rpb->rpb_b_line, org_rpb->rpb_f_page,
org_rpb->rpb_f_line, org_rpb->rpb_flags);
@ -320,6 +367,8 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb)
const Compressor dcc(*tdbb->getDefaultPool(), new_rpb->rpb_length, new_rpb->rpb_address);
const ULONG size = (ULONG) dcc.getPackedLength();
const FB_SIZE_T header_size = (new_rpb->rpb_transaction_nr > MAX_ULONG) ? RHDE_SIZE : RHD_SIZE;
if (!DPM_get(tdbb, org_rpb, LCK_write))
{
#ifdef VIO_DEBUG
@ -343,7 +392,6 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb)
return false;
}
if ((org_rpb->rpb_flags & rpb_delta) && temp.rpb_prior)
org_rpb->rpb_prior = temp.rpb_prior;
else if (org_rpb->rpb_flags & rpb_delta)
@ -360,7 +408,7 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb)
// If the record obviously isn't going to fit, don't even try
if (size > dbb->dbb_page_size - (sizeof(data_page) + RHD_SIZE))
if (size > dbb->dbb_page_size - (sizeof(data_page) + header_size))
{
CCH_RELEASE(tdbb, &org_rpb->getWindow(tdbb));
#ifdef VIO_DEBUG
@ -373,12 +421,12 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb)
// The record must be long enough to permit fragmentation later. If it's
// too small, compute the number of pad bytes required
SLONG fill = (RHDF_SIZE - RHD_SIZE) - size;
SLONG fill = (RHDF_SIZE - header_size) - size;
if (fill < 0 || (new_rpb->rpb_flags & rpb_deleted))
fill = 0;
// Accomodate max record size i.e. 64K
const SLONG length = ROUNDUP(RHD_SIZE + size + fill, ODS_ALIGNMENT);
const SLONG length = ROUNDUP(header_size + size + fill, ODS_ALIGNMENT);
// Find space on page and open slot
@ -447,19 +495,21 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb)
page->dpg_rpt[slot] = *index2;
index2->dpg_offset = space;
index2->dpg_length = RHD_SIZE + size + fill;
index2->dpg_length = header_size + size + fill;
header = (rhd*) ((SCHAR *) page + space);
header->rhd_flags = new_rpb->rpb_flags;
header->rhd_transaction = new_rpb->rpb_transaction_nr;
Ods::writeTraNum(header, new_rpb->rpb_transaction_nr, header_size);
header->rhd_format = new_rpb->rpb_format_number;
header->rhd_b_page = new_rpb->rpb_b_page;
header->rhd_b_line = new_rpb->rpb_b_line;
dcc.pack(new_rpb->rpb_address, header->rhd_data);
UCHAR* const data = (UCHAR*) header + header_size;
dcc.pack(new_rpb->rpb_address, data);
if (fill)
memset(header->rhd_data + size, 0, fill);
memset(data + size, 0, fill);
if (page->dpg_header.pag_flags & dpg_swept)
{
@ -609,7 +659,7 @@ ULONG DPM_data_pages(thread_db* tdbb, jrd_rel* relation)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE_ALL,
" returned pages: %"SLONGFORMAT"\n", pages);
" returned pages: %"ULONGFORMAT"\n", pages);
#endif
return pages;
@ -638,12 +688,12 @@ void DPM_delete( thread_db* tdbb, record_param* rpb, ULONG prior_page)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES,
"DPM_delete (record_param %"QUADFORMAT", prior_page %"SLONGFORMAT")\n",
"DPM_delete (record_param %"QUADFORMAT", prior_page %"ULONGFORMAT")\n",
rpb->rpb_number.getValue(), prior_page);
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %"
SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %"
ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
rpb->rpb_f_line, rpb->rpb_flags);
@ -873,7 +923,7 @@ void DPM_delete( thread_db* tdbb, record_param* rpb, ULONG prior_page)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
"\tDPM_delete: page %"SLONGFORMAT
"\tDPM_delete: page %"ULONGFORMAT
" is empty and about to be released from relation %d\n",
window->win_page.getPageNum(), rpb->rpb_relation->rel_id);
#endif
@ -1062,7 +1112,7 @@ bool DPM_fetch(thread_db* tdbb, record_param* rpb, USHORT lock)
rpb->rpb_number.getValue(), lock);
VIO_trace(DEBUG_READS_INFO,
" record %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line);
" record %"ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line);
#endif
const RecordNumber number = rpb->rpb_number;
@ -1078,8 +1128,8 @@ bool DPM_fetch(thread_db* tdbb, record_param* rpb, USHORT lock)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %"
SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %"
ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
rpb->rpb_f_line, rpb->rpb_flags);
@ -1124,8 +1174,8 @@ bool DPM_fetch_back(thread_db* tdbb, record_param* rpb, USHORT lock, SSHORT latc
rpb->rpb_number.getValue(), lock);
VIO_trace(DEBUG_READS_INFO,
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT
" back %"SLONGFORMAT":%d\n",
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT
" back %"ULONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_b_page, rpb->rpb_b_line);
#endif
@ -1153,8 +1203,8 @@ bool DPM_fetch_back(thread_db* tdbb, record_param* rpb, USHORT lock, SSHORT latc
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record fetched %"SLONGFORMAT":%d transaction %"
ULONGFORMAT" back %"SLONGFORMAT":%d fragment %"SLONGFORMAT
" record fetched %"ULONGFORMAT":%d transaction %"
ULONGFORMAT" back %"ULONGFORMAT":%d fragment %"ULONGFORMAT
":%d flags %d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
@ -1188,8 +1238,8 @@ void DPM_fetch_fragment( thread_db* tdbb, record_param* rpb, USHORT lock)
rpb->rpb_number.getValue(), lock);
VIO_trace(DEBUG_READS_INFO,
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT
" back %"SLONGFORMAT":%d\n",
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT
" back %"ULONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_b_page, rpb->rpb_b_line);
#endif
@ -1207,8 +1257,8 @@ void DPM_fetch_fragment( thread_db* tdbb, record_param* rpb, USHORT lock)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record fetched %"SLONGFORMAT":%d transaction %"ULONGFORMAT
" back %"SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
" record fetched %"ULONGFORMAT":%d transaction %"ULONGFORMAT
" back %"ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
rpb->rpb_f_line, rpb->rpb_flags);
@ -1370,7 +1420,7 @@ bool DPM_get(thread_db* tdbb, record_param* rpb, SSHORT lock_type)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record %"SLONGFORMAT":%d\n", page->ppg_page[slot], line);
" record %"ULONGFORMAT":%d\n", page->ppg_page[slot], line);
#endif
const ULONG page_number = page->ppg_page[slot];
@ -1420,7 +1470,7 @@ ULONG DPM_get_blob(thread_db* tdbb,
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS,
"DPM_get_blob (blob, record_number %"QUADFORMAT
"d, delete_flag %d, prior_page %"SLONGFORMAT")\n",
"d, delete_flag %d, prior_page %"ULONGFORMAT")\n",
record_number.getValue(), (int) delete_flag, prior_page);
#endif
@ -1724,7 +1774,7 @@ void DPM_pages(thread_db* tdbb, SSHORT rel_id, int type, ULONG sequence, ULONG p
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE_ALL,
"DPM_pages (rel_id %d, type %d, sequence %"ULONGFORMAT", page %"SLONGFORMAT")\n",
"DPM_pages (rel_id %d, type %d, sequence %"ULONGFORMAT", page %"ULONGFORMAT")\n",
rel_id, type, sequence, page);
#endif
@ -1909,8 +1959,8 @@ void DPM_store( thread_db* tdbb, record_param* rpb, PageStack& stack, const Jrd:
rpb->rpb_number.getValue(), type);
VIO_trace(DEBUG_WRITES_INFO,
" record to store %"SLONGFORMAT":%d transaction %"ULONGFORMAT
" back %"SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
" record to store %"ULONGFORMAT":%d transaction %"ULONGFORMAT
" back %"ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
rpb->rpb_f_line, rpb->rpb_flags);
@ -1919,35 +1969,39 @@ void DPM_store( thread_db* tdbb, record_param* rpb, PageStack& stack, const Jrd:
const Compressor dcc(*tdbb->getDefaultPool(), rpb->rpb_length, rpb->rpb_address);
const ULONG size = (ULONG) dcc.getPackedLength();
const FB_SIZE_T header_size = (rpb->rpb_transaction_nr > MAX_ULONG) ? RHDE_SIZE : RHD_SIZE;
// If the record isn't going to fit on a page, even if fragmented,
// handle it a little differently.
if (size > dbb->dbb_page_size - (sizeof(data_page) + RHD_SIZE))
if (size > dbb->dbb_page_size - (sizeof(data_page) + header_size))
{
store_big_record(tdbb, rpb, stack, dcc.getControl() + dcc.getControlSize(), size, type);
return;
}
SLONG fill = (RHDF_SIZE - RHD_SIZE) - size;
SLONG fill = (RHDF_SIZE - header_size) - size;
if (fill < 0)
fill = 0;
// Accomodate max record size i.e. 64K
const SLONG length = RHD_SIZE + size + fill;
const SLONG length = header_size + size + fill;
rhd* header = locate_space(tdbb, rpb, (SSHORT) length, stack, NULL, type);
header->rhd_flags = rpb->rpb_flags;
header->rhd_transaction = rpb->rpb_transaction_nr;
Ods::writeTraNum(header, rpb->rpb_transaction_nr, header_size);
header->rhd_format = rpb->rpb_format_number;
header->rhd_b_page = rpb->rpb_b_page;
header->rhd_b_line = rpb->rpb_b_line;
dcc.pack(rpb->rpb_address, header->rhd_data);
UCHAR* const data = (UCHAR*) header + header_size;
dcc.pack(rpb->rpb_address, data);
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT":%d, length %"SLONGFORMAT
", rpb_flags %d, f_page %"SLONGFORMAT":%d, b_page %"SLONGFORMAT
" record %"ULONGFORMAT":%d, length %"SLONGFORMAT
", rpb_flags %d, f_page %"ULONGFORMAT":%d, b_page %"ULONGFORMAT
":%d\n",
rpb->rpb_page, rpb->rpb_line, length, rpb->rpb_flags,
rpb->rpb_f_page, rpb->rpb_f_line, rpb->rpb_b_page,
@ -1955,7 +2009,7 @@ void DPM_store( thread_db* tdbb, record_param* rpb, PageStack& stack, const Jrd:
#endif
if (fill)
memset(header->rhd_data + size, 0, fill);
memset(data + size, 0, fill);
Ods::pag* page = rpb->getWindow(tdbb).win_buffer;
if (page->pag_flags & dpg_swept)
@ -2057,7 +2111,7 @@ void DPM_rewrite_header( thread_db* tdbb, record_param* rpb)
"DPM_rewrite_header (record_param %"QUADFORMAT"d)\n", rpb->rpb_number.getValue());
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line);
" record %"ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line);
#endif
WIN* window = &rpb->getWindow(tdbb);
@ -2066,20 +2120,23 @@ void DPM_rewrite_header( thread_db* tdbb, record_param* rpb)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
" old flags %d, old transaction %"ULONGFORMAT
", old format %d, old back record %"SLONGFORMAT":%d\n",
header->rhd_flags, header->rhd_transaction, (int) header->rhd_format,
" old flags %d, old transaction %"SQUADFORMAT
", old format %d, old back record %"ULONGFORMAT":%d\n",
header->rhd_flags, Ods::getTraNum(header), (int) header->rhd_format,
header->rhd_b_page, header->rhd_b_line);
VIO_trace(DEBUG_WRITES_INFO,
" new flags %d, new transaction %"ULONGFORMAT
", new format %d, new back record %"SLONGFORMAT":%d\n",
" new flags %d, new transaction %"SQUADFORMAT
", new format %d, new back record %"ULONGFORMAT":%d\n",
rpb->rpb_flags, rpb->rpb_transaction_nr, rpb->rpb_format_number,
rpb->rpb_b_page, rpb->rpb_b_line);
#endif
// dimitr: current code is not expected to change the transaction number
fb_assert(rpb->rpb_transaction_nr == Ods::getTraNum(header));
// Ods::writeTraNum(header, rpb->rpb_transaction_nr);
header->rhd_flags = rpb->rpb_flags;
header->rhd_transaction = rpb->rpb_transaction_nr;
header->rhd_format = rpb->rpb_format_number;
header->rhd_b_page = rpb->rpb_b_page;
header->rhd_b_line = rpb->rpb_b_line;
@ -2108,8 +2165,8 @@ void DPM_update( thread_db* tdbb, record_param* rpb, PageStack* stack, const jrd
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %"
SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %"
ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
rpb->rpb_f_line, rpb->rpb_flags);
@ -2131,15 +2188,17 @@ void DPM_update( thread_db* tdbb, record_param* rpb, PageStack* stack, const jrd
const Compressor dcc(*tdbb->getDefaultPool(), rpb->rpb_length, rpb->rpb_address);
const ULONG size = (ULONG) dcc.getPackedLength();
const FB_SIZE_T header_size = (rpb->rpb_transaction_nr > MAX_ULONG) ? RHDE_SIZE : RHD_SIZE;
// It is critical that the record be padded, if necessary, to the length of
// a fragmented record header. Compute the amount of fill required.
SLONG fill = (RHDF_SIZE - RHD_SIZE) - size;
SLONG fill = (RHDF_SIZE - header_size) - size;
if (fill < 0)
fill = 0;
// Accomodate max record size i.e. 64K
const SLONG length = ROUNDUP(RHD_SIZE + size + fill, ODS_ALIGNMENT);
const SLONG length = ROUNDUP(header_size + size + fill, ODS_ALIGNMENT);
const USHORT slot = rpb->rpb_line;
// Find space on page
@ -2173,29 +2232,33 @@ void DPM_update( thread_db* tdbb, record_param* rpb, PageStack* stack, const jrd
fb_assert(space >= top);
page->dpg_rpt[slot].dpg_offset = space;
page->dpg_rpt[slot].dpg_length = RHD_SIZE + size + fill;
page->dpg_rpt[slot].dpg_length = header_size + size + fill;
rhd* header = (rhd*) ((SCHAR *) page + space);
header->rhd_flags = rpb->rpb_flags;
header->rhd_transaction = rpb->rpb_transaction_nr;
Ods::writeTraNum(header, rpb->rpb_transaction_nr, header_size);
header->rhd_format = rpb->rpb_format_number;
header->rhd_b_page = rpb->rpb_b_page;
header->rhd_b_line = rpb->rpb_b_line;
dcc.pack(rpb->rpb_address, header->rhd_data);
release_gc_active(tdbb, rpb);
UCHAR* const data = (UCHAR*) header + header_size;
dcc.pack(rpb->rpb_address, data);
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT
":%d, dpg_length %d, rpb_flags %d, rpb_f record %"SLONGFORMAT
":%d, rpb_b record %"SLONGFORMAT":%d\n",
" record %"ULONGFORMAT
":%d, dpg_length %d, rpb_flags %d, rpb_f record %"ULONGFORMAT
":%d, rpb_b record %"ULONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, page->dpg_rpt[slot].dpg_length,
rpb->rpb_flags, rpb->rpb_f_page, rpb->rpb_f_line,
rpb->rpb_b_page, rpb->rpb_b_line);
#endif
if (fill)
memset(header->rhd_data + size, 0, fill);
memset(data + size, 0, fill);
if (page->dpg_header.pag_flags & dpg_swept)
{
@ -2254,7 +2317,7 @@ static void check_swept(thread_db* tdbb, record_param* rpb)
if (index->dpg_offset)
{
rhd* header = (rhd*) ((SCHAR*) dpage + index->dpg_offset);
if (header->rhd_transaction > transaction->tra_oldest ||
if (Ods::getTraNum(header) > transaction->tra_oldest ||
header->rhd_flags & (rpb_blob | rpb_chained | rpb_fragment) ||
header->rhd_b_page)
{
@ -2290,7 +2353,7 @@ static USHORT compress(thread_db* tdbb, data_page* page)
"compress (page)\n");
VIO_trace(DEBUG_TRACE_ALL_INFO,
" sequence %"SLONGFORMAT"\n", page->dpg_sequence);
" sequence %"ULONGFORMAT"\n", page->dpg_sequence);
#endif
UCHAR temp_page[MAX_PAGE_SIZE];
@ -2344,9 +2407,9 @@ static void delete_tail(thread_db* tdbb, rhdf* header, const USHORT page_space,
"delete_tail (header, length)\n");
VIO_trace(DEBUG_WRITES_INFO,
" transaction %"ULONGFORMAT" flags %d fragment %"
SLONGFORMAT":%d back %"SLONGFORMAT":%d\n",
header->rhdf_transaction, header->rhdf_flags,
" transaction %"SQUADFORMAT" flags %d fragment %"
ULONGFORMAT":%d back %"ULONGFORMAT":%d\n",
Ods::getTraNum(header), header->rhdf_flags,
header->rhdf_f_page, header->rhdf_f_line,
header->rhdf_b_page, header->rhdf_b_line);
#endif
@ -2477,8 +2540,8 @@ static void fragment(thread_db* tdbb,
transaction ? transaction->tra_number : 0);
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %"
SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %"
ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
rpb->rpb_f_line, rpb->rpb_flags);
@ -2497,11 +2560,9 @@ static void fragment(thread_db* tdbb,
const USHORT line = rpb->rpb_line;
rhdf* header;
if (transaction->tra_number != rpb->rpb_transaction_nr)
if (rpb->rpb_transaction_nr != transaction->tra_number)
{
header = (rhdf*) ((SCHAR *) page + page->dpg_rpt[line].dpg_offset);
header->rhdf_transaction = transaction->tra_number;
header->rhdf_flags |= rhd_gc_active;
page->dpg_rpt[line].dpg_length = available_space = length;
}
else
@ -2521,17 +2582,20 @@ static void fragment(thread_db* tdbb,
page->dpg_rpt[line].dpg_offset = space;
page->dpg_rpt[line].dpg_length = available_space;
}
header->rhdf_transaction = rpb->rpb_transaction_nr;
header->rhdf_b_page = rpb->rpb_b_page;
header->rhdf_b_line = rpb->rpb_b_line;
}
header->rhdf_flags |= rhd_gc_active;
lock_gc_active(tdbb, transaction, rpb);
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
" rhdf_transaction %"ULONGFORMAT", window record %"SLONGFORMAT
" rhdf_transaction %"SQUADFORMAT", window record %"ULONGFORMAT
":%d, available_space %d, rhdf_flags %d, rhdf_f record %"
SLONGFORMAT":%d, rhdf_b record %"SLONGFORMAT":%d\n",
header->rhdf_transaction, window->win_page.getPageNum(), line,
ULONGFORMAT":%d, rhdf_b record %"ULONGFORMAT":%d\n",
Ods::getTraNum(header), window->win_page.getPageNum(), line,
available_space, header->rhdf_flags, header->rhdf_f_page,
header->rhdf_f_line, header->rhdf_b_page, header->rhdf_b_line);
#endif
@ -2572,17 +2636,19 @@ static void fragment(thread_db* tdbb,
header = (rhdf*) ((SCHAR *) page + page->dpg_rpt[line].dpg_offset);
header->rhdf_flags = rhd_incomplete | rpb->rpb_flags;
header->rhdf_transaction = rpb->rpb_transaction_nr;
Ods::writeTraNum(header, rpb->rpb_transaction_nr, RHDF_SIZE);
header->rhdf_format = rpb->rpb_format_number;
header->rhdf_f_page = tail_rpb.rpb_page;
header->rhdf_f_line = tail_rpb.rpb_line;
if (transaction->tra_number != rpb->rpb_transaction_nr)
if (rpb->rpb_transaction_nr != transaction->tra_number)
{
header->rhdf_b_page = rpb->rpb_b_page;
header->rhdf_b_line = rpb->rpb_b_line;
}
release_gc_active(tdbb, rpb);
const size_t post_header_length =
dcc.pack(rpb->rpb_address, available_space - RHDF_SIZE, header->rhdf_data);
@ -2591,10 +2657,10 @@ static void fragment(thread_db* tdbb,
" fragment head \n");
VIO_trace(DEBUG_WRITES_INFO,
" rhdf_trans %"ULONGFORMAT", window record %"SLONGFORMAT
":%d, dpg_length %d\n\trhdf_flags %d, rhdf_f record %"SLONGFORMAT
":%d, rhdf_b record %"SLONGFORMAT":%d\n",
header->rhdf_transaction, window->win_page.getPageNum(), line,
" rhdf_trans %"SQUADFORMAT", window record %"ULONGFORMAT
":%d, dpg_length %d\n\trhdf_flags %d, rhdf_f record %"ULONGFORMAT
":%d, rhdf_b record %"ULONGFORMAT":%d\n",
Ods::getTraNum(header), window->win_page.getPageNum(), line,
page->dpg_rpt[line].dpg_length, header->rhdf_flags,
header->rhdf_f_page, header->rhdf_f_line, header->rhdf_b_page,
header->rhdf_b_line);
@ -2793,7 +2859,7 @@ static void extend_relation(thread_db* tdbb, jrd_rel* relation, WIN* window, con
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
" extended_relation (relation %d, window_page %"SLONGFORMAT")\n",
" extended_relation (relation %d, window_page %"ULONGFORMAT")\n",
relation->rel_id, window->win_page.getPageNum());
#endif
}
@ -2952,23 +3018,26 @@ static bool get_header(WIN* window, USHORT line, record_param* rpb)
{
rpb->rpb_b_page = header->rhdf_b_page;
rpb->rpb_b_line = header->rhdf_b_line;
rpb->rpb_transaction_nr = header->rhdf_transaction;
rpb->rpb_transaction_nr = Ods::getTraNum(header);
rpb->rpb_format_number = header->rhdf_format;
}
FB_SIZE_T header_size;
if (rpb->rpb_flags & rpb_incomplete)
{
rpb->rpb_f_page = header->rhdf_f_page;
rpb->rpb_f_line = header->rhdf_f_line;
rpb->rpb_address = header->rhdf_data;
rpb->rpb_length = index->dpg_length - RHDF_SIZE;
header_size = RHDF_SIZE;
}
else
{
rpb->rpb_address = ((rhd*) header)->rhd_data;
rpb->rpb_length = index->dpg_length - RHD_SIZE;
header_size = (rpb->rpb_flags & rpb_long_tranum) ? RHDE_SIZE : RHD_SIZE;
}
rpb->rpb_address = (UCHAR*) header + header_size;
rpb->rpb_length = index->dpg_length - header_size;
return true;
}
@ -3221,7 +3290,7 @@ static rhd* locate_space(thread_db* tdbb,
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
" extended relation %d with page %"SLONGFORMAT" to get %d bytes\n",
" extended relation %d with page %"ULONGFORMAT" to get %d bytes\n",
relation->rel_id, window->win_page.getPageNum(), size);
#endif
@ -3483,8 +3552,8 @@ static void store_big_record(thread_db* tdbb,
" back portion\n");
VIO_trace(DEBUG_WRITES_INFO,
" getWindow(tdbb) page %"SLONGFORMAT
", max_data %d, \n\trhdf_flags %d, prior %"SLONGFORMAT"\n",
" getWindow(tdbb) page %"ULONGFORMAT
", max_data %d, \n\trhdf_flags %d, prior %"ULONGFORMAT"\n",
rpb->getWindow(tdbb).win_page.getPageNum(), max_data, header->rhdf_flags,
prior.getPageNum());
#endif
@ -3500,7 +3569,7 @@ static void store_big_record(thread_db* tdbb,
rhdf* header = (rhdf*) locate_space(tdbb, rpb, (SSHORT) (RHDF_SIZE + size), stack, NULL, type);
header->rhdf_flags = rhd_incomplete | rhd_large | rpb->rpb_flags;
header->rhdf_transaction = rpb->rpb_transaction_nr;
Ods::writeTraNum(header, rpb->rpb_transaction_nr, RHDF_SIZE);
header->rhdf_format = rpb->rpb_format_number;
header->rhdf_b_page = rpb->rpb_b_page;
header->rhdf_b_line = rpb->rpb_b_line;
@ -3515,10 +3584,10 @@ static void store_big_record(thread_db* tdbb,
" front part\n");
VIO_trace(DEBUG_WRITES_INFO,
" rhdf_trans %"ULONGFORMAT", rpb_window record %"SLONGFORMAT
":%d, dpg_length %d \n\trhdf_flags %d, rhdf_f record %"SLONGFORMAT
":%d, rhdf_b record %"SLONGFORMAT":%d\n",
header->rhdf_transaction, rpb->getWindow(tdbb).win_page.getPageNum(),
" rhdf_trans %"SQUADFORMAT", rpb_window record %"ULONGFORMAT
":%d, dpg_length %d \n\trhdf_flags %d, rhdf_f record %"ULONGFORMAT
":%d, rhdf_b record %"ULONGFORMAT":%d\n",
Ods::getTraNum(header), rpb->getWindow(tdbb).win_page.getPageNum(),
rpb->rpb_line, page->dpg_rpt[rpb->rpb_line].dpg_length,
header->rhdf_flags, header->rhdf_f_page, header->rhdf_f_line,
header->rhdf_b_page, header->rhdf_b_line);

View File

@ -76,7 +76,7 @@
FIELD(fld_mechanism , nam_mechanism , dtype_short , sizeof(SSHORT) , 0 , NULL , true)
FIELD(fld_f_descr , nam_desc , dtype_blob , BLOB_SIZE , isc_blob_format , NULL , true)
FIELD(fld_fun_type , nam_fun_type , dtype_short , sizeof(SSHORT) , 0 , NULL , true)
FIELD(fld_trans_id , nam_trans_id , dtype_long , sizeof(SLONG) , 0 , NULL , true)
FIELD(fld_trans_id , nam_trans_id , dtype_int64 , sizeof(SINT64) , 0 , NULL , true)
FIELD(fld_trans_state , nam_trans_state , dtype_short , sizeof(SSHORT) , 0 , NULL , true)
FIELD(fld_time , nam_time , dtype_timestamp, TIMESTAMP_SIZE , 0 , NULL , true)
FIELD(fld_trans_desc , nam_trans_desc , dtype_blob , BLOB_SIZE , isc_blob_tra , NULL , true)
@ -127,9 +127,9 @@
FIELD(fld_r_type , nam_r_type , dtype_short , sizeof(SSHORT) , 0 , NULL , true)
FIELD(fld_prc_type , nam_prc_type , dtype_short , sizeof(SSHORT) , 0 , NULL , true)
FIELD(fld_att_id , nam_att_id , dtype_long , sizeof(SLONG) , 0 , NULL , true)
FIELD(fld_stmt_id , nam_stmt_id , dtype_long , sizeof(SLONG) , 0 , NULL , true)
FIELD(fld_call_id , nam_call_id , dtype_long , sizeof(SLONG) , 0 , NULL , true)
FIELD(fld_att_id , nam_att_id , dtype_int64 , sizeof(SINT64) , 0 , NULL , true)
FIELD(fld_stmt_id , nam_stmt_id , dtype_int64 , sizeof(SINT64) , 0 , NULL , true)
FIELD(fld_call_id , nam_call_id , dtype_int64 , sizeof(SINT64) , 0 , NULL , true)
FIELD(fld_stat_id , nam_stat_id , dtype_long , sizeof(SLONG) , 0 , NULL , true)
FIELD(fld_pid , nam_pid , dtype_long , sizeof(SLONG) , 0 , NULL , true)

View File

@ -1110,11 +1110,8 @@ ISC_STATUS filter_trans(USHORT action, BlobControl* control)
break;
case TDR_TRANSACTION_ID:
{
const SLONG id = gds__vax_integer(p, length);
sprintf(out, " Transaction id: %"SLONGFORMAT, id);
break;
}
sprintf(out, " Transaction id: %"SQUADFORMAT, isc_portable_integer(p, length));
break;
default:
sprintf(out, "item %d not understood", (int) p[-1]);

View File

@ -105,6 +105,18 @@ static inline USHORT getNullSegment(const temporary_key& key)
return MAX_USHORT;
}
IndexReserveLock::IndexReserveLock(thread_db* tdbb, const jrd_rel* relation, const index_desc* idx)
: Lock(tdbb, sizeof(SLONG), LCK_idx_reserve), m_tdbb(tdbb)
{
lck_key.lck_long = (relation->rel_id << 16) | idx->idx_id;
}
IndexReserveLock::~IndexReserveLock()
{
LCK_release(m_tdbb, this);
}
void IDX_check_access(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view, jrd_rel* relation)
{
/**************************************
@ -129,15 +141,15 @@ void IDX_check_access(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view, jrd_
WIN window(relPages->rel_pg_space_id, -1);
WIN referenced_window(relPages->rel_pg_space_id, -1);
while (BTR_next_index(tdbb, relation, 0, &idx, &window))
while (BTR_next_index(tdbb, relation, NULL, &idx, &window))
{
if (idx.idx_flags & idx_foreign)
{
// find the corresponding primary key index
if (!MET_lookup_partner(tdbb, relation, &idx, 0)) {
if (!MET_lookup_partner(tdbb, relation, &idx, 0))
continue;
}
jrd_rel* referenced_relation = MET_relation(tdbb, idx.idx_primary_relation);
MET_scan_relation(tdbb, referenced_relation);
const USHORT index_id = idx.idx_primary_index;
@ -264,11 +276,6 @@ void IDX_create_index(thread_db* tdbb,
fb_assert(transaction);
BTR_reserve_slot(tdbb, relation, transaction, idx);
if (index_id)
*index_id = idx->idx_id;
record_param primary, secondary;
secondary.rpb_relation = relation;
primary.rpb_relation = relation;
@ -297,6 +304,17 @@ void IDX_create_index(thread_db* tdbb,
Arg::Gds(isc_keytoobig) << Arg::Str(index_name));
}
IndexCreation creation;
creation.index = idx;
creation.relation = relation;
creation.transaction = transaction;
creation.key_length = key_length;
BTR_reserve_slot(tdbb, creation);
if (index_id)
*index_id = idx->idx_id;
RecordStack stack;
const UCHAR pad = isDescending ? -1 : 0;
@ -322,9 +340,10 @@ void IDX_create_index(thread_db* tdbb,
FPTR_REJECT_DUP_CALLBACK callback = (idx->idx_flags & idx_unique) ? duplicate_key : NULL;
void* callback_arg = (idx->idx_flags & idx_unique) ? &ifl_data : NULL;
AutoPtr<Sort> scb(FB_NEW_POOL(transaction->tra_sorts.getPool())
Sort* const scb = FB_NEW_POOL(transaction->tra_sorts.getPool())
Sort(dbb, &transaction->tra_sorts, key_length + sizeof(index_sort_record),
2, 1, key_desc, callback, callback_arg));
2, 1, key_desc, callback, callback_arg);
creation.sort = scb;
jrd_rel* partner_relation = NULL;
USHORT partner_index_id = 0;
@ -520,7 +539,7 @@ void IDX_create_index(thread_db* tdbb,
context.raise(tdbb, idx_e_duplicate, error_record);
}
BTR_create(tdbb, relation, idx, key_length, scb, selectivity);
BTR_create(tdbb, creation, selectivity);
if ((relation->rel_flags & REL_temp_conn) && (relation->getPages(tdbb)->rel_instance_id != 0))
{
@ -528,9 +547,8 @@ void IDX_create_index(thread_db* tdbb,
if (idx_lock)
{
++idx_lock->idl_count;
if (idx_lock->idl_count == 1) {
if (idx_lock->idl_count == 1)
LCK_lock(tdbb, idx_lock->idl_lock, LCK_SR, LCK_WAIT);
}
}
}
}

View File

@ -993,7 +993,7 @@ public:
const char* getRemoteProcessName() { return m_options->dpb_remote_process.c_str(); }
// TraceDatabaseConnection implementation
int getConnectionID() { return 0; }
ISC_INT64 getConnectionID() { return 0; }
const char* getDatabaseName() { return m_filename; }
private:
@ -6267,7 +6267,7 @@ static void init_database_lock(thread_db* tdbb)
// Main database lock
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, 0)
Lock* const lock = FB_NEW_RPT(*dbb->dbb_permanent, 0)
Lock(tdbb, 0, LCK_database, dbb, CCH_down_grade_dbb);
dbb->dbb_lock = lock;
@ -6430,7 +6430,6 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
}
}
tdbb->setAttachment(NULL);
Jrd::Attachment::destroy(attachment); // string were re-saved in the beginning of this function,
// keep that in sync please

View File

@ -140,7 +140,6 @@ static const bool compatibility[LCK_max][LCK_max] =
//#define COMPATIBLE(st1, st2) compatibility [st1 * LCK_max + st2]
const int LOCK_HASH_SIZE = 19;
inline void ENQUEUE(thread_db* tdbb, CheckStatusWrapper* statusVector, Lock* lock, USHORT level, SSHORT wait)
{
if (lock->lck_compatible)
@ -547,7 +546,9 @@ static SLONG get_owner_handle(thread_db* tdbb, enum lck_t lock_type)
case LCK_cancel:
case LCK_monitor:
case LCK_btr_dont_gc:
case LCK_idx_reserve:
case LCK_rel_gc:
case LCK_record_gc:
handle = *LCK_OWNER_HANDLE_ATT(tdbb);
break;
@ -704,7 +705,7 @@ bool LCK_lock_opt(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
}
SLONG LCK_query_data(thread_db* tdbb, enum lck_t lock_type, USHORT aggregate)
SINT64 LCK_query_data(thread_db* tdbb, enum lck_t lock_type, USHORT aggregate)
{
/**************************************
*
@ -725,7 +726,7 @@ SLONG LCK_query_data(thread_db* tdbb, enum lck_t lock_type, USHORT aggregate)
}
SLONG LCK_read_data(thread_db* tdbb, Lock* lock)
SINT64 LCK_read_data(thread_db* tdbb, Lock* lock)
{
/**************************************
*
@ -742,9 +743,9 @@ SLONG LCK_read_data(thread_db* tdbb, Lock* lock)
fb_assert(LCK_CHECK_LOCK(lock));
const SLONG data =
const SINT64 data =
dbb->dbb_lock_mgr->readData2(lock->lck_type,
(UCHAR*) &lock->lck_key, lock->lck_length,
lock->lck_key.lck_string, lock->lck_length,
lock->lck_owner_handle);
fb_assert(LCK_CHECK_LOCK(lock));
return data;
@ -815,7 +816,7 @@ void LCK_re_post(thread_db* tdbb, Lock* lock)
}
void LCK_write_data(thread_db* tdbb, Lock* lock, SLONG data)
void LCK_write_data(thread_db* tdbb, Lock* lock, SINT64 data)
{
/**************************************
*
@ -916,7 +917,7 @@ static void enqueue(thread_db* tdbb, CheckStatusWrapper* statusVector, Lock* loc
fb_assert(LCK_CHECK_LOCK(lock));
lock->lck_id = dbb->dbb_lock_mgr->enqueue(att, statusVector, lock->lck_id,
lock->lck_type, (const UCHAR*) &lock->lck_key, lock->lck_length,
lock->lck_type, lock->lck_key.lck_string, lock->lck_length,
level, lock->lck_ast, lock->lck_object, lock->lck_data, wait,
lock->lck_owner_handle);
@ -1459,21 +1460,21 @@ static bool internal_enqueue(thread_db* tdbb, CheckStatusWrapper* statusVector,
Lock::Lock(thread_db* tdbb, USHORT length, lck_t type, void* object, lock_ast_t ast)
: lck_dbb(tdbb->getDatabase()),
lck_attachment(0),
lck_compatible(0),
lck_compatible2(0),
lck_attachment(NULL),
lck_compatible(NULL),
lck_compatible2(NULL),
lck_ast(ast),
lck_object(object),
lck_next(0),
lck_prior(0),
lck_collision(0),
lck_identical(0),
lck_next(NULL),
lck_prior(NULL),
lck_collision(NULL),
lck_identical(NULL),
lck_id(0),
lck_owner_handle(get_owner_handle(tdbb, type)),
lck_length(length),
lck_type(type),
lck_logical(0),
lck_physical(0),
lck_logical(LCK_none),
lck_physical(LCK_none),
lck_data(0)
{
lck_key.lck_long = 0;
@ -1525,7 +1526,6 @@ void Lock::setLockAttachment(thread_db* tdbb, Jrd::Attachment* attachment)
lck_prior = NULL;
}
// Enlist in new attachment
if (attachment)
{

View File

@ -69,7 +69,9 @@ enum lck_t {
LCK_fun_exist, // Function existence lock
LCK_rel_rescan, // Relation forced rescan lock
LCK_crypt, // Crypt lock for single crypt thread
LCK_crypt_status // Notifies about changed database encryption status
LCK_crypt_status, // Notifies about changed database encryption status
LCK_idx_reserve, // Index reservation lock
LCK_record_gc // Record-level GC lock
};
// Lock owner types
@ -129,12 +131,12 @@ public:
public:
UCHAR lck_logical; // Logical lock level
UCHAR lck_physical; // Physical lock level
SLONG lck_data; // Data associated with a lock
SINT64 lck_data; // Data associated with a lock
union
{
UCHAR lck_string[1];
SLONG lck_long;
SINT64 lck_long;
} lck_key; // Lock key string
UCHAR lck_tail[1]; // Makes the allocator happy

View File

@ -40,11 +40,11 @@ void LCK_fini(Jrd::thread_db*, Jrd::lck_owner_t);
void LCK_init(Jrd::thread_db*, Jrd::lck_owner_t);
bool LCK_lock(Jrd::thread_db*, Jrd::Lock*, USHORT, SSHORT);
bool LCK_lock_opt(Jrd::thread_db*, Jrd::Lock*, USHORT, SSHORT);
SLONG LCK_query_data(Jrd::thread_db*, Jrd::lck_t, USHORT);
SLONG LCK_read_data(Jrd::thread_db*, Jrd::Lock*);
SINT64 LCK_query_data(Jrd::thread_db*, Jrd::lck_t, USHORT);
SINT64 LCK_read_data(Jrd::thread_db*, Jrd::Lock*);
void LCK_release(Jrd::thread_db*, Jrd::Lock*);
void LCK_re_post(Jrd::thread_db*, Jrd::Lock*);
void LCK_write_data(Jrd::thread_db*, Jrd::Lock*, SLONG);
void LCK_write_data(Jrd::thread_db*, Jrd::Lock*, SINT64);
class AutoLock

View File

@ -135,14 +135,10 @@ static bool verify_TRG_ignore_perm(thread_db*, const MetaName&);
static void release_cached_triggers(thread_db* tdbb, trig_vec* vector)
{
if (!vector)
{
return;
}
for (FB_SIZE_T i = 0; i < vector->getCount(); i++)
{
(*vector)[i].release(tdbb);
}
}
@ -186,9 +182,7 @@ static void inc_int_use_count(JrdStatement* statement)
static void post_used_procedures(trig_vec* vector)
{
if (!vector)
{
return;
}
for (FB_SIZE_T i = 0; i < vector->getCount(); i++)
{
@ -355,7 +349,7 @@ void MET_update_partners(thread_db* tdbb)
*
**************************************/
SET_TDBB(tdbb);
Attachment* attachment = tdbb->getAttachment();
Attachment* const attachment = tdbb->getAttachment();
vec<jrd_rel*>* relations = attachment->att_relations;
@ -363,9 +357,8 @@ void MET_update_partners(thread_db* tdbb)
for (const vec<jrd_rel*>::const_iterator end = relations->end(); ptr < end; ++ptr)
{
jrd_rel* relation = *ptr;
if (!relation) {
if (!relation)
continue;
}
// signal other processes
LCK_lock(tdbb, relation->rel_partners_lock, LCK_EX, LCK_WAIT);
@ -706,7 +699,7 @@ void MET_clear_cache(thread_db* tdbb)
for (jrd_prc** iter = att->att_procedures.begin(); iter != att->att_procedures.end(); ++iter)
{
Routine* routine = *iter;
Routine* const routine = *iter;
if (routine && routine->getStatement() &&
!(routine->flags & Routine::FLAG_OBSOLETE) )
@ -717,7 +710,7 @@ void MET_clear_cache(thread_db* tdbb)
for (Function** iter = att->att_functions.begin(); iter != att->att_functions.end(); ++iter)
{
Function* routine = *iter;
Function* const routine = *iter;
if (routine && routine->getStatement() &&
!(routine->flags & Routine::FLAG_OBSOLETE) )
@ -730,7 +723,7 @@ void MET_clear_cache(thread_db* tdbb)
for (jrd_prc** iter = att->att_procedures.begin(); iter != att->att_procedures.end(); ++iter)
{
Routine* routine = *iter;
Routine* const routine = *iter;
if (routine && routine->getStatement() &&
!(routine->flags & Routine::FLAG_OBSOLETE) &&
@ -742,7 +735,7 @@ void MET_clear_cache(thread_db* tdbb)
for (Function** iter = att->att_functions.begin(); iter != att->att_functions.end(); ++iter)
{
Function* routine = *iter;
Function* const routine = *iter;
if (routine && routine->getStatement() &&
!(routine->flags & Routine::FLAG_OBSOLETE) &&
@ -756,7 +749,7 @@ void MET_clear_cache(thread_db* tdbb)
for (jrd_prc** iter = att->att_procedures.begin(); iter != att->att_procedures.end(); ++iter)
{
Routine* routine = *iter;
Routine* const routine = *iter;
if (routine)
{
@ -782,7 +775,7 @@ void MET_clear_cache(thread_db* tdbb)
for (Function** iter = att->att_functions.begin(); iter != att->att_functions.end(); ++iter)
{
Function* routine = *iter;
Function* const routine = *iter;
if (routine)
{
@ -831,7 +824,7 @@ bool MET_routine_in_use(thread_db* tdbb, Routine* routine)
MET_verify_cache(tdbb);
#endif
Attachment* att = tdbb->getAttachment();
Attachment* const att = tdbb->getAttachment();
vec<jrd_rel*>* relations = att->att_relations;
{ // scope
@ -2214,9 +2207,7 @@ int MET_lookup_field(thread_db* tdbb, jrd_rel* relation, const MetaName& name)
int id = -1;
if (relation->rel_flags & REL_deleted)
{
return id;
}
AutoCacheRequest request(tdbb, irq_l_field, IRQ_REQUESTS);
@ -2521,9 +2512,8 @@ bool MET_lookup_partner(thread_db* tdbb, jrd_rel* relation, index_desc* idx, con
SET_TDBB(tdbb);
Attachment* attachment = tdbb->getAttachment();
if (relation->rel_flags & REL_check_partners) {
if (relation->rel_flags & REL_check_partners)
scan_partners(tdbb, relation);
}
if (idx->idx_flags & idx_foreign)
{
@ -2846,7 +2836,7 @@ jrd_rel* MET_lookup_relation_id(thread_db* tdbb, SLONG id, bool return_deleted)
*
**************************************/
SET_TDBB(tdbb);
Attachment* attachment = tdbb->getAttachment();
Attachment* const attachment = tdbb->getAttachment();
// System relations are above suspicion
@ -3514,9 +3504,8 @@ jrd_rel* MET_relation(thread_db* tdbb, USHORT id)
}
// This should check system flag instead.
if (relation->rel_id <= max_sys_rel) {
if (relation->rel_id <= max_sys_rel)
return relation;
}
{ // Scope block.
Lock* lock = FB_NEW_RPT(*pool, 0)
@ -3631,9 +3620,7 @@ void MET_scan_partners(thread_db* tdbb, jrd_rel* relation)
SET_TDBB(tdbb);
if (relation->rel_flags & REL_check_partners)
{
scan_partners(tdbb, relation);
}
}
@ -3691,9 +3678,8 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
relation->rel_current_fmt = REL.RDB$FORMAT;
vec<jrd_fld*>* vector = relation->rel_fields =
vec<jrd_fld*>::newVector(*relation->rel_pool, relation->rel_fields, REL.RDB$FIELD_ID + 1);
if (!REL.RDB$SECURITY_CLASS.NULL) {
if (!REL.RDB$SECURITY_CLASS.NULL)
relation->rel_security_name = REL.RDB$SECURITY_CLASS;
}
relation->rel_name = REL.RDB$RELATION_NAME;
relation->rel_owner_name = REL.RDB$OWNER_NAME;
@ -4595,10 +4581,9 @@ void MET_release_triggers( thread_db* tdbb, trig_vec** vector_ptr)
*
**************************************/
trig_vec* vector = *vector_ptr;
if (!vector)
{
return;
}
SET_TDBB(tdbb);

View File

@ -24,6 +24,16 @@
#include "../jrd/ods.h"
#include "../jrd/ods_proto.h"
using namespace Firebird;
namespace
{
const FB_SIZE_T NEXT_INDEX = 0;
const FB_SIZE_T OIT_INDEX = 1;
const FB_SIZE_T OAT_INDEX = 2;
const FB_SIZE_T OST_INDEX = 3;
}
namespace Ods {
bool isSupported(USHORT majorVersion, USHORT minorVersion)
@ -34,24 +44,6 @@ bool isSupported(USHORT majorVersion, USHORT minorVersion)
if (!isFirebird)
return false;
#ifdef ODS_8_TO_CURRENT
// Obsolete: Support InterBase major ODS numbers from 8 to 10
/*
if (!isFirebird)
{
return (majorVersion >= ODS_VERSION8 &&
majorVersion <= ODS_VERSION10);
}
*/
// This is for future ODS versions
if (majorVersion > ODS_VERSION10 &&
majorVersion < ODS_VERSION)
{
return true;
}
#endif
// Support current ODS of the engine
if (majorVersion == ODS_VERSION &&
minorVersion >= ODS_RELEASED &&
@ -168,4 +160,97 @@ Firebird::string pagtype(UCHAR type)
return rc;
}
TraNumber getNT(const header_page* page)
{
return (TraNumber) page->hdr_tra_high[NEXT_INDEX] << BITS_PER_LONG | page->hdr_next_transaction;
}
TraNumber getOIT(const header_page* page)
{
return (TraNumber) page->hdr_tra_high[OIT_INDEX] << BITS_PER_LONG | page->hdr_oldest_transaction;
}
TraNumber getOAT(const header_page* page)
{
return (TraNumber) page->hdr_tra_high[OAT_INDEX] << BITS_PER_LONG | page->hdr_oldest_active;
}
TraNumber getOST(const header_page* page)
{
return (TraNumber) page->hdr_tra_high[OST_INDEX] << BITS_PER_LONG | page->hdr_oldest_snapshot;
}
void writeNT(header_page* page, TraNumber number)
{
page->hdr_next_transaction = (ULONG) (number & MAX_ULONG);
const SLONG high_word = number >> BITS_PER_LONG;
fb_assert(high_word <= MAX_USHORT);
page->hdr_tra_high[NEXT_INDEX] = (USHORT) high_word;
}
void writeOIT(header_page* page, TraNumber number)
{
page->hdr_oldest_transaction = (ULONG) (number & MAX_ULONG);
const SLONG high_word = number >> BITS_PER_LONG;
fb_assert(high_word <= MAX_USHORT);
page->hdr_tra_high[OIT_INDEX] = (USHORT) high_word;
}
void writeOAT(header_page* page, TraNumber number)
{
page->hdr_oldest_active = (ULONG) (number & MAX_ULONG);
const SLONG high_word = number >> BITS_PER_LONG;
fb_assert(high_word <= MAX_USHORT);
page->hdr_tra_high[OAT_INDEX] = (USHORT) high_word;
}
void writeOST(header_page* page, TraNumber number)
{
page->hdr_oldest_snapshot = (ULONG) (number & MAX_ULONG);
const SLONG high_word = number >> BITS_PER_LONG;
fb_assert(high_word <= MAX_USHORT);
page->hdr_tra_high[OST_INDEX] = (USHORT) high_word;
}
TraNumber getTraNum(const void* ptr)
{
rhd* const record = (rhd*) ptr;
USHORT high_word = 0;
if (record->rhd_flags & rhd_long_tranum)
{
high_word = (record->rhd_flags & rhd_incomplete) ?
((rhdf*) ptr)->rhdf_tra_high : ((rhde*) ptr)->rhde_tra_high;
}
return ((TraNumber) high_word << BITS_PER_LONG) | record->rhd_transaction;
}
void writeTraNum(void* ptr, TraNumber number, FB_SIZE_T header_size)
{
rhd* const record = (rhd*) ptr;
record->rhd_transaction = (ULONG) (number & MAX_ULONG);
const SLONG high_word = number >> BITS_PER_LONG;
fb_assert(high_word <= MAX_USHORT);
if (high_word)
record->rhd_flags |= rhd_long_tranum;
if (record->rhd_flags & rhd_long_tranum)
{
if (record->rhd_flags & rhd_incomplete)
{
fb_assert(header_size == RHDF_SIZE);
((rhdf*) ptr)->rhdf_tra_high = (USHORT) high_word;
}
else
{
fb_assert(header_size == RHDE_SIZE);
((rhde*) ptr)->rhde_tra_high = (USHORT) high_word;
}
}
}
} // namespace

View File

@ -310,7 +310,7 @@ struct index_root_page
struct irt_repeat
{
ULONG irt_root; // page number of index root
TraNumber irt_transaction; // transaction in progress
ULONG irt_transaction; // transaction in progress (lowest 32 bits)
USHORT irt_desc; // offset to key descriptions
UCHAR irt_keys; // number of keys in index
UCHAR irt_flags;
@ -348,13 +348,13 @@ struct header_page
USHORT hdr_ods_version; // Version of on-disk structure
ULONG hdr_PAGES; // Page number of PAGES relation
ULONG hdr_next_page; // Page number of next hdr page
TraNumber hdr_oldest_transaction; // Oldest interesting transaction
TraNumber hdr_oldest_active; // Oldest transaction thought active
TraNumber hdr_next_transaction; // Next transaction id
ULONG hdr_oldest_transaction; // Oldest interesting transaction
ULONG hdr_oldest_active; // Oldest transaction thought active
ULONG hdr_next_transaction; // Next transaction id
USHORT hdr_sequence; // sequence number of file
USHORT hdr_flags; // Flag settings, see below
SLONG hdr_creation_date[2]; // Date/time of creation
SLONG hdr_attachment_id; // Next attachment id
ULONG hdr_attachment_id; // Next attachment id
SLONG hdr_shadow_count; // Event count for shadow synchronization
UCHAR hdr_cpu; // CPU database was created on
UCHAR hdr_os; // OS database was created under
@ -363,12 +363,13 @@ struct header_page
USHORT hdr_ods_minor; // Update version of ODS
USHORT hdr_end; // offset of HDR_end in page
ULONG hdr_page_buffers; // Page buffers for database cache
TraNumber hdr_oldest_snapshot; // Oldest snapshot of active transactions
ULONG hdr_oldest_snapshot; // Oldest snapshot of active transactions
SLONG hdr_backup_pages; // The amount of pages in files locked for backup
ULONG hdr_crypt_page; // Page at which processing is in progress
ULONG hdr_top_crypt; // Last page to crypt
TEXT hdr_crypt_plugin[32]; // Name of plugin used to crypt this DB
SLONG hdr_misc[3]; // Stuff to be named later - reserved for minor changes
SLONG hdr_att_high; // High word of the next attachment counter
USHORT hdr_tra_high[4]; // High words of the transaction counters
UCHAR hdr_data[1]; // Misc data
};
@ -527,28 +528,44 @@ struct generator_page
struct rhd
{
TraNumber rhd_transaction; // transaction id
ULONG rhd_transaction; // transaction id (lowest 32 bits)
ULONG rhd_b_page; // back pointer
USHORT rhd_b_line; // back line
USHORT rhd_flags; // flags, etc
UCHAR rhd_format; // format version
UCHAR rhd_data[1];
UCHAR rhd_data[1]; // record data
};
#define RHD_SIZE static_cast<FB_SIZE_T>(offsetof(Ods::rhd, rhd_data[0]))
// Record header extended to hold long transaction id
struct rhde
{
ULONG rhde_transaction; // transaction id (lowest 32 bits)
ULONG rhde_b_page; // back pointer
USHORT rhde_b_line; // back line
USHORT rhde_flags; // flags, etc
UCHAR rhde_format; // format version // until here, same as rhd
USHORT rhde_tra_high; // higher bits of transaction id
UCHAR rhde_data[1]; // record data
};
#define RHDE_SIZE static_cast<FB_SIZE_T>(offsetof(Ods::rhde, rhde_data[0]))
// Record header for fragmented record
struct rhdf
{
TraNumber rhdf_transaction; // transaction id
ULONG rhdf_transaction; // transaction id (lowest 32 bits)
ULONG rhdf_b_page; // back pointer
USHORT rhdf_b_line; // back line
USHORT rhdf_flags; // flags, etc
UCHAR rhdf_format; // format version // until here, same than rhd
UCHAR rhdf_format; // format version // until here, same as rhd
USHORT rhdf_tra_high; // higher bits of transaction id
ULONG rhdf_f_page; // next fragment page
USHORT rhdf_f_line; // next fragment line
UCHAR rhdf_data[1]; // Blob data
UCHAR rhdf_data[1]; // record data
};
#define RHDF_SIZE static_cast<FB_SIZE_T>(offsetof(Ods::rhdf, rhdf_data[0]))
@ -583,12 +600,11 @@ const USHORT rhd_incomplete = 8; // record is incomplete
const USHORT rhd_blob = 16; // isn't a record but a blob
const USHORT rhd_stream_blob = 32; // blob is a stream mode blob
const USHORT rhd_delta = 32; // prior version is differences only
// Tested in validation.cpp's walk_chain but never set
const USHORT rhd_large = 64; // object is large
const USHORT rhd_damaged = 128; // object is known to be damaged
const USHORT rhd_gc_active = 256; // garbage collecting dead record version
//const USHORT rhd_uk_modified = 512; // record key field values are changed
const USHORT rhd_uk_modified = 512; // record key field values are changed
const USHORT rhd_long_tranum = 1024; // transaction number is 64-bit
// This (not exact) copy of class DSC is used to store descriptors on disk.

View File

@ -39,6 +39,19 @@ namespace Ods {
ULONG maxRecsPerDP(ULONG page_size);
ULONG maxIndices(ULONG page_size);
TraNumber getNT(const header_page* page);
TraNumber getOIT(const header_page* page);
TraNumber getOAT(const header_page* page);
TraNumber getOST(const header_page* page);
void writeNT(header_page* page, TraNumber number);
void writeOIT(header_page* page, TraNumber number);
void writeOAT(header_page* page, TraNumber number);
void writeOST(header_page* page, TraNumber number);
TraNumber getTraNum(const void* ptr);
void writeTraNum(void* ptr, TraNumber number, FB_SIZE_T header_size);
} // namespace
#endif //ODS_PROTO_H

View File

@ -2647,7 +2647,7 @@ SortedStream* OPT_gen_sort(thread_db* tdbb, CompilerScratch* csb, const StreamLi
map_item++;
}
// Make fields for record numbers record for all streams
// Make fields for record numbers and transaction ids for all streams
map_length = ROUNDUP(map_length, sizeof(SINT64));
for (const StreamType* ptr = streams.begin(); ptr < end_ptr; ptr++, map_item++)
@ -2660,18 +2660,15 @@ SortedStream* OPT_gen_sort(thread_db* tdbb, CompilerScratch* csb, const StreamLi
desc->dsc_length = sizeof(SINT64);
desc->dsc_address = (UCHAR*)(IPTR) map_length;
map_length += desc->dsc_length;
}
// Make fields for transaction id of record for all streams
map_item++;
for (const StreamType* ptr = streams.begin(); ptr < end_ptr; ptr++, map_item++)
{
map_item->clear();
map_item->fieldId = SortedStream::ID_TRANS;
map_item->stream = *ptr;
dsc* desc = &map_item->desc;
desc->dsc_dtype = dtype_long;
desc->dsc_length = sizeof(SLONG);
desc = &map_item->desc;
desc->dsc_dtype = dtype_int64;
desc->dsc_length = sizeof(SINT64);
desc->dsc_address = (UCHAR*)(IPTR) map_length;
map_length += desc->dsc_length;
}

View File

@ -834,7 +834,7 @@ static ULONG ensureDiskSpace(thread_db* tdbb, WIN* pip_window, const PageNumber
}
SLONG PAG_attachment_id(thread_db* tdbb)
AttNumber PAG_attachment_id(thread_db* tdbb)
{
/******************************************
*
@ -860,15 +860,18 @@ SLONG PAG_attachment_id(thread_db* tdbb)
// Get new attachment id
if (dbb->readOnly()) {
if (dbb->readOnly())
attachment->att_attachment_id = dbb->dbb_attachment_id + dbb->generateAttachmentId(tdbb);
}
else
{
window.win_page = HEADER_PAGE_NUMBER;
header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
CCH_MARK(tdbb, &window);
attachment->att_attachment_id = ++header->hdr_attachment_id;
const AttNumber att_id =
((SINT64) header->hdr_att_high << BITS_PER_LONG | header->hdr_attachment_id) + 1;
attachment->att_attachment_id = att_id;
header->hdr_att_high = att_id >> BITS_PER_LONG;
header->hdr_attachment_id = (ULONG) (att_id & MAX_ULONG);
CCH_RELEASE(tdbb, &window);
}
@ -960,9 +963,8 @@ void PAG_format_header(thread_db* tdbb)
header->hdr_end = HDR_SIZE;
header->hdr_data[0] = HDR_end;
if (dbb->dbb_flags & DBB_DB_SQL_dialect_3) {
if (dbb->dbb_flags & DBB_DB_SQL_dialect_3)
header->hdr_flags |= hdr_SQL_dialect_3;
}
dbb->dbb_ods_version = header->hdr_ods_version & ~ODS_FIREBIRD_FLAG;
dbb->dbb_minor_version = header->hdr_ods_minor;
@ -1106,12 +1108,17 @@ void PAG_header(thread_db* tdbb, bool info)
try {
if (header->hdr_next_transaction)
const TraNumber next_transaction = Ods::getNT(header);
const TraNumber oldest_transaction = Ods::getOIT(header);
const TraNumber oldest_active = Ods::getOAT(header);
const TraNumber oldest_snapshot = Ods::getOST(header);
if (next_transaction)
{
if (header->hdr_oldest_active > header->hdr_next_transaction)
if (oldest_active > next_transaction)
BUGCHECK(266); // next transaction older than oldest active
if (header->hdr_oldest_transaction > header->hdr_next_transaction)
if (oldest_transaction > next_transaction)
BUGCHECK(267); // next transaction older than oldest transaction
}
@ -1134,17 +1141,16 @@ void PAG_header(thread_db* tdbb, bool info)
(*vector)[0] = header->hdr_PAGES;
}
dbb->dbb_next_transaction = header->hdr_next_transaction;
dbb->dbb_next_transaction = next_transaction;
if (!info || dbb->dbb_oldest_transaction < header->hdr_oldest_transaction) {
dbb->dbb_oldest_transaction = header->hdr_oldest_transaction;
}
if (!info || dbb->dbb_oldest_active < header->hdr_oldest_active) {
dbb->dbb_oldest_active = header->hdr_oldest_active;
}
if (!info || dbb->dbb_oldest_snapshot < header->hdr_oldest_snapshot) {
dbb->dbb_oldest_snapshot = header->hdr_oldest_snapshot;
}
if (!info || dbb->dbb_oldest_transaction < oldest_transaction)
dbb->dbb_oldest_transaction = oldest_transaction;
if (!info || dbb->dbb_oldest_active < oldest_active)
dbb->dbb_oldest_active = oldest_active;
if (!info || dbb->dbb_oldest_snapshot < oldest_snapshot)
dbb->dbb_oldest_snapshot = oldest_snapshot;
dbb->dbb_attachment_id = header->hdr_attachment_id;
dbb->dbb_creation_date = *(ISC_TIMESTAMP*) header->hdr_creation_date;
@ -2286,7 +2292,8 @@ void PageManager::initTempPageSpace(thread_db* tdbb)
if (!attachment->att_temp_pg_lock)
{
Lock* lock = FB_NEW_RPT(*attachment->att_pool, 0) Lock(tdbb, sizeof(SLONG), LCK_page_space);
Lock* const lock = FB_NEW_RPT(*attachment->att_pool, 0)
Lock(tdbb, sizeof(SLONG), LCK_page_space);
while (true)
{

View File

@ -45,7 +45,7 @@ bool PAG_add_header_entry(Jrd::thread_db* tdbb, Ods::header_page*, USHORT, USHOR
bool PAG_replace_entry_first(Jrd::thread_db* tdbb, Ods::header_page*, USHORT, USHORT, const UCHAR*);
Ods::pag* PAG_allocate(Jrd::thread_db* tdbb, Jrd::win*);
Ods::pag* PAG_allocate_pages(Jrd::thread_db* tdbb, Jrd::win* window, int cntAlloc, bool aligned);
SLONG PAG_attachment_id(Jrd::thread_db*);
AttNumber PAG_attachment_id(Jrd::thread_db*);
bool PAG_delete_clump_entry(Jrd::thread_db* tdbb, USHORT);
void PAG_format_header(Jrd::thread_db*);
void PAG_format_pip(Jrd::thread_db*, Jrd::PageSpace& pageSpace);

View File

@ -68,16 +68,26 @@ BufferedStream::BufferedStream(CompilerScratch* csb, RecordSource* next)
fields.add(*desc);
} while (accessor.getNext());
}
}
dsc desc;
dsc desc;
desc.makeLong(0);
for (StreamList::iterator i = streams.begin(); i != streams.end(); ++i)
{
const StreamType stream = *i;
desc.makeInt64(0);
m_map.add(FieldMap(FieldMap::TRANSACTION_ID, stream, 0));
fields.add(desc);
desc.makeInt64(0);
m_map.add(FieldMap(FieldMap::DBKEY_NUMBER, stream, 0));
fields.add(desc);
}
for (StreamList::iterator i = streams.begin(); i != streams.end(); ++i)
{
const StreamType stream = *i;
desc.makeText(1, CS_BINARY);
m_map.add(FieldMap(FieldMap::DBKEY_VALID, stream, 0));
@ -191,7 +201,7 @@ bool BufferedStream::getRecord(thread_db* tdbb) const
break;
case FieldMap::TRANSACTION_ID:
*reinterpret_cast<ULONG*>(to.dsc_address) = rpb->rpb_transaction_nr;
*reinterpret_cast<SINT64*>(to.dsc_address) = rpb->rpb_transaction_nr;
break;
case FieldMap::DBKEY_NUMBER:
@ -258,7 +268,7 @@ bool BufferedStream::getRecord(thread_db* tdbb) const
break;
case FieldMap::TRANSACTION_ID:
rpb->rpb_transaction_nr = *reinterpret_cast<ULONG*>(from.dsc_address);
rpb->rpb_transaction_nr = *reinterpret_cast<SINT64*>(from.dsc_address);
break;
case FieldMap::DBKEY_NUMBER:

View File

@ -219,7 +219,7 @@ Sort* SortedStream::init(thread_db* tdbb) const
switch (item->fieldId)
{
case ID_TRANS:
*reinterpret_cast<ULONG*>(to.dsc_address) = rpb->rpb_transaction_nr;
*reinterpret_cast<SINT64*>(to.dsc_address) = rpb->rpb_transaction_nr;
break;
case ID_DBKEY:
*reinterpret_cast<SINT64*>(to.dsc_address) = rpb->rpb_number.getValue();
@ -353,7 +353,7 @@ void SortedStream::mapData(thread_db* tdbb, jrd_req* request, UCHAR* data) const
switch (id)
{
case ID_TRANS:
rpb->rpb_transaction_nr = *reinterpret_cast<ULONG*>(from.dsc_address);
rpb->rpb_transaction_nr = *reinterpret_cast<SINT64*>(from.dsc_address);
break;
case ID_DBKEY:
rpb->rpb_number.setValue(*reinterpret_cast<SINT64*>(from.dsc_address));

View File

@ -62,7 +62,7 @@ struct record_param
rpb_f_page(0), rpb_f_line(0),
rpb_b_page(0), rpb_b_line(0),
rpb_address(NULL), rpb_length(0), rpb_flags(0), rpb_stream_flags(0),
rpb_org_scans(0),
rpb_org_scans(0), rpb_gc_lock(NULL),
rpb_window(DB_PAGE_SPACE, -1)
{
}
@ -90,6 +90,7 @@ struct record_param
USHORT rpb_stream_flags; // stream flags
USHORT rpb_runtime_flags; // runtime flags
SSHORT rpb_org_scans; // relation scan count at stream open
Lock* rpb_gc_lock; // lock for transient record changes
inline WIN& getWindow(thread_db* tdbb)
{
@ -106,16 +107,17 @@ private:
// Record flags must be an exact replica of ODS record header flags
const USHORT rpb_deleted = 1;
const USHORT rpb_chained = 2;
const USHORT rpb_fragment = 4;
const USHORT rpb_incomplete = 8;
const USHORT rpb_blob = 16;
const USHORT rpb_delta = 32; // prior version is a differences record
// rpb_large = 64 is missing
const USHORT rpb_damaged = 128; // record is busted
const USHORT rpb_gc_active = 256; // garbage collecting dead record version
const USHORT rpb_uk_modified= 512; // record key field values are changed
const USHORT rpb_deleted = 1;
const USHORT rpb_chained = 2;
const USHORT rpb_fragment = 4;
const USHORT rpb_incomplete = 8;
const USHORT rpb_blob = 16;
const USHORT rpb_delta = 32; // prior version is a differences record
const USHORT rpb_large = 64; // object is large
const USHORT rpb_damaged = 128; // record is busted
const USHORT rpb_gc_active = 256; // garbage collecting dead record version
const USHORT rpb_uk_modified = 512; // record key field values are changed
const USHORT rpb_long_tranum = 1024; // transaction number is 64-bit
// Stream flags
@ -217,7 +219,7 @@ private:
public:
MemoryPool* req_pool;
Attachment* req_attachment; // database attachment
SLONG req_id; // request identifier
StmtNumber req_id; // request identifier
USHORT req_incarnation; // incarnation number
Firebird::MemoryStats req_memory_stats;

View File

@ -42,6 +42,9 @@ typedef Firebird::SparseBitmap<ULONG> PageBitmap;
// Bitmap of generic 32-bit integers
typedef Firebird::SparseBitmap<ULONG> UInt32Bitmap;
// Bitmap of transaction numbers
typedef Firebird::SparseBitmap<TraNumber> TransactionBitmap;
// Please do not try to turn these macros to inline routines simply.
// They are used in very performance-sensitive places and we don't want
// pool thread-specific pool pointer be expanded unless necessary.
@ -61,6 +64,10 @@ typedef Firebird::SparseBitmap<ULONG> UInt32Bitmap;
#define PBM_SET(POOL_PTR, BITMAP_PPTR, VALUE) \
(*(BITMAP_PPTR) ? *(BITMAP_PPTR) : (*(BITMAP_PPTR) = FB_NEW_POOL(*(POOL_PTR)) Jrd::PageBitmap(*(POOL_PTR))))->set(VALUE)
// Bitmap of transaction numbers
#define TBM_SET(POOL_PTR, BITMAP_PPTR, VALUE) \
(*(BITMAP_PPTR) ? *(BITMAP_PPTR) : (*(BITMAP_PPTR) = FB_NEW_POOL(*(POOL_PTR)) Jrd::TransactionBitmap(*(POOL_PTR))))->set(VALUE)
} //namespace Jrd
#endif // JRD_SBM_H

View File

@ -449,6 +449,21 @@ void Service::putSLong(char tag, SLONG val)
enqueue(buf, sizeof buf);
}
void Service::putSInt64(char tag, SINT64 val)
{
UCHAR buf[5];
buf[0] = tag;
buf[1] = val;
buf[2] = val >> 8;
buf[3] = val >> 16;
buf[4] = val >> 24;
buf[5] = val >> 32;
buf[6] = val >> 40;
buf[7] = val >> 48;
buf[8] = val >> 56;
enqueue(buf, sizeof buf);
}
void Service::putChar(char tag, char val)
{
UCHAR buf[2];

View File

@ -119,6 +119,7 @@ public: // utilities interface with service
// put various info items in info buffer
virtual void putLine(char tag, const char* val);
virtual void putSLong(char tag, SLONG val);
virtual void putSInt64(char tag, SINT64 val);
virtual void putChar(char tag, char val);
// put raw bytes to svc_stdout
virtual void putBytes(const UCHAR*, FB_SIZE_T);

View File

@ -28,6 +28,7 @@
#include "../jrd/pag.h"
#include "../jrd/cch_proto.h"
#include "../jrd/lck_proto.h"
#include "../jrd/ods_proto.h"
#include "../jrd/tpc_proto.h"
#include "../jrd/tra_proto.h"
@ -85,7 +86,7 @@ int TipCache::cacheState(thread_db* tdbb, TraNumber number)
// locate the specific TIP cache block for the transaction
const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
const ULONG base = number - number % trans_per_tip;
const TraNumber base = number - number % trans_per_tip;
FB_SIZE_T pos;
if (m_cache.find(base, pos))
@ -142,7 +143,7 @@ TraNumber TipCache::findLimbo(thread_db* tdbb, TraNumber minNumber, TraNumber ma
minNumber = tip_cache->tpc_base;
const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
const ULONG base = minNumber - minNumber % trans_per_tip;
const TraNumber base = minNumber - minNumber % trans_per_tip;
// Scan the TIP cache and return the first (i.e. oldest) limbo transaction
@ -232,7 +233,7 @@ void TipCache::setState(TraNumber number, SSHORT state)
**************************************/
const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
const ULONG base = number - number % trans_per_tip;
const TraNumber base = number - number % trans_per_tip;
const ULONG byte = TRANS_OFFSET(number % trans_per_tip);
const USHORT shift = TRANS_SHIFT(number);
@ -299,7 +300,7 @@ int TipCache::snapshotState(thread_db* tdbb, TraNumber number)
// locate the specific TIP cache block for the transaction
const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
const ULONG base = number - number % trans_per_tip;
const TraNumber base = number - number % trans_per_tip;
FB_SIZE_T pos;
if (m_cache.find(base, pos))
@ -322,7 +323,7 @@ int TipCache::snapshotState(thread_db* tdbb, TraNumber number)
// see if we can get a lock on the transaction; if we can't
// then we know it is still active
Lock temp_lock(tdbb, sizeof(SLONG), LCK_tra);
Lock temp_lock(tdbb, sizeof(TraNumber), LCK_tra);
temp_lock.lck_key.lck_long = number;
// If we can't get a lock on the transaction, it must be active.
@ -368,7 +369,7 @@ void TipCache::updateCache(const Ods::tx_inv_page* tip_page, ULONG sequence)
**************************************/
const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
const TraNumber first_trans = sequence * trans_per_tip;
const TraNumber first_trans = (TraNumber) sequence * trans_per_tip;
// while we're in the area we can check to see if there are
// any tip cache pages we can release--this is cheaper and
@ -462,8 +463,8 @@ TraNumber TipCache::cacheTransactions(thread_db* tdbb, TraNumber oldest)
#else
WIN window(HEADER_PAGE_NUMBER);
const Ods::header_page* header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header);
const TraNumber top = header->hdr_next_transaction;
const TraNumber hdr_oldest = header->hdr_oldest_transaction;
const TraNumber top = Ods::getNT(header);
const TraNumber hdr_oldest = Ods::getOIT(header);
CCH_RELEASE(tdbb, &window);
#endif
@ -557,7 +558,8 @@ int TipCache::extendCache(thread_db* tdbb, TraNumber number)
// find the right block for this transaction and return the state
const ULONG base = number - number % trans_per_tip;
const TraNumber base = number - number % trans_per_tip;
FB_SIZE_T pos;
if (m_cache.find(base, pos))
{
@ -573,6 +575,7 @@ int TipCache::extendCache(thread_db* tdbb, TraNumber number)
// we should never get to this point, but if we do the
// safest thing to do is return active
fb_assert(false);
return tra_active;
}

View File

@ -228,8 +228,8 @@ void TRA_cleanup(thread_db* tdbb)
WIN window(HEADER_PAGE_NUMBER);
const header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header);
const TraNumber ceiling = header->hdr_next_transaction;
const TraNumber active = header->hdr_oldest_active;
const TraNumber ceiling = Ods::getNT(header);
const TraNumber active = Ods::getOAT(header);
CCH_RELEASE(tdbb, &window);
if (ceiling == 0)
@ -246,7 +246,7 @@ void TRA_cleanup(thread_db* tdbb)
{
window.win_page = inventory_page(tdbb, sequence);
tx_inv_page* tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_transactions);
ULONG max = ceiling - (sequence * trans_per_tip);
TraNumber max = ceiling - (TraNumber) sequence * trans_per_tip;
if (max > trans_per_tip)
max = trans_per_tip - 1;
for (; number <= max; number++)
@ -256,7 +256,7 @@ void TRA_cleanup(thread_db* tdbb)
const USHORT shift = TRANS_SHIFT(number);
const int state = (*byte >> shift) & TRA_MASK;
if (state == tra_limbo && limbo == 0)
limbo = sequence * trans_per_tip + number;
limbo = (TraNumber) sequence * trans_per_tip + number;
else if (state == tra_active)
{
CCH_MARK(tdbb, &window);
@ -314,7 +314,7 @@ void TRA_cleanup(thread_db* tdbb)
}
if (!tip->tip_next)
dbb->dbb_next_transaction = last * trans_per_tip;
dbb->dbb_next_transaction = (TraNumber) last * trans_per_tip;
}
CCH_RELEASE(tdbb, &window);
@ -579,7 +579,7 @@ void TRA_get_inventory(thread_db* tdbb, UCHAR* bit_vector, TraNumber base, TraNu
while (sequence <= last)
{
base = sequence * trans_per_tip;
base = (TraNumber) sequence * trans_per_tip;
// release the read lock as we go, so that some one else can
// commit without having to signal all other transactions.
@ -658,12 +658,17 @@ void TRA_header_write(thread_db* tdbb, Database* dbb, TraNumber number)
WIN window(HEADER_PAGE_NUMBER);
header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
if (header->hdr_next_transaction)
const TraNumber next_transaction = Ods::getNT(header);
const TraNumber oldest_active = Ods::getOAT(header);
const TraNumber oldest_transaction = Ods::getOIT(header);
const TraNumber oldest_snapshot = Ods::getOST(header);
if (next_transaction)
{
if (header->hdr_oldest_active > header->hdr_next_transaction)
if (oldest_active > next_transaction)
BUGCHECK(266); //next transaction older than oldest active
if (header->hdr_oldest_transaction > header->hdr_next_transaction)
if (oldest_transaction > next_transaction)
BUGCHECK(267); // next transaction older than oldest transaction
}
@ -674,17 +679,18 @@ void TRA_header_write(thread_db* tdbb, Database* dbb, TraNumber number)
if (!number || dbb->dbb_last_header_write < number)
{
CCH_MARK_MUST_WRITE(tdbb, &window);
if (dbb->dbb_next_transaction > header->hdr_next_transaction)
header->hdr_next_transaction = dbb->dbb_next_transaction;
if (dbb->dbb_oldest_active > header->hdr_oldest_active)
header->hdr_oldest_active = dbb->dbb_oldest_active;
if (dbb->dbb_next_transaction > next_transaction)
Ods::writeNT(header, dbb->dbb_next_transaction);
if (dbb->dbb_oldest_transaction > header->hdr_oldest_transaction)
header->hdr_oldest_transaction = dbb->dbb_oldest_transaction;
if (dbb->dbb_oldest_active > oldest_active)
Ods::writeOAT(header, dbb->dbb_oldest_active);
if (dbb->dbb_oldest_snapshot > header->hdr_oldest_snapshot)
header->hdr_oldest_snapshot = dbb->dbb_oldest_snapshot;
if (dbb->dbb_oldest_transaction > oldest_transaction)
Ods::writeOIT(header, dbb->dbb_oldest_transaction);
if (dbb->dbb_oldest_snapshot > oldest_snapshot)
Ods::writeOST(header, dbb->dbb_oldest_snapshot);
}
CCH_RELEASE(tdbb, &window);
@ -905,7 +911,7 @@ bool TRA_precommited(thread_db* tdbb, TraNumber old_number, TraNumber new_number
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Database* const dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
Sync sync(&dbb->dbb_pc_sync, "TRA_precommited");
@ -1104,7 +1110,7 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr
*
**************************************/
SET_TDBB(tdbb);
Jrd::Attachment* attachment = tdbb->getAttachment();
Jrd::Attachment* const attachment = tdbb->getAttachment();
if (!transaction->tra_outer)
{
@ -1205,7 +1211,7 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr
if (trace)
trace->finish(ITracePlugin::RESULT_SUCCESS);
// Unlink the transaction from the database block
// Unlink the transaction from the attachment block
for (jrd_tra** ptr = &attachment->att_transactions; *ptr; ptr = &(*ptr)->tra_next)
{
@ -1548,12 +1554,10 @@ int TRA_snapshot_state(thread_db* tdbb, const jrd_tra* trans, TraNumber number)
return state;
}
// If the transaction is a commited sub-transction - do the easy lookup.
// If the transaction is a committed sub-transaction - do the easy lookup.
if (trans->tra_commit_sub_trans && UInt32Bitmap::test(trans->tra_commit_sub_trans, number))
{
if (trans->tra_commit_sub_trans && trans->tra_commit_sub_trans->test(number))
return tra_committed;
}
// If the transaction is younger than we are and we are not read committed
// or the system transaction, the transaction must be considered active.
@ -1685,7 +1689,7 @@ int TRA_state(const UCHAR* bit_vector, TraNumber oldest, TraNumber number)
* to this code make them in the replicated code also.
*
**************************************/
const ULONG base = oldest & ~TRA_MASK;
const TraNumber base = oldest & ~TRA_MASK;
const ULONG byte = TRANS_OFFSET(number - base);
const USHORT shift = TRANS_SHIFT(number);
@ -1779,12 +1783,12 @@ void TRA_sweep(thread_db* tdbb)
CCH_flush(tdbb, FLUSH_SWEEP, 0);
WIN window(HEADER_PAGE_NUMBER);
header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
header_page* const header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
if (header->hdr_oldest_transaction < --transaction_oldest_active)
if (Ods::getOIT(header) < --transaction_oldest_active)
{
CCH_MARK_MUST_WRITE(tdbb, &window);
header->hdr_oldest_transaction = MIN(active, transaction_oldest_active);
Ods::writeOIT(header, MIN(active, transaction_oldest_active));
}
traceSweep.update(header);
@ -1855,7 +1859,7 @@ int TRA_wait(thread_db* tdbb, jrd_tra* trans, TraNumber number, jrd_tra::wait_t
if (wait != jrd_tra::tra_no_wait)
{
Lock temp_lock(tdbb, sizeof(SLONG), LCK_tra);
Lock temp_lock(tdbb, sizeof(TraNumber), LCK_tra);
temp_lock.lck_key.lck_long = number;
const SSHORT timeout = (wait == jrd_tra::tra_wait) ? trans->getLockWait() : 0;
@ -1972,23 +1976,29 @@ static header_page* bump_transaction_id(thread_db* tdbb, WIN* window)
window->win_page = HEADER_PAGE_NUMBER;
header_page* header = (header_page*) CCH_FETCH(tdbb, window, LCK_write, pag_header);
const TraNumber next_transaction = Ods::getNT(header);
const TraNumber oldest_active = Ods::getOAT(header);
const TraNumber oldest_transaction = Ods::getOIT(header);
const TraNumber oldest_snapshot = Ods::getOST(header);
// Before incrementing the next transaction Id, make sure the current one is valid
if (header->hdr_next_transaction)
if (next_transaction)
{
if (header->hdr_oldest_active > header->hdr_next_transaction)
if (oldest_active > next_transaction)
BUGCHECK(266); //next transaction older than oldest active
if (header->hdr_oldest_transaction > header->hdr_next_transaction)
if (oldest_transaction > next_transaction)
BUGCHECK(267); // next transaction older than oldest transaction
}
if (header->hdr_next_transaction >= MAX_TRA_NUMBER - 1)
if (next_transaction >= MAX_TRA_NUMBER - 1)
{
CCH_RELEASE(tdbb, window);
ERR_post(Arg::Gds(isc_imp_exc) <<
Arg::Gds(isc_tra_num_exc));
}
const TraNumber number = header->hdr_next_transaction + 1;
const TraNumber number = next_transaction + 1;
// If this is the first transaction on a TIP, allocate the TIP now.
// Note, first TIP page is created with the database itself,
@ -2002,17 +2012,18 @@ static header_page* bump_transaction_id(thread_db* tdbb, WIN* window)
// Extend, if necessary, has apparently succeeded. Next, update header page
CCH_MARK_MUST_WRITE(tdbb, window);
header->hdr_next_transaction = number;
dbb->dbb_next_transaction = number;
if (dbb->dbb_oldest_active > header->hdr_oldest_active)
header->hdr_oldest_active = dbb->dbb_oldest_active;
Ods::writeNT(header, number);
if (dbb->dbb_oldest_transaction > header->hdr_oldest_transaction)
header->hdr_oldest_transaction = dbb->dbb_oldest_transaction;
if (dbb->dbb_oldest_active > oldest_active)
Ods::writeOAT(header, dbb->dbb_oldest_active);
if (dbb->dbb_oldest_snapshot > header->hdr_oldest_snapshot)
header->hdr_oldest_snapshot = dbb->dbb_oldest_snapshot;
if (dbb->dbb_oldest_transaction > oldest_transaction)
Ods::writeOIT(header, dbb->dbb_oldest_transaction);
if (dbb->dbb_oldest_snapshot > oldest_snapshot)
Ods::writeOST(header, dbb->dbb_oldest_snapshot);
return header;
}
@ -2233,16 +2244,20 @@ static ULONG inventory_page(thread_db* tdbb, ULONG sequence)
while (!vector || sequence >= vector->count())
{
DPM_scan_pages(tdbb);
if ((vector = dbb->dbb_t_pages) && sequence < vector->count())
break;
if (!vector)
BUGCHECK(165); // msg 165 cannot find tip page
window.win_page = (*vector)[vector->count() - 1];
tx_inv_page* tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_transactions);
const ULONG next = tip->tip_next;
CCH_RELEASE(tdbb, &window);
if (!(window.win_page = next))
BUGCHECK(165); // msg 165 cannot find tip page
// Type check it
tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_transactions);
CCH_RELEASE(tdbb, &window);
@ -2375,10 +2390,7 @@ static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, i
// its snapshot doesn't contain these operations.
if (commit)
{
//fb_assert(sizeof(transaction->tra_number) == sizeof(ULONG));
SBM_SET(tdbb->getDefaultPool(), &transaction->tra_commit_sub_trans, transaction->tra_number);
}
TBM_SET(tdbb->getDefaultPool(), &transaction->tra_commit_sub_trans, transaction->tra_number);
// Create a new transaction lock, inheriting oldest active from transaction being committed.
@ -2391,8 +2403,8 @@ static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, i
new_number = dbb->dbb_next_transaction + dbb->generateTransactionId(tdbb);
else
{
const header_page* header = bump_transaction_id(tdbb, &window);
new_number = header->hdr_next_transaction;
const header_page* const header = bump_transaction_id(tdbb, &window);
new_number = Ods::getNT(header);
}
#endif
@ -2400,7 +2412,7 @@ static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, i
Lock* old_lock = transaction->tra_lock;
if (old_lock)
{
new_lock = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) Lock(tdbb, sizeof(SLONG), LCK_tra);
new_lock = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) Lock(tdbb, sizeof(TraNumber), LCK_tra);
new_lock->lck_key.lck_long = new_number;
new_lock->lck_data = transaction->tra_lock->lck_data;
@ -3032,11 +3044,12 @@ static void transaction_options(thread_db* tdbb,
Lock* lock = (*vector)[id];
if (!lock)
continue;
USHORT level = lock->lck_logical;
if (level == LCK_none || LCK_lock(tdbb, lock, level, transaction->getLockWait()))
{
continue;
}
for (ULONG l = 0; l < id; l++)
{
if ( (lock = (*vector)[l]) )
@ -3046,6 +3059,7 @@ static void transaction_options(thread_db* tdbb,
lock->lck_logical = level;
}
}
id = 0;
ERR_punt();
}
@ -3069,7 +3083,7 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans)
Jrd::Attachment* const attachment = tdbb->getAttachment();
WIN window(DB_PAGE_SPACE, -1);
Lock* lock = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) Lock(tdbb, sizeof(SLONG), LCK_tra);
Lock* lock = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) Lock(tdbb, sizeof(TraNumber), LCK_tra);
// Read header page and allocate transaction number. Since
// the transaction inventory page was initialized to zero, it
@ -3095,10 +3109,10 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans)
else
{
const header_page* header = bump_transaction_id(tdbb, &window);
number = header->hdr_next_transaction;
oldest = header->hdr_oldest_transaction;
oldest_active = header->hdr_oldest_active;
oldest_snapshot = header->hdr_oldest_snapshot;
number = Ods::getNT(header);
oldest = Ods::getOIT(header);
oldest_active = Ods::getOAT(header);
oldest_snapshot = Ods::getOST(header);
}
// oldest (OIT) > oldest_active (OAT) if OIT was advanced by sweep
@ -3179,7 +3193,7 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans)
// more complicated by the fact that existing transaction may have oldest
// actives older than they are.
Lock temp_lock(tdbb, sizeof(SLONG), LCK_tra, trans);
Lock temp_lock(tdbb, sizeof(TraNumber), LCK_tra, trans);
trans->tra_oldest_active = number;
base = oldest & ~TRA_MASK;
@ -3197,6 +3211,7 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans)
const USHORT shift = TRANS_SHIFT(active);
oldest_state = (trans->tra_transactions[byte] >> shift) & TRA_MASK;
}
if (oldest_state == tra_active)
{
temp_lock.lck_key.lck_long = active;

View File

@ -80,12 +80,6 @@ public:
int savePoint;
};
//Moved to fb_types.h
//typedef ULONG TraNumber;
// Moved to constants.h
//const TraNumber MAX_TRA_NUMBER = ~TraNumber(0);
// 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.
struct BlobIndex
@ -263,8 +257,8 @@ public:
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
vec<Lock*>* tra_relation_locks; // locks for relations
TransactionBitmap* 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
@ -433,9 +427,6 @@ const int tra_committed = 3;
const int tra_us = 4; // Transaction is us
const int tra_precommitted = 5; // Transaction is precommitted
// The highest transaction number possible. This is 0x7fffffff if SLONG is 32 bits.
//#define MAX_TRA_NUMBER (~(1L << (BITS_PER_LONG - 1)))
// Savepoint block
class Savepoint : public pool_alloc<type_sav>

View File

@ -65,7 +65,7 @@ unsigned TraceConnectionImpl::getKind()
return KIND_DATABASE;
}
int TraceConnectionImpl::getConnectionID()
ISC_INT64 TraceConnectionImpl::getConnectionID()
{
return m_att->att_attachment_id;
//return PAG_attachment_id(JRD_get_thread_data());
@ -122,7 +122,7 @@ const char* TraceConnectionImpl::getRemoteProcessName()
/// TraceTransactionImpl
unsigned TraceTransactionImpl::getTransactionID()
ISC_INT64 TraceTransactionImpl::getTransactionID()
{
return m_tran->tra_number;
}
@ -162,7 +162,7 @@ unsigned TraceTransactionImpl::getIsolation()
/// TraceSQLStatementImpl
int TraceSQLStatementImpl::getStmtID()
ISC_INT64 TraceSQLStatementImpl::getStmtID()
{
if (m_stmt->req_request)
return m_stmt->req_request->req_id;

View File

@ -35,6 +35,7 @@
#include "../../jrd/ntrace.h"
#include "../../common/dsc.h"
#include "../../common/isc_s_proto.h"
#include "../../jrd/ods_proto.h"
#include "../../jrd/req.h"
#include "../../jrd/svc.h"
#include "../../jrd/tra.h"
@ -72,7 +73,7 @@ public:
const char* getRemoteProcessName();
// TraceDatabaseConnection implementation
int getConnectionID();
ISC_INT64 getConnectionID();
const char* getDatabaseName();
private:
const Attachment* const m_att;
@ -89,7 +90,7 @@ public:
{}
// TraceTransaction implementation
unsigned getTransactionID();
ISC_INT64 getTransactionID();
FB_BOOLEAN getReadOnly();
int getWait();
unsigned getIsolation();
@ -147,7 +148,7 @@ public:
m_perf(perf)
{}
int getStmtID() { return m_stmt->req_id; }
ISC_INT64 getStmtID() { return m_stmt->req_id; }
PerformanceInfo* getPerf() { return m_perf; }
private:
@ -163,7 +164,7 @@ public:
BLRPrinter(blr, length)
{}
int getStmtID() { return 0; }
ISC_INT64 getStmtID() { return 0; }
PerformanceInfo* getPerf() { return NULL; }
};
@ -180,7 +181,7 @@ public:
{}
// TraceSQLStatement implementation
int getStmtID();
ISC_INT64 getStmtID();
PerformanceInfo* getPerf();
Firebird::ITraceParams* getInputs();
const char* getText();
@ -234,7 +235,7 @@ public:
{}
// TraceSQLStatement implementation
int getStmtID() { return 0; }
ISC_INT64 getStmtID() { return 0; }
PerformanceInfo* getPerf() { return NULL; }
Firebird::ITraceParams* getInputs() { return NULL; }
const char* getText() { return m_text.c_str(); }
@ -608,10 +609,10 @@ public:
void update(const Ods::header_page* header)
{
m_oit = header->hdr_oldest_transaction;
m_ost = header->hdr_oldest_snapshot;
m_oat = header->hdr_oldest_active;
m_next = header->hdr_next_transaction;
m_oit = Ods::getOIT(header);
m_ost = Ods::getOST(header);
m_oat = Ods::getOAT(header);
m_next = Ods::getNT(header);
}
void setPerf(PerformanceInfo* perf)
@ -619,10 +620,10 @@ public:
m_perf = perf;
}
ISC_UINT64 getOIT() { return m_oit; };
ISC_UINT64 getOST() { return m_ost; };
ISC_UINT64 getOAT() { return m_oat; };
ISC_UINT64 getNext() { return m_next; };
ISC_INT64 getOIT() { return m_oit; };
ISC_INT64 getOST() { return m_ost; };
ISC_INT64 getOAT() { return m_oat; };
ISC_INT64 getNext() { return m_next; };
PerformanceInfo* getPerf() { return m_perf; };
private:

View File

@ -561,6 +561,7 @@ VI. ADDITIONAL NOTES
#include "../yvalve/gds_proto.h"
#include "../common/isc_proto.h"
#include "../jrd/met_proto.h"
#include "../jrd/ods_proto.h"
#include "../jrd/tra_proto.h"
#include "../jrd/val_proto.h"
#include "../jrd/validation.h"
@ -1404,8 +1405,8 @@ static void print_rhd(USHORT length, const rhd* header)
**************************************/
if (VAL_debug_level)
{
fprintf(stdout, "rhd: len %d TX %d format %d ",
length, header->rhd_transaction, (int) header->rhd_format);
fprintf(stdout, "rhd: len %d TX %"SQUADFORMAT" format %d ",
length, Ods::getTraNum(header), (int) header->rhd_format);
fprintf(stdout, "BP %d/%d flags 0x%x ",
header->rhd_b_page, header->rhd_b_line, header->rhd_flags);
if (header->rhd_flags & rhd_incomplete)
@ -1769,11 +1770,11 @@ Validation::RTN Validation::walk_data_page(jrd_rel* relation, ULONG page_number,
RBM_SET(vdr_tdbb->getDefaultPool(), &vdr_rel_records, number.getValue());
else
{
int state;
if (header->rhd_transaction < dbb->dbb_oldest_transaction)
state = tra_committed;
else
state = TRA_fetch_state(vdr_tdbb, header->rhd_transaction);
const TraNumber transaction = Ods::getTraNum(header);
const int state = (transaction < dbb->dbb_oldest_transaction) ?
tra_committed : TRA_fetch_state(vdr_tdbb, transaction);
if (state == tra_committed || state == tra_limbo)
RBM_SET(vdr_tdbb->getDefaultPool(), &vdr_rel_records, number.getValue());
}
@ -2626,8 +2627,10 @@ Validation::RTN Validation::walk_record(jrd_rel* relation, const rhd* header, US
return rtn_ok;
}
if (header->rhd_transaction > vdr_max_transaction)
corrupt(VAL_REC_BAD_TID, relation, number.getValue(), header->rhd_transaction);
const TraNumber transaction = Ods::getTraNum(header);
if (transaction > vdr_max_transaction)
corrupt(VAL_REC_BAD_TID, relation, number.getValue(), transaction);
// If there's a back pointer, verify that it's good

View File

@ -259,15 +259,43 @@ inline void check_gbak_cheating_delete(thread_db* tdbb, const jrd_rel* relation)
}
}
inline int wait(thread_db* tdbb, jrd_tra* transaction,
const record_param* rpb, jrd_tra::wait_t wait)
inline int wait(thread_db* tdbb, jrd_tra* transaction, const record_param* rpb)
{
const SSHORT timeout = (wait == jrd_tra::tra_wait) ? transaction->getLockWait() : 0;
if (timeout)
if (transaction->getLockWait())
tdbb->bumpRelStats(RuntimeStatistics::RECORD_WAITS, rpb->rpb_relation->rel_id);
return TRA_wait(tdbb, transaction, rpb->rpb_transaction_nr, wait);
return TRA_wait(tdbb, transaction, rpb->rpb_transaction_nr, jrd_tra::tra_wait);
}
inline bool checkGCActive(thread_db* tdbb, record_param* rpb, int& state)
{
Lock temp_lock(tdbb, sizeof(SINT64), LCK_record_gc);
temp_lock.lck_key.lck_long = ((SINT64) rpb->rpb_page << 16) | rpb->rpb_line;
ThreadStatusGuard temp_status(tdbb);
if (!LCK_lock(tdbb, &temp_lock, LCK_SR, LCK_NO_WAIT))
{
rpb->rpb_transaction_nr = LCK_read_data(tdbb, &temp_lock);
state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_active;
return true;
}
LCK_release(tdbb, &temp_lock);
rpb->rpb_flags &= ~rpb_gc_active;
state = tra_dead;
return false;
}
inline void waitGCActive(thread_db* tdbb, const record_param* rpb)
{
Lock temp_lock(tdbb, sizeof(SINT64), LCK_record_gc);
temp_lock.lck_key.lck_long = ((SINT64) rpb->rpb_page << 16) | rpb->rpb_line;
if (!LCK_lock(tdbb, &temp_lock, LCK_SR, LCK_WAIT))
ERR_punt();
LCK_release(tdbb, &temp_lock);
}
static const UCHAR gc_tpb[] =
@ -386,7 +414,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES,
"VIO_backout (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT")\n",
"VIO_backout (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT")\n",
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
#endif
@ -403,7 +431,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
temp.rpb_page, temp.rpb_line, temp.rpb_transaction_nr,
temp.rpb_flags, temp.rpb_b_page, temp.rpb_b_line,
@ -534,20 +562,35 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
{
DPM_backout_mark(tdbb, rpb, transaction);
// dimitr: We don't need to clear the GC flag on the data page
// as the record version is to be removed. Just ensure
// that the appropriate lock is released at the same time.
AutoLock gcLockGuard(tdbb, rpb->rpb_gc_lock);
rpb->rpb_gc_lock = NULL;
RecordStack empty_staying;
IDX_garbage_collect(tdbb, rpb, going, empty_staying);
BLB_garbage_collect(tdbb, going, empty_staying, rpb->rpb_page, relation);
going.pop();
if (!DPM_get(tdbb, rpb, LCK_write))
return;
if (rpb->rpb_transaction_nr != transaction->tra_number)
{
fb_assert(false);
return;
}
if (rpb->rpb_b_page != temp2.rpb_b_page || rpb->rpb_b_line != temp2.rpb_b_line ||
rpb->rpb_transaction_nr != temp2.rpb_transaction_nr)
{
fb_assert(false);
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
return;
}
fb_assert(rpb->rpb_flags & rpb_gc_active);
rpb->rpb_flags &= ~rpb_gc_active;
temp2 = *rpb;
rpb->rpb_undo = old_data;
@ -581,10 +624,15 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
clearRecordStack(staying);
if (!DPM_get(tdbb, rpb, LCK_write))
return;
if (rpb->rpb_transaction_nr != transaction->tra_number)
{
fb_assert(false);
return;
}
if (rpb->rpb_b_page != temp2.rpb_b_page || rpb->rpb_b_line != temp2.rpb_b_line ||
rpb->rpb_transaction_nr != temp2.rpb_transaction_nr)
{
fb_assert(false);
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
return;
}
@ -624,7 +672,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
{
// There is cleanup to be done. Bring the old version forward first
rpb->rpb_flags &= ~(rpb_fragment | rpb_incomplete | rpb_chained | rpb_gc_active);
rpb->rpb_flags &= ~(rpb_fragment | rpb_incomplete | rpb_chained | rpb_gc_active | rpb_long_tranum);
DPM_update(tdbb, rpb, 0, transaction);
delete_tail(tdbb, &temp2, rpb->rpb_page, 0, 0);
}
@ -672,41 +720,26 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE_ALL,
"VIO_chase_record_version (record_param %"QUADFORMAT"d, transaction %"
ULONGFORMAT", pool %p)\n",
SQUADFORMAT", pool %p)\n",
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
(void*) pool);
VIO_trace(DEBUG_TRACE_ALL_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
rpb->rpb_f_page, rpb->rpb_f_line);
#endif
// Handle the fast path first. If the record is committed, isn't deleted,
// and doesn't have an old version that is a candidate for garbage collection,
// return without further ado
int state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
// Reset the garbage collect active flag if the transaction state is
// in a terminal state. If committed it must have been a precommitted
// transaction that was backing out a dead record version and the
// system crashed. Clear the flag and set the state to tra_dead to
// reattempt the backout.
// Reset (if appropriate) the garbage collect active flag to reattempt the backout
if (rpb->rpb_flags & rpb_gc_active)
{
if (!rpb->rpb_transaction_nr)
state = tra_active;
checkGCActive(tdbb, rpb, state);
if (state == tra_committed)
state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead;
if (state == tra_dead)
rpb->rpb_flags &= ~rpb_gc_active;
}
// Take care about modifications performed by our own transaction
rpb->rpb_runtime_flags &= ~(RPB_undo_data | RPB_undo_read);
int forceBack = 0;
@ -728,6 +761,10 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
}
}
// Handle the fast path first. If the record is committed, isn't deleted,
// and doesn't have an old version that is a candidate for garbage collection,
// return without further ado
if ((state == tra_committed || state == tra_us) && !forceBack &&
!(rpb->rpb_flags & (rpb_deleted | rpb_damaged)) &&
(rpb->rpb_b_page == 0 || rpb->rpb_transaction_nr >= oldest_snapshot))
@ -751,7 +788,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
{
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" chase record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" chase record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -766,7 +803,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
if (state == tra_limbo && !(transaction->tra_flags & TRA_ignore_limbo))
{
state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait);
state = wait(tdbb, transaction, rpb);
if (state == tra_active)
state = tra_limbo;
}
@ -783,7 +820,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
if (state == tra_limbo)
{
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait);
state = wait(tdbb, transaction, rpb);
if (!DPM_get(tdbb, rpb, LCK_read))
return false;
@ -814,7 +851,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
// of a dead record version.
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait);
state = wait(tdbb, transaction, rpb);
if (state == tra_precommitted)
state = check_precommitted(transaction, rpb);
@ -854,7 +891,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
case tra_dead:
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record's transaction (%"ULONGFORMAT") is dead (my TID - %"ULONGFORMAT")\n",
" record's transaction (%"SQUADFORMAT") is dead (my TID - %"SQUADFORMAT")\n",
rpb->rpb_transaction_nr, transaction->tra_number);
#endif
if (gcPolicyBackground && !(rpb->rpb_flags & rpb_chained) &&
@ -942,7 +979,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
case tra_limbo:
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record's transaction (%"ULONGFORMAT") is in limbo (my TID - %"ULONGFORMAT")\n",
" record's transaction (%"SQUADFORMAT") is in limbo (my TID - %"SQUADFORMAT")\n",
rpb->rpb_transaction_nr, transaction->tra_number);
#endif
@ -957,7 +994,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
if (state == tra_active)
{
VIO_trace(DEBUG_READS_INFO,
" record's transaction (%"ULONGFORMAT") is active (my TID - %"ULONGFORMAT")\n",
" record's transaction (%"SQUADFORMAT") is active (my TID - %"SQUADFORMAT")\n",
rpb->rpb_transaction_nr, transaction->tra_number);
}
#endif
@ -1065,7 +1102,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
case tra_us:
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record's transaction (%"ULONGFORMAT") is us (my TID - %"ULONGFORMAT")\n",
" record's transaction (%"SQUADFORMAT") is us (my TID - %"SQUADFORMAT")\n",
rpb->rpb_transaction_nr, transaction->tra_number);
#endif
@ -1103,7 +1140,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
case tra_committed:
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record's transaction (%"ULONGFORMAT") is committed (my TID - %"ULONGFORMAT")\n",
" record's transaction (%"SQUADFORMAT") is committed (my TID - %"SQUADFORMAT")\n",
rpb->rpb_transaction_nr, transaction->tra_number);
#endif
if (rpb->rpb_flags & rpb_deleted)
@ -1184,23 +1221,10 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
// Reset the garbage collect active flag if the transaction state is
// in a terminal state. If committed it must have been a precommitted
// transaction that was backing out a dead record version and the
// system crashed. Clear the flag and set the state to tra_dead to
// reattempt the backout.
// Reset (if appropriate) the garbage collect active flag to reattempt the backout
if (!(rpb->rpb_flags & rpb_chained) && (rpb->rpb_flags & rpb_gc_active))
{
if (!rpb->rpb_transaction_nr)
state = tra_active;
if (state == tra_committed)
state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead;
if (state == tra_dead)
rpb->rpb_flags &= ~rpb_gc_active;
}
checkGCActive(tdbb, rpb, state);
}
}
@ -1278,7 +1302,7 @@ void VIO_data(thread_db* tdbb, record_param* rpb, MemoryPool* pool)
VIO_trace(DEBUG_READS_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line,
rpb->rpb_transaction_nr, rpb->rpb_flags,
@ -1363,7 +1387,7 @@ void VIO_data(thread_db* tdbb, record_param* rpb, MemoryPool* pool)
rpb->rpb_number.getValue(), length, format->fmt_length);
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT"d:%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT"d:%d, rpb_trans %"SQUADFORMAT
"d, flags %d, back %"SLONGFORMAT"d:%d, fragment %"SLONGFORMAT"d:%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags,
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, rpb->rpb_f_line);
@ -1399,11 +1423,11 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES,
"VIO_erase (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT")\n",
"VIO_erase (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT")\n",
rpb->rpb_number.getValue(), transaction->tra_number);
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -1937,11 +1961,11 @@ bool VIO_garbage_collect(thread_db* tdbb, record_param* rpb, const jrd_tra* tran
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE,
"VIO_garbage_collect (record_param %"QUADFORMAT"d, transaction %"
ULONGFORMAT")\n",
SQUADFORMAT")\n",
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
VIO_trace(DEBUG_TRACE_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -1966,21 +1990,16 @@ bool VIO_garbage_collect(thread_db* tdbb, record_param* rpb, const jrd_tra* tran
int state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
// Reset the garbage collect active flag if the transaction state is
// in a terminal state. If committed it must have been a precommitted
// transaction that was backing out a dead record version and the
// system crashed. Clear the flag and set the state to tra_dead to
// reattempt the backout.
// Reset (if appropriate) the garbage collect active flag to reattempt the backout
if (rpb->rpb_flags & rpb_gc_active)
{
if (state == tra_committed)
state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead;
if (state == tra_dead)
rpb->rpb_flags &= ~rpb_gc_active;
if (checkGCActive(tdbb, rpb, state))
return true;
}
fb_assert(!(rpb->rpb_flags & rpb_gc_active));
if (state == tra_precommitted)
state = check_precommitted(transaction, rpb);
@ -2076,7 +2095,7 @@ bool VIO_get(thread_db* tdbb, record_param* rpb, jrd_tra* transaction, MemoryPoo
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS,
"VIO_get (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT", pool %p)\n",
"VIO_get (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT", pool %p)\n",
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
(void*) pool);
#endif
@ -2095,7 +2114,7 @@ bool VIO_get(thread_db* tdbb, record_param* rpb, jrd_tra* transaction, MemoryPoo
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -2155,7 +2174,7 @@ bool VIO_get_current(thread_db* tdbb,
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE,
"VIO_get_current (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT", pool %p)\n",
"VIO_get_current (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT", pool %p)\n",
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
(void*) pool);
#endif
@ -2173,7 +2192,7 @@ bool VIO_get_current(thread_db* tdbb,
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -2203,26 +2222,23 @@ bool VIO_get_current(thread_db* tdbb,
// For now check the state in the tip_cache or tip bitmap. If
// record is committed (most cases), this will be faster.
int state = (transaction->tra_flags & TRA_read_committed) ?
TPC_cache_state(tdbb, rpb->rpb_transaction_nr) :
TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
// Reset the garbage collect active flag if the transaction state is
// in a terminal state. If committed it must have been a precommitted
// transaction that was backing out a dead record version and the
// system crashed. Clear the flag and set the state to tra_dead to
// reattempt the backout.
// Reset (if appropriate) the garbage collect active flag to reattempt the backout
if (rpb->rpb_flags & rpb_gc_active)
{
if (state == tra_committed)
state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead;
if (state == tra_dead)
rpb->rpb_flags &= ~rpb_gc_active;
if (checkGCActive(tdbb, rpb, state))
{
waitGCActive(tdbb, rpb);
continue;
}
}
fb_assert(!(rpb->rpb_flags & rpb_gc_active));
if (state == tra_precommitted)
state = check_precommitted(transaction, rpb);
@ -2243,10 +2259,6 @@ bool VIO_get_current(thread_db* tdbb,
VIO_backout(tdbb, rpb, transaction);
}
continue;
case tra_precommitted:
Attachment::Checkout cout(attachment, FB_FUNCTION);
Thread::sleep(100); // milliseconds
continue;
}
// The record belongs to somebody else. Wait for him to commit, rollback, or die.
@ -2254,27 +2266,12 @@ bool VIO_get_current(thread_db* tdbb,
const TraNumber tid_fetch = rpb->rpb_transaction_nr;
// Wait as long as it takes for an active transaction which has modified
// the record. If an active transaction has used its TID to safely
// backout a fragmented dead record version, spin wait because it will finish shortly.
// the record.
if (!(rpb->rpb_flags & rpb_gc_active))
{
state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait);
state = wait(tdbb, transaction, rpb);
if (state == tra_precommitted)
state = check_precommitted(transaction, rpb);
}
else
{
state = wait(tdbb, transaction, rpb, jrd_tra::tra_probe);
if (state == tra_active)
{
Attachment::Checkout cout(attachment, FB_FUNCTION);
Thread::sleep(100); // milliseconds
continue;
}
}
if (state == tra_precommitted)
state = check_precommitted(transaction, rpb);
switch (state)
{
@ -2496,12 +2493,12 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES,
"VIO_modify (org_rpb %"QUADFORMAT"d, new_rpb %"QUADFORMAT"d, "
"transaction %"ULONGFORMAT")\n",
"transaction %"SQUADFORMAT")\n",
org_rpb->rpb_number.getValue(), new_rpb->rpb_number.getValue(),
transaction ? transaction->tra_number : 0);
VIO_trace(DEBUG_WRITES_INFO,
" old record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" old record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
org_rpb->rpb_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr,
org_rpb->rpb_flags, org_rpb->rpb_b_page, org_rpb->rpb_b_line,
@ -2967,12 +2964,12 @@ bool VIO_next_record(thread_db* tdbb,
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE,
"VIO_next_record (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT", pool %p)\n",
"VIO_next_record (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT", pool %p)\n",
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
(void*) pool);
VIO_trace(DEBUG_TRACE_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -3006,7 +3003,7 @@ bool VIO_next_record(thread_db* tdbb,
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
"VIO_next_record got record %"SLONGFORMAT":%d, rpb_trans %"
ULONGFORMAT", flags %d, back %"SLONGFORMAT":%d, fragment %"
SQUADFORMAT", flags %d, back %"SLONGFORMAT":%d, fragment %"
SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -3075,7 +3072,7 @@ bool VIO_refetch_record(thread_db* tdbb, record_param* rpb, jrd_tra* transaction
**************************************/
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS,
"VIO_refetch_record (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT")\n",
"VIO_refetch_record (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT")\n",
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
#endif
@ -3176,7 +3173,7 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES,
"VIO_store (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT
"VIO_store (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT
")\n", rpb->rpb_number.getValue(),
transaction ? transaction->tra_number : 0);
#endif
@ -3528,7 +3525,7 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -3568,7 +3565,7 @@ bool VIO_sweep(thread_db* tdbb, jrd_tra* transaction, TraceSweepEvent* traceSwee
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE,
"VIO_sweep (transaction %"ULONGFORMAT")\n", transaction ? transaction->tra_number : 0);
"VIO_sweep (transaction %"SQUADFORMAT")\n", transaction ? transaction->tra_number : 0);
#endif
if (transaction->tra_attachment->att_flags & ATT_NO_CLEANUP)
@ -3729,7 +3726,7 @@ void VIO_verb_cleanup(thread_db* tdbb, jrd_tra* transaction)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE,
"VIO_verb_cleanup (transaction %"ULONGFORMAT")\n",
"VIO_verb_cleanup (transaction %"SQUADFORMAT")\n",
transaction ? transaction->tra_number : 0);
#endif
if (transaction->tra_flags & TRA_system)
@ -3998,11 +3995,11 @@ bool VIO_writelock(thread_db* tdbb, record_param* org_rpb, jrd_tra* transaction)
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES,
"VIO_writelock (org_rpb %"QUADFORMAT"d, transaction %"ULONGFORMAT")\n",
"VIO_writelock (org_rpb %"QUADFORMAT"d, transaction %"SQUADFORMAT")\n",
org_rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
VIO_trace(DEBUG_WRITES_INFO,
" old record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" old record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
org_rpb->rpb_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr,
org_rpb->rpb_flags, org_rpb->rpb_b_page, org_rpb->rpb_b_line,
@ -4362,7 +4359,7 @@ static void delete_record(thread_db* tdbb, record_param* rpb, ULONG prior_page,
rpb->rpb_number.getValue(), prior_page, (void*) pool);
VIO_trace(DEBUG_WRITES_INFO,
" delete_record record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" delete_record record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -4439,7 +4436,7 @@ static UCHAR* delete_tail(thread_db* tdbb,
rpb->rpb_number.getValue(), prior_page, tail, tail_end);
VIO_trace(DEBUG_WRITES_INFO,
" tail of record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" tail of record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -4523,7 +4520,7 @@ static void expunge(thread_db* tdbb, record_param* rpb, const jrd_tra* transacti
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES,
"expunge (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT
"expunge (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT
", prior_page %"SLONGFORMAT")\n",
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
prior_page);
@ -4545,7 +4542,7 @@ static void expunge(thread_db* tdbb, record_param* rpb, const jrd_tra* transacti
#ifdef VIO_DEBUG
VIO_trace(DEBUG_WRITES_INFO,
" expunge record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" expunge record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -4612,7 +4609,7 @@ static void garbage_collect(thread_db* tdbb, record_param* rpb, ULONG prior_page
rpb->rpb_number.getValue(), prior_page);
VIO_trace(DEBUG_WRITES_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -5462,8 +5459,8 @@ static int prepare_update( thread_db* tdbb,
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE_ALL,
"prepare_update (transaction %"ULONGFORMAT
", commit_tid read %"ULONGFORMAT", record_param %"QUADFORMAT"d, ",
"prepare_update (transaction %"SQUADFORMAT
", commit_tid read %"SQUADFORMAT", record_param %"QUADFORMAT"d, ",
transaction ? transaction->tra_number : 0, commit_tid_read,
rpb ? rpb->rpb_number.getValue() : 0);
@ -5473,7 +5470,7 @@ static int prepare_update( thread_db* tdbb,
new_rpb ? new_rpb->rpb_number.getValue() : 0);
VIO_trace(DEBUG_TRACE_ALL_INFO,
" old record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" old record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT
":%d, prior %p\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
@ -5588,21 +5585,20 @@ static int prepare_update( thread_db* tdbb,
int state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
// Reset the garbage collect active flag if the transaction state is
// in a terminal state. If committed it must have been a precommitted
// transaction that was backing out a dead record version and the
// system crashed. Clear the flag and set the state to tra_dead to
// reattempt the backout.
// Reset (if appropriate) the garbage collect active flag to reattempt the backout
if (rpb->rpb_flags & rpb_gc_active)
{
if (state == tra_committed)
state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead;
if (state == tra_dead)
rpb->rpb_flags &= ~rpb_gc_active;
if (checkGCActive(tdbb, rpb, state))
{
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
waitGCActive(tdbb, rpb);
continue;
}
}
fb_assert(!(rpb->rpb_flags & rpb_gc_active));
if (state == tra_precommitted)
state = check_precommitted(transaction, rpb);
@ -5611,8 +5607,8 @@ static int prepare_update( thread_db* tdbb,
case tra_committed:
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record's transaction (%"ULONGFORMAT
") is committed (my TID - %"ULONGFORMAT")\n",
" record's transaction (%"SQUADFORMAT
") is committed (my TID - %"SQUADFORMAT")\n",
rpb->rpb_transaction_nr, transaction->tra_number);
#endif
if (rpb->rpb_flags & rpb_deleted)
@ -5642,7 +5638,6 @@ static int prepare_update( thread_db* tdbb,
// has been updated by another transaction which committed in the
// meantime, we cannot proceed further - update conflict error.
if ((transaction->tra_flags & TRA_read_committed) &&
(commit_tid_read != rpb->rpb_transaction_nr))
{
@ -5672,8 +5667,8 @@ static int prepare_update( thread_db* tdbb,
if (state == tra_us)
{
VIO_trace(DEBUG_READS_INFO,
" record's transaction (%"ULONGFORMAT
") is us (my TID - %"ULONGFORMAT")\n",
" record's transaction (%"SQUADFORMAT
") is us (my TID - %"SQUADFORMAT")\n",
rpb->rpb_transaction_nr, transaction->tra_number);
}
#endif
@ -5719,35 +5714,19 @@ static int prepare_update( thread_db* tdbb,
case tra_limbo:
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record's transaction (%"ULONGFORMAT") is %s (my TID - %"ULONGFORMAT")\n",
" record's transaction (%"SQUADFORMAT") is %s (my TID - %"SQUADFORMAT")\n",
rpb->rpb_transaction_nr, (state == tra_active) ? "active" : "limbo",
transaction->tra_number);
#endif
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
// Wait as long as it takes for an active transaction which has modified
// the record. If an active transaction has used its TID to safely
// backout a fragmented dead record version, spin wait because it will
// finish shortly.
// the record.
if (!(rpb->rpb_flags & rpb_gc_active))
{
state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait);
state = wait(tdbb, transaction, rpb);
if (state == tra_precommitted)
state = check_precommitted(transaction, rpb);
}
else
{
state = wait(tdbb, transaction, rpb, jrd_tra::tra_probe);
if (state == tra_active)
{
Attachment::Checkout cout(attachment, FB_FUNCTION);
Thread::sleep(100); // milliseconds
continue;
}
}
if (state == tra_precommitted)
state = check_precommitted(transaction, rpb);
// The snapshot says: transaction was active. The TIP page says: transaction
// is committed. Maybe the transaction was rolled back via a transaction
@ -5796,23 +5775,15 @@ static int prepare_update( thread_db* tdbb,
break;
case tra_dead:
case tra_precommitted:
#ifdef VIO_DEBUG
VIO_trace(DEBUG_READS_INFO,
" record's transaction (%"ULONGFORMAT") is dead (my TID - %"ULONGFORMAT")\n",
" record's transaction (%"SQUADFORMAT") is dead (my TID - %"SQUADFORMAT")\n",
rpb->rpb_transaction_nr, transaction->tra_number);
#endif
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
break;
}
if (state == tra_precommitted)
{
Attachment::Checkout cout(attachment, FB_FUNCTION);
Thread::sleep(100); // milliseconds
continue;
}
VIO_backout(tdbb, rpb, transaction);
}
@ -5909,7 +5880,7 @@ static void purge(thread_db* tdbb, record_param* rpb)
"purge (record_param %"QUADFORMAT"d)\n", rpb->rpb_number.getValue());
VIO_trace(DEBUG_TRACE_ALL_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
@ -5984,11 +5955,11 @@ static void replace_record(thread_db* tdbb,
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE_ALL,
"replace_record (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT")\n",
"replace_record (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT")\n",
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
VIO_trace(DEBUG_TRACE_ALL_INFO,
" record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT
":%d, prior %p\n",
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
@ -5997,7 +5968,7 @@ static void replace_record(thread_db* tdbb,
#endif
record_param temp = *rpb;
rpb->rpb_flags &= ~(rpb_fragment | rpb_incomplete | rpb_chained | rpb_gc_active);
rpb->rpb_flags &= ~(rpb_fragment | rpb_incomplete | rpb_chained | rpb_gc_active | rpb_long_tranum);
DPM_update(tdbb, rpb, stack, transaction);
delete_tail(tdbb, &temp, rpb->rpb_page, 0, 0);
@ -6136,13 +6107,13 @@ static void update_in_place(thread_db* tdbb,
#ifdef VIO_DEBUG
VIO_trace(DEBUG_TRACE_ALL,
"update_in_place (transaction %"ULONGFORMAT", org_rpb %"QUADFORMAT"d, "
"update_in_place (transaction %"SQUADFORMAT", org_rpb %"QUADFORMAT"d, "
"new_rpb %"QUADFORMAT"d)\n",
transaction ? transaction->tra_number : 0, org_rpb->rpb_number.getValue(),
new_rpb ? new_rpb->rpb_number.getValue() : 0);
VIO_trace(DEBUG_TRACE_ALL_INFO,
" old record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT
" old record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
org_rpb->rpb_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr,
org_rpb->rpb_flags, org_rpb->rpb_b_page, org_rpb->rpb_b_line,

View File

@ -499,7 +499,7 @@ SRQ_PTR LockManager::enqueue(Attachment* attachment,
UCHAR type,
lock_ast_t ast_routine,
void* ast_argument,
SLONG data,
SINT64 data,
SSHORT lck_wait,
SRQ_PTR owner_offset)
{
@ -883,7 +883,7 @@ bool LockManager::cancelWait(SRQ_PTR owner_offset)
}
SLONG LockManager::queryData(const USHORT series, const USHORT aggregate)
SINT64 LockManager::queryData(const USHORT series, const USHORT aggregate)
{
/**************************************
*
@ -909,7 +909,7 @@ SLONG LockManager::queryData(const USHORT series, const USHORT aggregate)
++(m_sharedMemory->getHeader()->lhb_query_data);
const srq& data_header = m_sharedMemory->getHeader()->lhb_data[series];
SLONG data = 0, count = 0;
SINT64 data = 0, count = 0;
// Simply walk the lock series data queue forward for the minimum
// and backward for the maximum -- it's maintained in sorted order.
@ -981,7 +981,7 @@ SLONG LockManager::queryData(const USHORT series, const USHORT aggregate)
}
SLONG LockManager::readData(SRQ_PTR request_offset)
SINT64 LockManager::readData(SRQ_PTR request_offset)
{
/**************************************
*
@ -1003,7 +1003,8 @@ SLONG LockManager::readData(SRQ_PTR request_offset)
++(m_sharedMemory->getHeader()->lhb_read_data);
const lbl* const lock = (lbl*) SRQ_ABS_PTR(request->lrq_lock);
const SLONG data = lock->lbl_data;
const SINT64 data = lock->lbl_data;
if (lock->lbl_series < LCK_MAX_SERIES)
++(m_sharedMemory->getHeader()->lhb_operations[lock->lbl_series]);
else
@ -1013,10 +1014,10 @@ SLONG LockManager::readData(SRQ_PTR request_offset)
}
SLONG LockManager::readData2(USHORT series,
const UCHAR* value,
USHORT length,
SRQ_PTR owner_offset)
SINT64 LockManager::readData2(USHORT series,
const UCHAR* value,
USHORT length,
SRQ_PTR owner_offset)
{
/**************************************
*
@ -1049,7 +1050,7 @@ SLONG LockManager::readData2(USHORT series,
}
SLONG LockManager::writeData(SRQ_PTR request_offset, SLONG data)
SINT64 LockManager::writeData(SRQ_PTR request_offset, SINT64 data)
{
/**************************************
*

View File

@ -168,7 +168,7 @@ struct lbl
srq lbl_requests; // Requests granted
srq lbl_lhb_hash; // Collision que for hash table
srq lbl_lhb_data; // Lock data que by series
SLONG lbl_data; // User data
SINT64 lbl_data; // User data
UCHAR lbl_series; // Lock series
UCHAR lbl_flags; // Unused. Misc flags
USHORT lbl_pending_lrq_count; // count of lbl_requests with LRQ_pending
@ -186,7 +186,7 @@ struct lrq
USHORT lrq_flags; // Misc crud
SRQ_PTR lrq_owner; // Owner making request
SRQ_PTR lrq_lock; // Lock requested
SLONG lrq_data; // Lock data requested
SINT64 lrq_data; // Lock data requested
srq lrq_own_requests; // Locks granted for owner
srq lrq_lbl_requests; // Que of requests (active, pending)
srq lrq_own_blocks; // Owner block que
@ -405,7 +405,7 @@ public:
void shutdownOwner(Attachment*, SRQ_PTR*);
SRQ_PTR enqueue(Attachment*, Firebird::CheckStatusWrapper*, SRQ_PTR, const USHORT,
const UCHAR*, const USHORT, UCHAR, lock_ast_t, void*, SLONG, SSHORT, SRQ_PTR);
const UCHAR*, const USHORT, UCHAR, lock_ast_t, void*, SINT64, SSHORT, SRQ_PTR);
bool convert(Attachment*, Firebird::CheckStatusWrapper*, SRQ_PTR, UCHAR, SSHORT, lock_ast_t, void*);
UCHAR downgrade(Attachment*, Firebird::CheckStatusWrapper*, const SRQ_PTR);
bool dequeue(const SRQ_PTR);
@ -413,10 +413,10 @@ public:
void repost(Attachment*, lock_ast_t, void*, SRQ_PTR);
bool cancelWait(SRQ_PTR);
SLONG queryData(const USHORT, const USHORT);
SLONG readData(SRQ_PTR);
SLONG readData2(USHORT, const UCHAR*, USHORT, SRQ_PTR);
SLONG writeData(SRQ_PTR, SLONG);
SINT64 queryData(const USHORT, const USHORT);
SINT64 readData(SRQ_PTR);
SINT64 readData2(USHORT, const UCHAR*, USHORT, SRQ_PTR);
SINT64 writeData(SRQ_PTR, SINT64);
private:
explicit LockManager(const Firebird::string&, Firebird::RefPtr<Config>);

View File

@ -1209,7 +1209,7 @@ static void prt_lock(OUTFILE outfile, const lhb* LOCK_header, const lbl* lock, U
preLock, rel_lock, rel_lock);
}
FPRINTF(outfile,
"\tSeries: %d, State: %d, Size: %d, Length: %d, Data: %"ULONGFORMAT"\n",
"\tSeries: %d, State: %d, Size: %d, Length: %d, Data: %"SQUADFORMAT"\n",
lock->lbl_series, lock->lbl_state, lock->lbl_size, lock->lbl_length, lock->lbl_data);
if ((lock->lbl_series == Jrd::LCK_bdb || lock->lbl_series == Jrd::LCK_btr_dont_gc) &&

View File

@ -549,17 +549,24 @@ const SvcSwitches actionSwitch[] =
bool getLine(string& dest, const char*& p)
{
unsigned short length = (unsigned short) isc_vax_integer (p, sizeof(unsigned short));
p += sizeof (unsigned short);
const USHORT length = (USHORT) isc_vax_integer(p, sizeof(USHORT));
p += sizeof(USHORT);
dest.assign(p, length);
p += length;
return length > 0;
}
int getNumeric(const char*& p)
SLONG getInt(const char*& p)
{
unsigned int num = (unsigned int) isc_vax_integer (p, sizeof(unsigned int));
p += sizeof (unsigned int);
const SLONG num = isc_vax_integer(p, sizeof(SLONG));
p += sizeof(SLONG);
return num;
}
SINT64 getInt64(const char*& p)
{
const SINT64 num = isc_portable_integer(reinterpret_cast<const UCHAR*>(p), sizeof(SINT64));
p += sizeof(SINT64);
return num;
}
@ -618,9 +625,14 @@ void printMessage(USHORT number, const SafeArg& arg, bool newLine = true)
printf("%s", buffer);
}
void printNumeric(const char*& p, int num)
void printInt(const char*& p, SLONG num)
{
printf ("%s: %d\n", getMessage(num).c_str(), getNumeric(p));
printf ("%s: %"SLONGFORMAT"\n", getMessage(num).c_str(), getInt(p));
}
void printInt64(const char*& p, SINT64 num)
{
printf ("%s: %"SQUADFORMAT"\n", getMessage(num).c_str(), getInt64(p));
}
const char* capArray[] = {
@ -641,7 +653,7 @@ void printCapabilities(const char*& p)
{
printMessage(57);
int caps = getNumeric(p);
int caps = getInt(p);
bool print = false;
for (unsigned i = 0; capArray[i]; ++i)
@ -718,7 +730,7 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq)
switch (*p++)
{
case isc_info_svc_version:
printNumeric(p, 7);
printInt(p, 7);
break;
case isc_info_svc_server_version:
printString(p, 8);
@ -749,10 +761,10 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq)
printString(p, 15);
break;
case isc_spb_num_att:
printNumeric(p, 16);
printInt(p, 16);
break;
case isc_spb_num_db:
printNumeric(p, 17);
printInt(p, 17);
break;
default:
status_exception::raise(Arg::Gds(isc_fbsvcmgr_info_err) <<
@ -814,13 +826,22 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq)
}
break;
case isc_spb_multi_tra_id:
printNumeric(p, 35);
printInt(p, 35);
break;
case isc_spb_single_tra_id:
printNumeric(p, 34);
printInt(p, 34);
break;
case isc_spb_tra_id:
printNumeric(p, 37);
printInt(p, 37);
break;
case isc_spb_multi_tra_id_64:
printInt64(p, 35);
break;
case isc_spb_single_tra_id_64:
printInt64(p, 34);
break;
case isc_spb_tra_id_64:
printInt64(p, 37);
break;
default:
status_exception::raise(Arg::Gds(isc_fbsvcmgr_info_err) <<
@ -847,13 +868,13 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq)
getLine(up.last, p);
break;
case isc_spb_sec_groupid:
up.gid = getNumeric(p);
up.gid = getInt(p);
break;
case isc_spb_sec_userid:
up.uid = getNumeric(p);
up.uid = getInt(p);
break;
case isc_spb_sec_admin:
up.admin = getNumeric(p);
up.admin = getInt(p);
break;
case isc_info_svc_line:
@ -880,7 +901,7 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq)
break;
case isc_info_svc_stdin:
stdinRq = getNumeric(p);
stdinRq = getInt(p);
if (stdinRq > 0)
{
ret = true;

View File

@ -30,6 +30,7 @@
#include "../common/classes/timestamp.h"
#include "../jrd/ibase.h"
#include "../jrd/ods.h"
#include "../jrd/ods_proto.h"
#include "../common/os/guid.h"
#include "../yvalve/gds_proto.h"
#include "../common/classes/DbImplementation.h"
@ -58,7 +59,6 @@ void PPG_print_header(const header_page* header, ULONG page,
else
uSvc->printf(false, "Database overflow header page information:\n");
if (page == HEADER_PAGE)
{
uSvc->printf(false, "\tFlags\t\t\t%d\n", header->hdr_header.pag_flags);
@ -68,13 +68,13 @@ void PPG_print_header(const header_page* header, ULONG page,
uSvc->printf(false, "\tPage size\t\t%d\n", header->hdr_page_size);
uSvc->printf(false, "\tODS version\t\t%d.%d\n",
header->hdr_ods_version & ~ODS_FIREBIRD_FLAG, header->hdr_ods_minor);
uSvc->printf(false, "\tOldest transaction\t%"ULONGFORMAT"\n", header->hdr_oldest_transaction);
uSvc->printf(false, "\tOldest active\t\t%"ULONGFORMAT"\n", header->hdr_oldest_active);
uSvc->printf(false, "\tOldest snapshot\t\t%"ULONGFORMAT"\n", header->hdr_oldest_snapshot);
uSvc->printf(false, "\tNext transaction\t%"ULONGFORMAT"\n", header->hdr_next_transaction);
uSvc->printf(false, "\tOldest transaction\t%"SQUADFORMAT"\n", Ods::getOIT(header));
uSvc->printf(false, "\tOldest active\t\t%"SQUADFORMAT"\n", Ods::getOAT(header));
uSvc->printf(false, "\tOldest snapshot\t\t%"SQUADFORMAT"\n", Ods::getOST(header));
uSvc->printf(false, "\tNext transaction\t%"SQUADFORMAT"\n", Ods::getNT(header));
uSvc->printf(false, "\tSequence number\t\t%d\n", header->hdr_sequence);
uSvc->printf(false, "\tNext attachment ID\t%"SLONGFORMAT"\n", header->hdr_attachment_id);
uSvc->printf(false, "\tNext attachment ID\t%"SQUADFORMAT"\n", header->hdr_attachment_id);
Firebird::DbImplementation imp(header);
uSvc->printf(false, "\tImplementation\t\tHW=%s %s-endian OS=%s CC=%s\n",

View File

@ -233,7 +233,7 @@ void TracePluginImpl::logRecord(const char* action)
void TracePluginImpl::logRecordConn(const char* action, ITraceDatabaseConnection* connection)
{
// Lookup connection description
const int conn_id = connection->getConnectionID();
const AttNumber conn_id = connection->getConnectionID();
bool reg = false;
while (true)
@ -251,7 +251,7 @@ void TracePluginImpl::logRecordConn(const char* action, ITraceDatabaseConnection
if (reg)
{
string temp;
temp.printf("\t%s (ATT_%d, <unknown, bug?>)" NEWLINE,
temp.printf("\t%s (ATT_%"SQUADFORMAT", <unknown, bug?>)" NEWLINE,
config.db_filename.c_str(), conn_id);
record.insert(0, temp);
break;
@ -279,7 +279,7 @@ void TracePluginImpl::logRecordConn(const char* action, ITraceDatabaseConnection
void TracePluginImpl::logRecordTrans(const char* action, ITraceDatabaseConnection* connection,
ITraceTransaction* transaction)
{
const unsigned tra_id = transaction->getTransactionID();
const TraNumber tra_id = transaction->getTransactionID();
bool reg = false;
while (true)
{
@ -297,7 +297,7 @@ void TracePluginImpl::logRecordTrans(const char* action, ITraceDatabaseConnectio
if (reg)
{
string temp;
temp.printf("\t\t(TRA_%lu, <unknown, bug?>)" NEWLINE, transaction->getTransactionID());
temp.printf("\t\t(TRA_%"SQUADFORMAT", <unknown, bug?>)" NEWLINE, transaction->getTransactionID());
record.insert(0, temp);
break;
}
@ -327,7 +327,7 @@ void TracePluginImpl::logRecordProcFunc(const char* action, ITraceDatabaseConnec
void TracePluginImpl::logRecordStmt(const char* action, ITraceDatabaseConnection* connection,
ITraceTransaction* transaction, ITraceStatement* statement, bool isSQL)
{
const int stmt_id = statement->getStmtID();
const StmtNumber stmt_id = statement->getStmtID();
bool reg = false;
bool log = true;
@ -354,7 +354,7 @@ void TracePluginImpl::logRecordStmt(const char* action, ITraceDatabaseConnection
if (reg)
{
string temp;
temp.printf(NEWLINE "Statement %d, <unknown, bug?>:" NEWLINE, stmt_id);
temp.printf(NEWLINE "Statement %"SQUADFORMAT", <unknown, bug?>:" NEWLINE, stmt_id);
record.insert(0, temp);
break;
}
@ -952,7 +952,7 @@ void TracePluginImpl::register_connection(ITraceDatabaseConnection* connection)
string tmp(*getDefaultMemoryPool());
conn_data.description->printf("\t%s (ATT_%d", connection->getDatabaseName(), connection->getConnectionID());
conn_data.description->printf("\t%s (ATT_%"SQUADFORMAT, connection->getDatabaseName(), connection->getConnectionID());
const char* user = connection->getUserName();
if (user)
@ -1050,7 +1050,7 @@ void TracePluginImpl::register_transaction(ITraceTransaction* transaction)
TransactionData trans_data;
trans_data.id = transaction->getTransactionID();
trans_data.description = FB_NEW_POOL(*getDefaultMemoryPool()) string(*getDefaultMemoryPool());
trans_data.description->printf("\t\t(TRA_%lu, ", trans_data.id);
trans_data.description->printf("\t\t(TRA_%"SQUADFORMAT", ", trans_data.id);
switch (transaction->getIsolation())
{
@ -1526,7 +1526,7 @@ void TracePluginImpl::register_blr_statement(ITraceBLRStatement* statement)
string* description = FB_NEW_POOL(*getDefaultMemoryPool()) string(*getDefaultMemoryPool());
if (statement->getStmtID()) {
description->printf(NEWLINE "Statement %d:" NEWLINE, statement->getStmtID());
description->printf(NEWLINE "Statement %"SQUADFORMAT":" NEWLINE, statement->getStmtID());
}
if (config.print_blr)

View File

@ -55,7 +55,7 @@ public:
// Data for tracked (active) connections
struct ConnectionData
{
int id;
AttNumber id;
Firebird::string* description;
// Deallocate memory used by objects hanging off this structure
@ -65,19 +65,19 @@ public:
description = NULL;
}
static const int& generate(const void* /*sender*/, const ConnectionData& item)
static const AttNumber& generate(const void* /*sender*/, const ConnectionData& item)
{
return item.id;
}
};
typedef Firebird::BePlusTree<ConnectionData, int, Firebird::MemoryPool, ConnectionData>
typedef Firebird::BePlusTree<ConnectionData, AttNumber, Firebird::MemoryPool, ConnectionData>
ConnectionsTree;
// Data for tracked (active) transactions
struct TransactionData
{
unsigned id;
TraNumber id;
Firebird::string* description;
// Deallocate memory used by objects hanging off this structure
@ -87,28 +87,28 @@ public:
description = NULL;
}
static const unsigned& generate(const void* /*sender*/, const TransactionData& item)
static const TraNumber& generate(const void* /*sender*/, const TransactionData& item)
{
return item.id;
}
};
typedef Firebird::BePlusTree<TransactionData, unsigned, Firebird::MemoryPool, TransactionData>
typedef Firebird::BePlusTree<TransactionData, TraNumber, Firebird::MemoryPool, TransactionData>
TransactionsTree;
// Data for tracked (active) statements
struct StatementData
{
unsigned int id;
StmtNumber id;
Firebird::string* description; // NULL in this field indicates that tracing of this statement is not desired
static const unsigned int& generate(const void* /*sender*/, const StatementData& item)
static const StmtNumber& generate(const void* /*sender*/, const StatementData& item)
{
return item.id;
}
};
typedef Firebird::BePlusTree<StatementData, unsigned int, Firebird::MemoryPool, StatementData>
typedef Firebird::BePlusTree<StatementData, StmtNumber, Firebird::MemoryPool, StatementData>
StatementsTree;
typedef void* ServiceId;

View File

@ -79,7 +79,7 @@ Firebird::ITracePlugin* TraceFactoryImpl::trace_create(Firebird::CheckStatusWrap
if (!config.enabled ||
(config.connection_id && connection &&
(connection->getConnectionID() != SLONG(config.connection_id))))
(connection->getConnectionID() != config.connection_id)))
{
return NULL; // Plugin is not needed, no error happened.
}