mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 14:03:07 +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:
parent
ae3b91aef3
commit
4e4d8002e5
@ -308,7 +308,7 @@ int alice(Firebird::UtilSvc* uSvc)
|
|||||||
ALICE_error(10); // msg 10: transaction number or "all" required
|
ALICE_error(10); // msg 10: transaction number or "all" required
|
||||||
}
|
}
|
||||||
ALICE_upper_case(*argv++, string, sizeof(string));
|
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")) {
|
if (strcmp(string, "ALL")) {
|
||||||
ALICE_error(10); // msg 10: transaction number or "all" required
|
ALICE_error(10); // msg 10: transaction number or "all" required
|
||||||
|
@ -79,7 +79,7 @@ struct user_action
|
|||||||
bool ua_read_only;
|
bool ua_read_only;
|
||||||
SLONG ua_shutdown_delay;
|
SLONG ua_shutdown_delay;
|
||||||
SLONG ua_sweep_interval;
|
SLONG ua_sweep_interval;
|
||||||
SLONG ua_transaction;
|
TraNumber ua_transaction;
|
||||||
SLONG ua_page_buffers;
|
SLONG ua_page_buffers;
|
||||||
USHORT ua_debug;
|
USHORT ua_debug;
|
||||||
ULONG ua_val_errors[MAX_VAL_ERRORS];
|
ULONG ua_val_errors[MAX_VAL_ERRORS];
|
||||||
@ -100,19 +100,19 @@ public:
|
|||||||
UCHAR str_data[2];
|
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
|
// Transaction Description Record
|
||||||
|
|
||||||
struct tdr : public pool_alloc<alice_type_tdr>
|
struct tdr : public pool_alloc<alice_type_tdr>
|
||||||
{
|
{
|
||||||
tdr* tdr_next; // next subtransaction
|
tdr* tdr_next; // next sub-transaction
|
||||||
SLONG tdr_id; // database-specific transaction id
|
TraNumber tdr_id; // database-specific transaction id
|
||||||
alice_str* tdr_fullpath; // full (possibly) remote pathname
|
alice_str* tdr_fullpath; // full (possibly) remote pathname
|
||||||
const TEXT* tdr_filename; // filename within full pathname
|
const TEXT* tdr_filename; // filename within full pathname
|
||||||
alice_str* tdr_host_site; // host for transaction
|
alice_str* tdr_host_site; // host for transaction
|
||||||
alice_str* tdr_remote_site; // site for remote transaction
|
alice_str* tdr_remote_site; // site for remote transaction
|
||||||
FB_API_HANDLE tdr_handle; // reconnected transaction handle
|
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_db_caps; // capabilities of database
|
||||||
USHORT tdr_state; // see flags below
|
USHORT tdr_state; // see flags below
|
||||||
};
|
};
|
||||||
|
@ -164,7 +164,7 @@ void MET_get_state(ISC_STATUS* user_status, tdr* trans)
|
|||||||
* in other databases.
|
* 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;
|
FB_API_HANDLE request = 0;
|
||||||
tdr* trans = NULL;
|
tdr* trans = NULL;
|
||||||
@ -328,7 +328,8 @@ static tdr* get_description(ISC_QUAD* blob_id)
|
|||||||
++p;
|
++p;
|
||||||
|
|
||||||
tdr* ptr = NULL; // silence uninitialized warning
|
tdr* ptr = NULL; // silence uninitialized warning
|
||||||
SLONG id_length, id;
|
SLONG id_length;
|
||||||
|
TraNumber id;
|
||||||
|
|
||||||
while (*p)
|
while (*p)
|
||||||
{
|
{
|
||||||
@ -344,7 +345,7 @@ static tdr* get_description(ISC_QUAD* blob_id)
|
|||||||
|
|
||||||
case TDR_TRANSACTION_ID:
|
case TDR_TRANSACTION_ID:
|
||||||
id_length = *p++;
|
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;
|
p += id_length;
|
||||||
if (!trans) {
|
if (!trans) {
|
||||||
trans = ptr = FB_NEW_POOL(*tdgbl->getDefaultPool()) tdr;
|
trans = ptr = FB_NEW_POOL(*tdgbl->getDefaultPool()) tdr;
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
void MET_disable_wal(ISC_STATUS*, isc_db_handle);
|
void MET_disable_wal(ISC_STATUS*, isc_db_handle);
|
||||||
void MET_get_state(ISC_STATUS*, tdr*);
|
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*);
|
void MET_set_capabilities(ISC_STATUS*, tdr*);
|
||||||
|
|
||||||
#endif // ALICE_ALICE_META_H
|
#endif // ALICE_ALICE_META_H
|
||||||
|
@ -53,7 +53,7 @@ static SINT64 ask();
|
|||||||
static void print_description(const tdr*);
|
static void print_description(const tdr*);
|
||||||
static void reattach_database(tdr*);
|
static void reattach_database(tdr*);
|
||||||
static void reattach_databases(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 };
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLONG id;
|
TraNumber id;
|
||||||
tdr* trans;
|
tdr* trans;
|
||||||
UCHAR* ptr = buffer;
|
UCHAR* ptr = buffer;
|
||||||
bool flag = true;
|
bool flag = true;
|
||||||
@ -298,7 +298,7 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche
|
|||||||
switch (item)
|
switch (item)
|
||||||
{
|
{
|
||||||
case isc_info_limbo:
|
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))
|
if (switches & (sw_commit | sw_rollback | sw_two_phase | sw_prompt))
|
||||||
{
|
{
|
||||||
TDR_reconnect_multiple(handle, id, name, switches);
|
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))
|
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);
|
reattach_databases(trans);
|
||||||
TDR_get_states(trans);
|
TDR_get_states(trans);
|
||||||
TDR_shutdown_databases(trans);
|
TDR_shutdown_databases(trans);
|
||||||
print_description(trans);
|
print_description(trans);
|
||||||
}
|
}
|
||||||
|
else if (id > TraNumber(MAX_SLONG))
|
||||||
|
tdgbl->uSvc->putSInt64(isc_spb_single_tra_id_64, id);
|
||||||
else
|
else
|
||||||
{
|
tdgbl->uSvc->putSLong(isc_spb_single_tra_id, (SLONG) id);
|
||||||
tdgbl->uSvc->putSLong(isc_spb_single_tra_id, id);
|
|
||||||
}
|
|
||||||
ptr += length;
|
ptr += length;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -362,7 +365,7 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche
|
|||||||
// gfix user.
|
// 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;
|
ISC_STATUS_ARRAY status_vector;
|
||||||
|
|
||||||
@ -531,7 +534,10 @@ static void print_description(const tdr* trans)
|
|||||||
// msg 94: Transaction %ld
|
// msg 94: Transaction %ld
|
||||||
ALICE_print(94, SafeArg() << ptr->tdr_id);
|
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)
|
switch (ptr->tdr_state)
|
||||||
@ -808,14 +814,13 @@ static void reattach_databases(tdr* trans)
|
|||||||
// Commit or rollback a named transaction.
|
// 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;
|
ISC_STATUS_ARRAY status_vector;
|
||||||
|
|
||||||
const SLONG id = gds__vax_integer(reinterpret_cast<const UCHAR*>(&number), 4);
|
|
||||||
FB_API_HANDLE transaction = 0;
|
FB_API_HANDLE transaction = 0;
|
||||||
if (isc_reconnect_transaction(status_vector, &handle, &transaction,
|
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);
|
ALICE_print(90, SafeArg() << name);
|
||||||
// msg 90: failed to reconnect to a transaction in database %s
|
// msg 90: failed to reconnect to a transaction in database %s
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#define ALICE_TDR_PROTO_H
|
#define ALICE_TDR_PROTO_H
|
||||||
|
|
||||||
void TDR_list_limbo(FB_API_HANDLE, const TEXT*, const SINT64);
|
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*);
|
void TDR_shutdown_databases(tdr*);
|
||||||
USHORT TDR_analyze(const tdr*);
|
USHORT TDR_analyze(const tdr*);
|
||||||
bool TDR_attach_database(ISC_STATUS*, tdr*, const TEXT*);
|
bool TDR_attach_database(ISC_STATUS*, tdr*, const TEXT*);
|
||||||
|
@ -134,6 +134,7 @@ public:
|
|||||||
virtual void started() { }
|
virtual void started() { }
|
||||||
virtual void putLine(char, const char*) { }
|
virtual void putLine(char, const char*) { }
|
||||||
virtual void putSLong(char, SLONG) { }
|
virtual void putSLong(char, SLONG) { }
|
||||||
|
virtual void putSInt64(char, SINT64) { }
|
||||||
virtual void putChar(char, char) { }
|
virtual void putChar(char, char) { }
|
||||||
virtual void putBytes(const UCHAR*, FB_SIZE_T) { }
|
virtual void putBytes(const UCHAR*, FB_SIZE_T) { }
|
||||||
virtual ULONG getBytes(UCHAR*, ULONG) { return 0; }
|
virtual ULONG getBytes(UCHAR*, ULONG) { return 0; }
|
||||||
|
@ -60,6 +60,7 @@ public:
|
|||||||
virtual void printf(bool err, const SCHAR* format, ...) = 0;
|
virtual void printf(bool err, const SCHAR* format, ...) = 0;
|
||||||
virtual void putLine(char, const char*) = 0;
|
virtual void putLine(char, const char*) = 0;
|
||||||
virtual void putSLong(char, SLONG) = 0;
|
virtual void putSLong(char, SLONG) = 0;
|
||||||
|
virtual void putSInt64(char, SINT64) = 0;
|
||||||
virtual void putChar(char, char) = 0;
|
virtual void putChar(char, char) = 0;
|
||||||
virtual void putBytes(const UCHAR*, FB_SIZE_T) = 0;
|
virtual void putBytes(const UCHAR*, FB_SIZE_T) = 0;
|
||||||
virtual ULONG getBytes(UCHAR*, ULONG) = 0;
|
virtual ULONG getBytes(UCHAR*, ULONG) = 0;
|
||||||
|
@ -6055,12 +6055,29 @@ void InternalInfoNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
|||||||
|
|
||||||
void InternalInfoNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc)
|
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)
|
switch (infoType)
|
||||||
|
{
|
||||||
|
case INFO_TYPE_SQLSTATE:
|
||||||
desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii);
|
desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii);
|
||||||
else
|
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);
|
desc->makeLong(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fb_assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InternalInfoNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
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);
|
arg->getDesc(tdbb, csb, &argDesc);
|
||||||
fb_assert(argDesc.dsc_dtype == dtype_long);
|
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)
|
switch (infoType)
|
||||||
|
{
|
||||||
|
case INFO_TYPE_SQLSTATE:
|
||||||
desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii);
|
desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii);
|
||||||
else
|
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);
|
desc->makeLong(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fb_assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueExprNode* InternalInfoNode::copy(thread_db* tdbb, NodeCopier& copier) const
|
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;
|
return NULL;
|
||||||
|
|
||||||
fb_assert(value->dsc_dtype == dtype_long);
|
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)
|
if (infoType == INFO_TYPE_SQLSTATE)
|
||||||
{
|
{
|
||||||
FB_SQLSTATE_STRING sqlstate;
|
FB_SQLSTATE_STRING sqlstate;
|
||||||
request->req_last_xcp.as_sqlstate(sqlstate);
|
request->req_last_xcp.as_sqlstate(sqlstate);
|
||||||
|
|
||||||
dsc desc;
|
|
||||||
desc.makeText(FB_SQLSTATE_LENGTH, ttype_ascii, (UCHAR*) sqlstate);
|
desc.makeText(FB_SQLSTATE_LENGTH, ttype_ascii, (UCHAR*) sqlstate);
|
||||||
EVL_make_value(tdbb, &desc, impure);
|
|
||||||
|
|
||||||
return &impure->vlu_desc;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
SLONG result = 0;
|
{
|
||||||
|
SLONG int32_result = 0;
|
||||||
|
SINT64 int64_result = 0;
|
||||||
|
|
||||||
switch (infoType)
|
switch (infoType)
|
||||||
{
|
{
|
||||||
case INFO_TYPE_CONNECTION_ID:
|
case INFO_TYPE_CONNECTION_ID:
|
||||||
result = PAG_attachment_id(tdbb);
|
int64_result = PAG_attachment_id(tdbb);
|
||||||
break;
|
break;
|
||||||
case INFO_TYPE_TRANSACTION_ID:
|
case INFO_TYPE_TRANSACTION_ID:
|
||||||
//fb_assert(sizeof(result) == sizeof(tdbb->getTransaction()->tra_number));
|
int64_result = tdbb->getTransaction()->tra_number;
|
||||||
// Conversion from unsigned to SLONG, big values will be reported as negative.
|
|
||||||
result = tdbb->getTransaction()->tra_number;
|
|
||||||
break;
|
break;
|
||||||
case INFO_TYPE_GDSCODE:
|
case INFO_TYPE_GDSCODE:
|
||||||
result = request->req_last_xcp.as_gdscode();
|
int32_result = request->req_last_xcp.as_gdscode();
|
||||||
break;
|
break;
|
||||||
case INFO_TYPE_SQLCODE:
|
case INFO_TYPE_SQLCODE:
|
||||||
result = request->req_last_xcp.as_sqlcode();
|
int32_result = request->req_last_xcp.as_sqlcode();
|
||||||
break;
|
break;
|
||||||
case INFO_TYPE_ROWS_AFFECTED:
|
case INFO_TYPE_ROWS_AFFECTED:
|
||||||
// CVC: Not sure if this counter can overflow in extreme cases
|
int64_result = request->req_records_affected.getCount();
|
||||||
result = request->req_records_affected.getCount();
|
|
||||||
break;
|
break;
|
||||||
case INFO_TYPE_TRIGGER_ACTION:
|
case INFO_TYPE_TRIGGER_ACTION:
|
||||||
result = request->req_trigger_action;
|
int32_result = request->req_trigger_action;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUGCHECK(232); // msg 232 EVL_expr: invalid operation
|
BUGCHECK(232); // msg 232 EVL_expr: invalid operation
|
||||||
}
|
}
|
||||||
|
|
||||||
dsc desc;
|
if (int64_result)
|
||||||
desc.makeLong(0, &result);
|
desc.makeInt64(0, &int64_result);
|
||||||
EVL_make_value(tdbb, &desc, impure);
|
else
|
||||||
|
desc.makeLong(0, &int32_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
EVL_make_value(tdbb, &desc, impure);
|
||||||
return &impure->vlu_desc;
|
return &impure->vlu_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8130,7 +8164,7 @@ void RecordKeyNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc)
|
|||||||
{
|
{
|
||||||
if (dbKeyLength == 8)
|
if (dbKeyLength == 8)
|
||||||
{
|
{
|
||||||
desc->makeLong(0);
|
desc->makeInt64(0);
|
||||||
desc->setNullable(true);
|
desc->setNullable(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -8181,13 +8215,13 @@ void RecordKeyNode::getDesc(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, dsc*
|
|||||||
case blr_record_version:
|
case blr_record_version:
|
||||||
desc->dsc_dtype = dtype_text;
|
desc->dsc_dtype = dtype_text;
|
||||||
desc->dsc_ttype() = ttype_binary;
|
desc->dsc_ttype() = ttype_binary;
|
||||||
desc->dsc_length = sizeof(SLONG);
|
desc->dsc_length = sizeof(SINT64);
|
||||||
desc->dsc_scale = 0;
|
desc->dsc_scale = 0;
|
||||||
desc->dsc_flags = 0;
|
desc->dsc_flags = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blr_record_version2:
|
case blr_record_version2:
|
||||||
desc->makeLong(0);
|
desc->makeInt64(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8433,10 +8467,10 @@ dsc* RecordKeyNode::execute(thread_db* /*tdbb*/, jrd_req* request) const
|
|||||||
|
|
||||||
// Initialize descriptor
|
// Initialize descriptor
|
||||||
|
|
||||||
impure->vlu_misc.vlu_long = rpb->rpb_transaction_nr;
|
impure->vlu_misc.vlu_int64 = rpb->rpb_transaction_nr;
|
||||||
impure->vlu_desc.dsc_address = (UCHAR*) &impure->vlu_misc.vlu_long;
|
impure->vlu_desc.dsc_address = (UCHAR*) &impure->vlu_misc.vlu_int64;
|
||||||
impure->vlu_desc.dsc_dtype = dtype_text;
|
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;
|
impure->vlu_desc.dsc_ttype() = ttype_binary;
|
||||||
}
|
}
|
||||||
else if (blrOp == blr_record_version2)
|
else if (blrOp == blr_record_version2)
|
||||||
@ -8450,8 +8484,8 @@ dsc* RecordKeyNode::execute(thread_db* /*tdbb*/, jrd_req* request) const
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
impure->vlu_misc.vlu_long = rpb->rpb_transaction_nr;
|
impure->vlu_misc.vlu_int64 = rpb->rpb_transaction_nr;
|
||||||
impure->vlu_desc.makeLong(0, &impure->vlu_misc.vlu_long);
|
impure->vlu_desc.makeInt64(0, &impure->vlu_misc.vlu_int64);
|
||||||
}
|
}
|
||||||
|
|
||||||
return &impure->vlu_desc;
|
return &impure->vlu_desc;
|
||||||
|
@ -60,11 +60,6 @@ const StreamType STREAM_MAP_LENGTH = MAX_STREAMS + 2;
|
|||||||
// New formula is simply MAX_STREAMS / BITS_PER_LONG
|
// New formula is simply MAX_STREAMS / BITS_PER_LONG
|
||||||
const int OPT_STREAM_BITS = MAX_STREAMS / BITS_PER_LONG; // 128 with 4096 streams
|
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::HalfStaticArray<StreamType, OPT_STATIC_ITEMS> StreamList;
|
||||||
typedef Firebird::SortedArray<StreamType> SortedStreamList;
|
typedef Firebird::SortedArray<StreamType> SortedStreamList;
|
||||||
|
|
||||||
|
@ -7358,7 +7358,7 @@ void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
|||||||
|
|
||||||
parameter->par_desc.dsc_dtype = dtype_text;
|
parameter->par_desc.dsc_dtype = dtype_text;
|
||||||
parameter->par_desc.dsc_ttype() = ttype_binary;
|
parameter->par_desc.dsc_ttype() = ttype_binary;
|
||||||
parameter->par_desc.dsc_length = relation->rel_dbkey_length / 2;
|
parameter->par_desc.dsc_length = sizeof(SINT64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -468,6 +468,9 @@
|
|||||||
#define isc_spb_tra_advise_commit 30
|
#define isc_spb_tra_advise_commit 30
|
||||||
#define isc_spb_tra_advise_rollback 31
|
#define isc_spb_tra_advise_rollback 31
|
||||||
#define isc_spb_tra_advise_unknown 33
|
#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_validate_db 0x01
|
||||||
#define isc_spb_rpr_sweep_db 0x02
|
#define isc_spb_rpr_sweep_db 0x02
|
||||||
|
@ -142,9 +142,6 @@ typedef USHORT TTYPE_ID;
|
|||||||
// Stream type, had to move it from dsql/Nodes.h due to circular dependencies.
|
// Stream type, had to move it from dsql/Nodes.h due to circular dependencies.
|
||||||
typedef ULONG StreamType;
|
typedef ULONG StreamType;
|
||||||
|
|
||||||
// The type of Jrd's transaction.
|
|
||||||
typedef ULONG TraNumber;
|
|
||||||
|
|
||||||
// Alignment rule
|
// Alignment rule
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T FB_ALIGN(T n, uintptr_t b)
|
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));
|
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 */
|
#endif /* INCLUDE_FB_TYPES_H */
|
||||||
|
@ -983,7 +983,7 @@ interface TraceConnection : Versioned
|
|||||||
|
|
||||||
interface TraceDatabaseConnection : TraceConnection
|
interface TraceDatabaseConnection : TraceConnection
|
||||||
{
|
{
|
||||||
int getConnectionID();
|
int64 getConnectionID();
|
||||||
const string getDatabaseName();
|
const string getDatabaseName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -994,7 +994,7 @@ interface TraceTransaction : Versioned
|
|||||||
const uint ISOLATION_READ_COMMITTED_RECVER = 3;
|
const uint ISOLATION_READ_COMMITTED_RECVER = 3;
|
||||||
const uint ISOLATION_READ_COMMITTED_NORECVER = 4;
|
const uint ISOLATION_READ_COMMITTED_NORECVER = 4;
|
||||||
|
|
||||||
uint getTransactionID();
|
int64 getTransactionID();
|
||||||
boolean getReadOnly();
|
boolean getReadOnly();
|
||||||
int getWait();
|
int getWait();
|
||||||
uint getIsolation();
|
uint getIsolation();
|
||||||
@ -1009,7 +1009,7 @@ interface TraceParams : Versioned
|
|||||||
|
|
||||||
interface TraceStatement : Versioned
|
interface TraceStatement : Versioned
|
||||||
{
|
{
|
||||||
int getStmtID();
|
int64 getStmtID();
|
||||||
PerformanceInfo* getPerf();
|
PerformanceInfo* getPerf();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1092,10 +1092,10 @@ interface TraceStatusVector : Versioned
|
|||||||
|
|
||||||
interface TraceSweepInfo : Versioned
|
interface TraceSweepInfo : Versioned
|
||||||
{
|
{
|
||||||
uint64 getOIT();
|
int64 getOIT();
|
||||||
uint64 getOST();
|
int64 getOST();
|
||||||
uint64 getOAT();
|
int64 getOAT();
|
||||||
uint64 getNext();
|
int64 getNext();
|
||||||
PerformanceInfo* getPerf();
|
PerformanceInfo* getPerf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3829,7 +3829,7 @@ namespace Firebird
|
|||||||
public:
|
public:
|
||||||
struct VTable : public ITraceConnection::VTable
|
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();
|
const char* (CLOOP_CARG *getDatabaseName)(ITraceDatabaseConnection* self) throw();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3846,9 +3846,9 @@ namespace Firebird
|
|||||||
public:
|
public:
|
||||||
static const unsigned VERSION = 3;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3864,7 +3864,7 @@ namespace Firebird
|
|||||||
public:
|
public:
|
||||||
struct VTable : public IVersioned::VTable
|
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();
|
FB_BOOLEAN (CLOOP_CARG *getReadOnly)(ITraceTransaction* self) throw();
|
||||||
int (CLOOP_CARG *getWait)(ITraceTransaction* self) throw();
|
int (CLOOP_CARG *getWait)(ITraceTransaction* self) throw();
|
||||||
unsigned (CLOOP_CARG *getIsolation)(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_RECVER = 3;
|
||||||
static const unsigned ISOLATION_READ_COMMITTED_NORECVER = 4;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3960,7 +3960,7 @@ namespace Firebird
|
|||||||
public:
|
public:
|
||||||
struct VTable : public IVersioned::VTable
|
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();
|
PerformanceInfo* (CLOOP_CARG *getPerf)(ITraceStatement* self) throw();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3977,9 +3977,9 @@ namespace Firebird
|
|||||||
public:
|
public:
|
||||||
static const unsigned VERSION = 2;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4419,10 +4419,10 @@ namespace Firebird
|
|||||||
public:
|
public:
|
||||||
struct VTable : public IVersioned::VTable
|
struct VTable : public IVersioned::VTable
|
||||||
{
|
{
|
||||||
ISC_UINT64 (CLOOP_CARG *getOIT)(ITraceSweepInfo* self) throw();
|
ISC_INT64 (CLOOP_CARG *getOIT)(ITraceSweepInfo* self) throw();
|
||||||
ISC_UINT64 (CLOOP_CARG *getOST)(ITraceSweepInfo* self) throw();
|
ISC_INT64 (CLOOP_CARG *getOST)(ITraceSweepInfo* self) throw();
|
||||||
ISC_UINT64 (CLOOP_CARG *getOAT)(ITraceSweepInfo* self) throw();
|
ISC_INT64 (CLOOP_CARG *getOAT)(ITraceSweepInfo* self) throw();
|
||||||
ISC_UINT64 (CLOOP_CARG *getNext)(ITraceSweepInfo* self) throw();
|
ISC_INT64 (CLOOP_CARG *getNext)(ITraceSweepInfo* self) throw();
|
||||||
PerformanceInfo* (CLOOP_CARG *getPerf)(ITraceSweepInfo* self) throw();
|
PerformanceInfo* (CLOOP_CARG *getPerf)(ITraceSweepInfo* self) throw();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4439,27 +4439,27 @@ namespace Firebird
|
|||||||
public:
|
public:
|
||||||
static const unsigned VERSION = 2;
|
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;
|
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;
|
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;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13032,7 +13032,7 @@ namespace Firebird
|
|||||||
this->cloopVTable = &vTable;
|
this->cloopVTable = &vTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CLOOP_CARG cloopgetConnectionIDDispatcher(ITraceDatabaseConnection* self) throw()
|
static ISC_INT64 CLOOP_CARG cloopgetConnectionIDDispatcher(ITraceDatabaseConnection* self) throw()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -13041,7 +13041,7 @@ namespace Firebird
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
StatusType::catchException(0);
|
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;
|
virtual const char* getDatabaseName() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -13217,7 +13217,7 @@ namespace Firebird
|
|||||||
this->cloopVTable = &vTable;
|
this->cloopVTable = &vTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned CLOOP_CARG cloopgetTransactionIDDispatcher(ITraceTransaction* self) throw()
|
static ISC_INT64 CLOOP_CARG cloopgetTransactionIDDispatcher(ITraceTransaction* self) throw()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -13226,7 +13226,7 @@ namespace Firebird
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
StatusType::catchException(0);
|
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 FB_BOOLEAN getReadOnly() = 0;
|
||||||
virtual int getWait() = 0;
|
virtual int getWait() = 0;
|
||||||
virtual unsigned getIsolation() = 0;
|
virtual unsigned getIsolation() = 0;
|
||||||
@ -13389,7 +13389,7 @@ namespace Firebird
|
|||||||
this->cloopVTable = &vTable;
|
this->cloopVTable = &vTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw()
|
static ISC_INT64 CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -13398,7 +13398,7 @@ namespace Firebird
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
StatusType::catchException(0);
|
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;
|
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
|
try
|
||||||
{
|
{
|
||||||
@ -13533,7 +13533,7 @@ namespace Firebird
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
StatusType::catchException(0);
|
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
|
try
|
||||||
{
|
{
|
||||||
@ -13643,7 +13643,7 @@ namespace Firebird
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
StatusType::catchException(0);
|
StatusType::catchException(0);
|
||||||
return static_cast<int>(0);
|
return static_cast<ISC_INT64>(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14449,7 +14449,7 @@ namespace Firebird
|
|||||||
this->cloopVTable = &vTable;
|
this->cloopVTable = &vTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ISC_UINT64 CLOOP_CARG cloopgetOITDispatcher(ITraceSweepInfo* self) throw()
|
static ISC_INT64 CLOOP_CARG cloopgetOITDispatcher(ITraceSweepInfo* self) throw()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -14458,11 +14458,11 @@ namespace Firebird
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
StatusType::catchException(0);
|
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
|
try
|
||||||
{
|
{
|
||||||
@ -14471,11 +14471,11 @@ namespace Firebird
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
StatusType::catchException(0);
|
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
|
try
|
||||||
{
|
{
|
||||||
@ -14484,11 +14484,11 @@ namespace Firebird
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
StatusType::catchException(0);
|
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
|
try
|
||||||
{
|
{
|
||||||
@ -14497,7 +14497,7 @@ namespace Firebird
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
StatusType::catchException(0);
|
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_INT64 getOIT() = 0;
|
||||||
virtual ISC_UINT64 getOST() = 0;
|
virtual ISC_INT64 getOST() = 0;
|
||||||
virtual ISC_UINT64 getOAT() = 0;
|
virtual ISC_INT64 getOAT() = 0;
|
||||||
virtual ISC_UINT64 getNext() = 0;
|
virtual ISC_INT64 getNext() = 0;
|
||||||
virtual PerformanceInfo* getPerf() = 0;
|
virtual PerformanceInfo* getPerf() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "../jrd/ext_proto.h"
|
#include "../jrd/ext_proto.h"
|
||||||
#include "../jrd/intl_proto.h"
|
#include "../jrd/intl_proto.h"
|
||||||
#include "../jrd/met_proto.h"
|
#include "../jrd/met_proto.h"
|
||||||
|
#include "../jrd/tra_proto.h"
|
||||||
|
|
||||||
#include "../jrd/extds/ExtDS.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;
|
const lock_ast_t ast = (att_flags & ATT_system) ? NULL : blockingAstShutdown;
|
||||||
|
|
||||||
Lock* lock = FB_NEW_RPT(*att_pool, sizeof(SLONG))
|
Lock* lock = FB_NEW_RPT(*att_pool, 0)
|
||||||
Lock(tdbb, sizeof(SLONG), LCK_attachment, this, ast);
|
Lock(tdbb, sizeof(AttNumber), LCK_attachment, this, ast);
|
||||||
att_id_lock = lock;
|
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);
|
LCK_lock(tdbb, lock, LCK_EX, LCK_WAIT);
|
||||||
|
|
||||||
// Allocate and take the monitoring lock
|
// Allocate and take the monitoring lock
|
||||||
|
|
||||||
lock = FB_NEW_RPT(*att_pool, sizeof(SLONG))
|
lock = FB_NEW_RPT(*att_pool, 0)
|
||||||
Lock(tdbb, sizeof(SLONG), LCK_monitor, this, blockingAstMonitor);
|
Lock(tdbb, sizeof(AttNumber), LCK_monitor, this, blockingAstMonitor);
|
||||||
att_monitor_lock = lock;
|
att_monitor_lock = lock;
|
||||||
lock->lck_key.lck_long = att_attachment_id;
|
lock->lck_key.lck_long = att_attachment_id;
|
||||||
LCK_lock(tdbb, lock, LCK_EX, LCK_WAIT);
|
LCK_lock(tdbb, lock, LCK_EX, LCK_WAIT);
|
||||||
@ -441,8 +442,8 @@ void Jrd::Attachment::initLocks(thread_db* tdbb)
|
|||||||
|
|
||||||
if (!(att_flags & ATT_system))
|
if (!(att_flags & ATT_system))
|
||||||
{
|
{
|
||||||
lock = FB_NEW_RPT(*att_pool, sizeof(SLONG))
|
lock = FB_NEW_RPT(*att_pool, 0)
|
||||||
Lock(tdbb, sizeof(SLONG), LCK_cancel, this, blockingAstCancel);
|
Lock(tdbb, sizeof(AttNumber), LCK_cancel, this, blockingAstCancel);
|
||||||
att_cancel_lock = lock;
|
att_cancel_lock = lock;
|
||||||
lock->lck_key.lck_long = att_attachment_id;
|
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)
|
int Jrd::Attachment::blockingAstShutdown(void* ast_object)
|
||||||
|
@ -327,7 +327,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
Firebird::SortedArray<jrd_req*> att_requests; // Requests belonging to attachment
|
Firebird::SortedArray<jrd_req*> att_requests; // Requests belonging to attachment
|
||||||
Lock* att_id_lock; // Attachment lock (if any)
|
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_cancel_lock; // Lock to cancel the active request
|
||||||
Lock* att_monitor_lock; // Lock for monitoring purposes
|
Lock* att_monitor_lock; // Lock for monitoring purposes
|
||||||
const ULONG att_lock_owner_id; // ID for the lock manager
|
const ULONG att_lock_owner_id; // ID for the lock manager
|
||||||
|
@ -237,7 +237,6 @@ namespace Jrd
|
|||||||
dbb_flags &= ~(DBB_sweep_in_progress | DBB_sweep_starting);
|
dbb_flags &= ~(DBB_sweep_in_progress | DBB_sweep_starting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Database::SharedCounter::shutdown(thread_db* tdbb)
|
void Database::SharedCounter::shutdown(thread_db* tdbb)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < TOTAL_ITEMS; i++)
|
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);
|
fb_assert(space < TOTAL_ITEMS);
|
||||||
ValueCache* const counter = &m_counters[space];
|
ValueCache* const counter = &m_counters[space];
|
||||||
|
|
||||||
if (m_localOnly)
|
|
||||||
{
|
|
||||||
SLONG result = 0;
|
|
||||||
while ( !(result = (SLONG) ++counter->curVal) )
|
|
||||||
;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Database* const dbb = tdbb->getDatabase();
|
Database* const dbb = tdbb->getDatabase();
|
||||||
SyncLockGuard guard(&dbb->dbb_sh_counter_sync, SYNC_EXCLUSIVE, "Database::SharedCounter::generate");
|
SyncLockGuard guard(&dbb->dbb_sh_counter_sync, SYNC_EXCLUSIVE, "Database::SharedCounter::generate");
|
||||||
|
|
||||||
|
SINT64 result = ++counter->curVal;
|
||||||
|
|
||||||
|
if (!m_localOnly && result > counter->maxVal)
|
||||||
|
{
|
||||||
if (!counter->lock)
|
if (!counter->lock)
|
||||||
{
|
{
|
||||||
Lock* const lock =
|
counter->lock =
|
||||||
FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock(tdbb, sizeof(SLONG), LCK_shared_counter);
|
FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock(tdbb, sizeof(SLONG), LCK_shared_counter);
|
||||||
counter->lock = lock;
|
counter->lock->lck_key.lck_long = space;
|
||||||
lock->lck_key.lck_long = space;
|
LCK_lock(tdbb, counter->lock, LCK_PW, LCK_WAIT);
|
||||||
LCK_lock(tdbb, lock, LCK_PW, LCK_WAIT);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
SLONG result = (SLONG) ++counter->curVal;
|
|
||||||
|
|
||||||
if (result > counter->maxVal)
|
|
||||||
{
|
|
||||||
LCK_convert(tdbb, counter->lock, LCK_PW, LCK_WAIT);
|
LCK_convert(tdbb, counter->lock, LCK_PW, LCK_WAIT);
|
||||||
|
|
||||||
result = LCK_read_data(tdbb, counter->lock);
|
result = LCK_read_data(tdbb, counter->lock);
|
||||||
|
|
||||||
// zero IDs are somewhat special, so let's better skip them
|
// zero IDs are somewhat special, so let's better skip them
|
||||||
|
@ -243,8 +243,8 @@ public:
|
|||||||
struct ValueCache
|
struct ValueCache
|
||||||
{
|
{
|
||||||
Lock* lock; // lock which holds shared counter value
|
Lock* lock; // lock which holds shared counter value
|
||||||
Firebird::AtomicCounter curVal; // current value of shared counter lock
|
SINT64 curVal; // current value of shared counter lock
|
||||||
SLONG maxVal; // maximum cached value of shared counter lock
|
SINT64 maxVal; // maximum cached value of shared counter lock
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -266,7 +266,7 @@ public:
|
|||||||
delete m_counters[i].lock;
|
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);
|
void shutdown(thread_db* tdbb);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -438,7 +438,7 @@ public:
|
|||||||
TraNumber dbb_oldest_transaction; // Cached "oldest interesting" transaction
|
TraNumber dbb_oldest_transaction; // Cached "oldest interesting" transaction
|
||||||
TraNumber dbb_oldest_snapshot; // Cached "oldest snapshot" of all active transactions
|
TraNumber dbb_oldest_snapshot; // Cached "oldest snapshot" of all active transactions
|
||||||
TraNumber dbb_next_transaction; // Next transaction id used by NETWARE
|
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
|
ULONG dbb_page_buffers; // Page buffers from header page
|
||||||
|
|
||||||
GarbageCollector* dbb_garbage_collector; // GarbageCollector class
|
GarbageCollector* dbb_garbage_collector; // GarbageCollector class
|
||||||
@ -531,17 +531,17 @@ private:
|
|||||||
~Database();
|
~Database();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SLONG generateAttachmentId(thread_db* tdbb)
|
AttNumber generateAttachmentId(thread_db* tdbb)
|
||||||
{
|
{
|
||||||
return dbb_shared_counter.generate(tdbb, SharedCounter::ATTACHMENT_ID_SPACE, 1);
|
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);
|
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);
|
return dbb_shared_counter.generate(tdbb, SharedCounter::STATEMENT_ID_SPACE);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
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));
|
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
|
// Remove information about the given session
|
||||||
|
|
||||||
@ -337,7 +337,7 @@ MonitoringSnapshot::MonitoringSnapshot(thread_db* tdbb, MemoryPool& pool)
|
|||||||
Attachment* const attachment = tdbb->getAttachment();
|
Attachment* const attachment = tdbb->getAttachment();
|
||||||
fb_assert(attachment);
|
fb_assert(attachment);
|
||||||
|
|
||||||
const SLONG self_att_id = attachment->att_attachment_id;
|
const AttNumber self_att_id = attachment->att_attachment_id;
|
||||||
|
|
||||||
// Initialize record buffers
|
// Initialize record buffers
|
||||||
RecordBuffer* const dbb_buffer = allocBuffer(tdbb, pool, rel_mon_database);
|
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);
|
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)
|
if (*iter != self_att_id)
|
||||||
{
|
{
|
||||||
@ -403,7 +403,7 @@ MonitoringSnapshot::MonitoringSnapshot(thread_db* tdbb, MemoryPool& pool)
|
|||||||
ThreadStatusGuard temp_status(tdbb);
|
ThreadStatusGuard temp_status(tdbb);
|
||||||
lock->lck_type = LCK_attachment;
|
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)
|
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,
|
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);
|
StringMap::ConstAccessor accessor(&variables);
|
||||||
|
|
||||||
@ -1180,10 +1181,8 @@ void Monitoring::putContextVars(SnapshotData::DumpRecord& record, const StringMa
|
|||||||
{
|
{
|
||||||
record.reset(rel_mon_ctx_vars);
|
record.reset(rel_mon_ctx_vars);
|
||||||
|
|
||||||
if (is_attachment)
|
const int field_id = is_attachment ? f_mon_ctx_var_att_id : f_mon_ctx_var_tra_id;
|
||||||
record.storeInteger(f_mon_ctx_var_att_id, object_id);
|
record.storeInteger(field_id, object_id);
|
||||||
else
|
|
||||||
record.storeInteger(f_mon_ctx_var_tra_id, object_id);
|
|
||||||
|
|
||||||
record.storeString(f_mon_ctx_var_name, accessor.current()->first);
|
record.storeString(f_mon_ctx_var_name, accessor.current()->first);
|
||||||
record.storeString(f_mon_ctx_var_value, accessor.current()->second);
|
record.storeString(f_mon_ctx_var_value, accessor.current()->second);
|
||||||
|
@ -242,7 +242,7 @@ class MonitoringData FB_FINAL : public Firebird::IpcObject
|
|||||||
|
|
||||||
struct Element
|
struct Element
|
||||||
{
|
{
|
||||||
SLONG attId;
|
AttNumber attId;
|
||||||
ULONG length;
|
ULONG length;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -273,7 +273,7 @@ public:
|
|||||||
class Writer
|
class Writer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Writer(MonitoringData* data, SLONG att_id)
|
Writer(MonitoringData* data, AttNumber att_id)
|
||||||
: dump(data)
|
: dump(data)
|
||||||
{
|
{
|
||||||
fb_assert(dump);
|
fb_assert(dump);
|
||||||
@ -325,7 +325,7 @@ public:
|
|||||||
Firebird::UCharBuffer buffer;
|
Firebird::UCharBuffer buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Firebird::HalfStaticArray<SLONG, 64> SessionList;
|
typedef Firebird::HalfStaticArray<AttNumber, 64> SessionList;
|
||||||
|
|
||||||
explicit MonitoringData(const Database*);
|
explicit MonitoringData(const Database*);
|
||||||
~MonitoringData();
|
~MonitoringData();
|
||||||
@ -336,11 +336,11 @@ public:
|
|||||||
void acquire();
|
void acquire();
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
void read(SLONG, TempSpace&);
|
void read(AttNumber, TempSpace&);
|
||||||
ULONG setup(SLONG);
|
ULONG setup(AttNumber);
|
||||||
void write(ULONG, ULONG, const void*);
|
void write(ULONG, ULONG, const void*);
|
||||||
|
|
||||||
void cleanup(SLONG);
|
void cleanup(AttNumber);
|
||||||
void enumerate(SessionList&);
|
void enumerate(SessionList&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -405,7 +405,7 @@ private:
|
|||||||
static void putStatistics(SnapshotData::DumpRecord&, const RuntimeStatistics&,
|
static void putStatistics(SnapshotData::DumpRecord&, const RuntimeStatistics&,
|
||||||
MonitoringData::Writer&, int, int);
|
MonitoringData::Writer&, int, int);
|
||||||
static void putContextVars(SnapshotData::DumpRecord&, const Firebird::StringMap&,
|
static void putContextVars(SnapshotData::DumpRecord&, const Firebird::StringMap&,
|
||||||
MonitoringData::Writer&, int, bool);
|
MonitoringData::Writer&, SINT64, bool);
|
||||||
static void putMemoryUsage(SnapshotData::DumpRecord&, const Firebird::MemoryStats&,
|
static void putMemoryUsage(SnapshotData::DumpRecord&, const Firebird::MemoryStats&,
|
||||||
MonitoringData::Writer&, int, int);
|
MonitoringData::Writer&, int, int);
|
||||||
};
|
};
|
||||||
|
@ -44,9 +44,10 @@ RelationPages* jrd_rel::getPagesInternal(thread_db* tdbb, TraNumber tran, bool a
|
|||||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||||
Database* dbb = tdbb->getDatabase();
|
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
|
// 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)
|
if (rel_flags & REL_temp_tran)
|
||||||
{
|
{
|
||||||
@ -136,7 +137,7 @@ RelationPages* jrd_rel::getPagesInternal(thread_db* tdbb, TraNumber tran, bool a
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES,
|
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_instance_id,
|
||||||
newPages->rel_index_root,
|
newPages->rel_index_root,
|
||||||
idx->idx_id,
|
idx->idx_id,
|
||||||
@ -190,13 +191,11 @@ bool jrd_rel::delPages(thread_db* tdbb, TraNumber tran, RelationPages* aPages)
|
|||||||
|
|
||||||
rel_pages_inst->remove(pos);
|
rel_pages_inst->remove(pos);
|
||||||
|
|
||||||
if (pages->rel_index_root) {
|
if (pages->rel_index_root)
|
||||||
IDX_delete_indices(tdbb, this, pages);
|
IDX_delete_indices(tdbb, this, pages);
|
||||||
}
|
|
||||||
|
|
||||||
if (pages->rel_pages) {
|
if (pages->rel_pages)
|
||||||
DPM_delete_relation_pages(tdbb, this, pages);
|
DPM_delete_relation_pages(tdbb, this, pages);
|
||||||
}
|
|
||||||
|
|
||||||
pages->free(rel_pages_free);
|
pages->free(rel_pages_free);
|
||||||
return true;
|
return true;
|
||||||
@ -208,13 +207,13 @@ void jrd_rel::getRelLockKey(thread_db* tdbb, UCHAR* key)
|
|||||||
memcpy(key, &val, sizeof(ULONG));
|
memcpy(key, &val, sizeof(ULONG));
|
||||||
key += sizeof(ULONG);
|
key += sizeof(ULONG);
|
||||||
|
|
||||||
const ULONG inst_id = getPages(tdbb)->rel_instance_id;
|
const SINT64 inst_id = getPages(tdbb)->rel_instance_id;
|
||||||
memcpy(key, &inst_id, sizeof(ULONG));
|
memcpy(key, &inst_id, sizeof(SINT64));
|
||||||
}
|
}
|
||||||
|
|
||||||
USHORT jrd_rel::getRelLockKeyLength() const
|
USHORT jrd_rel::getRelLockKeyLength() const
|
||||||
{
|
{
|
||||||
return sizeof(ULONG) + sizeof(SLONG);
|
return sizeof(ULONG) + sizeof(SINT64);
|
||||||
}
|
}
|
||||||
|
|
||||||
void jrd_rel::cleanUp()
|
void jrd_rel::cleanUp()
|
||||||
@ -238,7 +237,7 @@ void jrd_rel::fillPagesSnapshot(RelPagesSnapshot& snapshot, const bool attachmen
|
|||||||
relPages->addRef();
|
relPages->addRef();
|
||||||
}
|
}
|
||||||
else if ((rel_flags & REL_temp_conn) &&
|
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);
|
snapshot.add(relPages);
|
||||||
relPages->addRef();
|
relPages->addRef();
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define JRD_RELATION_H
|
#define JRD_RELATION_H
|
||||||
|
|
||||||
#include "../jrd/jrd.h"
|
#include "../jrd/jrd.h"
|
||||||
|
#include "../jrd/btr.h"
|
||||||
#include "../jrd/lck.h"
|
#include "../jrd/lck.h"
|
||||||
#include "../jrd/pag.h"
|
#include "../jrd/pag.h"
|
||||||
#include "../jrd/val.h"
|
#include "../jrd/val.h"
|
||||||
@ -68,11 +69,12 @@ typedef Firebird::SortedArray<ViewContext*, Firebird::EmptyStorage<ViewContext*>
|
|||||||
class RelationPages
|
class RelationPages
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ULONG RP_INSTANCE_ID;
|
typedef SINT64 RP_INSTANCE_ID;
|
||||||
vcl* rel_pages; // vector of pointer page numbers
|
vcl* rel_pages; // vector of pointer page numbers
|
||||||
RP_INSTANCE_ID rel_instance_id; // 0 or att_attachment_id or tra_number
|
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
|
// 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_index_root; // index root page number
|
||||||
SLONG rel_data_pages; // count of relation data pages
|
SLONG rel_data_pages; // count of relation data pages
|
||||||
@ -81,16 +83,13 @@ public:
|
|||||||
ULONG rel_sec_data_space; // lowest pointer page with secondary data page space
|
ULONG rel_sec_data_space; // lowest pointer page with secondary data page space
|
||||||
USHORT rel_pg_space_id;
|
USHORT rel_pg_space_id;
|
||||||
|
|
||||||
RelationPages()
|
explicit RelationPages()
|
||||||
{
|
: rel_pages(NULL), rel_instance_id(0),
|
||||||
rel_pages = 0;
|
rel_index_root(0), rel_data_pages(0), rel_slot_space(0),
|
||||||
rel_index_root = rel_data_pages = 0;
|
rel_pri_data_space(0), rel_sec_data_space(0),
|
||||||
rel_instance_id = 0;
|
rel_pg_space_id(DB_PAGE_SPACE), rel_next_free(NULL),
|
||||||
rel_slot_space = rel_pri_data_space = rel_sec_data_space = 0;
|
useCount(0)
|
||||||
rel_pg_space_id = DB_PAGE_SPACE;
|
{}
|
||||||
rel_next_free = 0;
|
|
||||||
useCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline SLONG addRef()
|
inline SLONG addRef()
|
||||||
{
|
{
|
||||||
@ -99,7 +98,7 @@ public:
|
|||||||
|
|
||||||
void free(RelationPages*& nextFree);
|
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;
|
return item->rel_instance_id;
|
||||||
}
|
}
|
||||||
@ -132,7 +131,6 @@ struct frgn
|
|||||||
vec<int>* frgn_indexes;
|
vec<int>* frgn_indexes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Relation block; one is created for each relation referenced
|
// Relation block; one is created for each relation referenced
|
||||||
// in the database, though it is not really filled out until
|
// in the database, though it is not really filled out until
|
||||||
// the relation is scanned
|
// the relation is scanned
|
||||||
@ -147,15 +145,17 @@ public:
|
|||||||
USHORT rel_current_fmt; // Current format number
|
USHORT rel_current_fmt; // Current format number
|
||||||
ULONG rel_flags;
|
ULONG rel_flags;
|
||||||
Format* rel_current_format; // Current record format
|
Format* rel_current_format; // Current record format
|
||||||
|
|
||||||
Firebird::MetaName rel_name; // ascii relation name
|
Firebird::MetaName rel_name; // ascii relation name
|
||||||
vec<Format*>* rel_formats; // Known record formats
|
|
||||||
Firebird::MetaName rel_owner_name; // ascii owner
|
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
|
vec<jrd_fld*>* rel_fields; // vector of field blocks
|
||||||
|
|
||||||
RseNode* rel_view_rse; // view record select expression
|
RseNode* rel_view_rse; // view record select expression
|
||||||
ViewContexts rel_view_contexts; // sorted array of view contexts
|
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
|
ExternalFile* rel_file; // external file name
|
||||||
|
|
||||||
GCRecordList rel_gc_records; // records for garbage collection
|
GCRecordList rel_gc_records; // records for garbage collection
|
||||||
@ -228,12 +228,13 @@ private:
|
|||||||
typedef Firebird::SortedArray<
|
typedef Firebird::SortedArray<
|
||||||
RelationPages*,
|
RelationPages*,
|
||||||
Firebird::EmptyStorage<RelationPages*>,
|
Firebird::EmptyStorage<RelationPages*>,
|
||||||
ULONG, // This type should be able to hold a TraNumber value
|
SINT64,
|
||||||
RelationPages>
|
RelationPages>
|
||||||
RelationPagesInstances;
|
RelationPagesInstances;
|
||||||
|
|
||||||
// Vlad asked for this compile-time check to make sure we can contain a txn number here
|
// 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;
|
RelationPagesInstances* rel_pages_inst;
|
||||||
RelationPages rel_pages_base;
|
RelationPages rel_pages_base;
|
||||||
@ -316,8 +317,9 @@ const ULONG REL_gc_lockneed = 0x80000; // gc lock should be acquired
|
|||||||
/// class jrd_rel
|
/// class jrd_rel
|
||||||
|
|
||||||
inline jrd_rel::jrd_rel(MemoryPool& p)
|
inline jrd_rel::jrd_rel(MemoryPool& p)
|
||||||
: rel_pool(&p), rel_flags(REL_gc_lockneed), rel_name(p), rel_owner_name(p),
|
: rel_pool(&p), rel_flags(REL_gc_lockneed),
|
||||||
rel_view_contexts(p), rel_security_name(p), rel_gc_records(p)
|
rel_name(p), rel_owner_name(p), rel_security_name(p),
|
||||||
|
rel_view_contexts(p), rel_gc_records(p)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,17 +105,19 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att,
|
|||||||
const RelCounters::const_iterator end = new_stat.rel_counts.end();
|
const RelCounters::const_iterator end = new_stat.rel_counts.end();
|
||||||
for (; new_cnts != end; ++new_cnts)
|
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
|
// Point TraceCounts to counts array from baseline object
|
||||||
if (base_cnts->setToDiff(*new_cnts))
|
if (base_cnts->setToDiff(*new_cnts))
|
||||||
{
|
{
|
||||||
jrd_rel* const relation =
|
jrd_rel* const relation =
|
||||||
new_cnts->getRelationId() < static_cast<SLONG>(att->att_relations->count()) ?
|
rel_id < static_cast<SLONG>(att->att_relations->count()) ?
|
||||||
(*att->att_relations)[new_cnts->getRelationId()] : NULL;
|
(*att->att_relations)[rel_id] : NULL;
|
||||||
|
|
||||||
TraceCounts traceCounts;
|
TraceCounts traceCounts;
|
||||||
traceCounts.trc_relation_id = new_cnts->getRelationId();
|
traceCounts.trc_relation_id = rel_id;
|
||||||
traceCounts.trc_counters = base_cnts->getCounterVector();
|
traceCounts.trc_counters = base_cnts->getCounterVector();
|
||||||
traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL;
|
traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL;
|
||||||
temp.add(traceCounts);
|
temp.add(traceCounts);
|
||||||
@ -127,12 +129,12 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
jrd_rel* const relation =
|
jrd_rel* const relation =
|
||||||
new_cnts->getRelationId() < static_cast<SLONG>(att->att_relations->count()) ?
|
rel_id < static_cast<SLONG>(att->att_relations->count()) ?
|
||||||
(*att->att_relations)[new_cnts->getRelationId()] : NULL;
|
(*att->att_relations)[rel_id] : NULL;
|
||||||
|
|
||||||
// Point TraceCounts to counts array from object with updated counters
|
// Point TraceCounts to counts array from object with updated counters
|
||||||
TraceCounts traceCounts;
|
TraceCounts traceCounts;
|
||||||
traceCounts.trc_relation_id = new_cnts->getRelationId();
|
traceCounts.trc_relation_id = rel_id;
|
||||||
traceCounts.trc_counters = new_cnts->getCounterVector();
|
traceCounts.trc_counters = new_cnts->getCounterVector();
|
||||||
traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL;
|
traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL;
|
||||||
temp.add(traceCounts);
|
temp.add(traceCounts);
|
||||||
|
@ -2164,7 +2164,7 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
|
|||||||
else if (nameStr == DATABASE_NAME)
|
else if (nameStr == DATABASE_NAME)
|
||||||
resultStr = dbb->dbb_database_name.ToString();
|
resultStr = dbb->dbb_database_name.ToString();
|
||||||
else if (nameStr == SESSION_ID_NAME)
|
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)
|
else if (nameStr == NETWORK_PROTOCOL_NAME)
|
||||||
{
|
{
|
||||||
if (attachment->att_network_protocol.isEmpty())
|
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)
|
if (!attachment->att_remote_pid)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
resultStr.printf("%d", attachment->att_remote_pid);
|
resultStr.printf("%"SLONGFORMAT, attachment->att_remote_pid);
|
||||||
}
|
}
|
||||||
else if (nameStr == CLIENT_PROCESS_NAME)
|
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;
|
resultStr = attachment->att_user->usr_sql_role_name;
|
||||||
}
|
}
|
||||||
else if (nameStr == TRANSACTION_ID_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)
|
else if (nameStr == ISOLATION_LEVEL_NAME)
|
||||||
{
|
{
|
||||||
if (transaction->tra_flags & TRA_read_committed)
|
if (transaction->tra_flags & TRA_read_committed)
|
||||||
@ -2219,7 +2219,7 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
|
|||||||
resultStr = SNAPSHOT_VALUE;
|
resultStr = SNAPSHOT_VALUE;
|
||||||
}
|
}
|
||||||
else if (nameStr == LOCK_TIMEOUT_NAME)
|
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)
|
else if (nameStr == READ_ONLY_NAME)
|
||||||
resultStr = (transaction->tra_flags & TRA_readonly) ? TRUE_VALUE : FALSE_VALUE;
|
resultStr = (transaction->tra_flags & TRA_readonly) ? TRUE_VALUE : FALSE_VALUE;
|
||||||
else
|
else
|
||||||
|
@ -90,10 +90,10 @@ void VirtualTable::erase(thread_db* tdbb, record_param* rpb)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SLONG id = MOV_get_long(&desc, 0);
|
const SINT64 id = MOV_get_int64(&desc, 0);
|
||||||
|
|
||||||
// Post a blocking request
|
// 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;
|
temp_lock.lck_key.lck_long = id;
|
||||||
|
|
||||||
ThreadStatusGuard temp_status(tdbb);
|
ThreadStatusGuard temp_status(tdbb);
|
||||||
|
132
src/jrd/btr.cpp
132
src/jrd/btr.cpp
@ -170,7 +170,7 @@ static void copy_key(const temporary_key*, temporary_key*);
|
|||||||
static contents delete_node(thread_db*, WIN*, UCHAR*);
|
static contents delete_node(thread_db*, WIN*, UCHAR*);
|
||||||
static void delete_tree(thread_db*, USHORT, USHORT, PageNumber, PageNumber);
|
static void delete_tree(thread_db*, USHORT, USHORT, PageNumber, PageNumber);
|
||||||
static DSC* eval(thread_db*, const ValueExprNode*, DSC*, bool*);
|
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 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*,
|
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,
|
void BTR_create(thread_db* tdbb,
|
||||||
jrd_rel* relation,
|
IndexCreation& creation,
|
||||||
index_desc* idx,
|
|
||||||
USHORT key_length,
|
|
||||||
AutoPtr<Sort>& scb,
|
|
||||||
SelectivityList& selectivity)
|
SelectivityList& selectivity)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
@ -396,22 +393,27 @@ void BTR_create(thread_db* tdbb,
|
|||||||
**************************************/
|
**************************************/
|
||||||
|
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
const Database* dbb = tdbb->getDatabase();
|
const Database* const dbb = tdbb->getDatabase();
|
||||||
CHECK_DBB(dbb);
|
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.
|
// 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
|
// Index is created. Go back to the index root page and update it to
|
||||||
// point to the index.
|
// 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);
|
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);
|
CCH_MARK(tdbb, &window);
|
||||||
root->irt_rpt[idx->idx_id].irt_root = idx->idx_root;
|
root->irt_rpt[idx->idx_id].irt_root = idx->idx_root;
|
||||||
root->irt_rpt[idx->idx_id].irt_flags &= ~irt_in_progress;
|
root->irt_rpt[idx->idx_id].irt_flags &= ~irt_in_progress;
|
||||||
update_selectivity(root, idx->idx_id, selectivity);
|
update_selectivity(root, idx->idx_id, selectivity);
|
||||||
|
|
||||||
|
LCK_release(tdbb, creation.lock);
|
||||||
|
|
||||||
CCH_RELEASE(tdbb, &window);
|
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);
|
SET_TDBB(tdbb);
|
||||||
WIN window(relPages->rel_pg_space_id, -1);
|
WIN window(relPages->rel_pg_space_id, -1);
|
||||||
|
|
||||||
index_root_page* root = fetch_root(tdbb, &window, relation, relPages);
|
index_root_page* const root = fetch_root(tdbb, &window, relation, relPages);
|
||||||
if (!root) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id >= root->irt_count || !BTR_description(tdbb, relation, root, buffer, id))
|
if (!root)
|
||||||
{
|
|
||||||
CCH_RELEASE(tdbb, &window);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
const bool result = (id < root->irt_count && BTR_description(tdbb, relation, root, buffer, id));
|
||||||
CCH_RELEASE(tdbb, &window);
|
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,
|
bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, index_desc* idx, WIN* window)
|
||||||
WIN* window)
|
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -1729,49 +1726,62 @@ bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, in
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RelationPages* relPages;
|
RelationPages* const relPages = transaction ?
|
||||||
if (transaction)
|
relation->getPages(tdbb, transaction->tra_number) : relation->getPages(tdbb);
|
||||||
relPages = relation->getPages(tdbb, transaction->tra_number);
|
|
||||||
else
|
|
||||||
relPages = relation->getPages(tdbb);
|
|
||||||
|
|
||||||
if (!(root = fetch_root(tdbb, window, relation, relPages)))
|
if (!(root = fetch_root(tdbb, window, relation, relPages)))
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (; id < root->irt_count; ++id)
|
for (; id < root->irt_count; ++id)
|
||||||
{
|
{
|
||||||
const index_root_page::irt_repeat* irt_desc = root->irt_rpt + id;
|
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)
|
if (!irt_desc->irt_root && (irt_desc->irt_flags & irt_in_progress) && transaction)
|
||||||
{
|
{
|
||||||
const TraNumber trans = irt_desc->irt_transaction;
|
Lock temp_lock(tdbb, sizeof(SLONG), LCK_idx_reserve);
|
||||||
CCH_RELEASE(tdbb, window);
|
temp_lock.lck_key.lck_long = (relation->rel_id << 16) | id;
|
||||||
const int trans_state = TRA_wait(tdbb, transaction, trans, jrd_tra::tra_wait);
|
|
||||||
if ((trans_state == tra_dead) || (trans_state == tra_committed))
|
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);
|
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;
|
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))
|
||||||
|
{
|
||||||
|
if (irt_desc->irt_transaction == tra_mask)
|
||||||
{
|
{
|
||||||
BTR_delete_index(tdbb, window, id);
|
BTR_delete_index(tdbb, window, id);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
CCH_RELEASE(tdbb, window);
|
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);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CCH_RELEASE(tdbb, window);
|
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);
|
SET_TDBB(tdbb);
|
||||||
const Database* dbb = tdbb->getDatabase();
|
const Database* const dbb = tdbb->getDatabase();
|
||||||
CHECK_DBB(dbb);
|
CHECK_DBB(dbb);
|
||||||
|
|
||||||
|
jrd_rel* const relation = creation.relation;
|
||||||
|
index_desc* const idx = creation.index;
|
||||||
|
jrd_tra* const transaction = creation.transaction;
|
||||||
|
|
||||||
fb_assert(relation);
|
fb_assert(relation);
|
||||||
RelationPages* relPages = relation->getPages(tdbb);
|
RelationPages* const relPages = relation->getPages(tdbb);
|
||||||
fb_assert(relPages && relPages->rel_index_root);
|
fb_assert(relPages && relPages->rel_index_root);
|
||||||
|
|
||||||
fb_assert(transaction);
|
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
|
// Index id for temporary index instance of global temporary table is
|
||||||
// already assigned, use it.
|
// already assigned, use it.
|
||||||
const bool use_idx_id = (relPages->rel_instance_id != 0);
|
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);
|
fb_assert(idx->idx_id <= dbb->dbb_max_idx);
|
||||||
}
|
|
||||||
|
|
||||||
WIN window(relPages->rel_pg_space_id, relPages->rel_index_root);
|
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* root = (index_root_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_root);
|
||||||
@ -1935,17 +1948,15 @@ void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction,
|
|||||||
end = root->irt_rpt + root->irt_count;
|
end = root->irt_rpt + root->irt_count;
|
||||||
for (index_root_page::irt_repeat* root_idx = root->irt_rpt; root_idx < end; root_idx++)
|
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);
|
space = MIN(space, root_idx->irt_desc);
|
||||||
}
|
|
||||||
if (!root_idx->irt_root && !slot && !(root_idx->irt_flags & irt_in_progress))
|
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)
|
if (!use_idx_id || (root_idx - root->irt_rpt) == idx->idx_id)
|
||||||
{
|
|
||||||
slot = root_idx;
|
slot = root_idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
space -= len;
|
space -= len;
|
||||||
desc = (UCHAR*)root + space;
|
desc = (UCHAR*)root + space;
|
||||||
@ -1980,14 +1991,21 @@ void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction,
|
|||||||
fb_assert(idx->idx_count <= MAX_UCHAR);
|
fb_assert(idx->idx_count <= MAX_UCHAR);
|
||||||
slot->irt_keys = (UCHAR) idx->idx_count;
|
slot->irt_keys = (UCHAR) idx->idx_count;
|
||||||
slot->irt_flags = idx->idx_flags | irt_in_progress;
|
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;
|
slot->irt_root = 0;
|
||||||
|
|
||||||
// Exploit the fact idx_repeat structure matches ODS IRTD one
|
// Exploit the fact idx_repeat structure matches ODS IRTD one
|
||||||
memcpy(desc, idx->idx_rpt, len);
|
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);
|
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,
|
static ULONG fast_load(thread_db* tdbb,
|
||||||
jrd_rel* relation,
|
IndexCreation& creation,
|
||||||
index_desc* idx,
|
|
||||||
USHORT key_length,
|
|
||||||
AutoPtr<Sort>& scb,
|
|
||||||
SelectivityList& selectivity)
|
SelectivityList& selectivity)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
@ -3291,9 +3306,14 @@ static ULONG fast_load(thread_db* tdbb,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
const Database* dbb = tdbb->getDatabase();
|
const Database* const dbb = tdbb->getDatabase();
|
||||||
CHECK_DBB(dbb);
|
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;
|
const USHORT pageSpaceID = relation->getPages(tdbb)->rel_pg_space_id;
|
||||||
// Variable initialization
|
// Variable initialization
|
||||||
for (int i = 0; i < MAX_LEVELS; i++)
|
for (int i = 0; i < MAX_LEVELS; i++)
|
||||||
@ -3974,7 +3994,7 @@ static ULONG fast_load(thread_db* tdbb,
|
|||||||
|
|
||||||
// do some final housekeeping
|
// do some final housekeeping
|
||||||
|
|
||||||
scb.reset();
|
creation.sort.reset();
|
||||||
|
|
||||||
// If index flush fails, try to delete the index tree.
|
// If index flush fails, try to delete the index tree.
|
||||||
// If the index delete fails, just go ahead and punt.
|
// If the index delete fails, just go ahead and punt.
|
||||||
|
@ -47,6 +47,7 @@ class JrdStatement;
|
|||||||
struct temporary_key;
|
struct temporary_key;
|
||||||
class jrd_tra;
|
class jrd_tra;
|
||||||
class BtrPageGCLock;
|
class BtrPageGCLock;
|
||||||
|
class Sort;
|
||||||
|
|
||||||
// Index descriptor block -- used to hold info from index root page
|
// 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);
|
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
|
// Class used to report any index related errors
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
USHORT BTR_all(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::IndexDescAlloc**, Jrd::RelationPages*);
|
USHORT BTR_all(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::IndexDescAlloc**, Jrd::RelationPages*);
|
||||||
void BTR_complement_key(Jrd::temporary_key*);
|
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_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);
|
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&);
|
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*);
|
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*);
|
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_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&);
|
void BTR_selectivity(Jrd::thread_db*, Jrd::jrd_rel*, USHORT, Jrd::SelectivityList&);
|
||||||
bool BTR_types_comparable(const dsc& target, const dsc& source);
|
bool BTR_types_comparable(const dsc& target, const dsc& source);
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
#include "../jrd/jrd_proto.h"
|
#include "../jrd/jrd_proto.h"
|
||||||
#include "../jrd/lck_proto.h"
|
#include "../jrd/lck_proto.h"
|
||||||
#include "../jrd/pag_proto.h"
|
#include "../jrd/pag_proto.h"
|
||||||
|
#include "../jrd/ods_proto.h"
|
||||||
#include "../jrd/os/pio_proto.h"
|
#include "../jrd/os/pio_proto.h"
|
||||||
#include "../jrd/sdw_proto.h"
|
#include "../jrd/sdw_proto.h"
|
||||||
#include "../jrd/shut_proto.h"
|
#include "../jrd/shut_proto.h"
|
||||||
@ -2412,8 +2413,8 @@ static Lock* alloc_page_lock(thread_db* tdbb, BufferDesc* bdb)
|
|||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
Database* dbb = tdbb->getDatabase();
|
Database* const dbb = tdbb->getDatabase();
|
||||||
BufferControl *bcb = bdb->bdb_bcb;
|
BufferControl* const bcb = bdb->bdb_bcb;
|
||||||
|
|
||||||
const USHORT lockLen = PageNumber::getLockLen();
|
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
|
// the next_transaction > oldest_active transaction
|
||||||
if (bdb->bdb_page == HEADER_PAGE_NUMBER)
|
if (bdb->bdb_page == HEADER_PAGE_NUMBER)
|
||||||
{
|
{
|
||||||
const header_page* header = (header_page*) page;
|
const header_page* const header = (header_page*) page;
|
||||||
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);
|
||||||
|
|
||||||
|
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
|
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
|
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
|
// We finished. Adjust transaction accounting and get ready for exit
|
||||||
if (bdb->bdb_page == HEADER_PAGE_NUMBER)
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -4916,7 +4922,7 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bdb->bdb_page == HEADER_PAGE_NUMBER)
|
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)
|
if (dbb->dbb_shadow && !isTempPage)
|
||||||
result = CCH_write_all_shadows(tdbb, 0, bdb, status, inAst);
|
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
|
// Destination difference page number is only valid between MARK and
|
||||||
// write_page so clean it now to avoid confusion
|
// write_page so clean it now to avoid confusion
|
||||||
bdb->bdb_difference_page = 0;
|
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))
|
if (!(bdb->bdb_bcb->bcb_flags & BCB_keep_pages))
|
||||||
removeDirty(bdb->bdb_bcb, bdb);
|
removeDirty(bdb->bdb_bcb, bdb);
|
||||||
|
@ -441,7 +441,13 @@ const int DDL_TRIGGER_DROP_MAPPING = 47;
|
|||||||
#define USERNAME_SWITCH "USER"
|
#define USERNAME_SWITCH "USER"
|
||||||
#define PASSWORD_SWITCH "PASSWORD"
|
#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"
|
#define CURRENT_ENGINE "Engine12"
|
||||||
|
|
||||||
|
265
src/jrd/dpm.epp
265
src/jrd/dpm.epp
@ -56,8 +56,10 @@
|
|||||||
#include "../jrd/dpm_proto.h"
|
#include "../jrd/dpm_proto.h"
|
||||||
#include "../jrd/err_proto.h"
|
#include "../jrd/err_proto.h"
|
||||||
#include "../jrd/exe_proto.h"
|
#include "../jrd/exe_proto.h"
|
||||||
|
#include "../jrd/lck_proto.h"
|
||||||
#include "../jrd/met_proto.h"
|
#include "../jrd/met_proto.h"
|
||||||
#include "../jrd/mov_proto.h"
|
#include "../jrd/mov_proto.h"
|
||||||
|
#include "../jrd/ods_proto.h"
|
||||||
#include "../jrd/pag_proto.h"
|
#include "../jrd/pag_proto.h"
|
||||||
#include "../common/StatusArg.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 mark_full(thread_db*, record_param*);
|
||||||
static void store_big_record(thread_db*, record_param*, PageStack&, const UCHAR*, ULONG, const Jrd::RecordStorageType type);
|
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)
|
PAG DPM_allocate(thread_db* tdbb, WIN* window)
|
||||||
{
|
{
|
||||||
@ -103,7 +149,7 @@ PAG DPM_allocate(thread_db* tdbb, WIN* window)
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
"DPM_allocate (window page %"SLONGFORMAT")\n",
|
"DPM_allocate (window page %"ULONGFORMAT")\n",
|
||||||
window ? window->win_page.getPageNum() : 0);
|
window ? window->win_page.getPageNum() : 0);
|
||||||
#endif
|
#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());
|
"DPM_backout (record_param %"QUADFORMAT"d)\n", rpb->rpb_number.getValue());
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %"
|
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %"
|
||||||
SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
|
ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
||||||
rpb->rpb_f_line, rpb->rpb_flags);
|
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);
|
rhd* header = (rhd*) ((SCHAR *) page + index1->dpg_offset);
|
||||||
header->rhd_flags &= ~(rhd_chain | rhd_gc_active);
|
header->rhd_flags &= ~(rhd_chain | rhd_gc_active);
|
||||||
|
|
||||||
|
release_gc_active(tdbb, rpb);
|
||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" old record %"SLONGFORMAT":%d, new record %"SLONGFORMAT
|
" old record %"ULONGFORMAT":%d, new record %"ULONGFORMAT
|
||||||
":%d, old dpg_count %d, ",
|
":%d, old dpg_count %d, ",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_b_page,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_b_page,
|
||||||
rpb->rpb_b_line, page->dpg_count);
|
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);
|
rhd* header = (rhd*) ((SCHAR*) page + index->dpg_offset);
|
||||||
|
|
||||||
header->rhd_flags |= rhd_gc_active;
|
header->rhd_flags |= rhd_gc_active;
|
||||||
header->rhd_transaction = transaction->tra_number;
|
|
||||||
|
|
||||||
rpb->rpb_flags |= rpb_gc_active;
|
rpb->rpb_flags |= rpb_gc_active;
|
||||||
rpb->rpb_transaction_nr = transaction->tra_number;
|
|
||||||
|
lock_gc_active(tdbb, transaction, rpb);
|
||||||
|
|
||||||
CCH_RELEASE(tdbb, window);
|
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);
|
new_rpb ? new_rpb->rpb_number.getValue() : 0);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" org record %"SLONGFORMAT":%d transaction %"ULONGFORMAT
|
" org record %"ULONGFORMAT":%d transaction %"ULONGFORMAT
|
||||||
" back %"SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
|
" 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_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_b_page, org_rpb->rpb_b_line, org_rpb->rpb_f_page,
|
||||||
org_rpb->rpb_f_line, org_rpb->rpb_flags);
|
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 Compressor dcc(*tdbb->getDefaultPool(), new_rpb->rpb_length, new_rpb->rpb_address);
|
||||||
const ULONG size = (ULONG) dcc.getPackedLength();
|
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))
|
if (!DPM_get(tdbb, org_rpb, LCK_write))
|
||||||
{
|
{
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
@ -343,7 +392,6 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((org_rpb->rpb_flags & rpb_delta) && temp.rpb_prior)
|
if ((org_rpb->rpb_flags & rpb_delta) && temp.rpb_prior)
|
||||||
org_rpb->rpb_prior = temp.rpb_prior;
|
org_rpb->rpb_prior = temp.rpb_prior;
|
||||||
else if (org_rpb->rpb_flags & rpb_delta)
|
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 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));
|
CCH_RELEASE(tdbb, &org_rpb->getWindow(tdbb));
|
||||||
#ifdef VIO_DEBUG
|
#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
|
// The record must be long enough to permit fragmentation later. If it's
|
||||||
// too small, compute the number of pad bytes required
|
// 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))
|
if (fill < 0 || (new_rpb->rpb_flags & rpb_deleted))
|
||||||
fill = 0;
|
fill = 0;
|
||||||
|
|
||||||
// Accomodate max record size i.e. 64K
|
// 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
|
// 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;
|
page->dpg_rpt[slot] = *index2;
|
||||||
|
|
||||||
index2->dpg_offset = space;
|
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*) ((SCHAR *) page + space);
|
||||||
header->rhd_flags = new_rpb->rpb_flags;
|
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_format = new_rpb->rpb_format_number;
|
||||||
header->rhd_b_page = new_rpb->rpb_b_page;
|
header->rhd_b_page = new_rpb->rpb_b_page;
|
||||||
header->rhd_b_line = new_rpb->rpb_b_line;
|
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)
|
if (fill)
|
||||||
memset(header->rhd_data + size, 0, fill);
|
memset(data + size, 0, fill);
|
||||||
|
|
||||||
if (page->dpg_header.pag_flags & dpg_swept)
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE_ALL,
|
VIO_trace(DEBUG_TRACE_ALL,
|
||||||
" returned pages: %"SLONGFORMAT"\n", pages);
|
" returned pages: %"ULONGFORMAT"\n", pages);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return pages;
|
return pages;
|
||||||
@ -638,12 +688,12 @@ void DPM_delete( thread_db* tdbb, record_param* rpb, ULONG prior_page)
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES,
|
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);
|
rpb->rpb_number.getValue(), prior_page);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %"
|
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %"
|
||||||
SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
|
ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
||||||
rpb->rpb_f_line, rpb->rpb_flags);
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
"\tDPM_delete: page %"SLONGFORMAT
|
"\tDPM_delete: page %"ULONGFORMAT
|
||||||
" is empty and about to be released from relation %d\n",
|
" is empty and about to be released from relation %d\n",
|
||||||
window->win_page.getPageNum(), rpb->rpb_relation->rel_id);
|
window->win_page.getPageNum(), rpb->rpb_relation->rel_id);
|
||||||
#endif
|
#endif
|
||||||
@ -1062,7 +1112,7 @@ bool DPM_fetch(thread_db* tdbb, record_param* rpb, USHORT lock)
|
|||||||
rpb->rpb_number.getValue(), lock);
|
rpb->rpb_number.getValue(), lock);
|
||||||
|
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
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
|
#endif
|
||||||
|
|
||||||
const RecordNumber number = rpb->rpb_number;
|
const RecordNumber number = rpb->rpb_number;
|
||||||
@ -1078,8 +1128,8 @@ bool DPM_fetch(thread_db* tdbb, record_param* rpb, USHORT lock)
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
VIO_trace(DEBUG_READS_INFO,
|
||||||
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %"
|
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %"
|
||||||
SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
|
ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
||||||
rpb->rpb_f_line, rpb->rpb_flags);
|
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);
|
rpb->rpb_number.getValue(), lock);
|
||||||
|
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
VIO_trace(DEBUG_READS_INFO,
|
||||||
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT
|
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT
|
||||||
" back %"SLONGFORMAT":%d\n",
|
" back %"ULONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line);
|
rpb->rpb_b_page, rpb->rpb_b_line);
|
||||||
#endif
|
#endif
|
||||||
@ -1153,8 +1203,8 @@ bool DPM_fetch_back(thread_db* tdbb, record_param* rpb, USHORT lock, SSHORT latc
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
VIO_trace(DEBUG_READS_INFO,
|
||||||
" record fetched %"SLONGFORMAT":%d transaction %"
|
" record fetched %"ULONGFORMAT":%d transaction %"
|
||||||
ULONGFORMAT" back %"SLONGFORMAT":%d fragment %"SLONGFORMAT
|
ULONGFORMAT" back %"ULONGFORMAT":%d fragment %"ULONGFORMAT
|
||||||
":%d flags %d\n",
|
":%d flags %d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
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);
|
rpb->rpb_number.getValue(), lock);
|
||||||
|
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
VIO_trace(DEBUG_READS_INFO,
|
||||||
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT
|
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT
|
||||||
" back %"SLONGFORMAT":%d\n",
|
" back %"ULONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line);
|
rpb->rpb_b_page, rpb->rpb_b_line);
|
||||||
#endif
|
#endif
|
||||||
@ -1207,8 +1257,8 @@ void DPM_fetch_fragment( thread_db* tdbb, record_param* rpb, USHORT lock)
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
VIO_trace(DEBUG_READS_INFO,
|
||||||
" record fetched %"SLONGFORMAT":%d transaction %"ULONGFORMAT
|
" record fetched %"ULONGFORMAT":%d transaction %"ULONGFORMAT
|
||||||
" back %"SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
|
" back %"ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
||||||
rpb->rpb_f_line, rpb->rpb_flags);
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
VIO_trace(DEBUG_READS_INFO,
|
||||||
" record %"SLONGFORMAT":%d\n", page->ppg_page[slot], line);
|
" record %"ULONGFORMAT":%d\n", page->ppg_page[slot], line);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const ULONG page_number = page->ppg_page[slot];
|
const ULONG page_number = page->ppg_page[slot];
|
||||||
@ -1420,7 +1470,7 @@ ULONG DPM_get_blob(thread_db* tdbb,
|
|||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS,
|
VIO_trace(DEBUG_READS,
|
||||||
"DPM_get_blob (blob, record_number %"QUADFORMAT
|
"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);
|
record_number.getValue(), (int) delete_flag, prior_page);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1724,7 +1774,7 @@ void DPM_pages(thread_db* tdbb, SSHORT rel_id, int type, ULONG sequence, ULONG p
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE_ALL,
|
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);
|
rel_id, type, sequence, page);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1909,8 +1959,8 @@ void DPM_store( thread_db* tdbb, record_param* rpb, PageStack& stack, const Jrd:
|
|||||||
rpb->rpb_number.getValue(), type);
|
rpb->rpb_number.getValue(), type);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" record to store %"SLONGFORMAT":%d transaction %"ULONGFORMAT
|
" record to store %"ULONGFORMAT":%d transaction %"ULONGFORMAT
|
||||||
" back %"SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
|
" back %"ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
||||||
rpb->rpb_f_line, rpb->rpb_flags);
|
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 Compressor dcc(*tdbb->getDefaultPool(), rpb->rpb_length, rpb->rpb_address);
|
||||||
const ULONG size = (ULONG) dcc.getPackedLength();
|
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,
|
// If the record isn't going to fit on a page, even if fragmented,
|
||||||
// handle it a little differently.
|
// 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);
|
store_big_record(tdbb, rpb, stack, dcc.getControl() + dcc.getControlSize(), size, type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLONG fill = (RHDF_SIZE - RHD_SIZE) - size;
|
SLONG fill = (RHDF_SIZE - header_size) - size;
|
||||||
if (fill < 0)
|
if (fill < 0)
|
||||||
fill = 0;
|
fill = 0;
|
||||||
|
|
||||||
// Accomodate max record size i.e. 64K
|
// 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);
|
rhd* header = locate_space(tdbb, rpb, (SSHORT) length, stack, NULL, type);
|
||||||
|
|
||||||
header->rhd_flags = rpb->rpb_flags;
|
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_format = rpb->rpb_format_number;
|
||||||
header->rhd_b_page = rpb->rpb_b_page;
|
header->rhd_b_page = rpb->rpb_b_page;
|
||||||
header->rhd_b_line = rpb->rpb_b_line;
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" record %"SLONGFORMAT":%d, length %"SLONGFORMAT
|
" record %"ULONGFORMAT":%d, length %"SLONGFORMAT
|
||||||
", rpb_flags %d, f_page %"SLONGFORMAT":%d, b_page %"SLONGFORMAT
|
", rpb_flags %d, f_page %"ULONGFORMAT":%d, b_page %"ULONGFORMAT
|
||||||
":%d\n",
|
":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, length, rpb->rpb_flags,
|
rpb->rpb_page, rpb->rpb_line, length, rpb->rpb_flags,
|
||||||
rpb->rpb_f_page, rpb->rpb_f_line, rpb->rpb_b_page,
|
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
|
#endif
|
||||||
|
|
||||||
if (fill)
|
if (fill)
|
||||||
memset(header->rhd_data + size, 0, fill);
|
memset(data + size, 0, fill);
|
||||||
|
|
||||||
Ods::pag* page = rpb->getWindow(tdbb).win_buffer;
|
Ods::pag* page = rpb->getWindow(tdbb).win_buffer;
|
||||||
if (page->pag_flags & dpg_swept)
|
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());
|
"DPM_rewrite_header (record_param %"QUADFORMAT"d)\n", rpb->rpb_number.getValue());
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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
|
#endif
|
||||||
|
|
||||||
WIN* window = &rpb->getWindow(tdbb);
|
WIN* window = &rpb->getWindow(tdbb);
|
||||||
@ -2066,20 +2120,23 @@ void DPM_rewrite_header( thread_db* tdbb, record_param* rpb)
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" old flags %d, old transaction %"ULONGFORMAT
|
" old flags %d, old transaction %"SQUADFORMAT
|
||||||
", old format %d, old back record %"SLONGFORMAT":%d\n",
|
", old format %d, old back record %"ULONGFORMAT":%d\n",
|
||||||
header->rhd_flags, header->rhd_transaction, (int) header->rhd_format,
|
header->rhd_flags, Ods::getTraNum(header), (int) header->rhd_format,
|
||||||
header->rhd_b_page, header->rhd_b_line);
|
header->rhd_b_page, header->rhd_b_line);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" new flags %d, new transaction %"ULONGFORMAT
|
" new flags %d, new transaction %"SQUADFORMAT
|
||||||
", new format %d, new back record %"SLONGFORMAT":%d\n",
|
", new format %d, new back record %"ULONGFORMAT":%d\n",
|
||||||
rpb->rpb_flags, rpb->rpb_transaction_nr, rpb->rpb_format_number,
|
rpb->rpb_flags, rpb->rpb_transaction_nr, rpb->rpb_format_number,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line);
|
rpb->rpb_b_page, rpb->rpb_b_line);
|
||||||
#endif
|
#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_flags = rpb->rpb_flags;
|
||||||
header->rhd_transaction = rpb->rpb_transaction_nr;
|
|
||||||
header->rhd_format = rpb->rpb_format_number;
|
header->rhd_format = rpb->rpb_format_number;
|
||||||
header->rhd_b_page = rpb->rpb_b_page;
|
header->rhd_b_page = rpb->rpb_b_page;
|
||||||
header->rhd_b_line = rpb->rpb_b_line;
|
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);
|
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %"
|
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %"
|
||||||
SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
|
ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
||||||
rpb->rpb_f_line, rpb->rpb_flags);
|
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 Compressor dcc(*tdbb->getDefaultPool(), rpb->rpb_length, rpb->rpb_address);
|
||||||
const ULONG size = (ULONG) dcc.getPackedLength();
|
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
|
// It is critical that the record be padded, if necessary, to the length of
|
||||||
// a fragmented record header. Compute the amount of fill required.
|
// 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)
|
if (fill < 0)
|
||||||
fill = 0;
|
fill = 0;
|
||||||
|
|
||||||
// Accomodate max record size i.e. 64K
|
// 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;
|
const USHORT slot = rpb->rpb_line;
|
||||||
|
|
||||||
// Find space on page
|
// 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);
|
fb_assert(space >= top);
|
||||||
|
|
||||||
page->dpg_rpt[slot].dpg_offset = space;
|
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);
|
rhd* header = (rhd*) ((SCHAR *) page + space);
|
||||||
header->rhd_flags = rpb->rpb_flags;
|
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_format = rpb->rpb_format_number;
|
||||||
header->rhd_b_page = rpb->rpb_b_page;
|
header->rhd_b_page = rpb->rpb_b_page;
|
||||||
header->rhd_b_line = rpb->rpb_b_line;
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" record %"SLONGFORMAT
|
" record %"ULONGFORMAT
|
||||||
":%d, dpg_length %d, rpb_flags %d, rpb_f record %"SLONGFORMAT
|
":%d, dpg_length %d, rpb_flags %d, rpb_f record %"ULONGFORMAT
|
||||||
":%d, rpb_b record %"SLONGFORMAT":%d\n",
|
":%d, rpb_b record %"ULONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, page->dpg_rpt[slot].dpg_length,
|
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_flags, rpb->rpb_f_page, rpb->rpb_f_line,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line);
|
rpb->rpb_b_page, rpb->rpb_b_line);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fill)
|
if (fill)
|
||||||
memset(header->rhd_data + size, 0, fill);
|
memset(data + size, 0, fill);
|
||||||
|
|
||||||
if (page->dpg_header.pag_flags & dpg_swept)
|
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)
|
if (index->dpg_offset)
|
||||||
{
|
{
|
||||||
rhd* header = (rhd*) ((SCHAR*) dpage + 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_flags & (rpb_blob | rpb_chained | rpb_fragment) ||
|
||||||
header->rhd_b_page)
|
header->rhd_b_page)
|
||||||
{
|
{
|
||||||
@ -2290,7 +2353,7 @@ static USHORT compress(thread_db* tdbb, data_page* page)
|
|||||||
"compress (page)\n");
|
"compress (page)\n");
|
||||||
|
|
||||||
VIO_trace(DEBUG_TRACE_ALL_INFO,
|
VIO_trace(DEBUG_TRACE_ALL_INFO,
|
||||||
" sequence %"SLONGFORMAT"\n", page->dpg_sequence);
|
" sequence %"ULONGFORMAT"\n", page->dpg_sequence);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UCHAR temp_page[MAX_PAGE_SIZE];
|
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");
|
"delete_tail (header, length)\n");
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" transaction %"ULONGFORMAT" flags %d fragment %"
|
" transaction %"SQUADFORMAT" flags %d fragment %"
|
||||||
SLONGFORMAT":%d back %"SLONGFORMAT":%d\n",
|
ULONGFORMAT":%d back %"ULONGFORMAT":%d\n",
|
||||||
header->rhdf_transaction, header->rhdf_flags,
|
Ods::getTraNum(header), header->rhdf_flags,
|
||||||
header->rhdf_f_page, header->rhdf_f_line,
|
header->rhdf_f_page, header->rhdf_f_line,
|
||||||
header->rhdf_b_page, header->rhdf_b_line);
|
header->rhdf_b_page, header->rhdf_b_line);
|
||||||
#endif
|
#endif
|
||||||
@ -2477,8 +2540,8 @@ static void fragment(thread_db* tdbb,
|
|||||||
transaction ? transaction->tra_number : 0);
|
transaction ? transaction->tra_number : 0);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %"
|
" record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %"
|
||||||
SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n",
|
ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page,
|
||||||
rpb->rpb_f_line, rpb->rpb_flags);
|
rpb->rpb_f_line, rpb->rpb_flags);
|
||||||
@ -2497,11 +2560,9 @@ static void fragment(thread_db* tdbb,
|
|||||||
const USHORT line = rpb->rpb_line;
|
const USHORT line = rpb->rpb_line;
|
||||||
|
|
||||||
rhdf* header;
|
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*) ((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;
|
page->dpg_rpt[line].dpg_length = available_space = length;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2521,17 +2582,20 @@ static void fragment(thread_db* tdbb,
|
|||||||
page->dpg_rpt[line].dpg_offset = space;
|
page->dpg_rpt[line].dpg_offset = space;
|
||||||
page->dpg_rpt[line].dpg_length = available_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_page = rpb->rpb_b_page;
|
||||||
header->rhdf_b_line = rpb->rpb_b_line;
|
header->rhdf_b_line = rpb->rpb_b_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header->rhdf_flags |= rhd_gc_active;
|
||||||
|
lock_gc_active(tdbb, transaction, rpb);
|
||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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 %"
|
":%d, available_space %d, rhdf_flags %d, rhdf_f record %"
|
||||||
SLONGFORMAT":%d, rhdf_b record %"SLONGFORMAT":%d\n",
|
ULONGFORMAT":%d, rhdf_b record %"ULONGFORMAT":%d\n",
|
||||||
header->rhdf_transaction, window->win_page.getPageNum(), line,
|
Ods::getTraNum(header), window->win_page.getPageNum(), line,
|
||||||
available_space, header->rhdf_flags, header->rhdf_f_page,
|
available_space, header->rhdf_flags, header->rhdf_f_page,
|
||||||
header->rhdf_f_line, header->rhdf_b_page, header->rhdf_b_line);
|
header->rhdf_f_line, header->rhdf_b_page, header->rhdf_b_line);
|
||||||
#endif
|
#endif
|
||||||
@ -2572,17 +2636,19 @@ static void fragment(thread_db* tdbb,
|
|||||||
|
|
||||||
header = (rhdf*) ((SCHAR *) page + page->dpg_rpt[line].dpg_offset);
|
header = (rhdf*) ((SCHAR *) page + page->dpg_rpt[line].dpg_offset);
|
||||||
header->rhdf_flags = rhd_incomplete | rpb->rpb_flags;
|
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_format = rpb->rpb_format_number;
|
||||||
header->rhdf_f_page = tail_rpb.rpb_page;
|
header->rhdf_f_page = tail_rpb.rpb_page;
|
||||||
header->rhdf_f_line = tail_rpb.rpb_line;
|
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_page = rpb->rpb_b_page;
|
||||||
header->rhdf_b_line = rpb->rpb_b_line;
|
header->rhdf_b_line = rpb->rpb_b_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
release_gc_active(tdbb, rpb);
|
||||||
|
|
||||||
const size_t post_header_length =
|
const size_t post_header_length =
|
||||||
dcc.pack(rpb->rpb_address, available_space - RHDF_SIZE, header->rhdf_data);
|
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");
|
" fragment head \n");
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" rhdf_trans %"ULONGFORMAT", window record %"SLONGFORMAT
|
" rhdf_trans %"SQUADFORMAT", window record %"ULONGFORMAT
|
||||||
":%d, dpg_length %d\n\trhdf_flags %d, rhdf_f record %"SLONGFORMAT
|
":%d, dpg_length %d\n\trhdf_flags %d, rhdf_f record %"ULONGFORMAT
|
||||||
":%d, rhdf_b record %"SLONGFORMAT":%d\n",
|
":%d, rhdf_b record %"ULONGFORMAT":%d\n",
|
||||||
header->rhdf_transaction, window->win_page.getPageNum(), line,
|
Ods::getTraNum(header), window->win_page.getPageNum(), line,
|
||||||
page->dpg_rpt[line].dpg_length, header->rhdf_flags,
|
page->dpg_rpt[line].dpg_length, header->rhdf_flags,
|
||||||
header->rhdf_f_page, header->rhdf_f_line, header->rhdf_b_page,
|
header->rhdf_f_page, header->rhdf_f_line, header->rhdf_b_page,
|
||||||
header->rhdf_b_line);
|
header->rhdf_b_line);
|
||||||
@ -2793,7 +2859,7 @@ static void extend_relation(thread_db* tdbb, jrd_rel* relation, WIN* window, con
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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());
|
relation->rel_id, window->win_page.getPageNum());
|
||||||
#endif
|
#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_page = header->rhdf_b_page;
|
||||||
rpb->rpb_b_line = header->rhdf_b_line;
|
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;
|
rpb->rpb_format_number = header->rhdf_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FB_SIZE_T header_size;
|
||||||
|
|
||||||
if (rpb->rpb_flags & rpb_incomplete)
|
if (rpb->rpb_flags & rpb_incomplete)
|
||||||
{
|
{
|
||||||
rpb->rpb_f_page = header->rhdf_f_page;
|
rpb->rpb_f_page = header->rhdf_f_page;
|
||||||
rpb->rpb_f_line = header->rhdf_f_line;
|
rpb->rpb_f_line = header->rhdf_f_line;
|
||||||
rpb->rpb_address = header->rhdf_data;
|
header_size = RHDF_SIZE;
|
||||||
rpb->rpb_length = index->dpg_length - RHDF_SIZE;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rpb->rpb_address = ((rhd*) header)->rhd_data;
|
header_size = (rpb->rpb_flags & rpb_long_tranum) ? RHDE_SIZE : RHD_SIZE;
|
||||||
rpb->rpb_length = index->dpg_length - RHD_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpb->rpb_address = (UCHAR*) header + header_size;
|
||||||
|
rpb->rpb_length = index->dpg_length - header_size;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3221,7 +3290,7 @@ static rhd* locate_space(thread_db* tdbb,
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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);
|
relation->rel_id, window->win_page.getPageNum(), size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -3483,8 +3552,8 @@ static void store_big_record(thread_db* tdbb,
|
|||||||
" back portion\n");
|
" back portion\n");
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" getWindow(tdbb) page %"SLONGFORMAT
|
" getWindow(tdbb) page %"ULONGFORMAT
|
||||||
", max_data %d, \n\trhdf_flags %d, prior %"SLONGFORMAT"\n",
|
", max_data %d, \n\trhdf_flags %d, prior %"ULONGFORMAT"\n",
|
||||||
rpb->getWindow(tdbb).win_page.getPageNum(), max_data, header->rhdf_flags,
|
rpb->getWindow(tdbb).win_page.getPageNum(), max_data, header->rhdf_flags,
|
||||||
prior.getPageNum());
|
prior.getPageNum());
|
||||||
#endif
|
#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);
|
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_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_format = rpb->rpb_format_number;
|
||||||
header->rhdf_b_page = rpb->rpb_b_page;
|
header->rhdf_b_page = rpb->rpb_b_page;
|
||||||
header->rhdf_b_line = rpb->rpb_b_line;
|
header->rhdf_b_line = rpb->rpb_b_line;
|
||||||
@ -3515,10 +3584,10 @@ static void store_big_record(thread_db* tdbb,
|
|||||||
" front part\n");
|
" front part\n");
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
VIO_trace(DEBUG_WRITES_INFO,
|
||||||
" rhdf_trans %"ULONGFORMAT", rpb_window record %"SLONGFORMAT
|
" rhdf_trans %"SQUADFORMAT", rpb_window record %"ULONGFORMAT
|
||||||
":%d, dpg_length %d \n\trhdf_flags %d, rhdf_f record %"SLONGFORMAT
|
":%d, dpg_length %d \n\trhdf_flags %d, rhdf_f record %"ULONGFORMAT
|
||||||
":%d, rhdf_b record %"SLONGFORMAT":%d\n",
|
":%d, rhdf_b record %"ULONGFORMAT":%d\n",
|
||||||
header->rhdf_transaction, rpb->getWindow(tdbb).win_page.getPageNum(),
|
Ods::getTraNum(header), rpb->getWindow(tdbb).win_page.getPageNum(),
|
||||||
rpb->rpb_line, page->dpg_rpt[rpb->rpb_line].dpg_length,
|
rpb->rpb_line, page->dpg_rpt[rpb->rpb_line].dpg_length,
|
||||||
header->rhdf_flags, header->rhdf_f_page, header->rhdf_f_line,
|
header->rhdf_flags, header->rhdf_f_page, header->rhdf_f_line,
|
||||||
header->rhdf_b_page, header->rhdf_b_line);
|
header->rhdf_b_page, header->rhdf_b_line);
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
FIELD(fld_mechanism , nam_mechanism , dtype_short , sizeof(SSHORT) , 0 , NULL , true)
|
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_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_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_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_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)
|
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_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_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_att_id , nam_att_id , dtype_int64 , sizeof(SINT64) , 0 , NULL , true)
|
||||||
FIELD(fld_stmt_id , nam_stmt_id , dtype_long , sizeof(SLONG) , 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_long , sizeof(SLONG) , 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_stat_id , nam_stat_id , dtype_long , sizeof(SLONG) , 0 , NULL , true)
|
||||||
|
|
||||||
FIELD(fld_pid , nam_pid , dtype_long , sizeof(SLONG) , 0 , NULL , true)
|
FIELD(fld_pid , nam_pid , dtype_long , sizeof(SLONG) , 0 , NULL , true)
|
||||||
|
@ -1110,11 +1110,8 @@ ISC_STATUS filter_trans(USHORT action, BlobControl* control)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TDR_TRANSACTION_ID:
|
case TDR_TRANSACTION_ID:
|
||||||
{
|
sprintf(out, " Transaction id: %"SQUADFORMAT, isc_portable_integer(p, length));
|
||||||
const SLONG id = gds__vax_integer(p, length);
|
|
||||||
sprintf(out, " Transaction id: %"SLONGFORMAT, id);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
sprintf(out, "item %d not understood", (int) p[-1]);
|
sprintf(out, "item %d not understood", (int) p[-1]);
|
||||||
|
@ -105,6 +105,18 @@ static inline USHORT getNullSegment(const temporary_key& key)
|
|||||||
return MAX_USHORT;
|
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)
|
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 window(relPages->rel_pg_space_id, -1);
|
||||||
WIN referenced_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)
|
if (idx.idx_flags & idx_foreign)
|
||||||
{
|
{
|
||||||
// find the corresponding primary key index
|
// find the corresponding primary key index
|
||||||
|
|
||||||
if (!MET_lookup_partner(tdbb, relation, &idx, 0)) {
|
if (!MET_lookup_partner(tdbb, relation, &idx, 0))
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
jrd_rel* referenced_relation = MET_relation(tdbb, idx.idx_primary_relation);
|
jrd_rel* referenced_relation = MET_relation(tdbb, idx.idx_primary_relation);
|
||||||
MET_scan_relation(tdbb, referenced_relation);
|
MET_scan_relation(tdbb, referenced_relation);
|
||||||
const USHORT index_id = idx.idx_primary_index;
|
const USHORT index_id = idx.idx_primary_index;
|
||||||
@ -264,11 +276,6 @@ void IDX_create_index(thread_db* tdbb,
|
|||||||
|
|
||||||
fb_assert(transaction);
|
fb_assert(transaction);
|
||||||
|
|
||||||
BTR_reserve_slot(tdbb, relation, transaction, idx);
|
|
||||||
|
|
||||||
if (index_id)
|
|
||||||
*index_id = idx->idx_id;
|
|
||||||
|
|
||||||
record_param primary, secondary;
|
record_param primary, secondary;
|
||||||
secondary.rpb_relation = relation;
|
secondary.rpb_relation = relation;
|
||||||
primary.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));
|
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;
|
RecordStack stack;
|
||||||
const UCHAR pad = isDescending ? -1 : 0;
|
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;
|
FPTR_REJECT_DUP_CALLBACK callback = (idx->idx_flags & idx_unique) ? duplicate_key : NULL;
|
||||||
void* callback_arg = (idx->idx_flags & idx_unique) ? &ifl_data : 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),
|
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;
|
jrd_rel* partner_relation = NULL;
|
||||||
USHORT partner_index_id = 0;
|
USHORT partner_index_id = 0;
|
||||||
@ -520,7 +539,7 @@ void IDX_create_index(thread_db* tdbb,
|
|||||||
context.raise(tdbb, idx_e_duplicate, error_record);
|
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))
|
if ((relation->rel_flags & REL_temp_conn) && (relation->getPages(tdbb)->rel_instance_id != 0))
|
||||||
{
|
{
|
||||||
@ -528,12 +547,11 @@ void IDX_create_index(thread_db* tdbb,
|
|||||||
if (idx_lock)
|
if (idx_lock)
|
||||||
{
|
{
|
||||||
++idx_lock->idl_count;
|
++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);
|
LCK_lock(tdbb, idx_lock->idl_lock, LCK_SR, LCK_WAIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
IndexBlock* IDX_create_index_block(thread_db* tdbb, jrd_rel* relation, USHORT id)
|
IndexBlock* IDX_create_index_block(thread_db* tdbb, jrd_rel* relation, USHORT id)
|
||||||
|
@ -993,7 +993,7 @@ public:
|
|||||||
const char* getRemoteProcessName() { return m_options->dpb_remote_process.c_str(); }
|
const char* getRemoteProcessName() { return m_options->dpb_remote_process.c_str(); }
|
||||||
|
|
||||||
// TraceDatabaseConnection implementation
|
// TraceDatabaseConnection implementation
|
||||||
int getConnectionID() { return 0; }
|
ISC_INT64 getConnectionID() { return 0; }
|
||||||
const char* getDatabaseName() { return m_filename; }
|
const char* getDatabaseName() { return m_filename; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -6267,7 +6267,7 @@ static void init_database_lock(thread_db* tdbb)
|
|||||||
|
|
||||||
// Main database lock
|
// 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);
|
Lock(tdbb, 0, LCK_database, dbb, CCH_down_grade_dbb);
|
||||||
dbb->dbb_lock = lock;
|
dbb->dbb_lock = lock;
|
||||||
|
|
||||||
@ -6430,7 +6430,6 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tdbb->setAttachment(NULL);
|
tdbb->setAttachment(NULL);
|
||||||
Jrd::Attachment::destroy(attachment); // string were re-saved in the beginning of this function,
|
Jrd::Attachment::destroy(attachment); // string were re-saved in the beginning of this function,
|
||||||
// keep that in sync please
|
// keep that in sync please
|
||||||
|
@ -140,7 +140,6 @@ static const bool compatibility[LCK_max][LCK_max] =
|
|||||||
//#define COMPATIBLE(st1, st2) compatibility [st1 * LCK_max + st2]
|
//#define COMPATIBLE(st1, st2) compatibility [st1 * LCK_max + st2]
|
||||||
const int LOCK_HASH_SIZE = 19;
|
const int LOCK_HASH_SIZE = 19;
|
||||||
|
|
||||||
|
|
||||||
inline void ENQUEUE(thread_db* tdbb, CheckStatusWrapper* statusVector, Lock* lock, USHORT level, SSHORT wait)
|
inline void ENQUEUE(thread_db* tdbb, CheckStatusWrapper* statusVector, Lock* lock, USHORT level, SSHORT wait)
|
||||||
{
|
{
|
||||||
if (lock->lck_compatible)
|
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_cancel:
|
||||||
case LCK_monitor:
|
case LCK_monitor:
|
||||||
case LCK_btr_dont_gc:
|
case LCK_btr_dont_gc:
|
||||||
|
case LCK_idx_reserve:
|
||||||
case LCK_rel_gc:
|
case LCK_rel_gc:
|
||||||
|
case LCK_record_gc:
|
||||||
handle = *LCK_OWNER_HANDLE_ATT(tdbb);
|
handle = *LCK_OWNER_HANDLE_ATT(tdbb);
|
||||||
break;
|
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));
|
fb_assert(LCK_CHECK_LOCK(lock));
|
||||||
|
|
||||||
const SLONG data =
|
const SINT64 data =
|
||||||
dbb->dbb_lock_mgr->readData2(lock->lck_type,
|
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);
|
lock->lck_owner_handle);
|
||||||
fb_assert(LCK_CHECK_LOCK(lock));
|
fb_assert(LCK_CHECK_LOCK(lock));
|
||||||
return data;
|
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));
|
fb_assert(LCK_CHECK_LOCK(lock));
|
||||||
|
|
||||||
lock->lck_id = dbb->dbb_lock_mgr->enqueue(att, statusVector, lock->lck_id,
|
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,
|
level, lock->lck_ast, lock->lck_object, lock->lck_data, wait,
|
||||||
lock->lck_owner_handle);
|
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)
|
Lock::Lock(thread_db* tdbb, USHORT length, lck_t type, void* object, lock_ast_t ast)
|
||||||
: lck_dbb(tdbb->getDatabase()),
|
: lck_dbb(tdbb->getDatabase()),
|
||||||
lck_attachment(0),
|
lck_attachment(NULL),
|
||||||
lck_compatible(0),
|
lck_compatible(NULL),
|
||||||
lck_compatible2(0),
|
lck_compatible2(NULL),
|
||||||
lck_ast(ast),
|
lck_ast(ast),
|
||||||
lck_object(object),
|
lck_object(object),
|
||||||
lck_next(0),
|
lck_next(NULL),
|
||||||
lck_prior(0),
|
lck_prior(NULL),
|
||||||
lck_collision(0),
|
lck_collision(NULL),
|
||||||
lck_identical(0),
|
lck_identical(NULL),
|
||||||
lck_id(0),
|
lck_id(0),
|
||||||
lck_owner_handle(get_owner_handle(tdbb, type)),
|
lck_owner_handle(get_owner_handle(tdbb, type)),
|
||||||
lck_length(length),
|
lck_length(length),
|
||||||
lck_type(type),
|
lck_type(type),
|
||||||
lck_logical(0),
|
lck_logical(LCK_none),
|
||||||
lck_physical(0),
|
lck_physical(LCK_none),
|
||||||
lck_data(0)
|
lck_data(0)
|
||||||
{
|
{
|
||||||
lck_key.lck_long = 0;
|
lck_key.lck_long = 0;
|
||||||
@ -1525,7 +1526,6 @@ void Lock::setLockAttachment(thread_db* tdbb, Jrd::Attachment* attachment)
|
|||||||
lck_prior = NULL;
|
lck_prior = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Enlist in new attachment
|
// Enlist in new attachment
|
||||||
if (attachment)
|
if (attachment)
|
||||||
{
|
{
|
||||||
|
@ -69,7 +69,9 @@ enum lck_t {
|
|||||||
LCK_fun_exist, // Function existence lock
|
LCK_fun_exist, // Function existence lock
|
||||||
LCK_rel_rescan, // Relation forced rescan lock
|
LCK_rel_rescan, // Relation forced rescan lock
|
||||||
LCK_crypt, // Crypt lock for single crypt thread
|
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
|
// Lock owner types
|
||||||
@ -129,12 +131,12 @@ public:
|
|||||||
public:
|
public:
|
||||||
UCHAR lck_logical; // Logical lock level
|
UCHAR lck_logical; // Logical lock level
|
||||||
UCHAR lck_physical; // Physical 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
|
union
|
||||||
{
|
{
|
||||||
UCHAR lck_string[1];
|
UCHAR lck_string[1];
|
||||||
SLONG lck_long;
|
SINT64 lck_long;
|
||||||
} lck_key; // Lock key string
|
} lck_key; // Lock key string
|
||||||
|
|
||||||
UCHAR lck_tail[1]; // Makes the allocator happy
|
UCHAR lck_tail[1]; // Makes the allocator happy
|
||||||
|
@ -40,11 +40,11 @@ void LCK_fini(Jrd::thread_db*, Jrd::lck_owner_t);
|
|||||||
void LCK_init(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(Jrd::thread_db*, Jrd::Lock*, USHORT, SSHORT);
|
||||||
bool LCK_lock_opt(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);
|
SINT64 LCK_query_data(Jrd::thread_db*, Jrd::lck_t, USHORT);
|
||||||
SLONG LCK_read_data(Jrd::thread_db*, Jrd::Lock*);
|
SINT64 LCK_read_data(Jrd::thread_db*, Jrd::Lock*);
|
||||||
void LCK_release(Jrd::thread_db*, Jrd::Lock*);
|
void LCK_release(Jrd::thread_db*, Jrd::Lock*);
|
||||||
void LCK_re_post(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
|
class AutoLock
|
||||||
|
@ -135,15 +135,11 @@ static bool verify_TRG_ignore_perm(thread_db*, const MetaName&);
|
|||||||
static void release_cached_triggers(thread_db* tdbb, trig_vec* vector)
|
static void release_cached_triggers(thread_db* tdbb, trig_vec* vector)
|
||||||
{
|
{
|
||||||
if (!vector)
|
if (!vector)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
for (FB_SIZE_T i = 0; i < vector->getCount(); i++)
|
for (FB_SIZE_T i = 0; i < vector->getCount(); i++)
|
||||||
{
|
|
||||||
(*vector)[i].release(tdbb);
|
(*vector)[i].release(tdbb);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void inc_int_use_count(JrdStatement* statement)
|
static void inc_int_use_count(JrdStatement* statement)
|
||||||
@ -186,9 +182,7 @@ static void inc_int_use_count(JrdStatement* statement)
|
|||||||
static void post_used_procedures(trig_vec* vector)
|
static void post_used_procedures(trig_vec* vector)
|
||||||
{
|
{
|
||||||
if (!vector)
|
if (!vector)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
for (FB_SIZE_T i = 0; i < vector->getCount(); i++)
|
for (FB_SIZE_T i = 0; i < vector->getCount(); i++)
|
||||||
{
|
{
|
||||||
@ -355,7 +349,7 @@ void MET_update_partners(thread_db* tdbb)
|
|||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
Attachment* attachment = tdbb->getAttachment();
|
Attachment* const attachment = tdbb->getAttachment();
|
||||||
|
|
||||||
vec<jrd_rel*>* relations = attachment->att_relations;
|
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)
|
for (const vec<jrd_rel*>::const_iterator end = relations->end(); ptr < end; ++ptr)
|
||||||
{
|
{
|
||||||
jrd_rel* relation = *ptr;
|
jrd_rel* relation = *ptr;
|
||||||
if (!relation) {
|
if (!relation)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// signal other processes
|
// signal other processes
|
||||||
LCK_lock(tdbb, relation->rel_partners_lock, LCK_EX, LCK_WAIT);
|
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)
|
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() &&
|
if (routine && routine->getStatement() &&
|
||||||
!(routine->flags & Routine::FLAG_OBSOLETE) )
|
!(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)
|
for (Function** iter = att->att_functions.begin(); iter != att->att_functions.end(); ++iter)
|
||||||
{
|
{
|
||||||
Function* routine = *iter;
|
Function* const routine = *iter;
|
||||||
|
|
||||||
if (routine && routine->getStatement() &&
|
if (routine && routine->getStatement() &&
|
||||||
!(routine->flags & Routine::FLAG_OBSOLETE) )
|
!(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)
|
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() &&
|
if (routine && routine->getStatement() &&
|
||||||
!(routine->flags & Routine::FLAG_OBSOLETE) &&
|
!(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)
|
for (Function** iter = att->att_functions.begin(); iter != att->att_functions.end(); ++iter)
|
||||||
{
|
{
|
||||||
Function* routine = *iter;
|
Function* const routine = *iter;
|
||||||
|
|
||||||
if (routine && routine->getStatement() &&
|
if (routine && routine->getStatement() &&
|
||||||
!(routine->flags & Routine::FLAG_OBSOLETE) &&
|
!(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)
|
for (jrd_prc** iter = att->att_procedures.begin(); iter != att->att_procedures.end(); ++iter)
|
||||||
{
|
{
|
||||||
Routine* routine = *iter;
|
Routine* const routine = *iter;
|
||||||
|
|
||||||
if (routine)
|
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)
|
for (Function** iter = att->att_functions.begin(); iter != att->att_functions.end(); ++iter)
|
||||||
{
|
{
|
||||||
Function* routine = *iter;
|
Function* const routine = *iter;
|
||||||
|
|
||||||
if (routine)
|
if (routine)
|
||||||
{
|
{
|
||||||
@ -831,7 +824,7 @@ bool MET_routine_in_use(thread_db* tdbb, Routine* routine)
|
|||||||
MET_verify_cache(tdbb);
|
MET_verify_cache(tdbb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Attachment* att = tdbb->getAttachment();
|
Attachment* const att = tdbb->getAttachment();
|
||||||
|
|
||||||
vec<jrd_rel*>* relations = att->att_relations;
|
vec<jrd_rel*>* relations = att->att_relations;
|
||||||
{ // scope
|
{ // scope
|
||||||
@ -2214,9 +2207,7 @@ int MET_lookup_field(thread_db* tdbb, jrd_rel* relation, const MetaName& name)
|
|||||||
int id = -1;
|
int id = -1;
|
||||||
|
|
||||||
if (relation->rel_flags & REL_deleted)
|
if (relation->rel_flags & REL_deleted)
|
||||||
{
|
|
||||||
return id;
|
return id;
|
||||||
}
|
|
||||||
|
|
||||||
AutoCacheRequest request(tdbb, irq_l_field, IRQ_REQUESTS);
|
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);
|
SET_TDBB(tdbb);
|
||||||
Attachment* attachment = tdbb->getAttachment();
|
Attachment* attachment = tdbb->getAttachment();
|
||||||
|
|
||||||
if (relation->rel_flags & REL_check_partners) {
|
if (relation->rel_flags & REL_check_partners)
|
||||||
scan_partners(tdbb, relation);
|
scan_partners(tdbb, relation);
|
||||||
}
|
|
||||||
|
|
||||||
if (idx->idx_flags & idx_foreign)
|
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);
|
SET_TDBB(tdbb);
|
||||||
Attachment* attachment = tdbb->getAttachment();
|
Attachment* const attachment = tdbb->getAttachment();
|
||||||
|
|
||||||
// System relations are above suspicion
|
// System relations are above suspicion
|
||||||
|
|
||||||
@ -3514,9 +3504,8 @@ jrd_rel* MET_relation(thread_db* tdbb, USHORT id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This should check system flag instead.
|
// This should check system flag instead.
|
||||||
if (relation->rel_id <= max_sys_rel) {
|
if (relation->rel_id <= max_sys_rel)
|
||||||
return relation;
|
return relation;
|
||||||
}
|
|
||||||
|
|
||||||
{ // Scope block.
|
{ // Scope block.
|
||||||
Lock* lock = FB_NEW_RPT(*pool, 0)
|
Lock* lock = FB_NEW_RPT(*pool, 0)
|
||||||
@ -3631,10 +3620,8 @@ void MET_scan_partners(thread_db* tdbb, jrd_rel* relation)
|
|||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
|
|
||||||
if (relation->rel_flags & REL_check_partners)
|
if (relation->rel_flags & REL_check_partners)
|
||||||
{
|
|
||||||
scan_partners(tdbb, relation);
|
scan_partners(tdbb, relation);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
|
void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
|
||||||
@ -3691,9 +3678,8 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
|
|||||||
relation->rel_current_fmt = REL.RDB$FORMAT;
|
relation->rel_current_fmt = REL.RDB$FORMAT;
|
||||||
vec<jrd_fld*>* vector = relation->rel_fields =
|
vec<jrd_fld*>* vector = relation->rel_fields =
|
||||||
vec<jrd_fld*>::newVector(*relation->rel_pool, relation->rel_fields, REL.RDB$FIELD_ID + 1);
|
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_security_name = REL.RDB$SECURITY_CLASS;
|
||||||
}
|
|
||||||
|
|
||||||
relation->rel_name = REL.RDB$RELATION_NAME;
|
relation->rel_name = REL.RDB$RELATION_NAME;
|
||||||
relation->rel_owner_name = REL.RDB$OWNER_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;
|
trig_vec* vector = *vector_ptr;
|
||||||
|
|
||||||
if (!vector)
|
if (!vector)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
|
|
||||||
|
121
src/jrd/ods.cpp
121
src/jrd/ods.cpp
@ -24,6 +24,16 @@
|
|||||||
#include "../jrd/ods.h"
|
#include "../jrd/ods.h"
|
||||||
#include "../jrd/ods_proto.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 {
|
namespace Ods {
|
||||||
|
|
||||||
bool isSupported(USHORT majorVersion, USHORT minorVersion)
|
bool isSupported(USHORT majorVersion, USHORT minorVersion)
|
||||||
@ -34,24 +44,6 @@ bool isSupported(USHORT majorVersion, USHORT minorVersion)
|
|||||||
if (!isFirebird)
|
if (!isFirebird)
|
||||||
return false;
|
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
|
// Support current ODS of the engine
|
||||||
if (majorVersion == ODS_VERSION &&
|
if (majorVersion == ODS_VERSION &&
|
||||||
minorVersion >= ODS_RELEASED &&
|
minorVersion >= ODS_RELEASED &&
|
||||||
@ -168,4 +160,97 @@ Firebird::string pagtype(UCHAR type)
|
|||||||
return rc;
|
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
|
} // namespace
|
||||||
|
@ -310,7 +310,7 @@ struct index_root_page
|
|||||||
struct irt_repeat
|
struct irt_repeat
|
||||||
{
|
{
|
||||||
ULONG irt_root; // page number of index root
|
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
|
USHORT irt_desc; // offset to key descriptions
|
||||||
UCHAR irt_keys; // number of keys in index
|
UCHAR irt_keys; // number of keys in index
|
||||||
UCHAR irt_flags;
|
UCHAR irt_flags;
|
||||||
@ -348,13 +348,13 @@ struct header_page
|
|||||||
USHORT hdr_ods_version; // Version of on-disk structure
|
USHORT hdr_ods_version; // Version of on-disk structure
|
||||||
ULONG hdr_PAGES; // Page number of PAGES relation
|
ULONG hdr_PAGES; // Page number of PAGES relation
|
||||||
ULONG hdr_next_page; // Page number of next hdr page
|
ULONG hdr_next_page; // Page number of next hdr page
|
||||||
TraNumber hdr_oldest_transaction; // Oldest interesting transaction
|
ULONG hdr_oldest_transaction; // Oldest interesting transaction
|
||||||
TraNumber hdr_oldest_active; // Oldest transaction thought active
|
ULONG hdr_oldest_active; // Oldest transaction thought active
|
||||||
TraNumber hdr_next_transaction; // Next transaction id
|
ULONG hdr_next_transaction; // Next transaction id
|
||||||
USHORT hdr_sequence; // sequence number of file
|
USHORT hdr_sequence; // sequence number of file
|
||||||
USHORT hdr_flags; // Flag settings, see below
|
USHORT hdr_flags; // Flag settings, see below
|
||||||
SLONG hdr_creation_date[2]; // Date/time of creation
|
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
|
SLONG hdr_shadow_count; // Event count for shadow synchronization
|
||||||
UCHAR hdr_cpu; // CPU database was created on
|
UCHAR hdr_cpu; // CPU database was created on
|
||||||
UCHAR hdr_os; // OS database was created under
|
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_ods_minor; // Update version of ODS
|
||||||
USHORT hdr_end; // offset of HDR_end in page
|
USHORT hdr_end; // offset of HDR_end in page
|
||||||
ULONG hdr_page_buffers; // Page buffers for database cache
|
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
|
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_crypt_page; // Page at which processing is in progress
|
||||||
ULONG hdr_top_crypt; // Last page to crypt
|
ULONG hdr_top_crypt; // Last page to crypt
|
||||||
TEXT hdr_crypt_plugin[32]; // Name of plugin used to crypt this DB
|
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
|
UCHAR hdr_data[1]; // Misc data
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -527,28 +528,44 @@ struct generator_page
|
|||||||
|
|
||||||
struct rhd
|
struct rhd
|
||||||
{
|
{
|
||||||
TraNumber rhd_transaction; // transaction id
|
ULONG rhd_transaction; // transaction id (lowest 32 bits)
|
||||||
ULONG rhd_b_page; // back pointer
|
ULONG rhd_b_page; // back pointer
|
||||||
USHORT rhd_b_line; // back line
|
USHORT rhd_b_line; // back line
|
||||||
USHORT rhd_flags; // flags, etc
|
USHORT rhd_flags; // flags, etc
|
||||||
UCHAR rhd_format; // format version
|
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]))
|
#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
|
// Record header for fragmented record
|
||||||
|
|
||||||
struct rhdf
|
struct rhdf
|
||||||
{
|
{
|
||||||
TraNumber rhdf_transaction; // transaction id
|
ULONG rhdf_transaction; // transaction id (lowest 32 bits)
|
||||||
ULONG rhdf_b_page; // back pointer
|
ULONG rhdf_b_page; // back pointer
|
||||||
USHORT rhdf_b_line; // back line
|
USHORT rhdf_b_line; // back line
|
||||||
USHORT rhdf_flags; // flags, etc
|
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
|
ULONG rhdf_f_page; // next fragment page
|
||||||
USHORT rhdf_f_line; // next fragment line
|
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]))
|
#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_blob = 16; // isn't a record but a blob
|
||||||
const USHORT rhd_stream_blob = 32; // blob is a stream mode blob
|
const USHORT rhd_stream_blob = 32; // blob is a stream mode blob
|
||||||
const USHORT rhd_delta = 32; // prior version is differences only
|
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_large = 64; // object is large
|
||||||
const USHORT rhd_damaged = 128; // object is known to be damaged
|
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_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.
|
// This (not exact) copy of class DSC is used to store descriptors on disk.
|
||||||
|
@ -39,6 +39,19 @@ namespace Ods {
|
|||||||
ULONG maxRecsPerDP(ULONG page_size);
|
ULONG maxRecsPerDP(ULONG page_size);
|
||||||
ULONG maxIndices(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
|
} // namespace
|
||||||
|
|
||||||
#endif //ODS_PROTO_H
|
#endif //ODS_PROTO_H
|
||||||
|
@ -2647,7 +2647,7 @@ SortedStream* OPT_gen_sort(thread_db* tdbb, CompilerScratch* csb, const StreamLi
|
|||||||
map_item++;
|
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));
|
map_length = ROUNDUP(map_length, sizeof(SINT64));
|
||||||
for (const StreamType* ptr = streams.begin(); ptr < end_ptr; ptr++, map_item++)
|
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_length = sizeof(SINT64);
|
||||||
desc->dsc_address = (UCHAR*)(IPTR) map_length;
|
desc->dsc_address = (UCHAR*)(IPTR) map_length;
|
||||||
map_length += desc->dsc_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->clear();
|
||||||
map_item->fieldId = SortedStream::ID_TRANS;
|
map_item->fieldId = SortedStream::ID_TRANS;
|
||||||
map_item->stream = *ptr;
|
map_item->stream = *ptr;
|
||||||
dsc* desc = &map_item->desc;
|
desc = &map_item->desc;
|
||||||
desc->dsc_dtype = dtype_long;
|
desc->dsc_dtype = dtype_int64;
|
||||||
desc->dsc_length = sizeof(SLONG);
|
desc->dsc_length = sizeof(SINT64);
|
||||||
desc->dsc_address = (UCHAR*)(IPTR) map_length;
|
desc->dsc_address = (UCHAR*)(IPTR) map_length;
|
||||||
map_length += desc->dsc_length;
|
map_length += desc->dsc_length;
|
||||||
}
|
}
|
||||||
|
@ -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
|
// Get new attachment id
|
||||||
|
|
||||||
if (dbb->readOnly()) {
|
if (dbb->readOnly())
|
||||||
attachment->att_attachment_id = dbb->dbb_attachment_id + dbb->generateAttachmentId(tdbb);
|
attachment->att_attachment_id = dbb->dbb_attachment_id + dbb->generateAttachmentId(tdbb);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
window.win_page = HEADER_PAGE_NUMBER;
|
window.win_page = HEADER_PAGE_NUMBER;
|
||||||
header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
||||||
CCH_MARK(tdbb, &window);
|
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);
|
CCH_RELEASE(tdbb, &window);
|
||||||
}
|
}
|
||||||
@ -960,9 +963,8 @@ void PAG_format_header(thread_db* tdbb)
|
|||||||
header->hdr_end = HDR_SIZE;
|
header->hdr_end = HDR_SIZE;
|
||||||
header->hdr_data[0] = HDR_end;
|
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;
|
header->hdr_flags |= hdr_SQL_dialect_3;
|
||||||
}
|
|
||||||
|
|
||||||
dbb->dbb_ods_version = header->hdr_ods_version & ~ODS_FIREBIRD_FLAG;
|
dbb->dbb_ods_version = header->hdr_ods_version & ~ODS_FIREBIRD_FLAG;
|
||||||
dbb->dbb_minor_version = header->hdr_ods_minor;
|
dbb->dbb_minor_version = header->hdr_ods_minor;
|
||||||
@ -1106,12 +1108,17 @@ void PAG_header(thread_db* tdbb, bool info)
|
|||||||
|
|
||||||
try {
|
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
|
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
|
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;
|
(*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) {
|
if (!info || dbb->dbb_oldest_transaction < oldest_transaction)
|
||||||
dbb->dbb_oldest_transaction = header->hdr_oldest_transaction;
|
dbb->dbb_oldest_transaction = oldest_transaction;
|
||||||
}
|
|
||||||
if (!info || dbb->dbb_oldest_active < header->hdr_oldest_active) {
|
if (!info || dbb->dbb_oldest_active < oldest_active)
|
||||||
dbb->dbb_oldest_active = header->hdr_oldest_active;
|
dbb->dbb_oldest_active = oldest_active;
|
||||||
}
|
|
||||||
if (!info || dbb->dbb_oldest_snapshot < header->hdr_oldest_snapshot) {
|
if (!info || dbb->dbb_oldest_snapshot < oldest_snapshot)
|
||||||
dbb->dbb_oldest_snapshot = header->hdr_oldest_snapshot;
|
dbb->dbb_oldest_snapshot = oldest_snapshot;
|
||||||
}
|
|
||||||
|
|
||||||
dbb->dbb_attachment_id = header->hdr_attachment_id;
|
dbb->dbb_attachment_id = header->hdr_attachment_id;
|
||||||
dbb->dbb_creation_date = *(ISC_TIMESTAMP*) header->hdr_creation_date;
|
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)
|
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)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -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*);
|
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(Jrd::thread_db* tdbb, Jrd::win*);
|
||||||
Ods::pag* PAG_allocate_pages(Jrd::thread_db* tdbb, Jrd::win* window, int cntAlloc, bool aligned);
|
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);
|
bool PAG_delete_clump_entry(Jrd::thread_db* tdbb, USHORT);
|
||||||
void PAG_format_header(Jrd::thread_db*);
|
void PAG_format_header(Jrd::thread_db*);
|
||||||
void PAG_format_pip(Jrd::thread_db*, Jrd::PageSpace& pageSpace);
|
void PAG_format_pip(Jrd::thread_db*, Jrd::PageSpace& pageSpace);
|
||||||
|
@ -68,16 +68,26 @@ BufferedStream::BufferedStream(CompilerScratch* csb, RecordSource* next)
|
|||||||
fields.add(*desc);
|
fields.add(*desc);
|
||||||
} while (accessor.getNext());
|
} 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));
|
m_map.add(FieldMap(FieldMap::TRANSACTION_ID, stream, 0));
|
||||||
fields.add(desc);
|
fields.add(desc);
|
||||||
|
|
||||||
desc.makeInt64(0);
|
desc.makeInt64(0);
|
||||||
m_map.add(FieldMap(FieldMap::DBKEY_NUMBER, stream, 0));
|
m_map.add(FieldMap(FieldMap::DBKEY_NUMBER, stream, 0));
|
||||||
fields.add(desc);
|
fields.add(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (StreamList::iterator i = streams.begin(); i != streams.end(); ++i)
|
||||||
|
{
|
||||||
|
const StreamType stream = *i;
|
||||||
|
|
||||||
desc.makeText(1, CS_BINARY);
|
desc.makeText(1, CS_BINARY);
|
||||||
m_map.add(FieldMap(FieldMap::DBKEY_VALID, stream, 0));
|
m_map.add(FieldMap(FieldMap::DBKEY_VALID, stream, 0));
|
||||||
@ -191,7 +201,7 @@ bool BufferedStream::getRecord(thread_db* tdbb) const
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FieldMap::TRANSACTION_ID:
|
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;
|
break;
|
||||||
|
|
||||||
case FieldMap::DBKEY_NUMBER:
|
case FieldMap::DBKEY_NUMBER:
|
||||||
@ -258,7 +268,7 @@ bool BufferedStream::getRecord(thread_db* tdbb) const
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FieldMap::TRANSACTION_ID:
|
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;
|
break;
|
||||||
|
|
||||||
case FieldMap::DBKEY_NUMBER:
|
case FieldMap::DBKEY_NUMBER:
|
||||||
|
@ -219,7 +219,7 @@ Sort* SortedStream::init(thread_db* tdbb) const
|
|||||||
switch (item->fieldId)
|
switch (item->fieldId)
|
||||||
{
|
{
|
||||||
case ID_TRANS:
|
case ID_TRANS:
|
||||||
*reinterpret_cast<ULONG*>(to.dsc_address) = rpb->rpb_transaction_nr;
|
*reinterpret_cast<SINT64*>(to.dsc_address) = rpb->rpb_transaction_nr;
|
||||||
break;
|
break;
|
||||||
case ID_DBKEY:
|
case ID_DBKEY:
|
||||||
*reinterpret_cast<SINT64*>(to.dsc_address) = rpb->rpb_number.getValue();
|
*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)
|
switch (id)
|
||||||
{
|
{
|
||||||
case ID_TRANS:
|
case ID_TRANS:
|
||||||
rpb->rpb_transaction_nr = *reinterpret_cast<ULONG*>(from.dsc_address);
|
rpb->rpb_transaction_nr = *reinterpret_cast<SINT64*>(from.dsc_address);
|
||||||
break;
|
break;
|
||||||
case ID_DBKEY:
|
case ID_DBKEY:
|
||||||
rpb->rpb_number.setValue(*reinterpret_cast<SINT64*>(from.dsc_address));
|
rpb->rpb_number.setValue(*reinterpret_cast<SINT64*>(from.dsc_address));
|
||||||
|
@ -62,7 +62,7 @@ struct record_param
|
|||||||
rpb_f_page(0), rpb_f_line(0),
|
rpb_f_page(0), rpb_f_line(0),
|
||||||
rpb_b_page(0), rpb_b_line(0),
|
rpb_b_page(0), rpb_b_line(0),
|
||||||
rpb_address(NULL), rpb_length(0), rpb_flags(0), rpb_stream_flags(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)
|
rpb_window(DB_PAGE_SPACE, -1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -90,6 +90,7 @@ struct record_param
|
|||||||
USHORT rpb_stream_flags; // stream flags
|
USHORT rpb_stream_flags; // stream flags
|
||||||
USHORT rpb_runtime_flags; // runtime flags
|
USHORT rpb_runtime_flags; // runtime flags
|
||||||
SSHORT rpb_org_scans; // relation scan count at stream open
|
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)
|
inline WIN& getWindow(thread_db* tdbb)
|
||||||
{
|
{
|
||||||
@ -112,10 +113,11 @@ const USHORT rpb_fragment = 4;
|
|||||||
const USHORT rpb_incomplete = 8;
|
const USHORT rpb_incomplete = 8;
|
||||||
const USHORT rpb_blob = 16;
|
const USHORT rpb_blob = 16;
|
||||||
const USHORT rpb_delta = 32; // prior version is a differences record
|
const USHORT rpb_delta = 32; // prior version is a differences record
|
||||||
// rpb_large = 64 is missing
|
const USHORT rpb_large = 64; // object is large
|
||||||
const USHORT rpb_damaged = 128; // record is busted
|
const USHORT rpb_damaged = 128; // record is busted
|
||||||
const USHORT rpb_gc_active = 256; // garbage collecting dead record version
|
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_uk_modified = 512; // record key field values are changed
|
||||||
|
const USHORT rpb_long_tranum = 1024; // transaction number is 64-bit
|
||||||
|
|
||||||
// Stream flags
|
// Stream flags
|
||||||
|
|
||||||
@ -217,7 +219,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
MemoryPool* req_pool;
|
MemoryPool* req_pool;
|
||||||
Attachment* req_attachment; // database attachment
|
Attachment* req_attachment; // database attachment
|
||||||
SLONG req_id; // request identifier
|
StmtNumber req_id; // request identifier
|
||||||
USHORT req_incarnation; // incarnation number
|
USHORT req_incarnation; // incarnation number
|
||||||
Firebird::MemoryStats req_memory_stats;
|
Firebird::MemoryStats req_memory_stats;
|
||||||
|
|
||||||
|
@ -42,6 +42,9 @@ typedef Firebird::SparseBitmap<ULONG> PageBitmap;
|
|||||||
// Bitmap of generic 32-bit integers
|
// Bitmap of generic 32-bit integers
|
||||||
typedef Firebird::SparseBitmap<ULONG> UInt32Bitmap;
|
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.
|
// 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
|
// They are used in very performance-sensitive places and we don't want
|
||||||
// pool thread-specific pool pointer be expanded unless necessary.
|
// 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) \
|
#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_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
|
} //namespace Jrd
|
||||||
|
|
||||||
#endif // JRD_SBM_H
|
#endif // JRD_SBM_H
|
||||||
|
@ -449,6 +449,21 @@ void Service::putSLong(char tag, SLONG val)
|
|||||||
enqueue(buf, sizeof buf);
|
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)
|
void Service::putChar(char tag, char val)
|
||||||
{
|
{
|
||||||
UCHAR buf[2];
|
UCHAR buf[2];
|
||||||
|
@ -119,6 +119,7 @@ public: // utilities interface with service
|
|||||||
// put various info items in info buffer
|
// put various info items in info buffer
|
||||||
virtual void putLine(char tag, const char* val);
|
virtual void putLine(char tag, const char* val);
|
||||||
virtual void putSLong(char tag, SLONG val);
|
virtual void putSLong(char tag, SLONG val);
|
||||||
|
virtual void putSInt64(char tag, SINT64 val);
|
||||||
virtual void putChar(char tag, char val);
|
virtual void putChar(char tag, char val);
|
||||||
// put raw bytes to svc_stdout
|
// put raw bytes to svc_stdout
|
||||||
virtual void putBytes(const UCHAR*, FB_SIZE_T);
|
virtual void putBytes(const UCHAR*, FB_SIZE_T);
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "../jrd/pag.h"
|
#include "../jrd/pag.h"
|
||||||
#include "../jrd/cch_proto.h"
|
#include "../jrd/cch_proto.h"
|
||||||
#include "../jrd/lck_proto.h"
|
#include "../jrd/lck_proto.h"
|
||||||
|
#include "../jrd/ods_proto.h"
|
||||||
#include "../jrd/tpc_proto.h"
|
#include "../jrd/tpc_proto.h"
|
||||||
#include "../jrd/tra_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
|
// locate the specific TIP cache block for the transaction
|
||||||
|
|
||||||
const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
|
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;
|
FB_SIZE_T pos;
|
||||||
if (m_cache.find(base, 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;
|
minNumber = tip_cache->tpc_base;
|
||||||
|
|
||||||
const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
|
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
|
// 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 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 ULONG byte = TRANS_OFFSET(number % trans_per_tip);
|
||||||
const USHORT shift = TRANS_SHIFT(number);
|
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
|
// locate the specific TIP cache block for the transaction
|
||||||
|
|
||||||
const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
|
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;
|
FB_SIZE_T pos;
|
||||||
if (m_cache.find(base, 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
|
// see if we can get a lock on the transaction; if we can't
|
||||||
// then we know it is still active
|
// 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;
|
temp_lock.lck_key.lck_long = number;
|
||||||
|
|
||||||
// If we can't get a lock on the transaction, it must be active.
|
// 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 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
|
// 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
|
// any tip cache pages we can release--this is cheaper and
|
||||||
@ -462,8 +463,8 @@ TraNumber TipCache::cacheTransactions(thread_db* tdbb, TraNumber oldest)
|
|||||||
#else
|
#else
|
||||||
WIN window(HEADER_PAGE_NUMBER);
|
WIN window(HEADER_PAGE_NUMBER);
|
||||||
const Ods::header_page* header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header);
|
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 top = Ods::getNT(header);
|
||||||
const TraNumber hdr_oldest = header->hdr_oldest_transaction;
|
const TraNumber hdr_oldest = Ods::getOIT(header);
|
||||||
CCH_RELEASE(tdbb, &window);
|
CCH_RELEASE(tdbb, &window);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -557,7 +558,8 @@ int TipCache::extendCache(thread_db* tdbb, TraNumber number)
|
|||||||
|
|
||||||
// find the right block for this transaction and return the state
|
// 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;
|
FB_SIZE_T pos;
|
||||||
if (m_cache.find(base, 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
|
// we should never get to this point, but if we do the
|
||||||
// safest thing to do is return active
|
// safest thing to do is return active
|
||||||
|
|
||||||
|
fb_assert(false);
|
||||||
return tra_active;
|
return tra_active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
127
src/jrd/tra.cpp
127
src/jrd/tra.cpp
@ -228,8 +228,8 @@ void TRA_cleanup(thread_db* tdbb)
|
|||||||
|
|
||||||
WIN window(HEADER_PAGE_NUMBER);
|
WIN window(HEADER_PAGE_NUMBER);
|
||||||
const header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header);
|
const header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header);
|
||||||
const TraNumber ceiling = header->hdr_next_transaction;
|
const TraNumber ceiling = Ods::getNT(header);
|
||||||
const TraNumber active = header->hdr_oldest_active;
|
const TraNumber active = Ods::getOAT(header);
|
||||||
CCH_RELEASE(tdbb, &window);
|
CCH_RELEASE(tdbb, &window);
|
||||||
|
|
||||||
if (ceiling == 0)
|
if (ceiling == 0)
|
||||||
@ -246,7 +246,7 @@ void TRA_cleanup(thread_db* tdbb)
|
|||||||
{
|
{
|
||||||
window.win_page = inventory_page(tdbb, sequence);
|
window.win_page = inventory_page(tdbb, sequence);
|
||||||
tx_inv_page* tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_transactions);
|
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)
|
if (max > trans_per_tip)
|
||||||
max = trans_per_tip - 1;
|
max = trans_per_tip - 1;
|
||||||
for (; number <= max; number++)
|
for (; number <= max; number++)
|
||||||
@ -256,7 +256,7 @@ void TRA_cleanup(thread_db* tdbb)
|
|||||||
const USHORT shift = TRANS_SHIFT(number);
|
const USHORT shift = TRANS_SHIFT(number);
|
||||||
const int state = (*byte >> shift) & TRA_MASK;
|
const int state = (*byte >> shift) & TRA_MASK;
|
||||||
if (state == tra_limbo && limbo == 0)
|
if (state == tra_limbo && limbo == 0)
|
||||||
limbo = sequence * trans_per_tip + number;
|
limbo = (TraNumber) sequence * trans_per_tip + number;
|
||||||
else if (state == tra_active)
|
else if (state == tra_active)
|
||||||
{
|
{
|
||||||
CCH_MARK(tdbb, &window);
|
CCH_MARK(tdbb, &window);
|
||||||
@ -314,7 +314,7 @@ void TRA_cleanup(thread_db* tdbb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!tip->tip_next)
|
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);
|
CCH_RELEASE(tdbb, &window);
|
||||||
@ -579,7 +579,7 @@ void TRA_get_inventory(thread_db* tdbb, UCHAR* bit_vector, TraNumber base, TraNu
|
|||||||
|
|
||||||
while (sequence <= last)
|
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
|
// release the read lock as we go, so that some one else can
|
||||||
// commit without having to signal all other transactions.
|
// 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);
|
WIN window(HEADER_PAGE_NUMBER);
|
||||||
header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
|
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
|
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
|
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)
|
if (!number || dbb->dbb_last_header_write < number)
|
||||||
{
|
{
|
||||||
CCH_MARK_MUST_WRITE(tdbb, &window);
|
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)
|
if (dbb->dbb_next_transaction > next_transaction)
|
||||||
header->hdr_oldest_active = dbb->dbb_oldest_active;
|
Ods::writeNT(header, dbb->dbb_next_transaction);
|
||||||
|
|
||||||
if (dbb->dbb_oldest_transaction > header->hdr_oldest_transaction)
|
if (dbb->dbb_oldest_active > oldest_active)
|
||||||
header->hdr_oldest_transaction = dbb->dbb_oldest_transaction;
|
Ods::writeOAT(header, dbb->dbb_oldest_active);
|
||||||
|
|
||||||
if (dbb->dbb_oldest_snapshot > header->hdr_oldest_snapshot)
|
if (dbb->dbb_oldest_transaction > oldest_transaction)
|
||||||
header->hdr_oldest_snapshot = dbb->dbb_oldest_snapshot;
|
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);
|
CCH_RELEASE(tdbb, &window);
|
||||||
@ -905,7 +911,7 @@ bool TRA_precommited(thread_db* tdbb, TraNumber old_number, TraNumber new_number
|
|||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
Database* dbb = tdbb->getDatabase();
|
Database* const dbb = tdbb->getDatabase();
|
||||||
CHECK_DBB(dbb);
|
CHECK_DBB(dbb);
|
||||||
|
|
||||||
Sync sync(&dbb->dbb_pc_sync, "TRA_precommited");
|
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);
|
SET_TDBB(tdbb);
|
||||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
Jrd::Attachment* const attachment = tdbb->getAttachment();
|
||||||
|
|
||||||
if (!transaction->tra_outer)
|
if (!transaction->tra_outer)
|
||||||
{
|
{
|
||||||
@ -1205,7 +1211,7 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr
|
|||||||
if (trace)
|
if (trace)
|
||||||
trace->finish(ITracePlugin::RESULT_SUCCESS);
|
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)
|
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;
|
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;
|
return tra_committed;
|
||||||
}
|
|
||||||
|
|
||||||
// If the transaction is younger than we are and we are not read 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.
|
// 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.
|
* 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 ULONG byte = TRANS_OFFSET(number - base);
|
||||||
const USHORT shift = TRANS_SHIFT(number);
|
const USHORT shift = TRANS_SHIFT(number);
|
||||||
|
|
||||||
@ -1779,12 +1783,12 @@ void TRA_sweep(thread_db* tdbb)
|
|||||||
CCH_flush(tdbb, FLUSH_SWEEP, 0);
|
CCH_flush(tdbb, FLUSH_SWEEP, 0);
|
||||||
|
|
||||||
WIN window(HEADER_PAGE_NUMBER);
|
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);
|
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);
|
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)
|
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;
|
temp_lock.lck_key.lck_long = number;
|
||||||
|
|
||||||
const SSHORT timeout = (wait == jrd_tra::tra_wait) ? trans->getLockWait() : 0;
|
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;
|
window->win_page = HEADER_PAGE_NUMBER;
|
||||||
header_page* header = (header_page*) CCH_FETCH(tdbb, window, LCK_write, pag_header);
|
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
|
// 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
|
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
|
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);
|
CCH_RELEASE(tdbb, window);
|
||||||
ERR_post(Arg::Gds(isc_imp_exc) <<
|
ERR_post(Arg::Gds(isc_imp_exc) <<
|
||||||
Arg::Gds(isc_tra_num_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.
|
// If this is the first transaction on a TIP, allocate the TIP now.
|
||||||
// Note, first TIP page is created with the database itself,
|
// 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
|
// Extend, if necessary, has apparently succeeded. Next, update header page
|
||||||
|
|
||||||
CCH_MARK_MUST_WRITE(tdbb, window);
|
CCH_MARK_MUST_WRITE(tdbb, window);
|
||||||
header->hdr_next_transaction = number;
|
|
||||||
dbb->dbb_next_transaction = number;
|
dbb->dbb_next_transaction = number;
|
||||||
|
|
||||||
if (dbb->dbb_oldest_active > header->hdr_oldest_active)
|
Ods::writeNT(header, number);
|
||||||
header->hdr_oldest_active = dbb->dbb_oldest_active;
|
|
||||||
|
|
||||||
if (dbb->dbb_oldest_transaction > header->hdr_oldest_transaction)
|
if (dbb->dbb_oldest_active > oldest_active)
|
||||||
header->hdr_oldest_transaction = dbb->dbb_oldest_transaction;
|
Ods::writeOAT(header, dbb->dbb_oldest_active);
|
||||||
|
|
||||||
if (dbb->dbb_oldest_snapshot > header->hdr_oldest_snapshot)
|
if (dbb->dbb_oldest_transaction > oldest_transaction)
|
||||||
header->hdr_oldest_snapshot = dbb->dbb_oldest_snapshot;
|
Ods::writeOIT(header, dbb->dbb_oldest_transaction);
|
||||||
|
|
||||||
|
if (dbb->dbb_oldest_snapshot > oldest_snapshot)
|
||||||
|
Ods::writeOST(header, dbb->dbb_oldest_snapshot);
|
||||||
|
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
@ -2233,16 +2244,20 @@ static ULONG inventory_page(thread_db* tdbb, ULONG sequence)
|
|||||||
while (!vector || sequence >= vector->count())
|
while (!vector || sequence >= vector->count())
|
||||||
{
|
{
|
||||||
DPM_scan_pages(tdbb);
|
DPM_scan_pages(tdbb);
|
||||||
|
|
||||||
if ((vector = dbb->dbb_t_pages) && sequence < vector->count())
|
if ((vector = dbb->dbb_t_pages) && sequence < vector->count())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!vector)
|
if (!vector)
|
||||||
BUGCHECK(165); // msg 165 cannot find tip page
|
BUGCHECK(165); // msg 165 cannot find tip page
|
||||||
|
|
||||||
window.win_page = (*vector)[vector->count() - 1];
|
window.win_page = (*vector)[vector->count() - 1];
|
||||||
tx_inv_page* tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_transactions);
|
tx_inv_page* tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_transactions);
|
||||||
const ULONG next = tip->tip_next;
|
const ULONG next = tip->tip_next;
|
||||||
CCH_RELEASE(tdbb, &window);
|
CCH_RELEASE(tdbb, &window);
|
||||||
if (!(window.win_page = next))
|
if (!(window.win_page = next))
|
||||||
BUGCHECK(165); // msg 165 cannot find tip page
|
BUGCHECK(165); // msg 165 cannot find tip page
|
||||||
|
|
||||||
// Type check it
|
// Type check it
|
||||||
tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_transactions);
|
tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_transactions);
|
||||||
CCH_RELEASE(tdbb, &window);
|
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.
|
// its snapshot doesn't contain these operations.
|
||||||
|
|
||||||
if (commit)
|
if (commit)
|
||||||
{
|
TBM_SET(tdbb->getDefaultPool(), &transaction->tra_commit_sub_trans, transaction->tra_number);
|
||||||
//fb_assert(sizeof(transaction->tra_number) == sizeof(ULONG));
|
|
||||||
SBM_SET(tdbb->getDefaultPool(), &transaction->tra_commit_sub_trans, transaction->tra_number);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new transaction lock, inheriting oldest active from transaction being committed.
|
// 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);
|
new_number = dbb->dbb_next_transaction + dbb->generateTransactionId(tdbb);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const header_page* header = bump_transaction_id(tdbb, &window);
|
const header_page* const header = bump_transaction_id(tdbb, &window);
|
||||||
new_number = header->hdr_next_transaction;
|
new_number = Ods::getNT(header);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2400,7 +2412,7 @@ static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, i
|
|||||||
Lock* old_lock = transaction->tra_lock;
|
Lock* old_lock = transaction->tra_lock;
|
||||||
if (old_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_key.lck_long = new_number;
|
||||||
new_lock->lck_data = transaction->tra_lock->lck_data;
|
new_lock->lck_data = transaction->tra_lock->lck_data;
|
||||||
|
|
||||||
@ -3032,11 +3044,12 @@ static void transaction_options(thread_db* tdbb,
|
|||||||
Lock* lock = (*vector)[id];
|
Lock* lock = (*vector)[id];
|
||||||
if (!lock)
|
if (!lock)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
USHORT level = lock->lck_logical;
|
USHORT level = lock->lck_logical;
|
||||||
|
|
||||||
if (level == LCK_none || LCK_lock(tdbb, lock, level, transaction->getLockWait()))
|
if (level == LCK_none || LCK_lock(tdbb, lock, level, transaction->getLockWait()))
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
for (ULONG l = 0; l < id; l++)
|
for (ULONG l = 0; l < id; l++)
|
||||||
{
|
{
|
||||||
if ( (lock = (*vector)[l]) )
|
if ( (lock = (*vector)[l]) )
|
||||||
@ -3046,6 +3059,7 @@ static void transaction_options(thread_db* tdbb,
|
|||||||
lock->lck_logical = level;
|
lock->lck_logical = level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id = 0;
|
id = 0;
|
||||||
ERR_punt();
|
ERR_punt();
|
||||||
}
|
}
|
||||||
@ -3069,7 +3083,7 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans)
|
|||||||
Jrd::Attachment* const attachment = tdbb->getAttachment();
|
Jrd::Attachment* const attachment = tdbb->getAttachment();
|
||||||
WIN window(DB_PAGE_SPACE, -1);
|
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
|
// Read header page and allocate transaction number. Since
|
||||||
// the transaction inventory page was initialized to zero, it
|
// the transaction inventory page was initialized to zero, it
|
||||||
@ -3095,10 +3109,10 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
const header_page* header = bump_transaction_id(tdbb, &window);
|
const header_page* header = bump_transaction_id(tdbb, &window);
|
||||||
number = header->hdr_next_transaction;
|
number = Ods::getNT(header);
|
||||||
oldest = header->hdr_oldest_transaction;
|
oldest = Ods::getOIT(header);
|
||||||
oldest_active = header->hdr_oldest_active;
|
oldest_active = Ods::getOAT(header);
|
||||||
oldest_snapshot = header->hdr_oldest_snapshot;
|
oldest_snapshot = Ods::getOST(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
// oldest (OIT) > oldest_active (OAT) if OIT was advanced by sweep
|
// 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
|
// more complicated by the fact that existing transaction may have oldest
|
||||||
// actives older than they are.
|
// 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;
|
trans->tra_oldest_active = number;
|
||||||
base = oldest & ~TRA_MASK;
|
base = oldest & ~TRA_MASK;
|
||||||
@ -3197,6 +3211,7 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans)
|
|||||||
const USHORT shift = TRANS_SHIFT(active);
|
const USHORT shift = TRANS_SHIFT(active);
|
||||||
oldest_state = (trans->tra_transactions[byte] >> shift) & TRA_MASK;
|
oldest_state = (trans->tra_transactions[byte] >> shift) & TRA_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldest_state == tra_active)
|
if (oldest_state == tra_active)
|
||||||
{
|
{
|
||||||
temp_lock.lck_key.lck_long = active;
|
temp_lock.lck_key.lck_long = active;
|
||||||
|
@ -80,12 +80,6 @@ public:
|
|||||||
int savePoint;
|
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
|
// 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.
|
// structure small as there can be huge amount of them floating in memory.
|
||||||
struct BlobIndex
|
struct BlobIndex
|
||||||
@ -264,7 +258,7 @@ public:
|
|||||||
ArrayField* tra_arrays; // Linked list of active arrays
|
ArrayField* tra_arrays; // Linked list of active arrays
|
||||||
Lock* tra_lock; // lock for transaction
|
Lock* tra_lock; // lock for transaction
|
||||||
vec<Lock*>* tra_relation_locks; // locks for relations
|
vec<Lock*>* tra_relation_locks; // locks for relations
|
||||||
UInt32Bitmap* tra_commit_sub_trans; // commited sub-transactions
|
TransactionBitmap* tra_commit_sub_trans; // commited sub-transactions
|
||||||
Savepoint* tra_save_point; // list of savepoints
|
Savepoint* tra_save_point; // list of savepoints
|
||||||
Savepoint* tra_save_free; // free savepoints
|
Savepoint* tra_save_free; // free savepoints
|
||||||
SLONG tra_save_point_number; // next save point number to use
|
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_us = 4; // Transaction is us
|
||||||
const int tra_precommitted = 5; // Transaction is precommitted
|
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
|
// Savepoint block
|
||||||
|
|
||||||
class Savepoint : public pool_alloc<type_sav>
|
class Savepoint : public pool_alloc<type_sav>
|
||||||
|
@ -65,7 +65,7 @@ unsigned TraceConnectionImpl::getKind()
|
|||||||
return KIND_DATABASE;
|
return KIND_DATABASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TraceConnectionImpl::getConnectionID()
|
ISC_INT64 TraceConnectionImpl::getConnectionID()
|
||||||
{
|
{
|
||||||
return m_att->att_attachment_id;
|
return m_att->att_attachment_id;
|
||||||
//return PAG_attachment_id(JRD_get_thread_data());
|
//return PAG_attachment_id(JRD_get_thread_data());
|
||||||
@ -122,7 +122,7 @@ const char* TraceConnectionImpl::getRemoteProcessName()
|
|||||||
|
|
||||||
/// TraceTransactionImpl
|
/// TraceTransactionImpl
|
||||||
|
|
||||||
unsigned TraceTransactionImpl::getTransactionID()
|
ISC_INT64 TraceTransactionImpl::getTransactionID()
|
||||||
{
|
{
|
||||||
return m_tran->tra_number;
|
return m_tran->tra_number;
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ unsigned TraceTransactionImpl::getIsolation()
|
|||||||
|
|
||||||
/// TraceSQLStatementImpl
|
/// TraceSQLStatementImpl
|
||||||
|
|
||||||
int TraceSQLStatementImpl::getStmtID()
|
ISC_INT64 TraceSQLStatementImpl::getStmtID()
|
||||||
{
|
{
|
||||||
if (m_stmt->req_request)
|
if (m_stmt->req_request)
|
||||||
return m_stmt->req_request->req_id;
|
return m_stmt->req_request->req_id;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "../../jrd/ntrace.h"
|
#include "../../jrd/ntrace.h"
|
||||||
#include "../../common/dsc.h"
|
#include "../../common/dsc.h"
|
||||||
#include "../../common/isc_s_proto.h"
|
#include "../../common/isc_s_proto.h"
|
||||||
|
#include "../../jrd/ods_proto.h"
|
||||||
#include "../../jrd/req.h"
|
#include "../../jrd/req.h"
|
||||||
#include "../../jrd/svc.h"
|
#include "../../jrd/svc.h"
|
||||||
#include "../../jrd/tra.h"
|
#include "../../jrd/tra.h"
|
||||||
@ -72,7 +73,7 @@ public:
|
|||||||
const char* getRemoteProcessName();
|
const char* getRemoteProcessName();
|
||||||
|
|
||||||
// TraceDatabaseConnection implementation
|
// TraceDatabaseConnection implementation
|
||||||
int getConnectionID();
|
ISC_INT64 getConnectionID();
|
||||||
const char* getDatabaseName();
|
const char* getDatabaseName();
|
||||||
private:
|
private:
|
||||||
const Attachment* const m_att;
|
const Attachment* const m_att;
|
||||||
@ -89,7 +90,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
// TraceTransaction implementation
|
// TraceTransaction implementation
|
||||||
unsigned getTransactionID();
|
ISC_INT64 getTransactionID();
|
||||||
FB_BOOLEAN getReadOnly();
|
FB_BOOLEAN getReadOnly();
|
||||||
int getWait();
|
int getWait();
|
||||||
unsigned getIsolation();
|
unsigned getIsolation();
|
||||||
@ -147,7 +148,7 @@ public:
|
|||||||
m_perf(perf)
|
m_perf(perf)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int getStmtID() { return m_stmt->req_id; }
|
ISC_INT64 getStmtID() { return m_stmt->req_id; }
|
||||||
PerformanceInfo* getPerf() { return m_perf; }
|
PerformanceInfo* getPerf() { return m_perf; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -163,7 +164,7 @@ public:
|
|||||||
BLRPrinter(blr, length)
|
BLRPrinter(blr, length)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int getStmtID() { return 0; }
|
ISC_INT64 getStmtID() { return 0; }
|
||||||
PerformanceInfo* getPerf() { return NULL; }
|
PerformanceInfo* getPerf() { return NULL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -180,7 +181,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
// TraceSQLStatement implementation
|
// TraceSQLStatement implementation
|
||||||
int getStmtID();
|
ISC_INT64 getStmtID();
|
||||||
PerformanceInfo* getPerf();
|
PerformanceInfo* getPerf();
|
||||||
Firebird::ITraceParams* getInputs();
|
Firebird::ITraceParams* getInputs();
|
||||||
const char* getText();
|
const char* getText();
|
||||||
@ -234,7 +235,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
// TraceSQLStatement implementation
|
// TraceSQLStatement implementation
|
||||||
int getStmtID() { return 0; }
|
ISC_INT64 getStmtID() { return 0; }
|
||||||
PerformanceInfo* getPerf() { return NULL; }
|
PerformanceInfo* getPerf() { return NULL; }
|
||||||
Firebird::ITraceParams* getInputs() { return NULL; }
|
Firebird::ITraceParams* getInputs() { return NULL; }
|
||||||
const char* getText() { return m_text.c_str(); }
|
const char* getText() { return m_text.c_str(); }
|
||||||
@ -608,10 +609,10 @@ public:
|
|||||||
|
|
||||||
void update(const Ods::header_page* header)
|
void update(const Ods::header_page* header)
|
||||||
{
|
{
|
||||||
m_oit = header->hdr_oldest_transaction;
|
m_oit = Ods::getOIT(header);
|
||||||
m_ost = header->hdr_oldest_snapshot;
|
m_ost = Ods::getOST(header);
|
||||||
m_oat = header->hdr_oldest_active;
|
m_oat = Ods::getOAT(header);
|
||||||
m_next = header->hdr_next_transaction;
|
m_next = Ods::getNT(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPerf(PerformanceInfo* perf)
|
void setPerf(PerformanceInfo* perf)
|
||||||
@ -619,10 +620,10 @@ public:
|
|||||||
m_perf = perf;
|
m_perf = perf;
|
||||||
}
|
}
|
||||||
|
|
||||||
ISC_UINT64 getOIT() { return m_oit; };
|
ISC_INT64 getOIT() { return m_oit; };
|
||||||
ISC_UINT64 getOST() { return m_ost; };
|
ISC_INT64 getOST() { return m_ost; };
|
||||||
ISC_UINT64 getOAT() { return m_oat; };
|
ISC_INT64 getOAT() { return m_oat; };
|
||||||
ISC_UINT64 getNext() { return m_next; };
|
ISC_INT64 getNext() { return m_next; };
|
||||||
PerformanceInfo* getPerf() { return m_perf; };
|
PerformanceInfo* getPerf() { return m_perf; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -561,6 +561,7 @@ VI. ADDITIONAL NOTES
|
|||||||
#include "../yvalve/gds_proto.h"
|
#include "../yvalve/gds_proto.h"
|
||||||
#include "../common/isc_proto.h"
|
#include "../common/isc_proto.h"
|
||||||
#include "../jrd/met_proto.h"
|
#include "../jrd/met_proto.h"
|
||||||
|
#include "../jrd/ods_proto.h"
|
||||||
#include "../jrd/tra_proto.h"
|
#include "../jrd/tra_proto.h"
|
||||||
#include "../jrd/val_proto.h"
|
#include "../jrd/val_proto.h"
|
||||||
#include "../jrd/validation.h"
|
#include "../jrd/validation.h"
|
||||||
@ -1404,8 +1405,8 @@ static void print_rhd(USHORT length, const rhd* header)
|
|||||||
**************************************/
|
**************************************/
|
||||||
if (VAL_debug_level)
|
if (VAL_debug_level)
|
||||||
{
|
{
|
||||||
fprintf(stdout, "rhd: len %d TX %d format %d ",
|
fprintf(stdout, "rhd: len %d TX %"SQUADFORMAT" format %d ",
|
||||||
length, header->rhd_transaction, (int) header->rhd_format);
|
length, Ods::getTraNum(header), (int) header->rhd_format);
|
||||||
fprintf(stdout, "BP %d/%d flags 0x%x ",
|
fprintf(stdout, "BP %d/%d flags 0x%x ",
|
||||||
header->rhd_b_page, header->rhd_b_line, header->rhd_flags);
|
header->rhd_b_page, header->rhd_b_line, header->rhd_flags);
|
||||||
if (header->rhd_flags & rhd_incomplete)
|
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());
|
RBM_SET(vdr_tdbb->getDefaultPool(), &vdr_rel_records, number.getValue());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int state;
|
const TraNumber transaction = Ods::getTraNum(header);
|
||||||
if (header->rhd_transaction < dbb->dbb_oldest_transaction)
|
|
||||||
state = tra_committed;
|
const int state = (transaction < dbb->dbb_oldest_transaction) ?
|
||||||
else
|
tra_committed : TRA_fetch_state(vdr_tdbb, transaction);
|
||||||
state = TRA_fetch_state(vdr_tdbb, header->rhd_transaction);
|
|
||||||
if (state == tra_committed || state == tra_limbo)
|
if (state == tra_committed || state == tra_limbo)
|
||||||
RBM_SET(vdr_tdbb->getDefaultPool(), &vdr_rel_records, number.getValue());
|
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;
|
return rtn_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->rhd_transaction > vdr_max_transaction)
|
const TraNumber transaction = Ods::getTraNum(header);
|
||||||
corrupt(VAL_REC_BAD_TID, relation, number.getValue(), header->rhd_transaction);
|
|
||||||
|
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
|
// If there's a back pointer, verify that it's good
|
||||||
|
|
||||||
|
331
src/jrd/vio.cpp
331
src/jrd/vio.cpp
@ -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,
|
inline int wait(thread_db* tdbb, jrd_tra* transaction, const record_param* rpb)
|
||||||
const record_param* rpb, jrd_tra::wait_t wait)
|
|
||||||
{
|
{
|
||||||
const SSHORT timeout = (wait == jrd_tra::tra_wait) ? transaction->getLockWait() : 0;
|
if (transaction->getLockWait())
|
||||||
|
|
||||||
if (timeout)
|
|
||||||
tdbb->bumpRelStats(RuntimeStatistics::RECORD_WAITS, rpb->rpb_relation->rel_id);
|
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[] =
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES,
|
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);
|
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -403,7 +431,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
temp.rpb_page, temp.rpb_line, temp.rpb_transaction_nr,
|
temp.rpb_page, temp.rpb_line, temp.rpb_transaction_nr,
|
||||||
temp.rpb_flags, temp.rpb_b_page, temp.rpb_b_line,
|
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);
|
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;
|
RecordStack empty_staying;
|
||||||
IDX_garbage_collect(tdbb, rpb, going, empty_staying);
|
IDX_garbage_collect(tdbb, rpb, going, empty_staying);
|
||||||
BLB_garbage_collect(tdbb, going, empty_staying, rpb->rpb_page, relation);
|
BLB_garbage_collect(tdbb, going, empty_staying, rpb->rpb_page, relation);
|
||||||
going.pop();
|
going.pop();
|
||||||
|
|
||||||
if (!DPM_get(tdbb, rpb, LCK_write))
|
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));
|
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fb_assert(rpb->rpb_flags & rpb_gc_active);
|
||||||
|
rpb->rpb_flags &= ~rpb_gc_active;
|
||||||
|
|
||||||
temp2 = *rpb;
|
temp2 = *rpb;
|
||||||
rpb->rpb_undo = old_data;
|
rpb->rpb_undo = old_data;
|
||||||
|
|
||||||
@ -581,10 +624,15 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
|
|||||||
clearRecordStack(staying);
|
clearRecordStack(staying);
|
||||||
|
|
||||||
if (!DPM_get(tdbb, rpb, LCK_write))
|
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));
|
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
||||||
return;
|
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
|
// 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);
|
DPM_update(tdbb, rpb, 0, transaction);
|
||||||
delete_tail(tdbb, &temp2, rpb->rpb_page, 0, 0);
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE_ALL,
|
VIO_trace(DEBUG_TRACE_ALL,
|
||||||
"VIO_chase_record_version (record_param %"QUADFORMAT"d, transaction %"
|
"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,
|
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||||
(void*) pool);
|
(void*) pool);
|
||||||
|
|
||||||
VIO_trace(DEBUG_TRACE_ALL_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
||||||
rpb->rpb_f_page, rpb->rpb_f_line);
|
rpb->rpb_f_page, rpb->rpb_f_line);
|
||||||
#endif
|
#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);
|
int state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
|
||||||
|
|
||||||
// Reset the garbage collect active flag if the transaction state is
|
// Reset (if appropriate) the garbage collect active flag to reattempt the backout
|
||||||
// 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.
|
|
||||||
|
|
||||||
if (rpb->rpb_flags & rpb_gc_active)
|
if (rpb->rpb_flags & rpb_gc_active)
|
||||||
{
|
checkGCActive(tdbb, rpb, state);
|
||||||
if (!rpb->rpb_transaction_nr)
|
|
||||||
state = tra_active;
|
|
||||||
|
|
||||||
if (state == tra_committed)
|
// Take care about modifications performed by our own transaction
|
||||||
state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead;
|
|
||||||
|
|
||||||
if (state == tra_dead)
|
|
||||||
rpb->rpb_flags &= ~rpb_gc_active;
|
|
||||||
}
|
|
||||||
|
|
||||||
rpb->rpb_runtime_flags &= ~(RPB_undo_data | RPB_undo_read);
|
rpb->rpb_runtime_flags &= ~(RPB_undo_data | RPB_undo_read);
|
||||||
int forceBack = 0;
|
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 &&
|
if ((state == tra_committed || state == tra_us) && !forceBack &&
|
||||||
!(rpb->rpb_flags & (rpb_deleted | rpb_damaged)) &&
|
!(rpb->rpb_flags & (rpb_deleted | rpb_damaged)) &&
|
||||||
(rpb->rpb_b_page == 0 || rpb->rpb_transaction_nr >= oldest_snapshot))
|
(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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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))
|
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)
|
if (state == tra_active)
|
||||||
state = tra_limbo;
|
state = tra_limbo;
|
||||||
}
|
}
|
||||||
@ -783,7 +820,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
|||||||
if (state == tra_limbo)
|
if (state == tra_limbo)
|
||||||
{
|
{
|
||||||
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
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))
|
if (!DPM_get(tdbb, rpb, LCK_read))
|
||||||
return false;
|
return false;
|
||||||
@ -814,7 +851,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
|||||||
// of a dead record version.
|
// of a dead record version.
|
||||||
|
|
||||||
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
||||||
state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait);
|
state = wait(tdbb, transaction, rpb);
|
||||||
|
|
||||||
if (state == tra_precommitted)
|
if (state == tra_precommitted)
|
||||||
state = check_precommitted(transaction, rpb);
|
state = check_precommitted(transaction, rpb);
|
||||||
@ -854,7 +891,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
|||||||
case tra_dead:
|
case tra_dead:
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
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);
|
rpb->rpb_transaction_nr, transaction->tra_number);
|
||||||
#endif
|
#endif
|
||||||
if (gcPolicyBackground && !(rpb->rpb_flags & rpb_chained) &&
|
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:
|
case tra_limbo:
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
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);
|
rpb->rpb_transaction_nr, transaction->tra_number);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -957,7 +994,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
|||||||
if (state == tra_active)
|
if (state == tra_active)
|
||||||
{
|
{
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
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);
|
rpb->rpb_transaction_nr, transaction->tra_number);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1065,7 +1102,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
|||||||
case tra_us:
|
case tra_us:
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
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);
|
rpb->rpb_transaction_nr, transaction->tra_number);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1103,7 +1140,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
|||||||
case tra_committed:
|
case tra_committed:
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
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);
|
rpb->rpb_transaction_nr, transaction->tra_number);
|
||||||
#endif
|
#endif
|
||||||
if (rpb->rpb_flags & rpb_deleted)
|
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);
|
state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
|
||||||
|
|
||||||
// Reset the garbage collect active flag if the transaction state is
|
// Reset (if appropriate) the garbage collect active flag to reattempt the backout
|
||||||
// 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.
|
|
||||||
|
|
||||||
if (!(rpb->rpb_flags & rpb_chained) && (rpb->rpb_flags & rpb_gc_active))
|
if (!(rpb->rpb_flags & rpb_chained) && (rpb->rpb_flags & rpb_gc_active))
|
||||||
{
|
checkGCActive(tdbb, rpb, state);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1278,7 +1302,7 @@ void VIO_data(thread_db* tdbb, record_param* rpb, MemoryPool* pool)
|
|||||||
|
|
||||||
|
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line,
|
rpb->rpb_page, rpb->rpb_line,
|
||||||
rpb->rpb_transaction_nr, rpb->rpb_flags,
|
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);
|
rpb->rpb_number.getValue(), length, format->fmt_length);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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",
|
"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_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);
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES,
|
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);
|
rpb->rpb_number.getValue(), transaction->tra_number);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE,
|
VIO_trace(DEBUG_TRACE,
|
||||||
"VIO_garbage_collect (record_param %"QUADFORMAT"d, transaction %"
|
"VIO_garbage_collect (record_param %"QUADFORMAT"d, transaction %"
|
||||||
ULONGFORMAT")\n",
|
SQUADFORMAT")\n",
|
||||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||||
|
|
||||||
VIO_trace(DEBUG_TRACE_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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);
|
int state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
|
||||||
|
|
||||||
// Reset the garbage collect active flag if the transaction state is
|
// Reset (if appropriate) the garbage collect active flag to reattempt the backout
|
||||||
// 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.
|
|
||||||
|
|
||||||
if (rpb->rpb_flags & rpb_gc_active)
|
if (rpb->rpb_flags & rpb_gc_active)
|
||||||
{
|
{
|
||||||
if (state == tra_committed)
|
if (checkGCActive(tdbb, rpb, state))
|
||||||
state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead;
|
return true;
|
||||||
|
|
||||||
if (state == tra_dead)
|
|
||||||
rpb->rpb_flags &= ~rpb_gc_active;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fb_assert(!(rpb->rpb_flags & rpb_gc_active));
|
||||||
|
|
||||||
if (state == tra_precommitted)
|
if (state == tra_precommitted)
|
||||||
state = check_precommitted(transaction, rpb);
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS,
|
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,
|
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||||
(void*) pool);
|
(void*) pool);
|
||||||
#endif
|
#endif
|
||||||
@ -2095,7 +2114,7 @@ bool VIO_get(thread_db* tdbb, record_param* rpb, jrd_tra* transaction, MemoryPoo
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE,
|
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,
|
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||||
(void*) pool);
|
(void*) pool);
|
||||||
#endif
|
#endif
|
||||||
@ -2173,7 +2192,7 @@ bool VIO_get_current(thread_db* tdbb,
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
||||||
@ -2203,25 +2222,22 @@ bool VIO_get_current(thread_db* tdbb,
|
|||||||
// For now check the state in the tip_cache or tip bitmap. If
|
// For now check the state in the tip_cache or tip bitmap. If
|
||||||
// record is committed (most cases), this will be faster.
|
// record is committed (most cases), this will be faster.
|
||||||
|
|
||||||
|
|
||||||
int state = (transaction->tra_flags & TRA_read_committed) ?
|
int state = (transaction->tra_flags & TRA_read_committed) ?
|
||||||
TPC_cache_state(tdbb, rpb->rpb_transaction_nr) :
|
TPC_cache_state(tdbb, rpb->rpb_transaction_nr) :
|
||||||
TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
|
TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
|
||||||
|
|
||||||
// Reset the garbage collect active flag if the transaction state is
|
// Reset (if appropriate) the garbage collect active flag to reattempt the backout
|
||||||
// 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.
|
|
||||||
|
|
||||||
if (rpb->rpb_flags & rpb_gc_active)
|
if (rpb->rpb_flags & rpb_gc_active)
|
||||||
{
|
{
|
||||||
if (state == tra_committed)
|
if (checkGCActive(tdbb, rpb, state))
|
||||||
state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead;
|
{
|
||||||
|
waitGCActive(tdbb, rpb);
|
||||||
if (state == tra_dead)
|
continue;
|
||||||
rpb->rpb_flags &= ~rpb_gc_active;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fb_assert(!(rpb->rpb_flags & rpb_gc_active));
|
||||||
|
|
||||||
if (state == tra_precommitted)
|
if (state == tra_precommitted)
|
||||||
state = check_precommitted(transaction, rpb);
|
state = check_precommitted(transaction, rpb);
|
||||||
@ -2243,10 +2259,6 @@ bool VIO_get_current(thread_db* tdbb,
|
|||||||
VIO_backout(tdbb, rpb, transaction);
|
VIO_backout(tdbb, rpb, transaction);
|
||||||
}
|
}
|
||||||
continue;
|
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.
|
// 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;
|
const TraNumber tid_fetch = rpb->rpb_transaction_nr;
|
||||||
|
|
||||||
// Wait as long as it takes for an active transaction which has modified
|
// 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
|
// the record.
|
||||||
// backout a fragmented dead record version, spin wait because it will finish shortly.
|
|
||||||
|
|
||||||
if (!(rpb->rpb_flags & rpb_gc_active))
|
state = wait(tdbb, transaction, rpb);
|
||||||
{
|
|
||||||
state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait);
|
|
||||||
|
|
||||||
if (state == tra_precommitted)
|
if (state == tra_precommitted)
|
||||||
state = check_precommitted(transaction, rpb);
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
@ -2496,12 +2493,12 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
|
|||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES,
|
VIO_trace(DEBUG_WRITES,
|
||||||
"VIO_modify (org_rpb %"QUADFORMAT"d, new_rpb %"QUADFORMAT"d, "
|
"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(),
|
org_rpb->rpb_number.getValue(), new_rpb->rpb_number.getValue(),
|
||||||
transaction ? transaction->tra_number : 0);
|
transaction ? transaction->tra_number : 0);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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",
|
", 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_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr,
|
||||||
org_rpb->rpb_flags, org_rpb->rpb_b_page, org_rpb->rpb_b_line,
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE,
|
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,
|
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||||
(void*) pool);
|
(void*) pool);
|
||||||
|
|
||||||
VIO_trace(DEBUG_TRACE_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
VIO_trace(DEBUG_READS_INFO,
|
||||||
"VIO_next_record got record %"SLONGFORMAT":%d, rpb_trans %"
|
"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",
|
SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS,
|
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);
|
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -3176,7 +3173,7 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES,
|
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(),
|
")\n", rpb->rpb_number.getValue(),
|
||||||
transaction ? transaction->tra_number : 0);
|
transaction ? transaction->tra_number : 0);
|
||||||
#endif
|
#endif
|
||||||
@ -3528,7 +3525,7 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE,
|
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
|
#endif
|
||||||
|
|
||||||
if (transaction->tra_attachment->att_flags & ATT_NO_CLEANUP)
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE,
|
VIO_trace(DEBUG_TRACE,
|
||||||
"VIO_verb_cleanup (transaction %"ULONGFORMAT")\n",
|
"VIO_verb_cleanup (transaction %"SQUADFORMAT")\n",
|
||||||
transaction ? transaction->tra_number : 0);
|
transaction ? transaction->tra_number : 0);
|
||||||
#endif
|
#endif
|
||||||
if (transaction->tra_flags & TRA_system)
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES,
|
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);
|
org_rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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",
|
", 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_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr,
|
||||||
org_rpb->rpb_flags, org_rpb->rpb_b_page, org_rpb->rpb_b_line,
|
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);
|
rpb->rpb_number.getValue(), prior_page, (void*) pool);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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);
|
rpb->rpb_number.getValue(), prior_page, tail, tail_end);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES,
|
VIO_trace(DEBUG_WRITES,
|
||||||
"expunge (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT
|
"expunge (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT
|
||||||
", prior_page %"SLONGFORMAT")\n",
|
", prior_page %"SLONGFORMAT")\n",
|
||||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||||
prior_page);
|
prior_page);
|
||||||
@ -4545,7 +4542,7 @@ static void expunge(thread_db* tdbb, record_param* rpb, const jrd_tra* transacti
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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);
|
rpb->rpb_number.getValue(), prior_page);
|
||||||
|
|
||||||
VIO_trace(DEBUG_WRITES_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE_ALL,
|
VIO_trace(DEBUG_TRACE_ALL,
|
||||||
"prepare_update (transaction %"ULONGFORMAT
|
"prepare_update (transaction %"SQUADFORMAT
|
||||||
", commit_tid read %"ULONGFORMAT", record_param %"QUADFORMAT"d, ",
|
", commit_tid read %"SQUADFORMAT", record_param %"QUADFORMAT"d, ",
|
||||||
transaction ? transaction->tra_number : 0, commit_tid_read,
|
transaction ? transaction->tra_number : 0, commit_tid_read,
|
||||||
rpb ? rpb->rpb_number.getValue() : 0);
|
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);
|
new_rpb ? new_rpb->rpb_number.getValue() : 0);
|
||||||
|
|
||||||
VIO_trace(DEBUG_TRACE_ALL_INFO,
|
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
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT
|
||||||
":%d, prior %p\n",
|
":%d, prior %p\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
@ -5588,20 +5585,19 @@ static int prepare_update( thread_db* tdbb,
|
|||||||
|
|
||||||
int state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
|
int state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr);
|
||||||
|
|
||||||
// Reset the garbage collect active flag if the transaction state is
|
// Reset (if appropriate) the garbage collect active flag to reattempt the backout
|
||||||
// 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.
|
|
||||||
|
|
||||||
if (rpb->rpb_flags & rpb_gc_active)
|
if (rpb->rpb_flags & rpb_gc_active)
|
||||||
{
|
{
|
||||||
if (state == tra_committed)
|
if (checkGCActive(tdbb, rpb, state))
|
||||||
state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead;
|
{
|
||||||
|
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
||||||
if (state == tra_dead)
|
waitGCActive(tdbb, rpb);
|
||||||
rpb->rpb_flags &= ~rpb_gc_active;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fb_assert(!(rpb->rpb_flags & rpb_gc_active));
|
||||||
|
|
||||||
if (state == tra_precommitted)
|
if (state == tra_precommitted)
|
||||||
state = check_precommitted(transaction, rpb);
|
state = check_precommitted(transaction, rpb);
|
||||||
@ -5611,8 +5607,8 @@ static int prepare_update( thread_db* tdbb,
|
|||||||
case tra_committed:
|
case tra_committed:
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
VIO_trace(DEBUG_READS_INFO,
|
||||||
" record's transaction (%"ULONGFORMAT
|
" record's transaction (%"SQUADFORMAT
|
||||||
") is committed (my TID - %"ULONGFORMAT")\n",
|
") is committed (my TID - %"SQUADFORMAT")\n",
|
||||||
rpb->rpb_transaction_nr, transaction->tra_number);
|
rpb->rpb_transaction_nr, transaction->tra_number);
|
||||||
#endif
|
#endif
|
||||||
if (rpb->rpb_flags & rpb_deleted)
|
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
|
// has been updated by another transaction which committed in the
|
||||||
// meantime, we cannot proceed further - update conflict error.
|
// meantime, we cannot proceed further - update conflict error.
|
||||||
|
|
||||||
|
|
||||||
if ((transaction->tra_flags & TRA_read_committed) &&
|
if ((transaction->tra_flags & TRA_read_committed) &&
|
||||||
(commit_tid_read != rpb->rpb_transaction_nr))
|
(commit_tid_read != rpb->rpb_transaction_nr))
|
||||||
{
|
{
|
||||||
@ -5672,8 +5667,8 @@ static int prepare_update( thread_db* tdbb,
|
|||||||
if (state == tra_us)
|
if (state == tra_us)
|
||||||
{
|
{
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
VIO_trace(DEBUG_READS_INFO,
|
||||||
" record's transaction (%"ULONGFORMAT
|
" record's transaction (%"SQUADFORMAT
|
||||||
") is us (my TID - %"ULONGFORMAT")\n",
|
") is us (my TID - %"SQUADFORMAT")\n",
|
||||||
rpb->rpb_transaction_nr, transaction->tra_number);
|
rpb->rpb_transaction_nr, transaction->tra_number);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -5719,35 +5714,19 @@ static int prepare_update( thread_db* tdbb,
|
|||||||
case tra_limbo:
|
case tra_limbo:
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
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",
|
rpb->rpb_transaction_nr, (state == tra_active) ? "active" : "limbo",
|
||||||
transaction->tra_number);
|
transaction->tra_number);
|
||||||
#endif
|
#endif
|
||||||
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
||||||
|
|
||||||
// Wait as long as it takes for an active transaction which has modified
|
// 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
|
// the record.
|
||||||
// backout a fragmented dead record version, spin wait because it will
|
|
||||||
// finish shortly.
|
|
||||||
|
|
||||||
if (!(rpb->rpb_flags & rpb_gc_active))
|
state = wait(tdbb, transaction, rpb);
|
||||||
{
|
|
||||||
state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait);
|
|
||||||
|
|
||||||
if (state == tra_precommitted)
|
if (state == tra_precommitted)
|
||||||
state = check_precommitted(transaction, rpb);
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The snapshot says: transaction was active. The TIP page says: transaction
|
// The snapshot says: transaction was active. The TIP page says: transaction
|
||||||
// is committed. Maybe the transaction was rolled back via a transaction
|
// is committed. Maybe the transaction was rolled back via a transaction
|
||||||
@ -5796,23 +5775,15 @@ static int prepare_update( thread_db* tdbb,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case tra_dead:
|
case tra_dead:
|
||||||
case tra_precommitted:
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_READS_INFO,
|
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);
|
rpb->rpb_transaction_nr, transaction->tra_number);
|
||||||
#endif
|
#endif
|
||||||
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == tra_precommitted)
|
|
||||||
{
|
|
||||||
Attachment::Checkout cout(attachment, FB_FUNCTION);
|
|
||||||
Thread::sleep(100); // milliseconds
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
VIO_backout(tdbb, rpb, transaction);
|
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());
|
"purge (record_param %"QUADFORMAT"d)\n", rpb->rpb_number.getValue());
|
||||||
|
|
||||||
VIO_trace(DEBUG_TRACE_ALL_INFO,
|
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",
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
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
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE_ALL,
|
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);
|
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||||
|
|
||||||
VIO_trace(DEBUG_TRACE_ALL_INFO,
|
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
|
", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT
|
||||||
":%d, prior %p\n",
|
":%d, prior %p\n",
|
||||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||||
@ -5997,7 +5968,7 @@ static void replace_record(thread_db* tdbb,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
record_param temp = *rpb;
|
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);
|
DPM_update(tdbb, rpb, stack, transaction);
|
||||||
delete_tail(tdbb, &temp, rpb->rpb_page, 0, 0);
|
delete_tail(tdbb, &temp, rpb->rpb_page, 0, 0);
|
||||||
|
|
||||||
@ -6136,13 +6107,13 @@ static void update_in_place(thread_db* tdbb,
|
|||||||
|
|
||||||
#ifdef VIO_DEBUG
|
#ifdef VIO_DEBUG
|
||||||
VIO_trace(DEBUG_TRACE_ALL,
|
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",
|
"new_rpb %"QUADFORMAT"d)\n",
|
||||||
transaction ? transaction->tra_number : 0, org_rpb->rpb_number.getValue(),
|
transaction ? transaction->tra_number : 0, org_rpb->rpb_number.getValue(),
|
||||||
new_rpb ? new_rpb->rpb_number.getValue() : 0);
|
new_rpb ? new_rpb->rpb_number.getValue() : 0);
|
||||||
|
|
||||||
VIO_trace(DEBUG_TRACE_ALL_INFO,
|
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",
|
", 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_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr,
|
||||||
org_rpb->rpb_flags, org_rpb->rpb_b_page, org_rpb->rpb_b_line,
|
org_rpb->rpb_flags, org_rpb->rpb_b_page, org_rpb->rpb_b_line,
|
||||||
|
@ -499,7 +499,7 @@ SRQ_PTR LockManager::enqueue(Attachment* attachment,
|
|||||||
UCHAR type,
|
UCHAR type,
|
||||||
lock_ast_t ast_routine,
|
lock_ast_t ast_routine,
|
||||||
void* ast_argument,
|
void* ast_argument,
|
||||||
SLONG data,
|
SINT64 data,
|
||||||
SSHORT lck_wait,
|
SSHORT lck_wait,
|
||||||
SRQ_PTR owner_offset)
|
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);
|
++(m_sharedMemory->getHeader()->lhb_query_data);
|
||||||
|
|
||||||
const srq& data_header = m_sharedMemory->getHeader()->lhb_data[series];
|
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
|
// Simply walk the lock series data queue forward for the minimum
|
||||||
// and backward for the maximum -- it's maintained in sorted order.
|
// 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);
|
++(m_sharedMemory->getHeader()->lhb_read_data);
|
||||||
|
|
||||||
const lbl* const lock = (lbl*) SRQ_ABS_PTR(request->lrq_lock);
|
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)
|
if (lock->lbl_series < LCK_MAX_SERIES)
|
||||||
++(m_sharedMemory->getHeader()->lhb_operations[lock->lbl_series]);
|
++(m_sharedMemory->getHeader()->lhb_operations[lock->lbl_series]);
|
||||||
else
|
else
|
||||||
@ -1013,7 +1014,7 @@ SLONG LockManager::readData(SRQ_PTR request_offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SLONG LockManager::readData2(USHORT series,
|
SINT64 LockManager::readData2(USHORT series,
|
||||||
const UCHAR* value,
|
const UCHAR* value,
|
||||||
USHORT length,
|
USHORT length,
|
||||||
SRQ_PTR owner_offset)
|
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)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
|
@ -168,7 +168,7 @@ struct lbl
|
|||||||
srq lbl_requests; // Requests granted
|
srq lbl_requests; // Requests granted
|
||||||
srq lbl_lhb_hash; // Collision que for hash table
|
srq lbl_lhb_hash; // Collision que for hash table
|
||||||
srq lbl_lhb_data; // Lock data que by series
|
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_series; // Lock series
|
||||||
UCHAR lbl_flags; // Unused. Misc flags
|
UCHAR lbl_flags; // Unused. Misc flags
|
||||||
USHORT lbl_pending_lrq_count; // count of lbl_requests with LRQ_pending
|
USHORT lbl_pending_lrq_count; // count of lbl_requests with LRQ_pending
|
||||||
@ -186,7 +186,7 @@ struct lrq
|
|||||||
USHORT lrq_flags; // Misc crud
|
USHORT lrq_flags; // Misc crud
|
||||||
SRQ_PTR lrq_owner; // Owner making request
|
SRQ_PTR lrq_owner; // Owner making request
|
||||||
SRQ_PTR lrq_lock; // Lock requested
|
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_own_requests; // Locks granted for owner
|
||||||
srq lrq_lbl_requests; // Que of requests (active, pending)
|
srq lrq_lbl_requests; // Que of requests (active, pending)
|
||||||
srq lrq_own_blocks; // Owner block que
|
srq lrq_own_blocks; // Owner block que
|
||||||
@ -405,7 +405,7 @@ public:
|
|||||||
void shutdownOwner(Attachment*, SRQ_PTR*);
|
void shutdownOwner(Attachment*, SRQ_PTR*);
|
||||||
|
|
||||||
SRQ_PTR enqueue(Attachment*, Firebird::CheckStatusWrapper*, SRQ_PTR, const USHORT,
|
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*);
|
bool convert(Attachment*, Firebird::CheckStatusWrapper*, SRQ_PTR, UCHAR, SSHORT, lock_ast_t, void*);
|
||||||
UCHAR downgrade(Attachment*, Firebird::CheckStatusWrapper*, const SRQ_PTR);
|
UCHAR downgrade(Attachment*, Firebird::CheckStatusWrapper*, const SRQ_PTR);
|
||||||
bool dequeue(const SRQ_PTR);
|
bool dequeue(const SRQ_PTR);
|
||||||
@ -413,10 +413,10 @@ public:
|
|||||||
void repost(Attachment*, lock_ast_t, void*, SRQ_PTR);
|
void repost(Attachment*, lock_ast_t, void*, SRQ_PTR);
|
||||||
bool cancelWait(SRQ_PTR);
|
bool cancelWait(SRQ_PTR);
|
||||||
|
|
||||||
SLONG queryData(const USHORT, const USHORT);
|
SINT64 queryData(const USHORT, const USHORT);
|
||||||
SLONG readData(SRQ_PTR);
|
SINT64 readData(SRQ_PTR);
|
||||||
SLONG readData2(USHORT, const UCHAR*, USHORT, SRQ_PTR);
|
SINT64 readData2(USHORT, const UCHAR*, USHORT, SRQ_PTR);
|
||||||
SLONG writeData(SRQ_PTR, SLONG);
|
SINT64 writeData(SRQ_PTR, SINT64);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit LockManager(const Firebird::string&, Firebird::RefPtr<Config>);
|
explicit LockManager(const Firebird::string&, Firebird::RefPtr<Config>);
|
||||||
|
@ -1209,7 +1209,7 @@ static void prt_lock(OUTFILE outfile, const lhb* LOCK_header, const lbl* lock, U
|
|||||||
preLock, rel_lock, rel_lock);
|
preLock, rel_lock, rel_lock);
|
||||||
}
|
}
|
||||||
FPRINTF(outfile,
|
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);
|
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) &&
|
if ((lock->lbl_series == Jrd::LCK_bdb || lock->lbl_series == Jrd::LCK_btr_dont_gc) &&
|
||||||
|
@ -549,17 +549,24 @@ const SvcSwitches actionSwitch[] =
|
|||||||
|
|
||||||
bool getLine(string& dest, const char*& p)
|
bool getLine(string& dest, const char*& p)
|
||||||
{
|
{
|
||||||
unsigned short length = (unsigned short) isc_vax_integer (p, sizeof(unsigned short));
|
const USHORT length = (USHORT) isc_vax_integer(p, sizeof(USHORT));
|
||||||
p += sizeof (unsigned short);
|
p += sizeof(USHORT);
|
||||||
dest.assign(p, length);
|
dest.assign(p, length);
|
||||||
p += length;
|
p += length;
|
||||||
return length > 0;
|
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));
|
const SLONG num = isc_vax_integer(p, sizeof(SLONG));
|
||||||
p += sizeof (unsigned int);
|
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;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,9 +625,14 @@ void printMessage(USHORT number, const SafeArg& arg, bool newLine = true)
|
|||||||
printf("%s", buffer);
|
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[] = {
|
const char* capArray[] = {
|
||||||
@ -641,7 +653,7 @@ void printCapabilities(const char*& p)
|
|||||||
{
|
{
|
||||||
printMessage(57);
|
printMessage(57);
|
||||||
|
|
||||||
int caps = getNumeric(p);
|
int caps = getInt(p);
|
||||||
bool print = false;
|
bool print = false;
|
||||||
|
|
||||||
for (unsigned i = 0; capArray[i]; ++i)
|
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++)
|
switch (*p++)
|
||||||
{
|
{
|
||||||
case isc_info_svc_version:
|
case isc_info_svc_version:
|
||||||
printNumeric(p, 7);
|
printInt(p, 7);
|
||||||
break;
|
break;
|
||||||
case isc_info_svc_server_version:
|
case isc_info_svc_server_version:
|
||||||
printString(p, 8);
|
printString(p, 8);
|
||||||
@ -749,10 +761,10 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq)
|
|||||||
printString(p, 15);
|
printString(p, 15);
|
||||||
break;
|
break;
|
||||||
case isc_spb_num_att:
|
case isc_spb_num_att:
|
||||||
printNumeric(p, 16);
|
printInt(p, 16);
|
||||||
break;
|
break;
|
||||||
case isc_spb_num_db:
|
case isc_spb_num_db:
|
||||||
printNumeric(p, 17);
|
printInt(p, 17);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
status_exception::raise(Arg::Gds(isc_fbsvcmgr_info_err) <<
|
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;
|
break;
|
||||||
case isc_spb_multi_tra_id:
|
case isc_spb_multi_tra_id:
|
||||||
printNumeric(p, 35);
|
printInt(p, 35);
|
||||||
break;
|
break;
|
||||||
case isc_spb_single_tra_id:
|
case isc_spb_single_tra_id:
|
||||||
printNumeric(p, 34);
|
printInt(p, 34);
|
||||||
break;
|
break;
|
||||||
case isc_spb_tra_id:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
status_exception::raise(Arg::Gds(isc_fbsvcmgr_info_err) <<
|
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);
|
getLine(up.last, p);
|
||||||
break;
|
break;
|
||||||
case isc_spb_sec_groupid:
|
case isc_spb_sec_groupid:
|
||||||
up.gid = getNumeric(p);
|
up.gid = getInt(p);
|
||||||
break;
|
break;
|
||||||
case isc_spb_sec_userid:
|
case isc_spb_sec_userid:
|
||||||
up.uid = getNumeric(p);
|
up.uid = getInt(p);
|
||||||
break;
|
break;
|
||||||
case isc_spb_sec_admin:
|
case isc_spb_sec_admin:
|
||||||
up.admin = getNumeric(p);
|
up.admin = getInt(p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case isc_info_svc_line:
|
case isc_info_svc_line:
|
||||||
@ -880,7 +901,7 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case isc_info_svc_stdin:
|
case isc_info_svc_stdin:
|
||||||
stdinRq = getNumeric(p);
|
stdinRq = getInt(p);
|
||||||
if (stdinRq > 0)
|
if (stdinRq > 0)
|
||||||
{
|
{
|
||||||
ret = true;
|
ret = true;
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "../common/classes/timestamp.h"
|
#include "../common/classes/timestamp.h"
|
||||||
#include "../jrd/ibase.h"
|
#include "../jrd/ibase.h"
|
||||||
#include "../jrd/ods.h"
|
#include "../jrd/ods.h"
|
||||||
|
#include "../jrd/ods_proto.h"
|
||||||
#include "../common/os/guid.h"
|
#include "../common/os/guid.h"
|
||||||
#include "../yvalve/gds_proto.h"
|
#include "../yvalve/gds_proto.h"
|
||||||
#include "../common/classes/DbImplementation.h"
|
#include "../common/classes/DbImplementation.h"
|
||||||
@ -58,7 +59,6 @@ void PPG_print_header(const header_page* header, ULONG page,
|
|||||||
else
|
else
|
||||||
uSvc->printf(false, "Database overflow header page information:\n");
|
uSvc->printf(false, "Database overflow header page information:\n");
|
||||||
|
|
||||||
|
|
||||||
if (page == HEADER_PAGE)
|
if (page == HEADER_PAGE)
|
||||||
{
|
{
|
||||||
uSvc->printf(false, "\tFlags\t\t\t%d\n", header->hdr_header.pag_flags);
|
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, "\tPage size\t\t%d\n", header->hdr_page_size);
|
||||||
uSvc->printf(false, "\tODS version\t\t%d.%d\n",
|
uSvc->printf(false, "\tODS version\t\t%d.%d\n",
|
||||||
header->hdr_ods_version & ~ODS_FIREBIRD_FLAG, header->hdr_ods_minor);
|
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 transaction\t%"SQUADFORMAT"\n", Ods::getOIT(header));
|
||||||
uSvc->printf(false, "\tOldest active\t\t%"ULONGFORMAT"\n", header->hdr_oldest_active);
|
uSvc->printf(false, "\tOldest active\t\t%"SQUADFORMAT"\n", Ods::getOAT(header));
|
||||||
uSvc->printf(false, "\tOldest snapshot\t\t%"ULONGFORMAT"\n", header->hdr_oldest_snapshot);
|
uSvc->printf(false, "\tOldest snapshot\t\t%"SQUADFORMAT"\n", Ods::getOST(header));
|
||||||
uSvc->printf(false, "\tNext transaction\t%"ULONGFORMAT"\n", header->hdr_next_transaction);
|
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, "\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);
|
Firebird::DbImplementation imp(header);
|
||||||
uSvc->printf(false, "\tImplementation\t\tHW=%s %s-endian OS=%s CC=%s\n",
|
uSvc->printf(false, "\tImplementation\t\tHW=%s %s-endian OS=%s CC=%s\n",
|
||||||
|
@ -233,7 +233,7 @@ void TracePluginImpl::logRecord(const char* action)
|
|||||||
void TracePluginImpl::logRecordConn(const char* action, ITraceDatabaseConnection* connection)
|
void TracePluginImpl::logRecordConn(const char* action, ITraceDatabaseConnection* connection)
|
||||||
{
|
{
|
||||||
// Lookup connection description
|
// Lookup connection description
|
||||||
const int conn_id = connection->getConnectionID();
|
const AttNumber conn_id = connection->getConnectionID();
|
||||||
bool reg = false;
|
bool reg = false;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
@ -251,7 +251,7 @@ void TracePluginImpl::logRecordConn(const char* action, ITraceDatabaseConnection
|
|||||||
if (reg)
|
if (reg)
|
||||||
{
|
{
|
||||||
string temp;
|
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);
|
config.db_filename.c_str(), conn_id);
|
||||||
record.insert(0, temp);
|
record.insert(0, temp);
|
||||||
break;
|
break;
|
||||||
@ -279,7 +279,7 @@ void TracePluginImpl::logRecordConn(const char* action, ITraceDatabaseConnection
|
|||||||
void TracePluginImpl::logRecordTrans(const char* action, ITraceDatabaseConnection* connection,
|
void TracePluginImpl::logRecordTrans(const char* action, ITraceDatabaseConnection* connection,
|
||||||
ITraceTransaction* transaction)
|
ITraceTransaction* transaction)
|
||||||
{
|
{
|
||||||
const unsigned tra_id = transaction->getTransactionID();
|
const TraNumber tra_id = transaction->getTransactionID();
|
||||||
bool reg = false;
|
bool reg = false;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@ -297,7 +297,7 @@ void TracePluginImpl::logRecordTrans(const char* action, ITraceDatabaseConnectio
|
|||||||
if (reg)
|
if (reg)
|
||||||
{
|
{
|
||||||
string temp;
|
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);
|
record.insert(0, temp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -327,7 +327,7 @@ void TracePluginImpl::logRecordProcFunc(const char* action, ITraceDatabaseConnec
|
|||||||
void TracePluginImpl::logRecordStmt(const char* action, ITraceDatabaseConnection* connection,
|
void TracePluginImpl::logRecordStmt(const char* action, ITraceDatabaseConnection* connection,
|
||||||
ITraceTransaction* transaction, ITraceStatement* statement, bool isSQL)
|
ITraceTransaction* transaction, ITraceStatement* statement, bool isSQL)
|
||||||
{
|
{
|
||||||
const int stmt_id = statement->getStmtID();
|
const StmtNumber stmt_id = statement->getStmtID();
|
||||||
bool reg = false;
|
bool reg = false;
|
||||||
bool log = true;
|
bool log = true;
|
||||||
|
|
||||||
@ -354,7 +354,7 @@ void TracePluginImpl::logRecordStmt(const char* action, ITraceDatabaseConnection
|
|||||||
if (reg)
|
if (reg)
|
||||||
{
|
{
|
||||||
string temp;
|
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);
|
record.insert(0, temp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -952,7 +952,7 @@ void TracePluginImpl::register_connection(ITraceDatabaseConnection* connection)
|
|||||||
|
|
||||||
string tmp(*getDefaultMemoryPool());
|
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();
|
const char* user = connection->getUserName();
|
||||||
if (user)
|
if (user)
|
||||||
@ -1050,7 +1050,7 @@ void TracePluginImpl::register_transaction(ITraceTransaction* transaction)
|
|||||||
TransactionData trans_data;
|
TransactionData trans_data;
|
||||||
trans_data.id = transaction->getTransactionID();
|
trans_data.id = transaction->getTransactionID();
|
||||||
trans_data.description = FB_NEW_POOL(*getDefaultMemoryPool()) string(*getDefaultMemoryPool());
|
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())
|
switch (transaction->getIsolation())
|
||||||
{
|
{
|
||||||
@ -1526,7 +1526,7 @@ void TracePluginImpl::register_blr_statement(ITraceBLRStatement* statement)
|
|||||||
string* description = FB_NEW_POOL(*getDefaultMemoryPool()) string(*getDefaultMemoryPool());
|
string* description = FB_NEW_POOL(*getDefaultMemoryPool()) string(*getDefaultMemoryPool());
|
||||||
|
|
||||||
if (statement->getStmtID()) {
|
if (statement->getStmtID()) {
|
||||||
description->printf(NEWLINE "Statement %d:" NEWLINE, statement->getStmtID());
|
description->printf(NEWLINE "Statement %"SQUADFORMAT":" NEWLINE, statement->getStmtID());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.print_blr)
|
if (config.print_blr)
|
||||||
|
@ -55,7 +55,7 @@ public:
|
|||||||
// Data for tracked (active) connections
|
// Data for tracked (active) connections
|
||||||
struct ConnectionData
|
struct ConnectionData
|
||||||
{
|
{
|
||||||
int id;
|
AttNumber id;
|
||||||
Firebird::string* description;
|
Firebird::string* description;
|
||||||
|
|
||||||
// Deallocate memory used by objects hanging off this structure
|
// Deallocate memory used by objects hanging off this structure
|
||||||
@ -65,19 +65,19 @@ public:
|
|||||||
description = NULL;
|
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;
|
return item.id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Firebird::BePlusTree<ConnectionData, int, Firebird::MemoryPool, ConnectionData>
|
typedef Firebird::BePlusTree<ConnectionData, AttNumber, Firebird::MemoryPool, ConnectionData>
|
||||||
ConnectionsTree;
|
ConnectionsTree;
|
||||||
|
|
||||||
// Data for tracked (active) transactions
|
// Data for tracked (active) transactions
|
||||||
struct TransactionData
|
struct TransactionData
|
||||||
{
|
{
|
||||||
unsigned id;
|
TraNumber id;
|
||||||
Firebird::string* description;
|
Firebird::string* description;
|
||||||
|
|
||||||
// Deallocate memory used by objects hanging off this structure
|
// Deallocate memory used by objects hanging off this structure
|
||||||
@ -87,28 +87,28 @@ public:
|
|||||||
description = NULL;
|
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;
|
return item.id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Firebird::BePlusTree<TransactionData, unsigned, Firebird::MemoryPool, TransactionData>
|
typedef Firebird::BePlusTree<TransactionData, TraNumber, Firebird::MemoryPool, TransactionData>
|
||||||
TransactionsTree;
|
TransactionsTree;
|
||||||
|
|
||||||
// Data for tracked (active) statements
|
// Data for tracked (active) statements
|
||||||
struct StatementData
|
struct StatementData
|
||||||
{
|
{
|
||||||
unsigned int id;
|
StmtNumber id;
|
||||||
Firebird::string* description; // NULL in this field indicates that tracing of this statement is not desired
|
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;
|
return item.id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Firebird::BePlusTree<StatementData, unsigned int, Firebird::MemoryPool, StatementData>
|
typedef Firebird::BePlusTree<StatementData, StmtNumber, Firebird::MemoryPool, StatementData>
|
||||||
StatementsTree;
|
StatementsTree;
|
||||||
|
|
||||||
typedef void* ServiceId;
|
typedef void* ServiceId;
|
||||||
|
@ -79,7 +79,7 @@ Firebird::ITracePlugin* TraceFactoryImpl::trace_create(Firebird::CheckStatusWrap
|
|||||||
|
|
||||||
if (!config.enabled ||
|
if (!config.enabled ||
|
||||||
(config.connection_id && connection &&
|
(config.connection_id && connection &&
|
||||||
(connection->getConnectionID() != SLONG(config.connection_id))))
|
(connection->getConnectionID() != config.connection_id)))
|
||||||
{
|
{
|
||||||
return NULL; // Plugin is not needed, no error happened.
|
return NULL; // Plugin is not needed, no error happened.
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user