From 4e4d8002e5fe9968b4d5a493fdb567ed773ccbab Mon Sep 17 00:00:00 2001 From: dimitr Date: Mon, 19 Oct 2015 13:32:02 +0000 Subject: [PATCH] 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. --- src/alice/alice.cpp | 2 +- src/alice/alice.h | 10 +- src/alice/alice_meta.epp | 7 +- src/alice/alice_meta.h | 2 +- src/alice/tdr.cpp | 29 +- src/alice/tdr_proto.h | 2 +- src/common/UtilSvc.cpp | 1 + src/common/UtilSvc.h | 1 + src/dsql/ExprNodes.cpp | 140 +++++---- src/dsql/Nodes.h | 5 - src/dsql/StmtNodes.cpp | 2 +- src/include/consts_pub.h | 3 + src/include/fb_types.h | 9 +- src/include/firebird/FirebirdInterface.idl | 14 +- src/include/firebird/IdlFbInterfaces.h | 92 +++--- src/jrd/Attachment.cpp | 16 +- src/jrd/Attachment.h | 2 +- src/jrd/Database.cpp | 35 +-- src/jrd/Database.h | 14 +- src/jrd/Monitoring.cpp | 21 +- src/jrd/Monitoring.h | 14 +- src/jrd/Relation.cpp | 21 +- src/jrd/Relation.h | 58 ++-- src/jrd/RuntimeStatistics.cpp | 16 +- src/jrd/SysFunction.cpp | 8 +- src/jrd/VirtualTable.cpp | 4 +- src/jrd/btr.cpp | 134 ++++---- src/jrd/btr.h | 22 ++ src/jrd/btr_proto.h | 4 +- src/jrd/cch.cpp | 25 +- src/jrd/constants.h | 8 +- src/jrd/dpm.epp | 265 ++++++++++------ src/jrd/fields.h | 8 +- src/jrd/filters.cpp | 7 +- src/jrd/idx.cpp | 44 ++- src/jrd/jrd.cpp | 5 +- src/jrd/lck.cpp | 34 +-- src/jrd/lck.h | 8 +- src/jrd/lck_proto.h | 6 +- src/jrd/met.epp | 43 +-- src/jrd/ods.cpp | 121 ++++++-- src/jrd/ods.h | 46 ++- src/jrd/ods_proto.h | 13 + src/jrd/opt.cpp | 13 +- src/jrd/pag.cpp | 47 +-- src/jrd/pag_proto.h | 2 +- src/jrd/recsrc/BufferedStream.cpp | 18 +- src/jrd/recsrc/SortedStream.cpp | 4 +- src/jrd/req.h | 26 +- src/jrd/sbm.h | 7 + src/jrd/svc.cpp | 15 + src/jrd/svc.h | 1 + src/jrd/tpc.cpp | 21 +- src/jrd/tra.cpp | 127 ++++---- src/jrd/tra.h | 13 +- src/jrd/trace/TraceObjects.cpp | 6 +- src/jrd/trace/TraceObjects.h | 29 +- src/jrd/validation.cpp | 21 +- src/jrd/vio.cpp | 339 ++++++++++----------- src/lock/lock.cpp | 21 +- src/lock/lock_proto.h | 14 +- src/lock/print.cpp | 2 +- src/utilities/fbsvcmgr/fbsvcmgr.cpp | 57 ++-- src/utilities/gstat/ppg.cpp | 12 +- src/utilities/ntrace/TracePluginImpl.cpp | 18 +- src/utilities/ntrace/TracePluginImpl.h | 18 +- src/utilities/ntrace/traceplugin.cpp | 2 +- 67 files changed, 1237 insertions(+), 917 deletions(-) diff --git a/src/alice/alice.cpp b/src/alice/alice.cpp index 9c44a0c4a7..abb790ac21 100644 --- a/src/alice/alice.cpp +++ b/src/alice/alice.cpp @@ -308,7 +308,7 @@ int alice(Firebird::UtilSvc* uSvc) ALICE_error(10); // msg 10: transaction number or "all" required } ALICE_upper_case(*argv++, string, sizeof(string)); - if (!(tdgbl->ALICE_data.ua_transaction = atoi(string))) + if (!sscanf(string, "%"SQUADFORMAT, &tdgbl->ALICE_data.ua_transaction)) { if (strcmp(string, "ALL")) { ALICE_error(10); // msg 10: transaction number or "all" required diff --git a/src/alice/alice.h b/src/alice/alice.h index 7834a3700c..7a337762a4 100644 --- a/src/alice/alice.h +++ b/src/alice/alice.h @@ -79,7 +79,7 @@ struct user_action bool ua_read_only; SLONG ua_shutdown_delay; SLONG ua_sweep_interval; - SLONG ua_transaction; + TraNumber ua_transaction; SLONG ua_page_buffers; USHORT ua_debug; ULONG ua_val_errors[MAX_VAL_ERRORS]; @@ -100,19 +100,19 @@ public: UCHAR str_data[2]; }; -// Transaction block: used to store info about a multidatabase transaction. +// Transaction block: used to store info about a multi-database transaction. // Transaction Description Record struct tdr : public pool_alloc { - tdr* tdr_next; // next subtransaction - SLONG tdr_id; // database-specific transaction id + tdr* tdr_next; // next sub-transaction + TraNumber tdr_id; // database-specific transaction id alice_str* tdr_fullpath; // full (possibly) remote pathname const TEXT* tdr_filename; // filename within full pathname alice_str* tdr_host_site; // host for transaction alice_str* tdr_remote_site; // site for remote transaction FB_API_HANDLE tdr_handle; // reconnected transaction handle - FB_API_HANDLE tdr_db_handle; // reattached database handle + FB_API_HANDLE tdr_db_handle; // re-attached database handle USHORT tdr_db_caps; // capabilities of database USHORT tdr_state; // see flags below }; diff --git a/src/alice/alice_meta.epp b/src/alice/alice_meta.epp index 209d1e767d..d0f59bc87d 100644 --- a/src/alice/alice_meta.epp +++ b/src/alice/alice_meta.epp @@ -164,7 +164,7 @@ void MET_get_state(ISC_STATUS* user_status, tdr* trans) * in other databases. */ -tdr* MET_get_transaction(ISC_STATUS* user_status, isc_db_handle handle, SLONG id) +tdr* MET_get_transaction(ISC_STATUS* user_status, isc_db_handle handle, TraNumber id) { FB_API_HANDLE request = 0; tdr* trans = NULL; @@ -328,7 +328,8 @@ static tdr* get_description(ISC_QUAD* blob_id) ++p; tdr* ptr = NULL; // silence uninitialized warning - SLONG id_length, id; + SLONG id_length; + TraNumber id; while (*p) { @@ -344,7 +345,7 @@ static tdr* get_description(ISC_QUAD* blob_id) case TDR_TRANSACTION_ID: id_length = *p++; - id = gds__vax_integer(reinterpret_cast(p), id_length); + id = isc_portable_integer(reinterpret_cast(p), id_length); p += id_length; if (!trans) { trans = ptr = FB_NEW_POOL(*tdgbl->getDefaultPool()) tdr; diff --git a/src/alice/alice_meta.h b/src/alice/alice_meta.h index 670b5000ba..fbd84b04a3 100644 --- a/src/alice/alice_meta.h +++ b/src/alice/alice_meta.h @@ -26,7 +26,7 @@ void MET_disable_wal(ISC_STATUS*, isc_db_handle); void MET_get_state(ISC_STATUS*, tdr*); -tdr* MET_get_transaction(ISC_STATUS*, isc_db_handle, SLONG); +tdr* MET_get_transaction(ISC_STATUS*, isc_db_handle, TraNumber); void MET_set_capabilities(ISC_STATUS*, tdr*); #endif // ALICE_ALICE_META_H diff --git a/src/alice/tdr.cpp b/src/alice/tdr.cpp index 8ccbe468c5..e14672f91f 100644 --- a/src/alice/tdr.cpp +++ b/src/alice/tdr.cpp @@ -53,7 +53,7 @@ static SINT64 ask(); static void print_description(const tdr*); static void reattach_database(tdr*); static void reattach_databases(tdr*); -static bool reconnect(FB_API_HANDLE, SLONG, const TEXT*, SINT64); +static bool reconnect(FB_API_HANDLE, TraNumber, const TEXT*, SINT64); static const UCHAR limbo_info[] = { isc_info_limbo, isc_info_end }; @@ -285,7 +285,7 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche return; } - SLONG id; + TraNumber id; tdr* trans; UCHAR* ptr = buffer; bool flag = true; @@ -298,7 +298,7 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche switch (item) { case isc_info_limbo: - id = gds__vax_integer(ptr, length); + id = isc_portable_integer(ptr, length); if (switches & (sw_commit | sw_rollback | sw_two_phase | sw_prompt)) { TDR_reconnect_multiple(handle, id, name, switches); @@ -312,16 +312,19 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche } if (trans = MET_get_transaction(status_vector, handle, id)) { - tdgbl->uSvc->putSLong(isc_spb_multi_tra_id, id); + if (id > TraNumber(MAX_SLONG)) + tdgbl->uSvc->putSInt64(isc_spb_multi_tra_id_64, id); + else + tdgbl->uSvc->putSLong(isc_spb_multi_tra_id, (SLONG) id); reattach_databases(trans); TDR_get_states(trans); TDR_shutdown_databases(trans); print_description(trans); } + else if (id > TraNumber(MAX_SLONG)) + tdgbl->uSvc->putSInt64(isc_spb_single_tra_id_64, id); else - { - tdgbl->uSvc->putSLong(isc_spb_single_tra_id, id); - } + tdgbl->uSvc->putSLong(isc_spb_single_tra_id, (SLONG) id); ptr += length; break; @@ -362,7 +365,7 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche // gfix user. // -bool TDR_reconnect_multiple(FB_API_HANDLE handle, SLONG id, const TEXT* name, SINT64 switches) +bool TDR_reconnect_multiple(FB_API_HANDLE handle, TraNumber id, const TEXT* name, SINT64 switches) { ISC_STATUS_ARRAY status_vector; @@ -531,7 +534,10 @@ static void print_description(const tdr* trans) // msg 94: Transaction %ld ALICE_print(94, SafeArg() << ptr->tdr_id); } - tdgbl->uSvc->putSLong(isc_spb_tra_id, ptr->tdr_id); + if (ptr->tdr_id > TraNumber(MAX_SLONG)) + tdgbl->uSvc->putSInt64(isc_spb_tra_id_64, ptr->tdr_id); + else + tdgbl->uSvc->putSLong(isc_spb_tra_id, (SLONG) ptr->tdr_id); } switch (ptr->tdr_state) @@ -808,14 +814,13 @@ static void reattach_databases(tdr* trans) // Commit or rollback a named transaction. // -static bool reconnect(FB_API_HANDLE handle, SLONG number, const TEXT* name, SINT64 switches) +static bool reconnect(FB_API_HANDLE handle, TraNumber number, const TEXT* name, SINT64 switches) { ISC_STATUS_ARRAY status_vector; - const SLONG id = gds__vax_integer(reinterpret_cast(&number), 4); FB_API_HANDLE transaction = 0; if (isc_reconnect_transaction(status_vector, &handle, &transaction, - sizeof(id), reinterpret_cast(&id))) + sizeof(number), reinterpret_cast(&number))) { ALICE_print(90, SafeArg() << name); // msg 90: failed to reconnect to a transaction in database %s diff --git a/src/alice/tdr_proto.h b/src/alice/tdr_proto.h index 17803b87a4..bcedfa7513 100644 --- a/src/alice/tdr_proto.h +++ b/src/alice/tdr_proto.h @@ -25,7 +25,7 @@ #define ALICE_TDR_PROTO_H void TDR_list_limbo(FB_API_HANDLE, const TEXT*, const SINT64); -bool TDR_reconnect_multiple(FB_API_HANDLE, SLONG, const TEXT*, SINT64); +bool TDR_reconnect_multiple(FB_API_HANDLE, TraNumber, const TEXT*, SINT64); void TDR_shutdown_databases(tdr*); USHORT TDR_analyze(const tdr*); bool TDR_attach_database(ISC_STATUS*, tdr*, const TEXT*); diff --git a/src/common/UtilSvc.cpp b/src/common/UtilSvc.cpp index 158766b167..53fdf26a29 100644 --- a/src/common/UtilSvc.cpp +++ b/src/common/UtilSvc.cpp @@ -134,6 +134,7 @@ public: virtual void started() { } virtual void putLine(char, const char*) { } virtual void putSLong(char, SLONG) { } + virtual void putSInt64(char, SINT64) { } virtual void putChar(char, char) { } virtual void putBytes(const UCHAR*, FB_SIZE_T) { } virtual ULONG getBytes(UCHAR*, ULONG) { return 0; } diff --git a/src/common/UtilSvc.h b/src/common/UtilSvc.h index 1e30ac277f..f7cb602da9 100644 --- a/src/common/UtilSvc.h +++ b/src/common/UtilSvc.h @@ -60,6 +60,7 @@ public: virtual void printf(bool err, const SCHAR* format, ...) = 0; virtual void putLine(char, const char*) = 0; virtual void putSLong(char, SLONG) = 0; + virtual void putSInt64(char, SINT64) = 0; virtual void putChar(char, char) = 0; virtual void putBytes(const UCHAR*, FB_SIZE_T) = 0; virtual ULONG getBytes(UCHAR*, ULONG) = 0; diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp index 741dd896b3..ec5728d689 100644 --- a/src/dsql/ExprNodes.cpp +++ b/src/dsql/ExprNodes.cpp @@ -6055,12 +6055,29 @@ void InternalInfoNode::genBlr(DsqlCompilerScratch* dsqlScratch) void InternalInfoNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc) { - InfoType infoType = static_cast(arg->as()->getSlong()); + const InfoType infoType = static_cast(arg->as()->getSlong()); - if (infoType == INFO_TYPE_SQLSTATE) - desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii); - else - desc->makeLong(0); + switch (infoType) + { + case INFO_TYPE_SQLSTATE: + desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii); + break; + + case INFO_TYPE_CONNECTION_ID: + case INFO_TYPE_TRANSACTION_ID: + case INFO_TYPE_ROWS_AFFECTED: + desc->makeInt64(0); + break; + + case INFO_TYPE_GDSCODE: + case INFO_TYPE_SQLCODE: + case INFO_TYPE_TRIGGER_ACTION: + desc->makeLong(0); + break; + + default: + fb_assert(false); + } } void InternalInfoNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc) @@ -6071,12 +6088,29 @@ void InternalInfoNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc) arg->getDesc(tdbb, csb, &argDesc); fb_assert(argDesc.dsc_dtype == dtype_long); - InfoType infoType = static_cast(*reinterpret_cast(argDesc.dsc_address)); + const InfoType infoType = static_cast(*reinterpret_cast(argDesc.dsc_address)); - if (infoType == INFO_TYPE_SQLSTATE) - desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii); - else - desc->makeLong(0); + switch (infoType) + { + case INFO_TYPE_SQLSTATE: + desc->makeText(FB_SQLSTATE_LENGTH, ttype_ascii); + break; + + case INFO_TYPE_CONNECTION_ID: + case INFO_TYPE_TRANSACTION_ID: + case INFO_TYPE_ROWS_AFFECTED: + desc->makeInt64(0); + break; + + case INFO_TYPE_GDSCODE: + case INFO_TYPE_SQLCODE: + case INFO_TYPE_TRIGGER_ACTION: + desc->makeLong(0); + break; + + default: + fb_assert(false); + } } ValueExprNode* InternalInfoNode::copy(thread_db* tdbb, NodeCopier& copier) const @@ -6108,53 +6142,53 @@ dsc* InternalInfoNode::execute(thread_db* tdbb, jrd_req* request) const return NULL; fb_assert(value->dsc_dtype == dtype_long); - InfoType infoType = static_cast(*reinterpret_cast(value->dsc_address)); + const InfoType infoType = static_cast(*reinterpret_cast(value->dsc_address)); + + dsc desc; if (infoType == INFO_TYPE_SQLSTATE) { FB_SQLSTATE_STRING sqlstate; request->req_last_xcp.as_sqlstate(sqlstate); - dsc desc; desc.makeText(FB_SQLSTATE_LENGTH, ttype_ascii, (UCHAR*) sqlstate); - EVL_make_value(tdbb, &desc, impure); - - return &impure->vlu_desc; } - - SLONG result = 0; - - switch (infoType) + else { - case INFO_TYPE_CONNECTION_ID: - result = PAG_attachment_id(tdbb); - break; - case INFO_TYPE_TRANSACTION_ID: - //fb_assert(sizeof(result) == sizeof(tdbb->getTransaction()->tra_number)); - // Conversion from unsigned to SLONG, big values will be reported as negative. - result = tdbb->getTransaction()->tra_number; - break; - case INFO_TYPE_GDSCODE: - result = request->req_last_xcp.as_gdscode(); - break; - case INFO_TYPE_SQLCODE: - result = request->req_last_xcp.as_sqlcode(); - break; - case INFO_TYPE_ROWS_AFFECTED: - // CVC: Not sure if this counter can overflow in extreme cases - result = request->req_records_affected.getCount(); - break; - case INFO_TYPE_TRIGGER_ACTION: - result = request->req_trigger_action; - break; - default: - BUGCHECK(232); // msg 232 EVL_expr: invalid operation + SLONG int32_result = 0; + SINT64 int64_result = 0; + + switch (infoType) + { + case INFO_TYPE_CONNECTION_ID: + int64_result = PAG_attachment_id(tdbb); + break; + case INFO_TYPE_TRANSACTION_ID: + int64_result = tdbb->getTransaction()->tra_number; + break; + case INFO_TYPE_GDSCODE: + int32_result = request->req_last_xcp.as_gdscode(); + break; + case INFO_TYPE_SQLCODE: + int32_result = request->req_last_xcp.as_sqlcode(); + break; + case INFO_TYPE_ROWS_AFFECTED: + int64_result = request->req_records_affected.getCount(); + break; + case INFO_TYPE_TRIGGER_ACTION: + int32_result = request->req_trigger_action; + break; + default: + BUGCHECK(232); // msg 232 EVL_expr: invalid operation + } + + if (int64_result) + desc.makeInt64(0, &int64_result); + else + desc.makeLong(0, &int32_result); } - dsc desc; - desc.makeLong(0, &result); EVL_make_value(tdbb, &desc, impure); - return &impure->vlu_desc; } @@ -8130,7 +8164,7 @@ void RecordKeyNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc) { if (dbKeyLength == 8) { - desc->makeLong(0); + desc->makeInt64(0); desc->setNullable(true); } else @@ -8181,13 +8215,13 @@ void RecordKeyNode::getDesc(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, dsc* case blr_record_version: desc->dsc_dtype = dtype_text; desc->dsc_ttype() = ttype_binary; - desc->dsc_length = sizeof(SLONG); + desc->dsc_length = sizeof(SINT64); desc->dsc_scale = 0; desc->dsc_flags = 0; break; case blr_record_version2: - desc->makeLong(0); + desc->makeInt64(0); break; } } @@ -8433,10 +8467,10 @@ dsc* RecordKeyNode::execute(thread_db* /*tdbb*/, jrd_req* request) const // Initialize descriptor - impure->vlu_misc.vlu_long = rpb->rpb_transaction_nr; - impure->vlu_desc.dsc_address = (UCHAR*) &impure->vlu_misc.vlu_long; + impure->vlu_misc.vlu_int64 = rpb->rpb_transaction_nr; + impure->vlu_desc.dsc_address = (UCHAR*) &impure->vlu_misc.vlu_int64; impure->vlu_desc.dsc_dtype = dtype_text; - impure->vlu_desc.dsc_length = 4; + impure->vlu_desc.dsc_length = sizeof(SINT64); impure->vlu_desc.dsc_ttype() = ttype_binary; } else if (blrOp == blr_record_version2) @@ -8450,8 +8484,8 @@ dsc* RecordKeyNode::execute(thread_db* /*tdbb*/, jrd_req* request) const return NULL; } - impure->vlu_misc.vlu_long = rpb->rpb_transaction_nr; - impure->vlu_desc.makeLong(0, &impure->vlu_misc.vlu_long); + impure->vlu_misc.vlu_int64 = rpb->rpb_transaction_nr; + impure->vlu_desc.makeInt64(0, &impure->vlu_misc.vlu_int64); } return &impure->vlu_desc; diff --git a/src/dsql/Nodes.h b/src/dsql/Nodes.h index ee5e2b3f7f..c9c127a20c 100644 --- a/src/dsql/Nodes.h +++ b/src/dsql/Nodes.h @@ -60,11 +60,6 @@ const StreamType STREAM_MAP_LENGTH = MAX_STREAMS + 2; // New formula is simply MAX_STREAMS / BITS_PER_LONG const int OPT_STREAM_BITS = MAX_STREAMS / BITS_PER_LONG; // 128 with 4096 streams -// Number of streams, conjuncts, indices that will be statically allocated -// in various arrays. Larger numbers will have to be allocated dynamically -// CVC: I think we need to have a special, higher value for streams. -const int OPT_STATIC_ITEMS = 64; - typedef Firebird::HalfStaticArray StreamList; typedef Firebird::SortedArray SortedStreamList; diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp index d92f5ab080..fbd3bbd4e9 100644 --- a/src/dsql/StmtNodes.cpp +++ b/src/dsql/StmtNodes.cpp @@ -7358,7 +7358,7 @@ void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch) parameter->par_desc.dsc_dtype = dtype_text; parameter->par_desc.dsc_ttype() = ttype_binary; - parameter->par_desc.dsc_length = relation->rel_dbkey_length / 2; + parameter->par_desc.dsc_length = sizeof(SINT64); } } } diff --git a/src/include/consts_pub.h b/src/include/consts_pub.h index ed22593c03..c81d2f336b 100644 --- a/src/include/consts_pub.h +++ b/src/include/consts_pub.h @@ -468,6 +468,9 @@ #define isc_spb_tra_advise_commit 30 #define isc_spb_tra_advise_rollback 31 #define isc_spb_tra_advise_unknown 33 +#define isc_spb_tra_id_64 46 +#define isc_spb_single_tra_id_64 47 +#define isc_spb_multi_tra_id_64 48 #define isc_spb_rpr_validate_db 0x01 #define isc_spb_rpr_sweep_db 0x02 diff --git a/src/include/fb_types.h b/src/include/fb_types.h index e9e11c2710..01930ff370 100644 --- a/src/include/fb_types.h +++ b/src/include/fb_types.h @@ -142,9 +142,6 @@ typedef USHORT TTYPE_ID; // Stream type, had to move it from dsql/Nodes.h due to circular dependencies. typedef ULONG StreamType; -// The type of Jrd's transaction. -typedef ULONG TraNumber; - // Alignment rule template inline T FB_ALIGN(T n, uintptr_t b) @@ -152,4 +149,10 @@ inline T FB_ALIGN(T n, uintptr_t b) return (T) ((((uintptr_t) n) + b - 1) & ~(b - 1)); } +// Various object IDs (longer-than-32-bit) + +typedef SINT64 AttNumber; +typedef SINT64 TraNumber; +typedef SINT64 StmtNumber; + #endif /* INCLUDE_FB_TYPES_H */ diff --git a/src/include/firebird/FirebirdInterface.idl b/src/include/firebird/FirebirdInterface.idl index 8d7a7aa3e0..66ccbfac77 100644 --- a/src/include/firebird/FirebirdInterface.idl +++ b/src/include/firebird/FirebirdInterface.idl @@ -983,7 +983,7 @@ interface TraceConnection : Versioned interface TraceDatabaseConnection : TraceConnection { - int getConnectionID(); + int64 getConnectionID(); const string getDatabaseName(); } @@ -994,7 +994,7 @@ interface TraceTransaction : Versioned const uint ISOLATION_READ_COMMITTED_RECVER = 3; const uint ISOLATION_READ_COMMITTED_NORECVER = 4; - uint getTransactionID(); + int64 getTransactionID(); boolean getReadOnly(); int getWait(); uint getIsolation(); @@ -1009,7 +1009,7 @@ interface TraceParams : Versioned interface TraceStatement : Versioned { - int getStmtID(); + int64 getStmtID(); PerformanceInfo* getPerf(); } @@ -1092,10 +1092,10 @@ interface TraceStatusVector : Versioned interface TraceSweepInfo : Versioned { - uint64 getOIT(); - uint64 getOST(); - uint64 getOAT(); - uint64 getNext(); + int64 getOIT(); + int64 getOST(); + int64 getOAT(); + int64 getNext(); PerformanceInfo* getPerf(); } diff --git a/src/include/firebird/IdlFbInterfaces.h b/src/include/firebird/IdlFbInterfaces.h index d10fec85e9..4b64aedd61 100644 --- a/src/include/firebird/IdlFbInterfaces.h +++ b/src/include/firebird/IdlFbInterfaces.h @@ -3829,7 +3829,7 @@ namespace Firebird public: struct VTable : public ITraceConnection::VTable { - int (CLOOP_CARG *getConnectionID)(ITraceDatabaseConnection* self) throw(); + ISC_INT64 (CLOOP_CARG *getConnectionID)(ITraceDatabaseConnection* self) throw(); const char* (CLOOP_CARG *getDatabaseName)(ITraceDatabaseConnection* self) throw(); }; @@ -3846,9 +3846,9 @@ namespace Firebird public: static const unsigned VERSION = 3; - int getConnectionID() + ISC_INT64 getConnectionID() { - int ret = static_cast(this->cloopVTable)->getConnectionID(this); + ISC_INT64 ret = static_cast(this->cloopVTable)->getConnectionID(this); return ret; } @@ -3864,7 +3864,7 @@ namespace Firebird public: struct VTable : public IVersioned::VTable { - unsigned (CLOOP_CARG *getTransactionID)(ITraceTransaction* self) throw(); + ISC_INT64 (CLOOP_CARG *getTransactionID)(ITraceTransaction* self) throw(); FB_BOOLEAN (CLOOP_CARG *getReadOnly)(ITraceTransaction* self) throw(); int (CLOOP_CARG *getWait)(ITraceTransaction* self) throw(); unsigned (CLOOP_CARG *getIsolation)(ITraceTransaction* self) throw(); @@ -3889,9 +3889,9 @@ namespace Firebird static const unsigned ISOLATION_READ_COMMITTED_RECVER = 3; static const unsigned ISOLATION_READ_COMMITTED_NORECVER = 4; - unsigned getTransactionID() + ISC_INT64 getTransactionID() { - unsigned ret = static_cast(this->cloopVTable)->getTransactionID(this); + ISC_INT64 ret = static_cast(this->cloopVTable)->getTransactionID(this); return ret; } @@ -3960,7 +3960,7 @@ namespace Firebird public: struct VTable : public IVersioned::VTable { - int (CLOOP_CARG *getStmtID)(ITraceStatement* self) throw(); + ISC_INT64 (CLOOP_CARG *getStmtID)(ITraceStatement* self) throw(); PerformanceInfo* (CLOOP_CARG *getPerf)(ITraceStatement* self) throw(); }; @@ -3977,9 +3977,9 @@ namespace Firebird public: static const unsigned VERSION = 2; - int getStmtID() + ISC_INT64 getStmtID() { - int ret = static_cast(this->cloopVTable)->getStmtID(this); + ISC_INT64 ret = static_cast(this->cloopVTable)->getStmtID(this); return ret; } @@ -4419,10 +4419,10 @@ namespace Firebird public: struct VTable : public IVersioned::VTable { - ISC_UINT64 (CLOOP_CARG *getOIT)(ITraceSweepInfo* self) throw(); - ISC_UINT64 (CLOOP_CARG *getOST)(ITraceSweepInfo* self) throw(); - ISC_UINT64 (CLOOP_CARG *getOAT)(ITraceSweepInfo* self) throw(); - ISC_UINT64 (CLOOP_CARG *getNext)(ITraceSweepInfo* self) throw(); + ISC_INT64 (CLOOP_CARG *getOIT)(ITraceSweepInfo* self) throw(); + ISC_INT64 (CLOOP_CARG *getOST)(ITraceSweepInfo* self) throw(); + ISC_INT64 (CLOOP_CARG *getOAT)(ITraceSweepInfo* self) throw(); + ISC_INT64 (CLOOP_CARG *getNext)(ITraceSweepInfo* self) throw(); PerformanceInfo* (CLOOP_CARG *getPerf)(ITraceSweepInfo* self) throw(); }; @@ -4439,27 +4439,27 @@ namespace Firebird public: static const unsigned VERSION = 2; - ISC_UINT64 getOIT() + ISC_INT64 getOIT() { - ISC_UINT64 ret = static_cast(this->cloopVTable)->getOIT(this); + ISC_INT64 ret = static_cast(this->cloopVTable)->getOIT(this); return ret; } - ISC_UINT64 getOST() + ISC_INT64 getOST() { - ISC_UINT64 ret = static_cast(this->cloopVTable)->getOST(this); + ISC_INT64 ret = static_cast(this->cloopVTable)->getOST(this); return ret; } - ISC_UINT64 getOAT() + ISC_INT64 getOAT() { - ISC_UINT64 ret = static_cast(this->cloopVTable)->getOAT(this); + ISC_INT64 ret = static_cast(this->cloopVTable)->getOAT(this); return ret; } - ISC_UINT64 getNext() + ISC_INT64 getNext() { - ISC_UINT64 ret = static_cast(this->cloopVTable)->getNext(this); + ISC_INT64 ret = static_cast(this->cloopVTable)->getNext(this); return ret; } @@ -13032,7 +13032,7 @@ namespace Firebird this->cloopVTable = &vTable; } - static int CLOOP_CARG cloopgetConnectionIDDispatcher(ITraceDatabaseConnection* self) throw() + static ISC_INT64 CLOOP_CARG cloopgetConnectionIDDispatcher(ITraceDatabaseConnection* self) throw() { try { @@ -13041,7 +13041,7 @@ namespace Firebird catch (...) { StatusType::catchException(0); - return static_cast(0); + return static_cast(0); } } @@ -13189,7 +13189,7 @@ namespace Firebird { } - virtual int getConnectionID() = 0; + virtual ISC_INT64 getConnectionID() = 0; virtual const char* getDatabaseName() = 0; }; @@ -13217,7 +13217,7 @@ namespace Firebird this->cloopVTable = &vTable; } - static unsigned CLOOP_CARG cloopgetTransactionIDDispatcher(ITraceTransaction* self) throw() + static ISC_INT64 CLOOP_CARG cloopgetTransactionIDDispatcher(ITraceTransaction* self) throw() { try { @@ -13226,7 +13226,7 @@ namespace Firebird catch (...) { StatusType::catchException(0); - return static_cast(0); + return static_cast(0); } } @@ -13296,7 +13296,7 @@ namespace Firebird { } - virtual unsigned getTransactionID() = 0; + virtual ISC_INT64 getTransactionID() = 0; virtual FB_BOOLEAN getReadOnly() = 0; virtual int getWait() = 0; virtual unsigned getIsolation() = 0; @@ -13389,7 +13389,7 @@ namespace Firebird this->cloopVTable = &vTable; } - static int CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw() + static ISC_INT64 CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw() { try { @@ -13398,7 +13398,7 @@ namespace Firebird catch (...) { StatusType::catchException(0); - return static_cast(0); + return static_cast(0); } } @@ -13429,7 +13429,7 @@ namespace Firebird { } - virtual int getStmtID() = 0; + virtual ISC_INT64 getStmtID() = 0; virtual PerformanceInfo* getPerf() = 0; }; @@ -13524,7 +13524,7 @@ namespace Firebird } } - static int CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw() + static ISC_INT64 CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw() { try { @@ -13533,7 +13533,7 @@ namespace Firebird catch (...) { StatusType::catchException(0); - return static_cast(0); + return static_cast(0); } } @@ -13634,7 +13634,7 @@ namespace Firebird } } - static int CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw() + static ISC_INT64 CLOOP_CARG cloopgetStmtIDDispatcher(ITraceStatement* self) throw() { try { @@ -13643,7 +13643,7 @@ namespace Firebird catch (...) { StatusType::catchException(0); - return static_cast(0); + return static_cast(0); } } @@ -14449,7 +14449,7 @@ namespace Firebird this->cloopVTable = &vTable; } - static ISC_UINT64 CLOOP_CARG cloopgetOITDispatcher(ITraceSweepInfo* self) throw() + static ISC_INT64 CLOOP_CARG cloopgetOITDispatcher(ITraceSweepInfo* self) throw() { try { @@ -14458,11 +14458,11 @@ namespace Firebird catch (...) { StatusType::catchException(0); - return static_cast(0); + return static_cast(0); } } - static ISC_UINT64 CLOOP_CARG cloopgetOSTDispatcher(ITraceSweepInfo* self) throw() + static ISC_INT64 CLOOP_CARG cloopgetOSTDispatcher(ITraceSweepInfo* self) throw() { try { @@ -14471,11 +14471,11 @@ namespace Firebird catch (...) { StatusType::catchException(0); - return static_cast(0); + return static_cast(0); } } - static ISC_UINT64 CLOOP_CARG cloopgetOATDispatcher(ITraceSweepInfo* self) throw() + static ISC_INT64 CLOOP_CARG cloopgetOATDispatcher(ITraceSweepInfo* self) throw() { try { @@ -14484,11 +14484,11 @@ namespace Firebird catch (...) { StatusType::catchException(0); - return static_cast(0); + return static_cast(0); } } - static ISC_UINT64 CLOOP_CARG cloopgetNextDispatcher(ITraceSweepInfo* self) throw() + static ISC_INT64 CLOOP_CARG cloopgetNextDispatcher(ITraceSweepInfo* self) throw() { try { @@ -14497,7 +14497,7 @@ namespace Firebird catch (...) { StatusType::catchException(0); - return static_cast(0); + return static_cast(0); } } @@ -14528,10 +14528,10 @@ namespace Firebird { } - virtual ISC_UINT64 getOIT() = 0; - virtual ISC_UINT64 getOST() = 0; - virtual ISC_UINT64 getOAT() = 0; - virtual ISC_UINT64 getNext() = 0; + virtual ISC_INT64 getOIT() = 0; + virtual ISC_INT64 getOST() = 0; + virtual ISC_INT64 getOAT() = 0; + virtual ISC_INT64 getNext() = 0; virtual PerformanceInfo* getPerf() = 0; }; diff --git a/src/jrd/Attachment.cpp b/src/jrd/Attachment.cpp index 61095e4c25..eb5540b321 100644 --- a/src/jrd/Attachment.cpp +++ b/src/jrd/Attachment.cpp @@ -37,6 +37,7 @@ #include "../jrd/ext_proto.h" #include "../jrd/intl_proto.h" #include "../jrd/met_proto.h" +#include "../jrd/tra_proto.h" #include "../jrd/extds/ExtDS.h" @@ -423,16 +424,16 @@ void Jrd::Attachment::initLocks(thread_db* tdbb) const lock_ast_t ast = (att_flags & ATT_system) ? NULL : blockingAstShutdown; - Lock* lock = FB_NEW_RPT(*att_pool, sizeof(SLONG)) - Lock(tdbb, sizeof(SLONG), LCK_attachment, this, ast); + Lock* lock = FB_NEW_RPT(*att_pool, 0) + Lock(tdbb, sizeof(AttNumber), LCK_attachment, this, ast); att_id_lock = lock; - lock->lck_key.lck_long = lock->lck_data = att_attachment_id; + lock->lck_key.lck_long = att_attachment_id; LCK_lock(tdbb, lock, LCK_EX, LCK_WAIT); // Allocate and take the monitoring lock - lock = FB_NEW_RPT(*att_pool, sizeof(SLONG)) - Lock(tdbb, sizeof(SLONG), LCK_monitor, this, blockingAstMonitor); + lock = FB_NEW_RPT(*att_pool, 0) + Lock(tdbb, sizeof(AttNumber), LCK_monitor, this, blockingAstMonitor); att_monitor_lock = lock; lock->lck_key.lck_long = att_attachment_id; LCK_lock(tdbb, lock, LCK_EX, LCK_WAIT); @@ -441,8 +442,8 @@ void Jrd::Attachment::initLocks(thread_db* tdbb) if (!(att_flags & ATT_system)) { - lock = FB_NEW_RPT(*att_pool, sizeof(SLONG)) - Lock(tdbb, sizeof(SLONG), LCK_cancel, this, blockingAstCancel); + lock = FB_NEW_RPT(*att_pool, 0) + Lock(tdbb, sizeof(AttNumber), LCK_cancel, this, blockingAstCancel); att_cancel_lock = lock; lock->lck_key.lck_long = att_attachment_id; } @@ -620,7 +621,6 @@ void Jrd::Attachment::releaseRelations(thread_db* tdbb) } } } - } int Jrd::Attachment::blockingAstShutdown(void* ast_object) diff --git a/src/jrd/Attachment.h b/src/jrd/Attachment.h index a7f607256f..51d109ac5b 100644 --- a/src/jrd/Attachment.h +++ b/src/jrd/Attachment.h @@ -327,7 +327,7 @@ private: public: Firebird::SortedArray att_requests; // Requests belonging to attachment Lock* att_id_lock; // Attachment lock (if any) - SLONG att_attachment_id; // Attachment ID + AttNumber att_attachment_id; // Attachment ID Lock* att_cancel_lock; // Lock to cancel the active request Lock* att_monitor_lock; // Lock for monitoring purposes const ULONG att_lock_owner_id; // ID for the lock manager diff --git a/src/jrd/Database.cpp b/src/jrd/Database.cpp index d9c7e23a29..6e8b3a54c2 100644 --- a/src/jrd/Database.cpp +++ b/src/jrd/Database.cpp @@ -237,7 +237,6 @@ namespace Jrd dbb_flags &= ~(DBB_sweep_in_progress | DBB_sweep_starting); } - void Database::SharedCounter::shutdown(thread_db* tdbb) { for (size_t i = 0; i < TOTAL_ITEMS; i++) @@ -247,36 +246,28 @@ namespace Jrd } } - SLONG Database::SharedCounter::generate(thread_db* tdbb, ULONG space, ULONG prefetch) + SINT64 Database::SharedCounter::generate(thread_db* tdbb, ULONG space, ULONG prefetch) { fb_assert(space < TOTAL_ITEMS); ValueCache* const counter = &m_counters[space]; - if (m_localOnly) - { - SLONG result = 0; - while ( !(result = (SLONG) ++counter->curVal) ) - ; - return result; - } - Database* const dbb = tdbb->getDatabase(); SyncLockGuard guard(&dbb->dbb_sh_counter_sync, SYNC_EXCLUSIVE, "Database::SharedCounter::generate"); - if (!counter->lock) - { - Lock* const lock = - FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock(tdbb, sizeof(SLONG), LCK_shared_counter); - counter->lock = lock; - lock->lck_key.lck_long = space; - LCK_lock(tdbb, lock, LCK_PW, LCK_WAIT); - } + SINT64 result = ++counter->curVal; - SLONG result = (SLONG) ++counter->curVal; - - if (result > counter->maxVal) + if (!m_localOnly && result > counter->maxVal) { - LCK_convert(tdbb, counter->lock, LCK_PW, LCK_WAIT); + if (!counter->lock) + { + counter->lock = + FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock(tdbb, sizeof(SLONG), LCK_shared_counter); + counter->lock->lck_key.lck_long = space; + LCK_lock(tdbb, counter->lock, LCK_PW, LCK_WAIT); + } + else + LCK_convert(tdbb, counter->lock, LCK_PW, LCK_WAIT); + result = LCK_read_data(tdbb, counter->lock); // zero IDs are somewhat special, so let's better skip them diff --git a/src/jrd/Database.h b/src/jrd/Database.h index 858782d764..1ace58e59c 100644 --- a/src/jrd/Database.h +++ b/src/jrd/Database.h @@ -243,8 +243,8 @@ public: struct ValueCache { Lock* lock; // lock which holds shared counter value - Firebird::AtomicCounter curVal; // current value of shared counter lock - SLONG maxVal; // maximum cached value of shared counter lock + SINT64 curVal; // current value of shared counter lock + SINT64 maxVal; // maximum cached value of shared counter lock }; public: @@ -266,7 +266,7 @@ public: delete m_counters[i].lock; } - SLONG generate(thread_db* tdbb, ULONG space, ULONG prefetch = DEFAULT_CACHE_SIZE); + SINT64 generate(thread_db* tdbb, ULONG space, ULONG prefetch = DEFAULT_CACHE_SIZE); void shutdown(thread_db* tdbb); private: @@ -438,7 +438,7 @@ public: TraNumber dbb_oldest_transaction; // Cached "oldest interesting" transaction TraNumber dbb_oldest_snapshot; // Cached "oldest snapshot" of all active transactions TraNumber dbb_next_transaction; // Next transaction id used by NETWARE - SLONG dbb_attachment_id; // Next attachment id for ReadOnly DB's + AttNumber dbb_attachment_id; // Next attachment id for ReadOnly DB's ULONG dbb_page_buffers; // Page buffers from header page GarbageCollector* dbb_garbage_collector; // GarbageCollector class @@ -531,17 +531,17 @@ private: ~Database(); public: - SLONG generateAttachmentId(thread_db* tdbb) + AttNumber generateAttachmentId(thread_db* tdbb) { return dbb_shared_counter.generate(tdbb, SharedCounter::ATTACHMENT_ID_SPACE, 1); } - SLONG generateTransactionId(thread_db* tdbb) + TraNumber generateTransactionId(thread_db* tdbb) { return dbb_shared_counter.generate(tdbb, SharedCounter::TRANSACTION_ID_SPACE, 1); } - SLONG generateStatementId(thread_db* tdbb) + StmtNumber generateStatementId(thread_db* tdbb) { return dbb_shared_counter.generate(tdbb, SharedCounter::STATEMENT_ID_SPACE); } diff --git a/src/jrd/Monitoring.cpp b/src/jrd/Monitoring.cpp index 06ff41a38c..283d3d1177 100644 --- a/src/jrd/Monitoring.cpp +++ b/src/jrd/Monitoring.cpp @@ -135,7 +135,7 @@ void MonitoringData::release() } -void MonitoringData::read(SLONG att_id, TempSpace& temp) +void MonitoringData::read(AttNumber att_id, TempSpace& temp) { offset_t position = 0; @@ -177,7 +177,7 @@ void MonitoringData::read(SLONG att_id, TempSpace& temp) } -ULONG MonitoringData::setup(SLONG att_id) +ULONG MonitoringData::setup(AttNumber att_id) { ensureSpace(sizeof(Element)); @@ -209,7 +209,7 @@ void MonitoringData::write(ULONG offset, ULONG length, const void* buffer) } -void MonitoringData::cleanup(SLONG att_id) +void MonitoringData::cleanup(AttNumber att_id) { // Remove information about the given session @@ -337,7 +337,7 @@ MonitoringSnapshot::MonitoringSnapshot(thread_db* tdbb, MemoryPool& pool) Attachment* const attachment = tdbb->getAttachment(); fb_assert(attachment); - const SLONG self_att_id = attachment->att_attachment_id; + const AttNumber self_att_id = attachment->att_attachment_id; // Initialize record buffers RecordBuffer* const dbb_buffer = allocBuffer(tdbb, pool, rel_mon_database); @@ -379,7 +379,7 @@ MonitoringSnapshot::MonitoringSnapshot(thread_db* tdbb, MemoryPool& pool) ThreadStatusGuard temp_status(tdbb); - for (SLONG* iter = sessions.begin(); iter != sessions.end(); iter++) + for (AttNumber* iter = sessions.begin(); iter != sessions.end(); iter++) { if (*iter != self_att_id) { @@ -403,7 +403,7 @@ MonitoringSnapshot::MonitoringSnapshot(thread_db* tdbb, MemoryPool& pool) ThreadStatusGuard temp_status(tdbb); lock->lck_type = LCK_attachment; - for (SLONG* iter = sessions.begin(); iter != sessions.end(); iter++) + for (AttNumber* iter = sessions.begin(); iter != sessions.end(); iter++) { if (*iter != self_att_id) { @@ -1172,7 +1172,8 @@ void Monitoring::putStatistics(SnapshotData::DumpRecord& record, const RuntimeSt } void Monitoring::putContextVars(SnapshotData::DumpRecord& record, const StringMap& variables, - MonitoringData::Writer& writer, int object_id, bool is_attachment) + MonitoringData::Writer& writer, SINT64 object_id, + bool is_attachment) { StringMap::ConstAccessor accessor(&variables); @@ -1180,10 +1181,8 @@ void Monitoring::putContextVars(SnapshotData::DumpRecord& record, const StringMa { record.reset(rel_mon_ctx_vars); - if (is_attachment) - record.storeInteger(f_mon_ctx_var_att_id, object_id); - else - record.storeInteger(f_mon_ctx_var_tra_id, object_id); + const int field_id = is_attachment ? f_mon_ctx_var_att_id : f_mon_ctx_var_tra_id; + record.storeInteger(field_id, object_id); record.storeString(f_mon_ctx_var_name, accessor.current()->first); record.storeString(f_mon_ctx_var_value, accessor.current()->second); diff --git a/src/jrd/Monitoring.h b/src/jrd/Monitoring.h index c0c6920aa7..5ec26055d0 100644 --- a/src/jrd/Monitoring.h +++ b/src/jrd/Monitoring.h @@ -242,7 +242,7 @@ class MonitoringData FB_FINAL : public Firebird::IpcObject struct Element { - SLONG attId; + AttNumber attId; ULONG length; }; @@ -273,7 +273,7 @@ public: class Writer { public: - Writer(MonitoringData* data, SLONG att_id) + Writer(MonitoringData* data, AttNumber att_id) : dump(data) { fb_assert(dump); @@ -325,7 +325,7 @@ public: Firebird::UCharBuffer buffer; }; - typedef Firebird::HalfStaticArray SessionList; + typedef Firebird::HalfStaticArray SessionList; explicit MonitoringData(const Database*); ~MonitoringData(); @@ -336,11 +336,11 @@ public: void acquire(); void release(); - void read(SLONG, TempSpace&); - ULONG setup(SLONG); + void read(AttNumber, TempSpace&); + ULONG setup(AttNumber); void write(ULONG, ULONG, const void*); - void cleanup(SLONG); + void cleanup(AttNumber); void enumerate(SessionList&); private: @@ -405,7 +405,7 @@ private: static void putStatistics(SnapshotData::DumpRecord&, const RuntimeStatistics&, MonitoringData::Writer&, int, int); static void putContextVars(SnapshotData::DumpRecord&, const Firebird::StringMap&, - MonitoringData::Writer&, int, bool); + MonitoringData::Writer&, SINT64, bool); static void putMemoryUsage(SnapshotData::DumpRecord&, const Firebird::MemoryStats&, MonitoringData::Writer&, int, int); }; diff --git a/src/jrd/Relation.cpp b/src/jrd/Relation.cpp index da93456452..71eafd9b85 100644 --- a/src/jrd/Relation.cpp +++ b/src/jrd/Relation.cpp @@ -44,9 +44,10 @@ RelationPages* jrd_rel::getPagesInternal(thread_db* tdbb, TraNumber tran, bool a Jrd::Attachment* attachment = tdbb->getAttachment(); Database* dbb = tdbb->getDatabase(); - ULONG inst_id; + SINT64 inst_id; // Vlad asked for this compile-time check to make sure we can contain a txn number here - typedef int RangeCheck[sizeof(inst_id) >= sizeof(TraNumber)]; + typedef int RangeCheck1[sizeof(inst_id) >= sizeof(TraNumber)]; + typedef int RangeCheck2[sizeof(inst_id) >= sizeof(AttNumber)]; if (rel_flags & REL_temp_tran) { @@ -136,7 +137,7 @@ RelationPages* jrd_rel::getPagesInternal(thread_db* tdbb, TraNumber tran, bool a #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES, - "jrd_rel::getPages inst %"ULONGFORMAT", irp %"SLONGFORMAT", idx %u, idx_root %"SLONGFORMAT", addr 0x%x\n", + "jrd_rel::getPages inst %"SQUADFORMAT", irp %"SLONGFORMAT", idx %u, idx_root %"SLONGFORMAT", addr 0x%x\n", newPages->rel_instance_id, newPages->rel_index_root, idx->idx_id, @@ -190,13 +191,11 @@ bool jrd_rel::delPages(thread_db* tdbb, TraNumber tran, RelationPages* aPages) rel_pages_inst->remove(pos); - if (pages->rel_index_root) { + if (pages->rel_index_root) IDX_delete_indices(tdbb, this, pages); - } - if (pages->rel_pages) { + if (pages->rel_pages) DPM_delete_relation_pages(tdbb, this, pages); - } pages->free(rel_pages_free); return true; @@ -208,13 +207,13 @@ void jrd_rel::getRelLockKey(thread_db* tdbb, UCHAR* key) memcpy(key, &val, sizeof(ULONG)); key += sizeof(ULONG); - const ULONG inst_id = getPages(tdbb)->rel_instance_id; - memcpy(key, &inst_id, sizeof(ULONG)); + const SINT64 inst_id = getPages(tdbb)->rel_instance_id; + memcpy(key, &inst_id, sizeof(SINT64)); } USHORT jrd_rel::getRelLockKeyLength() const { - return sizeof(ULONG) + sizeof(SLONG); + return sizeof(ULONG) + sizeof(SINT64); } void jrd_rel::cleanUp() @@ -238,7 +237,7 @@ void jrd_rel::fillPagesSnapshot(RelPagesSnapshot& snapshot, const bool attachmen relPages->addRef(); } else if ((rel_flags & REL_temp_conn) && - (ULONG) PAG_attachment_id(snapshot.spt_tdbb) == relPages->rel_instance_id) + PAG_attachment_id(snapshot.spt_tdbb) == relPages->rel_instance_id) { snapshot.add(relPages); relPages->addRef(); diff --git a/src/jrd/Relation.h b/src/jrd/Relation.h index 2e2476ff61..cce9c22f77 100644 --- a/src/jrd/Relation.h +++ b/src/jrd/Relation.h @@ -23,6 +23,7 @@ #define JRD_RELATION_H #include "../jrd/jrd.h" +#include "../jrd/btr.h" #include "../jrd/lck.h" #include "../jrd/pag.h" #include "../jrd/val.h" @@ -68,29 +69,27 @@ typedef Firebird::SortedArray class RelationPages { public: - typedef ULONG RP_INSTANCE_ID; - vcl* rel_pages; // vector of pointer page numbers - RP_INSTANCE_ID rel_instance_id; // 0 or att_attachment_id or tra_number + typedef SINT64 RP_INSTANCE_ID; + vcl* rel_pages; // vector of pointer page numbers + RP_INSTANCE_ID rel_instance_id; // 0 or att_attachment_id or tra_number // Vlad asked for this compile-time check to make sure we can contain a txn number here - typedef int RangeCheck[sizeof(RP_INSTANCE_ID) >= sizeof(TraNumber)]; + typedef int RangeCheck1[sizeof(RP_INSTANCE_ID) >= sizeof(TraNumber)]; + typedef int RangeCheck2[sizeof(RP_INSTANCE_ID) >= sizeof(AttNumber)]; - SLONG rel_index_root; // index root page number - SLONG rel_data_pages; // count of relation data pages - ULONG rel_slot_space; // lowest pointer page with slot space - ULONG rel_pri_data_space; // lowest pointer page with primary data page space - ULONG rel_sec_data_space; // lowest pointer page with secondary data page space - USHORT rel_pg_space_id; + SLONG rel_index_root; // index root page number + SLONG rel_data_pages; // count of relation data pages + ULONG rel_slot_space; // lowest pointer page with slot space + ULONG rel_pri_data_space; // lowest pointer page with primary data page space + ULONG rel_sec_data_space; // lowest pointer page with secondary data page space + USHORT rel_pg_space_id; - RelationPages() - { - rel_pages = 0; - rel_index_root = rel_data_pages = 0; - rel_instance_id = 0; - rel_slot_space = rel_pri_data_space = rel_sec_data_space = 0; - rel_pg_space_id = DB_PAGE_SPACE; - rel_next_free = 0; - useCount = 0; - } + explicit RelationPages() + : rel_pages(NULL), rel_instance_id(0), + rel_index_root(0), rel_data_pages(0), rel_slot_space(0), + rel_pri_data_space(0), rel_sec_data_space(0), + rel_pg_space_id(DB_PAGE_SPACE), rel_next_free(NULL), + useCount(0) + {} inline SLONG addRef() { @@ -99,7 +98,7 @@ public: void free(RelationPages*& nextFree); - static inline ULONG generate(const RelationPages* item) + static inline RP_INSTANCE_ID generate(const RelationPages* item) { return item->rel_instance_id; } @@ -132,7 +131,6 @@ struct frgn vec* frgn_indexes; }; - // Relation block; one is created for each relation referenced // in the database, though it is not really filled out until // the relation is scanned @@ -147,15 +145,17 @@ public: USHORT rel_current_fmt; // Current format number ULONG rel_flags; Format* rel_current_format; // Current record format + Firebird::MetaName rel_name; // ascii relation name - vec* rel_formats; // Known record formats Firebird::MetaName rel_owner_name; // ascii owner + Firebird::MetaName rel_security_name; // security class name for relation + + vec* rel_formats; // Known record formats vec* rel_fields; // vector of field blocks RseNode* rel_view_rse; // view record select expression ViewContexts rel_view_contexts; // sorted array of view contexts - Firebird::MetaName rel_security_name; // security class name for relation ExternalFile* rel_file; // external file name GCRecordList rel_gc_records; // records for garbage collection @@ -228,12 +228,13 @@ private: typedef Firebird::SortedArray< RelationPages*, Firebird::EmptyStorage, - ULONG, // This type should be able to hold a TraNumber value + SINT64, RelationPages> RelationPagesInstances; // Vlad asked for this compile-time check to make sure we can contain a txn number here - typedef int RangeCheck[sizeof(ULONG) >= sizeof(TraNumber)]; + typedef int RangeCheck1[sizeof(SINT64) >= sizeof(TraNumber)]; + typedef int RangeCheck2[sizeof(SINT64) >= sizeof(AttNumber)]; RelationPagesInstances* rel_pages_inst; RelationPages rel_pages_base; @@ -316,8 +317,9 @@ const ULONG REL_gc_lockneed = 0x80000; // gc lock should be acquired /// class jrd_rel inline jrd_rel::jrd_rel(MemoryPool& p) - : rel_pool(&p), rel_flags(REL_gc_lockneed), rel_name(p), rel_owner_name(p), - rel_view_contexts(p), rel_security_name(p), rel_gc_records(p) + : rel_pool(&p), rel_flags(REL_gc_lockneed), + rel_name(p), rel_owner_name(p), rel_security_name(p), + rel_view_contexts(p), rel_gc_records(p) { } diff --git a/src/jrd/RuntimeStatistics.cpp b/src/jrd/RuntimeStatistics.cpp index 378aadfb93..301c2240f3 100644 --- a/src/jrd/RuntimeStatistics.cpp +++ b/src/jrd/RuntimeStatistics.cpp @@ -105,17 +105,19 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att, const RelCounters::const_iterator end = new_stat.rel_counts.end(); for (; new_cnts != end; ++new_cnts) { - if (base_found && base_cnts->getRelationId() == new_cnts->getRelationId()) + const SLONG rel_id = new_cnts->getRelationId(); + + if (base_found && base_cnts->getRelationId() == rel_id) { // Point TraceCounts to counts array from baseline object if (base_cnts->setToDiff(*new_cnts)) { jrd_rel* const relation = - new_cnts->getRelationId() < static_cast(att->att_relations->count()) ? - (*att->att_relations)[new_cnts->getRelationId()] : NULL; + rel_id < static_cast(att->att_relations->count()) ? + (*att->att_relations)[rel_id] : NULL; TraceCounts traceCounts; - traceCounts.trc_relation_id = new_cnts->getRelationId(); + traceCounts.trc_relation_id = rel_id; traceCounts.trc_counters = base_cnts->getCounterVector(); traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL; temp.add(traceCounts); @@ -127,12 +129,12 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att, else { jrd_rel* const relation = - new_cnts->getRelationId() < static_cast(att->att_relations->count()) ? - (*att->att_relations)[new_cnts->getRelationId()] : NULL; + rel_id < static_cast(att->att_relations->count()) ? + (*att->att_relations)[rel_id] : NULL; // Point TraceCounts to counts array from object with updated counters TraceCounts traceCounts; - traceCounts.trc_relation_id = new_cnts->getRelationId(); + traceCounts.trc_relation_id = rel_id; traceCounts.trc_counters = new_cnts->getCounterVector(); traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL; temp.add(traceCounts); diff --git a/src/jrd/SysFunction.cpp b/src/jrd/SysFunction.cpp index 70adc57b67..5ed7154cb9 100644 --- a/src/jrd/SysFunction.cpp +++ b/src/jrd/SysFunction.cpp @@ -2164,7 +2164,7 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar else if (nameStr == DATABASE_NAME) resultStr = dbb->dbb_database_name.ToString(); else if (nameStr == SESSION_ID_NAME) - resultStr.printf("%d", PAG_attachment_id(tdbb)); + resultStr.printf("%"SQUADFORMAT, PAG_attachment_id(tdbb)); else if (nameStr == NETWORK_PROTOCOL_NAME) { if (attachment->att_network_protocol.isEmpty()) @@ -2184,7 +2184,7 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar if (!attachment->att_remote_pid) return NULL; - resultStr.printf("%d", attachment->att_remote_pid); + resultStr.printf("%"SLONGFORMAT, attachment->att_remote_pid); } else if (nameStr == CLIENT_PROCESS_NAME) { @@ -2208,7 +2208,7 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar resultStr = attachment->att_user->usr_sql_role_name; } else if (nameStr == TRANSACTION_ID_NAME) - resultStr.printf("%lu", transaction->tra_number); + resultStr.printf("%"SQUADFORMAT, transaction->tra_number); else if (nameStr == ISOLATION_LEVEL_NAME) { if (transaction->tra_flags & TRA_read_committed) @@ -2219,7 +2219,7 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar resultStr = SNAPSHOT_VALUE; } else if (nameStr == LOCK_TIMEOUT_NAME) - resultStr.printf("%d", transaction->tra_lock_timeout); + resultStr.printf("%"SLONGFORMAT, transaction->tra_lock_timeout); else if (nameStr == READ_ONLY_NAME) resultStr = (transaction->tra_flags & TRA_readonly) ? TRUE_VALUE : FALSE_VALUE; else diff --git a/src/jrd/VirtualTable.cpp b/src/jrd/VirtualTable.cpp index c6857490da..bd6d8733e7 100644 --- a/src/jrd/VirtualTable.cpp +++ b/src/jrd/VirtualTable.cpp @@ -90,10 +90,10 @@ void VirtualTable::erase(thread_db* tdbb, record_param* rpb) return; } - const SLONG id = MOV_get_long(&desc, 0); + const SINT64 id = MOV_get_int64(&desc, 0); // Post a blocking request - Lock temp_lock(tdbb, sizeof(SLONG), lock_type); + Lock temp_lock(tdbb, sizeof(SINT64), lock_type); temp_lock.lck_key.lck_long = id; ThreadStatusGuard temp_status(tdbb); diff --git a/src/jrd/btr.cpp b/src/jrd/btr.cpp index b3fcfd2ea5..839b74f239 100644 --- a/src/jrd/btr.cpp +++ b/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 void delete_tree(thread_db*, USHORT, USHORT, PageNumber, PageNumber); static DSC* eval(thread_db*, const ValueExprNode*, DSC*, bool*); -static ULONG fast_load(thread_db*, jrd_rel*, index_desc*, USHORT, AutoPtr&, SelectivityList&); +static ULONG fast_load(thread_db*, IndexCreation&, SelectivityList&); static index_root_page* fetch_root(thread_db*, WIN*, const jrd_rel*, const RelationPages*); static UCHAR* find_node_start_point(btree_page*, temporary_key*, UCHAR*, USHORT*, @@ -378,10 +378,7 @@ void BTR_complement_key(temporary_key* key) void BTR_create(thread_db* tdbb, - jrd_rel* relation, - index_desc* idx, - USHORT key_length, - AutoPtr& scb, + IndexCreation& creation, SelectivityList& selectivity) { /************************************** @@ -396,22 +393,27 @@ void BTR_create(thread_db* tdbb, **************************************/ SET_TDBB(tdbb); - const Database* dbb = tdbb->getDatabase(); + const Database* const dbb = tdbb->getDatabase(); CHECK_DBB(dbb); + jrd_rel* const relation = creation.relation; + index_desc* const idx = creation.index; + // Now that the index id has been checked out, create the index. - idx->idx_root = fast_load(tdbb, relation, idx, key_length, scb, selectivity); + idx->idx_root = fast_load(tdbb, creation, selectivity); // Index is created. Go back to the index root page and update it to // point to the index. - RelationPages* relPages = relation->getPages(tdbb); + RelationPages* const relPages = relation->getPages(tdbb); WIN window(relPages->rel_pg_space_id, relPages->rel_index_root); - index_root_page* root = (index_root_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_root); + index_root_page* const root = (index_root_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_root); CCH_MARK(tdbb, &window); root->irt_rpt[idx->idx_id].irt_root = idx->idx_root; root->irt_rpt[idx->idx_id].irt_flags &= ~irt_in_progress; update_selectivity(root, idx->idx_id, selectivity); + LCK_release(tdbb, creation.lock); + CCH_RELEASE(tdbb, &window); } @@ -1450,18 +1452,14 @@ bool BTR_lookup(thread_db* tdbb, jrd_rel* relation, USHORT id, index_desc* buffe SET_TDBB(tdbb); WIN window(relPages->rel_pg_space_id, -1); - index_root_page* root = fetch_root(tdbb, &window, relation, relPages); - if (!root) { - return false; - } + index_root_page* const root = fetch_root(tdbb, &window, relation, relPages); - if (id >= root->irt_count || !BTR_description(tdbb, relation, root, buffer, id)) - { - CCH_RELEASE(tdbb, &window); + if (!root) return false; - } + + const bool result = (id < root->irt_count && BTR_description(tdbb, relation, root, buffer, id)); CCH_RELEASE(tdbb, &window); - return true; + return result; } @@ -1697,8 +1695,7 @@ void BTR_make_null_key(thread_db* tdbb, const index_desc* idx, temporary_key* ke } -bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, index_desc* idx, - WIN* window) +bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, index_desc* idx, WIN* window) { /************************************** * @@ -1729,16 +1726,11 @@ bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, in } else { - RelationPages* relPages; - if (transaction) - relPages = relation->getPages(tdbb, transaction->tra_number); - else - relPages = relation->getPages(tdbb); + RelationPages* const relPages = transaction ? + relation->getPages(tdbb, transaction->tra_number) : relation->getPages(tdbb); if (!(root = fetch_root(tdbb, window, relation, relPages))) - { return false; - } } for (; id < root->irt_count; ++id) @@ -1746,31 +1738,49 @@ bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, in const index_root_page::irt_repeat* irt_desc = root->irt_rpt + id; if (!irt_desc->irt_root && (irt_desc->irt_flags & irt_in_progress) && transaction) { - const TraNumber trans = irt_desc->irt_transaction; - CCH_RELEASE(tdbb, window); - const int trans_state = TRA_wait(tdbb, transaction, trans, jrd_tra::tra_wait); - if ((trans_state == tra_dead) || (trans_state == tra_committed)) + Lock temp_lock(tdbb, sizeof(SLONG), LCK_idx_reserve); + temp_lock.lck_key.lck_long = (relation->rel_id << 16) | id; + + while (true) { - // clean up this left-over index + const ULONG tra_mask = irt_desc->irt_transaction; + + CCH_RELEASE(tdbb, window); + + if (!LCK_lock(tdbb, &temp_lock, LCK_SR, LCK_WAIT)) + ERR_punt(); + + LCK_release(tdbb, &temp_lock); + + // attempt to clean up this left-over index + root = (index_root_page*) CCH_FETCH(tdbb, window, LCK_write, pag_root); + + if (id >= root->irt_count) + return false; + irt_desc = root->irt_rpt + id; - if (!irt_desc->irt_root && irt_desc->irt_transaction == trans && - (irt_desc->irt_flags & irt_in_progress)) + + if (!irt_desc->irt_root && (irt_desc->irt_flags & irt_in_progress)) { - BTR_delete_index(tdbb, window, id); + if (irt_desc->irt_transaction == tra_mask) + { + BTR_delete_index(tdbb, window, id); + break; + } } - else { + else + { CCH_RELEASE(tdbb, window); + break; } - root = (index_root_page*) CCH_FETCH(tdbb, window, LCK_read, pag_root); - continue; } root = (index_root_page*) CCH_FETCH(tdbb, window, LCK_read, pag_root); } - if (BTR_description(tdbb, relation, root, idx, id)) { + + if (BTR_description(tdbb, relation, root, idx, id)) return true; - } } CCH_RELEASE(tdbb, window); @@ -1865,7 +1875,7 @@ void BTR_remove(thread_db* tdbb, WIN* root_window, index_insertion* insertion) } -void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, index_desc* idx) +void BTR_reserve_slot(thread_db* tdbb, IndexCreation& creation) { /************************************** * @@ -1880,11 +1890,15 @@ void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, **************************************/ SET_TDBB(tdbb); - const Database* dbb = tdbb->getDatabase(); + const Database* const dbb = tdbb->getDatabase(); CHECK_DBB(dbb); + jrd_rel* const relation = creation.relation; + index_desc* const idx = creation.index; + jrd_tra* const transaction = creation.transaction; + fb_assert(relation); - RelationPages* relPages = relation->getPages(tdbb); + RelationPages* const relPages = relation->getPages(tdbb); fb_assert(relPages && relPages->rel_index_root); fb_assert(transaction); @@ -1894,9 +1908,8 @@ void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, // Index id for temporary index instance of global temporary table is // already assigned, use it. const bool use_idx_id = (relPages->rel_instance_id != 0); - if (use_idx_id) { + if (use_idx_id) fb_assert(idx->idx_id <= dbb->dbb_max_idx); - } WIN window(relPages->rel_pg_space_id, relPages->rel_index_root); index_root_page* root = (index_root_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_root); @@ -1935,15 +1948,13 @@ void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, end = root->irt_rpt + root->irt_count; for (index_root_page::irt_repeat* root_idx = root->irt_rpt; root_idx < end; root_idx++) { - if (root_idx->irt_root || (root_idx->irt_flags & irt_in_progress)) { + if (root_idx->irt_root || (root_idx->irt_flags & irt_in_progress)) space = MIN(space, root_idx->irt_desc); - } + if (!root_idx->irt_root && !slot && !(root_idx->irt_flags & irt_in_progress)) { if (!use_idx_id || (root_idx - root->irt_rpt) == idx->idx_id) - { slot = root_idx; - } } } @@ -1980,14 +1991,21 @@ void BTR_reserve_slot(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, fb_assert(idx->idx_count <= MAX_UCHAR); slot->irt_keys = (UCHAR) idx->idx_count; slot->irt_flags = idx->idx_flags | irt_in_progress; - slot->irt_transaction = transaction->tra_number; - + slot->irt_transaction = (ULONG) transaction->tra_number; slot->irt_root = 0; // Exploit the fact idx_repeat structure matches ODS IRTD one memcpy(desc, idx->idx_rpt, len); + fb_assert(!creation.lock); + creation.lock = FB_NEW_RPT(*transaction->tra_pool, 0) IndexReserveLock(tdbb, relation, idx); + + const bool error = !LCK_lock(tdbb, creation.lock, LCK_EX, LCK_WAIT); + CCH_RELEASE(tdbb, &window); + + if (error) + ERR_punt(); } @@ -3259,10 +3277,7 @@ static DSC* eval(thread_db* tdbb, const ValueExprNode* node, DSC* temp, bool* is static ULONG fast_load(thread_db* tdbb, - jrd_rel* relation, - index_desc* idx, - USHORT key_length, - AutoPtr& scb, + IndexCreation& creation, SelectivityList& selectivity) { /************************************** @@ -3291,9 +3306,14 @@ static ULONG fast_load(thread_db* tdbb, #endif SET_TDBB(tdbb); - const Database* dbb = tdbb->getDatabase(); + const Database* const dbb = tdbb->getDatabase(); CHECK_DBB(dbb); + jrd_rel* const relation = creation.relation; + index_desc* const idx = creation.index; + const USHORT key_length = creation.key_length; + Sort* const scb = creation.sort; + const USHORT pageSpaceID = relation->getPages(tdbb)->rel_pg_space_id; // Variable initialization for (int i = 0; i < MAX_LEVELS; i++) @@ -3974,7 +3994,7 @@ static ULONG fast_load(thread_db* tdbb, // do some final housekeeping - scb.reset(); + creation.sort.reset(); // If index flush fails, try to delete the index tree. // If the index delete fails, just go ahead and punt. diff --git a/src/jrd/btr.h b/src/jrd/btr.h index 045e809463..d1437ccedb 100644 --- a/src/jrd/btr.h +++ b/src/jrd/btr.h @@ -47,6 +47,7 @@ class JrdStatement; struct temporary_key; class jrd_tra; class BtrPageGCLock; +class Sort; // Index descriptor block -- used to hold info from index root page @@ -252,6 +253,27 @@ public: static bool isPageGCAllowed(thread_db* tdbb, const PageNumber& page); }; +class IndexReserveLock : public Lock +{ +public: + IndexReserveLock(thread_db* tdbb, const jrd_rel* relation, const index_desc* idx); + ~IndexReserveLock(); + +private: + thread_db* const m_tdbb; +}; + +// Struct used for index creation + +struct IndexCreation +{ + jrd_rel* relation; + index_desc* index; + jrd_tra* transaction; + USHORT key_length; + Firebird::AutoPtr lock; + Firebird::AutoPtr sort; +}; // Class used to report any index related errors diff --git a/src/jrd/btr_proto.h b/src/jrd/btr_proto.h index 8fe021f694..71a38586fa 100644 --- a/src/jrd/btr_proto.h +++ b/src/jrd/btr_proto.h @@ -31,7 +31,7 @@ USHORT BTR_all(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::IndexDescAlloc**, Jrd::RelationPages*); void BTR_complement_key(Jrd::temporary_key*); -void BTR_create(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::index_desc*, USHORT, Firebird::AutoPtr&, Jrd::SelectivityList&); +void BTR_create(Jrd::thread_db*, Jrd::IndexCreation&, Jrd::SelectivityList&); bool BTR_delete_index(Jrd::thread_db*, Jrd::win*, USHORT); bool BTR_description(Jrd::thread_db*, Jrd::jrd_rel*, Ods::index_root_page*, Jrd::index_desc*, USHORT); DSC* BTR_eval_expression(Jrd::thread_db*, Jrd::index_desc*, Jrd::Record*, bool&); @@ -50,7 +50,7 @@ Jrd::idx_e BTR_make_key(Jrd::thread_db*, USHORT, const Jrd::ValueExprNode* const void BTR_make_null_key(Jrd::thread_db*, const Jrd::index_desc*, Jrd::temporary_key*); bool BTR_next_index(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::jrd_tra*, Jrd::index_desc*, Jrd::win*); void BTR_remove(Jrd::thread_db*, Jrd::win*, Jrd::index_insertion*); -void BTR_reserve_slot(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::jrd_tra*, Jrd::index_desc*); +void BTR_reserve_slot(Jrd::thread_db*, Jrd::IndexCreation&); void BTR_selectivity(Jrd::thread_db*, Jrd::jrd_rel*, USHORT, Jrd::SelectivityList&); bool BTR_types_comparable(const dsc& target, const dsc& source); diff --git a/src/jrd/cch.cpp b/src/jrd/cch.cpp index da62ef3d30..8a142d41c4 100644 --- a/src/jrd/cch.cpp +++ b/src/jrd/cch.cpp @@ -51,6 +51,7 @@ #include "../jrd/jrd_proto.h" #include "../jrd/lck_proto.h" #include "../jrd/pag_proto.h" +#include "../jrd/ods_proto.h" #include "../jrd/os/pio_proto.h" #include "../jrd/sdw_proto.h" #include "../jrd/shut_proto.h" @@ -2412,8 +2413,8 @@ static Lock* alloc_page_lock(thread_db* tdbb, BufferDesc* bdb) * **************************************/ SET_TDBB(tdbb); - Database* dbb = tdbb->getDatabase(); - BufferControl *bcb = bdb->bdb_bcb; + Database* const dbb = tdbb->getDatabase(); + BufferControl* const bcb = bdb->bdb_bcb; const USHORT lockLen = PageNumber::getLockLen(); @@ -4805,13 +4806,18 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s // the next_transaction > oldest_active transaction if (bdb->bdb_page == HEADER_PAGE_NUMBER) { - const header_page* header = (header_page*) page; - if (header->hdr_next_transaction) + const header_page* const header = (header_page*) page; + + const TraNumber next_transaction = Ods::getNT(header); + const TraNumber oldest_active = Ods::getOAT(header); + const TraNumber oldest_transaction = Ods::getOIT(header); + + if (next_transaction) { - if (header->hdr_oldest_active > header->hdr_next_transaction) + if (oldest_active > next_transaction) BUGCHECK(266); // next transaction older than oldest active - if (header->hdr_oldest_transaction > header->hdr_next_transaction) + if (oldest_transaction > next_transaction) BUGCHECK(267); // next transaction older than oldest transaction } } @@ -4887,7 +4893,7 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s { // We finished. Adjust transaction accounting and get ready for exit if (bdb->bdb_page == HEADER_PAGE_NUMBER) - dbb->dbb_last_header_write = ((header_page*) page)->hdr_next_transaction; + dbb->dbb_last_header_write = Ods::getNT((header_page*) page); } else { @@ -4916,7 +4922,7 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s } if (bdb->bdb_page == HEADER_PAGE_NUMBER) - dbb->dbb_last_header_write = ((header_page*) page)->hdr_next_transaction; + dbb->dbb_last_header_write = Ods::getNT((header_page*) page); if (dbb->dbb_shadow && !isTempPage) result = CCH_write_all_shadows(tdbb, 0, bdb, status, inAst); @@ -4945,7 +4951,8 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s // Destination difference page number is only valid between MARK and // write_page so clean it now to avoid confusion bdb->bdb_difference_page = 0; - bdb->bdb_transactions = bdb->bdb_mark_transaction = 0; + bdb->bdb_transactions = 0; + bdb->bdb_mark_transaction = 0; if (!(bdb->bdb_bcb->bcb_flags & BCB_keep_pages)) removeDirty(bdb->bdb_bcb, bdb); diff --git a/src/jrd/constants.h b/src/jrd/constants.h index e61795d628..2f8c9ebe57 100644 --- a/src/jrd/constants.h +++ b/src/jrd/constants.h @@ -441,7 +441,13 @@ const int DDL_TRIGGER_DROP_MAPPING = 47; #define USERNAME_SWITCH "USER" #define PASSWORD_SWITCH "PASSWORD" -const TraNumber MAX_TRA_NUMBER = ~TraNumber(0); +// The highest transaction number possible +const TraNumber MAX_TRA_NUMBER = 0x0000FFFFFFFFFFFF; // ~2.8 * 10^14 + +// Number of streams, conjuncts, indices that will be statically allocated +// in various arrays. Larger numbers will have to be allocated dynamically +// CVC: I think we need to have a special, higher value for streams. +const int OPT_STATIC_ITEMS = 64; #define CURRENT_ENGINE "Engine12" diff --git a/src/jrd/dpm.epp b/src/jrd/dpm.epp index 01618ead98..5c66f7fdb5 100644 --- a/src/jrd/dpm.epp +++ b/src/jrd/dpm.epp @@ -56,8 +56,10 @@ #include "../jrd/dpm_proto.h" #include "../jrd/err_proto.h" #include "../jrd/exe_proto.h" +#include "../jrd/lck_proto.h" #include "../jrd/met_proto.h" #include "../jrd/mov_proto.h" +#include "../jrd/ods_proto.h" #include "../jrd/pag_proto.h" #include "../common/StatusArg.h" @@ -84,6 +86,50 @@ static rhd* locate_space(thread_db*, record_param*, SSHORT, PageStack&, Record*, static void mark_full(thread_db*, record_param*); static void store_big_record(thread_db*, record_param*, PageStack&, const UCHAR*, ULONG, const Jrd::RecordStorageType type); +namespace +{ + void lock_gc_active(thread_db* tdbb, const jrd_tra* transaction, record_param* rpb) + { + if (rpb->rpb_gc_lock) + { + fb_assert(rpb->rpb_gc_lock->lck_id); + fb_assert(rpb->rpb_gc_lock->lck_logical == LCK_EX); + fb_assert(rpb->rpb_gc_lock->lck_data == transaction->tra_number); + } + else + { + AutoPtr lock(FB_NEW_RPT(*tdbb->getDefaultPool(), 0) + Lock(tdbb, sizeof(SINT64), LCK_record_gc)); + lock->lck_key.lck_long = ((SINT64) rpb->rpb_page << 16) | rpb->rpb_line; + lock->lck_data = transaction->tra_number; + + ThreadStatusGuard temp_status(tdbb); + + if (!LCK_lock(tdbb, lock, LCK_EX, LCK_NO_WAIT)) + { + fb_assert(false); + CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); + ERR_punt(); + } + + rpb->rpb_gc_lock = lock.release(); + } + } + + void release_gc_active(thread_db* tdbb, record_param* rpb) + { + if (rpb->rpb_gc_lock) + { + fb_assert(rpb->rpb_gc_lock->lck_id); + fb_assert(rpb->rpb_gc_lock->lck_logical == LCK_EX); + + LCK_release(tdbb, rpb->rpb_gc_lock); + delete rpb->rpb_gc_lock; + rpb->rpb_gc_lock = NULL; + } + } +} + PAG DPM_allocate(thread_db* tdbb, WIN* window) { @@ -103,7 +149,7 @@ PAG DPM_allocate(thread_db* tdbb, WIN* window) #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - "DPM_allocate (window page %"SLONGFORMAT")\n", + "DPM_allocate (window page %"ULONGFORMAT")\n", window ? window->win_page.getPageNum() : 0); #endif @@ -135,8 +181,8 @@ void DPM_backout( thread_db* tdbb, record_param* rpb) "DPM_backout (record_param %"QUADFORMAT"d)\n", rpb->rpb_number.getValue()); VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %" - SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n", + " record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %" + ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, rpb->rpb_f_line, rpb->rpb_flags); @@ -152,9 +198,11 @@ void DPM_backout( thread_db* tdbb, record_param* rpb) rhd* header = (rhd*) ((SCHAR *) page + index1->dpg_offset); header->rhd_flags &= ~(rhd_chain | rhd_gc_active); + release_gc_active(tdbb, rpb); + #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - " old record %"SLONGFORMAT":%d, new record %"SLONGFORMAT + " old record %"ULONGFORMAT":%d, new record %"ULONGFORMAT ":%d, old dpg_count %d, ", rpb->rpb_page, rpb->rpb_line, rpb->rpb_b_page, rpb->rpb_b_line, page->dpg_count); @@ -195,10 +243,9 @@ void DPM_backout_mark(thread_db* tdbb, record_param* rpb, const jrd_tra* transac rhd* header = (rhd*) ((SCHAR*) page + index->dpg_offset); header->rhd_flags |= rhd_gc_active; - header->rhd_transaction = transaction->tra_number; - rpb->rpb_flags |= rpb_gc_active; - rpb->rpb_transaction_nr = transaction->tra_number; + + lock_gc_active(tdbb, transaction, rpb); CCH_RELEASE(tdbb, window); } @@ -300,8 +347,8 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb) new_rpb ? new_rpb->rpb_number.getValue() : 0); VIO_trace(DEBUG_WRITES_INFO, - " org record %"SLONGFORMAT":%d transaction %"ULONGFORMAT - " back %"SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n", + " org record %"ULONGFORMAT":%d transaction %"ULONGFORMAT + " back %"ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n", org_rpb->rpb_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr, org_rpb->rpb_b_page, org_rpb->rpb_b_line, org_rpb->rpb_f_page, org_rpb->rpb_f_line, org_rpb->rpb_flags); @@ -320,6 +367,8 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb) const Compressor dcc(*tdbb->getDefaultPool(), new_rpb->rpb_length, new_rpb->rpb_address); const ULONG size = (ULONG) dcc.getPackedLength(); + const FB_SIZE_T header_size = (new_rpb->rpb_transaction_nr > MAX_ULONG) ? RHDE_SIZE : RHD_SIZE; + if (!DPM_get(tdbb, org_rpb, LCK_write)) { #ifdef VIO_DEBUG @@ -343,7 +392,6 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb) return false; } - if ((org_rpb->rpb_flags & rpb_delta) && temp.rpb_prior) org_rpb->rpb_prior = temp.rpb_prior; else if (org_rpb->rpb_flags & rpb_delta) @@ -360,7 +408,7 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb) // If the record obviously isn't going to fit, don't even try - if (size > dbb->dbb_page_size - (sizeof(data_page) + RHD_SIZE)) + if (size > dbb->dbb_page_size - (sizeof(data_page) + header_size)) { CCH_RELEASE(tdbb, &org_rpb->getWindow(tdbb)); #ifdef VIO_DEBUG @@ -373,12 +421,12 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb) // The record must be long enough to permit fragmentation later. If it's // too small, compute the number of pad bytes required - SLONG fill = (RHDF_SIZE - RHD_SIZE) - size; + SLONG fill = (RHDF_SIZE - header_size) - size; if (fill < 0 || (new_rpb->rpb_flags & rpb_deleted)) fill = 0; // Accomodate max record size i.e. 64K - const SLONG length = ROUNDUP(RHD_SIZE + size + fill, ODS_ALIGNMENT); + const SLONG length = ROUNDUP(header_size + size + fill, ODS_ALIGNMENT); // Find space on page and open slot @@ -447,19 +495,21 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb) page->dpg_rpt[slot] = *index2; index2->dpg_offset = space; - index2->dpg_length = RHD_SIZE + size + fill; + index2->dpg_length = header_size + size + fill; header = (rhd*) ((SCHAR *) page + space); header->rhd_flags = new_rpb->rpb_flags; - header->rhd_transaction = new_rpb->rpb_transaction_nr; + Ods::writeTraNum(header, new_rpb->rpb_transaction_nr, header_size); header->rhd_format = new_rpb->rpb_format_number; header->rhd_b_page = new_rpb->rpb_b_page; header->rhd_b_line = new_rpb->rpb_b_line; - dcc.pack(new_rpb->rpb_address, header->rhd_data); + UCHAR* const data = (UCHAR*) header + header_size; + + dcc.pack(new_rpb->rpb_address, data); if (fill) - memset(header->rhd_data + size, 0, fill); + memset(data + size, 0, fill); if (page->dpg_header.pag_flags & dpg_swept) { @@ -609,7 +659,7 @@ ULONG DPM_data_pages(thread_db* tdbb, jrd_rel* relation) #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE_ALL, - " returned pages: %"SLONGFORMAT"\n", pages); + " returned pages: %"ULONGFORMAT"\n", pages); #endif return pages; @@ -638,12 +688,12 @@ void DPM_delete( thread_db* tdbb, record_param* rpb, ULONG prior_page) #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES, - "DPM_delete (record_param %"QUADFORMAT", prior_page %"SLONGFORMAT")\n", + "DPM_delete (record_param %"QUADFORMAT", prior_page %"ULONGFORMAT")\n", rpb->rpb_number.getValue(), prior_page); VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %" - SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n", + " record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %" + ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, rpb->rpb_f_line, rpb->rpb_flags); @@ -873,7 +923,7 @@ void DPM_delete( thread_db* tdbb, record_param* rpb, ULONG prior_page) #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - "\tDPM_delete: page %"SLONGFORMAT + "\tDPM_delete: page %"ULONGFORMAT " is empty and about to be released from relation %d\n", window->win_page.getPageNum(), rpb->rpb_relation->rel_id); #endif @@ -1062,7 +1112,7 @@ bool DPM_fetch(thread_db* tdbb, record_param* rpb, USHORT lock) rpb->rpb_number.getValue(), lock); VIO_trace(DEBUG_READS_INFO, - " record %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line); + " record %"ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line); #endif const RecordNumber number = rpb->rpb_number; @@ -1078,8 +1128,8 @@ bool DPM_fetch(thread_db* tdbb, record_param* rpb, USHORT lock) #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %" - SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n", + " record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %" + ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, rpb->rpb_f_line, rpb->rpb_flags); @@ -1124,8 +1174,8 @@ bool DPM_fetch_back(thread_db* tdbb, record_param* rpb, USHORT lock, SSHORT latc rpb->rpb_number.getValue(), lock); VIO_trace(DEBUG_READS_INFO, - " record %"SLONGFORMAT":%d transaction %"ULONGFORMAT - " back %"SLONGFORMAT":%d\n", + " record %"ULONGFORMAT":%d transaction %"ULONGFORMAT + " back %"ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_b_page, rpb->rpb_b_line); #endif @@ -1153,8 +1203,8 @@ bool DPM_fetch_back(thread_db* tdbb, record_param* rpb, USHORT lock, SSHORT latc #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record fetched %"SLONGFORMAT":%d transaction %" - ULONGFORMAT" back %"SLONGFORMAT":%d fragment %"SLONGFORMAT + " record fetched %"ULONGFORMAT":%d transaction %" + ULONGFORMAT" back %"ULONGFORMAT":%d fragment %"ULONGFORMAT ":%d flags %d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, @@ -1188,8 +1238,8 @@ void DPM_fetch_fragment( thread_db* tdbb, record_param* rpb, USHORT lock) rpb->rpb_number.getValue(), lock); VIO_trace(DEBUG_READS_INFO, - " record %"SLONGFORMAT":%d transaction %"ULONGFORMAT - " back %"SLONGFORMAT":%d\n", + " record %"ULONGFORMAT":%d transaction %"ULONGFORMAT + " back %"ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_b_page, rpb->rpb_b_line); #endif @@ -1207,8 +1257,8 @@ void DPM_fetch_fragment( thread_db* tdbb, record_param* rpb, USHORT lock) #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record fetched %"SLONGFORMAT":%d transaction %"ULONGFORMAT - " back %"SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n", + " record fetched %"ULONGFORMAT":%d transaction %"ULONGFORMAT + " back %"ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, rpb->rpb_f_line, rpb->rpb_flags); @@ -1370,7 +1420,7 @@ bool DPM_get(thread_db* tdbb, record_param* rpb, SSHORT lock_type) #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record %"SLONGFORMAT":%d\n", page->ppg_page[slot], line); + " record %"ULONGFORMAT":%d\n", page->ppg_page[slot], line); #endif const ULONG page_number = page->ppg_page[slot]; @@ -1420,7 +1470,7 @@ ULONG DPM_get_blob(thread_db* tdbb, #ifdef VIO_DEBUG VIO_trace(DEBUG_READS, "DPM_get_blob (blob, record_number %"QUADFORMAT - "d, delete_flag %d, prior_page %"SLONGFORMAT")\n", + "d, delete_flag %d, prior_page %"ULONGFORMAT")\n", record_number.getValue(), (int) delete_flag, prior_page); #endif @@ -1724,7 +1774,7 @@ void DPM_pages(thread_db* tdbb, SSHORT rel_id, int type, ULONG sequence, ULONG p #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE_ALL, - "DPM_pages (rel_id %d, type %d, sequence %"ULONGFORMAT", page %"SLONGFORMAT")\n", + "DPM_pages (rel_id %d, type %d, sequence %"ULONGFORMAT", page %"ULONGFORMAT")\n", rel_id, type, sequence, page); #endif @@ -1909,8 +1959,8 @@ void DPM_store( thread_db* tdbb, record_param* rpb, PageStack& stack, const Jrd: rpb->rpb_number.getValue(), type); VIO_trace(DEBUG_WRITES_INFO, - " record to store %"SLONGFORMAT":%d transaction %"ULONGFORMAT - " back %"SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n", + " record to store %"ULONGFORMAT":%d transaction %"ULONGFORMAT + " back %"ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, rpb->rpb_f_line, rpb->rpb_flags); @@ -1919,35 +1969,39 @@ void DPM_store( thread_db* tdbb, record_param* rpb, PageStack& stack, const Jrd: const Compressor dcc(*tdbb->getDefaultPool(), rpb->rpb_length, rpb->rpb_address); const ULONG size = (ULONG) dcc.getPackedLength(); + const FB_SIZE_T header_size = (rpb->rpb_transaction_nr > MAX_ULONG) ? RHDE_SIZE : RHD_SIZE; + // If the record isn't going to fit on a page, even if fragmented, // handle it a little differently. - if (size > dbb->dbb_page_size - (sizeof(data_page) + RHD_SIZE)) + if (size > dbb->dbb_page_size - (sizeof(data_page) + header_size)) { store_big_record(tdbb, rpb, stack, dcc.getControl() + dcc.getControlSize(), size, type); return; } - SLONG fill = (RHDF_SIZE - RHD_SIZE) - size; + SLONG fill = (RHDF_SIZE - header_size) - size; if (fill < 0) fill = 0; // Accomodate max record size i.e. 64K - const SLONG length = RHD_SIZE + size + fill; + const SLONG length = header_size + size + fill; rhd* header = locate_space(tdbb, rpb, (SSHORT) length, stack, NULL, type); header->rhd_flags = rpb->rpb_flags; - header->rhd_transaction = rpb->rpb_transaction_nr; + Ods::writeTraNum(header, rpb->rpb_transaction_nr, header_size); header->rhd_format = rpb->rpb_format_number; header->rhd_b_page = rpb->rpb_b_page; header->rhd_b_line = rpb->rpb_b_line; - dcc.pack(rpb->rpb_address, header->rhd_data); + UCHAR* const data = (UCHAR*) header + header_size; + + dcc.pack(rpb->rpb_address, data); #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT":%d, length %"SLONGFORMAT - ", rpb_flags %d, f_page %"SLONGFORMAT":%d, b_page %"SLONGFORMAT + " record %"ULONGFORMAT":%d, length %"SLONGFORMAT + ", rpb_flags %d, f_page %"ULONGFORMAT":%d, b_page %"ULONGFORMAT ":%d\n", rpb->rpb_page, rpb->rpb_line, length, rpb->rpb_flags, rpb->rpb_f_page, rpb->rpb_f_line, rpb->rpb_b_page, @@ -1955,7 +2009,7 @@ void DPM_store( thread_db* tdbb, record_param* rpb, PageStack& stack, const Jrd: #endif if (fill) - memset(header->rhd_data + size, 0, fill); + memset(data + size, 0, fill); Ods::pag* page = rpb->getWindow(tdbb).win_buffer; if (page->pag_flags & dpg_swept) @@ -2057,7 +2111,7 @@ void DPM_rewrite_header( thread_db* tdbb, record_param* rpb) "DPM_rewrite_header (record_param %"QUADFORMAT"d)\n", rpb->rpb_number.getValue()); VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line); + " record %"ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line); #endif WIN* window = &rpb->getWindow(tdbb); @@ -2066,20 +2120,23 @@ void DPM_rewrite_header( thread_db* tdbb, record_param* rpb) #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - " old flags %d, old transaction %"ULONGFORMAT - ", old format %d, old back record %"SLONGFORMAT":%d\n", - header->rhd_flags, header->rhd_transaction, (int) header->rhd_format, + " old flags %d, old transaction %"SQUADFORMAT + ", old format %d, old back record %"ULONGFORMAT":%d\n", + header->rhd_flags, Ods::getTraNum(header), (int) header->rhd_format, header->rhd_b_page, header->rhd_b_line); VIO_trace(DEBUG_WRITES_INFO, - " new flags %d, new transaction %"ULONGFORMAT - ", new format %d, new back record %"SLONGFORMAT":%d\n", + " new flags %d, new transaction %"SQUADFORMAT + ", new format %d, new back record %"ULONGFORMAT":%d\n", rpb->rpb_flags, rpb->rpb_transaction_nr, rpb->rpb_format_number, rpb->rpb_b_page, rpb->rpb_b_line); #endif + // dimitr: current code is not expected to change the transaction number + fb_assert(rpb->rpb_transaction_nr == Ods::getTraNum(header)); +// Ods::writeTraNum(header, rpb->rpb_transaction_nr); + header->rhd_flags = rpb->rpb_flags; - header->rhd_transaction = rpb->rpb_transaction_nr; header->rhd_format = rpb->rpb_format_number; header->rhd_b_page = rpb->rpb_b_page; header->rhd_b_line = rpb->rpb_b_line; @@ -2108,8 +2165,8 @@ void DPM_update( thread_db* tdbb, record_param* rpb, PageStack* stack, const jrd rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0); VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %" - SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n", + " record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %" + ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, rpb->rpb_f_line, rpb->rpb_flags); @@ -2131,15 +2188,17 @@ void DPM_update( thread_db* tdbb, record_param* rpb, PageStack* stack, const jrd const Compressor dcc(*tdbb->getDefaultPool(), rpb->rpb_length, rpb->rpb_address); const ULONG size = (ULONG) dcc.getPackedLength(); + const FB_SIZE_T header_size = (rpb->rpb_transaction_nr > MAX_ULONG) ? RHDE_SIZE : RHD_SIZE; + // It is critical that the record be padded, if necessary, to the length of // a fragmented record header. Compute the amount of fill required. - SLONG fill = (RHDF_SIZE - RHD_SIZE) - size; + SLONG fill = (RHDF_SIZE - header_size) - size; if (fill < 0) fill = 0; // Accomodate max record size i.e. 64K - const SLONG length = ROUNDUP(RHD_SIZE + size + fill, ODS_ALIGNMENT); + const SLONG length = ROUNDUP(header_size + size + fill, ODS_ALIGNMENT); const USHORT slot = rpb->rpb_line; // Find space on page @@ -2173,29 +2232,33 @@ void DPM_update( thread_db* tdbb, record_param* rpb, PageStack* stack, const jrd fb_assert(space >= top); page->dpg_rpt[slot].dpg_offset = space; - page->dpg_rpt[slot].dpg_length = RHD_SIZE + size + fill; + page->dpg_rpt[slot].dpg_length = header_size + size + fill; rhd* header = (rhd*) ((SCHAR *) page + space); header->rhd_flags = rpb->rpb_flags; - header->rhd_transaction = rpb->rpb_transaction_nr; + Ods::writeTraNum(header, rpb->rpb_transaction_nr, header_size); header->rhd_format = rpb->rpb_format_number; header->rhd_b_page = rpb->rpb_b_page; header->rhd_b_line = rpb->rpb_b_line; - dcc.pack(rpb->rpb_address, header->rhd_data); + release_gc_active(tdbb, rpb); + + UCHAR* const data = (UCHAR*) header + header_size; + + dcc.pack(rpb->rpb_address, data); #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT - ":%d, dpg_length %d, rpb_flags %d, rpb_f record %"SLONGFORMAT - ":%d, rpb_b record %"SLONGFORMAT":%d\n", + " record %"ULONGFORMAT + ":%d, dpg_length %d, rpb_flags %d, rpb_f record %"ULONGFORMAT + ":%d, rpb_b record %"ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, page->dpg_rpt[slot].dpg_length, rpb->rpb_flags, rpb->rpb_f_page, rpb->rpb_f_line, rpb->rpb_b_page, rpb->rpb_b_line); #endif if (fill) - memset(header->rhd_data + size, 0, fill); + memset(data + size, 0, fill); if (page->dpg_header.pag_flags & dpg_swept) { @@ -2254,7 +2317,7 @@ static void check_swept(thread_db* tdbb, record_param* rpb) if (index->dpg_offset) { rhd* header = (rhd*) ((SCHAR*) dpage + index->dpg_offset); - if (header->rhd_transaction > transaction->tra_oldest || + if (Ods::getTraNum(header) > transaction->tra_oldest || header->rhd_flags & (rpb_blob | rpb_chained | rpb_fragment) || header->rhd_b_page) { @@ -2290,7 +2353,7 @@ static USHORT compress(thread_db* tdbb, data_page* page) "compress (page)\n"); VIO_trace(DEBUG_TRACE_ALL_INFO, - " sequence %"SLONGFORMAT"\n", page->dpg_sequence); + " sequence %"ULONGFORMAT"\n", page->dpg_sequence); #endif UCHAR temp_page[MAX_PAGE_SIZE]; @@ -2344,9 +2407,9 @@ static void delete_tail(thread_db* tdbb, rhdf* header, const USHORT page_space, "delete_tail (header, length)\n"); VIO_trace(DEBUG_WRITES_INFO, - " transaction %"ULONGFORMAT" flags %d fragment %" - SLONGFORMAT":%d back %"SLONGFORMAT":%d\n", - header->rhdf_transaction, header->rhdf_flags, + " transaction %"SQUADFORMAT" flags %d fragment %" + ULONGFORMAT":%d back %"ULONGFORMAT":%d\n", + Ods::getTraNum(header), header->rhdf_flags, header->rhdf_f_page, header->rhdf_f_line, header->rhdf_b_page, header->rhdf_b_line); #endif @@ -2477,8 +2540,8 @@ static void fragment(thread_db* tdbb, transaction ? transaction->tra_number : 0); VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT":%d transaction %"ULONGFORMAT" back %" - SLONGFORMAT":%d fragment %"SLONGFORMAT":%d flags %d\n", + " record %"ULONGFORMAT":%d transaction %"ULONGFORMAT" back %" + ULONGFORMAT":%d fragment %"ULONGFORMAT":%d flags %d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, rpb->rpb_f_line, rpb->rpb_flags); @@ -2497,11 +2560,9 @@ static void fragment(thread_db* tdbb, const USHORT line = rpb->rpb_line; rhdf* header; - if (transaction->tra_number != rpb->rpb_transaction_nr) + if (rpb->rpb_transaction_nr != transaction->tra_number) { header = (rhdf*) ((SCHAR *) page + page->dpg_rpt[line].dpg_offset); - header->rhdf_transaction = transaction->tra_number; - header->rhdf_flags |= rhd_gc_active; page->dpg_rpt[line].dpg_length = available_space = length; } else @@ -2521,17 +2582,20 @@ static void fragment(thread_db* tdbb, page->dpg_rpt[line].dpg_offset = space; page->dpg_rpt[line].dpg_length = available_space; } - header->rhdf_transaction = rpb->rpb_transaction_nr; + header->rhdf_b_page = rpb->rpb_b_page; header->rhdf_b_line = rpb->rpb_b_line; } + header->rhdf_flags |= rhd_gc_active; + lock_gc_active(tdbb, transaction, rpb); + #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - " rhdf_transaction %"ULONGFORMAT", window record %"SLONGFORMAT + " rhdf_transaction %"SQUADFORMAT", window record %"ULONGFORMAT ":%d, available_space %d, rhdf_flags %d, rhdf_f record %" - SLONGFORMAT":%d, rhdf_b record %"SLONGFORMAT":%d\n", - header->rhdf_transaction, window->win_page.getPageNum(), line, + ULONGFORMAT":%d, rhdf_b record %"ULONGFORMAT":%d\n", + Ods::getTraNum(header), window->win_page.getPageNum(), line, available_space, header->rhdf_flags, header->rhdf_f_page, header->rhdf_f_line, header->rhdf_b_page, header->rhdf_b_line); #endif @@ -2572,17 +2636,19 @@ static void fragment(thread_db* tdbb, header = (rhdf*) ((SCHAR *) page + page->dpg_rpt[line].dpg_offset); header->rhdf_flags = rhd_incomplete | rpb->rpb_flags; - header->rhdf_transaction = rpb->rpb_transaction_nr; + Ods::writeTraNum(header, rpb->rpb_transaction_nr, RHDF_SIZE); header->rhdf_format = rpb->rpb_format_number; header->rhdf_f_page = tail_rpb.rpb_page; header->rhdf_f_line = tail_rpb.rpb_line; - if (transaction->tra_number != rpb->rpb_transaction_nr) + if (rpb->rpb_transaction_nr != transaction->tra_number) { header->rhdf_b_page = rpb->rpb_b_page; header->rhdf_b_line = rpb->rpb_b_line; } + release_gc_active(tdbb, rpb); + const size_t post_header_length = dcc.pack(rpb->rpb_address, available_space - RHDF_SIZE, header->rhdf_data); @@ -2591,10 +2657,10 @@ static void fragment(thread_db* tdbb, " fragment head \n"); VIO_trace(DEBUG_WRITES_INFO, - " rhdf_trans %"ULONGFORMAT", window record %"SLONGFORMAT - ":%d, dpg_length %d\n\trhdf_flags %d, rhdf_f record %"SLONGFORMAT - ":%d, rhdf_b record %"SLONGFORMAT":%d\n", - header->rhdf_transaction, window->win_page.getPageNum(), line, + " rhdf_trans %"SQUADFORMAT", window record %"ULONGFORMAT + ":%d, dpg_length %d\n\trhdf_flags %d, rhdf_f record %"ULONGFORMAT + ":%d, rhdf_b record %"ULONGFORMAT":%d\n", + Ods::getTraNum(header), window->win_page.getPageNum(), line, page->dpg_rpt[line].dpg_length, header->rhdf_flags, header->rhdf_f_page, header->rhdf_f_line, header->rhdf_b_page, header->rhdf_b_line); @@ -2793,7 +2859,7 @@ static void extend_relation(thread_db* tdbb, jrd_rel* relation, WIN* window, con #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - " extended_relation (relation %d, window_page %"SLONGFORMAT")\n", + " extended_relation (relation %d, window_page %"ULONGFORMAT")\n", relation->rel_id, window->win_page.getPageNum()); #endif } @@ -2952,23 +3018,26 @@ static bool get_header(WIN* window, USHORT line, record_param* rpb) { rpb->rpb_b_page = header->rhdf_b_page; rpb->rpb_b_line = header->rhdf_b_line; - rpb->rpb_transaction_nr = header->rhdf_transaction; + rpb->rpb_transaction_nr = Ods::getTraNum(header); rpb->rpb_format_number = header->rhdf_format; } + FB_SIZE_T header_size; + if (rpb->rpb_flags & rpb_incomplete) { rpb->rpb_f_page = header->rhdf_f_page; rpb->rpb_f_line = header->rhdf_f_line; - rpb->rpb_address = header->rhdf_data; - rpb->rpb_length = index->dpg_length - RHDF_SIZE; + header_size = RHDF_SIZE; } else { - rpb->rpb_address = ((rhd*) header)->rhd_data; - rpb->rpb_length = index->dpg_length - RHD_SIZE; + header_size = (rpb->rpb_flags & rpb_long_tranum) ? RHDE_SIZE : RHD_SIZE; } + rpb->rpb_address = (UCHAR*) header + header_size; + rpb->rpb_length = index->dpg_length - header_size; + return true; } @@ -3221,7 +3290,7 @@ static rhd* locate_space(thread_db* tdbb, #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - " extended relation %d with page %"SLONGFORMAT" to get %d bytes\n", + " extended relation %d with page %"ULONGFORMAT" to get %d bytes\n", relation->rel_id, window->win_page.getPageNum(), size); #endif @@ -3483,8 +3552,8 @@ static void store_big_record(thread_db* tdbb, " back portion\n"); VIO_trace(DEBUG_WRITES_INFO, - " getWindow(tdbb) page %"SLONGFORMAT - ", max_data %d, \n\trhdf_flags %d, prior %"SLONGFORMAT"\n", + " getWindow(tdbb) page %"ULONGFORMAT + ", max_data %d, \n\trhdf_flags %d, prior %"ULONGFORMAT"\n", rpb->getWindow(tdbb).win_page.getPageNum(), max_data, header->rhdf_flags, prior.getPageNum()); #endif @@ -3500,7 +3569,7 @@ static void store_big_record(thread_db* tdbb, rhdf* header = (rhdf*) locate_space(tdbb, rpb, (SSHORT) (RHDF_SIZE + size), stack, NULL, type); header->rhdf_flags = rhd_incomplete | rhd_large | rpb->rpb_flags; - header->rhdf_transaction = rpb->rpb_transaction_nr; + Ods::writeTraNum(header, rpb->rpb_transaction_nr, RHDF_SIZE); header->rhdf_format = rpb->rpb_format_number; header->rhdf_b_page = rpb->rpb_b_page; header->rhdf_b_line = rpb->rpb_b_line; @@ -3515,10 +3584,10 @@ static void store_big_record(thread_db* tdbb, " front part\n"); VIO_trace(DEBUG_WRITES_INFO, - " rhdf_trans %"ULONGFORMAT", rpb_window record %"SLONGFORMAT - ":%d, dpg_length %d \n\trhdf_flags %d, rhdf_f record %"SLONGFORMAT - ":%d, rhdf_b record %"SLONGFORMAT":%d\n", - header->rhdf_transaction, rpb->getWindow(tdbb).win_page.getPageNum(), + " rhdf_trans %"SQUADFORMAT", rpb_window record %"ULONGFORMAT + ":%d, dpg_length %d \n\trhdf_flags %d, rhdf_f record %"ULONGFORMAT + ":%d, rhdf_b record %"ULONGFORMAT":%d\n", + Ods::getTraNum(header), rpb->getWindow(tdbb).win_page.getPageNum(), rpb->rpb_line, page->dpg_rpt[rpb->rpb_line].dpg_length, header->rhdf_flags, header->rhdf_f_page, header->rhdf_f_line, header->rhdf_b_page, header->rhdf_b_line); diff --git a/src/jrd/fields.h b/src/jrd/fields.h index 8d8e15da5d..bff5141fb7 100644 --- a/src/jrd/fields.h +++ b/src/jrd/fields.h @@ -76,7 +76,7 @@ FIELD(fld_mechanism , nam_mechanism , dtype_short , sizeof(SSHORT) , 0 , NULL , true) FIELD(fld_f_descr , nam_desc , dtype_blob , BLOB_SIZE , isc_blob_format , NULL , true) FIELD(fld_fun_type , nam_fun_type , dtype_short , sizeof(SSHORT) , 0 , NULL , true) - FIELD(fld_trans_id , nam_trans_id , dtype_long , sizeof(SLONG) , 0 , NULL , true) + FIELD(fld_trans_id , nam_trans_id , dtype_int64 , sizeof(SINT64) , 0 , NULL , true) FIELD(fld_trans_state , nam_trans_state , dtype_short , sizeof(SSHORT) , 0 , NULL , true) FIELD(fld_time , nam_time , dtype_timestamp, TIMESTAMP_SIZE , 0 , NULL , true) FIELD(fld_trans_desc , nam_trans_desc , dtype_blob , BLOB_SIZE , isc_blob_tra , NULL , true) @@ -127,9 +127,9 @@ FIELD(fld_r_type , nam_r_type , dtype_short , sizeof(SSHORT) , 0 , NULL , true) FIELD(fld_prc_type , nam_prc_type , dtype_short , sizeof(SSHORT) , 0 , NULL , true) - FIELD(fld_att_id , nam_att_id , dtype_long , sizeof(SLONG) , 0 , NULL , true) - FIELD(fld_stmt_id , nam_stmt_id , dtype_long , sizeof(SLONG) , 0 , NULL , true) - FIELD(fld_call_id , nam_call_id , dtype_long , sizeof(SLONG) , 0 , NULL , true) + FIELD(fld_att_id , nam_att_id , dtype_int64 , sizeof(SINT64) , 0 , NULL , true) + FIELD(fld_stmt_id , nam_stmt_id , dtype_int64 , sizeof(SINT64) , 0 , NULL , true) + FIELD(fld_call_id , nam_call_id , dtype_int64 , sizeof(SINT64) , 0 , NULL , true) FIELD(fld_stat_id , nam_stat_id , dtype_long , sizeof(SLONG) , 0 , NULL , true) FIELD(fld_pid , nam_pid , dtype_long , sizeof(SLONG) , 0 , NULL , true) diff --git a/src/jrd/filters.cpp b/src/jrd/filters.cpp index ef70e5ce12..682d3a4168 100644 --- a/src/jrd/filters.cpp +++ b/src/jrd/filters.cpp @@ -1110,11 +1110,8 @@ ISC_STATUS filter_trans(USHORT action, BlobControl* control) break; case TDR_TRANSACTION_ID: - { - const SLONG id = gds__vax_integer(p, length); - sprintf(out, " Transaction id: %"SLONGFORMAT, id); - break; - } + sprintf(out, " Transaction id: %"SQUADFORMAT, isc_portable_integer(p, length)); + break; default: sprintf(out, "item %d not understood", (int) p[-1]); diff --git a/src/jrd/idx.cpp b/src/jrd/idx.cpp index 0515c5b042..7fc2b9e5d8 100644 --- a/src/jrd/idx.cpp +++ b/src/jrd/idx.cpp @@ -105,6 +105,18 @@ static inline USHORT getNullSegment(const temporary_key& key) return MAX_USHORT; } +IndexReserveLock::IndexReserveLock(thread_db* tdbb, const jrd_rel* relation, const index_desc* idx) + : Lock(tdbb, sizeof(SLONG), LCK_idx_reserve), m_tdbb(tdbb) +{ + lck_key.lck_long = (relation->rel_id << 16) | idx->idx_id; +} + +IndexReserveLock::~IndexReserveLock() +{ + LCK_release(m_tdbb, this); +} + + void IDX_check_access(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view, jrd_rel* relation) { /************************************** @@ -129,15 +141,15 @@ void IDX_check_access(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view, jrd_ WIN window(relPages->rel_pg_space_id, -1); WIN referenced_window(relPages->rel_pg_space_id, -1); - while (BTR_next_index(tdbb, relation, 0, &idx, &window)) + while (BTR_next_index(tdbb, relation, NULL, &idx, &window)) { if (idx.idx_flags & idx_foreign) { // find the corresponding primary key index - if (!MET_lookup_partner(tdbb, relation, &idx, 0)) { + if (!MET_lookup_partner(tdbb, relation, &idx, 0)) continue; - } + jrd_rel* referenced_relation = MET_relation(tdbb, idx.idx_primary_relation); MET_scan_relation(tdbb, referenced_relation); const USHORT index_id = idx.idx_primary_index; @@ -264,11 +276,6 @@ void IDX_create_index(thread_db* tdbb, fb_assert(transaction); - BTR_reserve_slot(tdbb, relation, transaction, idx); - - if (index_id) - *index_id = idx->idx_id; - record_param primary, secondary; secondary.rpb_relation = relation; primary.rpb_relation = relation; @@ -297,6 +304,17 @@ void IDX_create_index(thread_db* tdbb, Arg::Gds(isc_keytoobig) << Arg::Str(index_name)); } + IndexCreation creation; + creation.index = idx; + creation.relation = relation; + creation.transaction = transaction; + creation.key_length = key_length; + + BTR_reserve_slot(tdbb, creation); + + if (index_id) + *index_id = idx->idx_id; + RecordStack stack; const UCHAR pad = isDescending ? -1 : 0; @@ -322,9 +340,10 @@ void IDX_create_index(thread_db* tdbb, FPTR_REJECT_DUP_CALLBACK callback = (idx->idx_flags & idx_unique) ? duplicate_key : NULL; void* callback_arg = (idx->idx_flags & idx_unique) ? &ifl_data : NULL; - AutoPtr scb(FB_NEW_POOL(transaction->tra_sorts.getPool()) + Sort* const scb = FB_NEW_POOL(transaction->tra_sorts.getPool()) Sort(dbb, &transaction->tra_sorts, key_length + sizeof(index_sort_record), - 2, 1, key_desc, callback, callback_arg)); + 2, 1, key_desc, callback, callback_arg); + creation.sort = scb; jrd_rel* partner_relation = NULL; USHORT partner_index_id = 0; @@ -520,7 +539,7 @@ void IDX_create_index(thread_db* tdbb, context.raise(tdbb, idx_e_duplicate, error_record); } - BTR_create(tdbb, relation, idx, key_length, scb, selectivity); + BTR_create(tdbb, creation, selectivity); if ((relation->rel_flags & REL_temp_conn) && (relation->getPages(tdbb)->rel_instance_id != 0)) { @@ -528,9 +547,8 @@ void IDX_create_index(thread_db* tdbb, if (idx_lock) { ++idx_lock->idl_count; - if (idx_lock->idl_count == 1) { + if (idx_lock->idl_count == 1) LCK_lock(tdbb, idx_lock->idl_lock, LCK_SR, LCK_WAIT); - } } } } diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index cbdfbc7d05..589e90c1a3 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -993,7 +993,7 @@ public: const char* getRemoteProcessName() { return m_options->dpb_remote_process.c_str(); } // TraceDatabaseConnection implementation - int getConnectionID() { return 0; } + ISC_INT64 getConnectionID() { return 0; } const char* getDatabaseName() { return m_filename; } private: @@ -6267,7 +6267,7 @@ static void init_database_lock(thread_db* tdbb) // Main database lock - Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, 0) + Lock* const lock = FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock(tdbb, 0, LCK_database, dbb, CCH_down_grade_dbb); dbb->dbb_lock = lock; @@ -6430,7 +6430,6 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment) } } - tdbb->setAttachment(NULL); Jrd::Attachment::destroy(attachment); // string were re-saved in the beginning of this function, // keep that in sync please diff --git a/src/jrd/lck.cpp b/src/jrd/lck.cpp index 9693e23f26..e4f508f440 100644 --- a/src/jrd/lck.cpp +++ b/src/jrd/lck.cpp @@ -140,7 +140,6 @@ static const bool compatibility[LCK_max][LCK_max] = //#define COMPATIBLE(st1, st2) compatibility [st1 * LCK_max + st2] const int LOCK_HASH_SIZE = 19; - inline void ENQUEUE(thread_db* tdbb, CheckStatusWrapper* statusVector, Lock* lock, USHORT level, SSHORT wait) { if (lock->lck_compatible) @@ -547,7 +546,9 @@ static SLONG get_owner_handle(thread_db* tdbb, enum lck_t lock_type) case LCK_cancel: case LCK_monitor: case LCK_btr_dont_gc: + case LCK_idx_reserve: case LCK_rel_gc: + case LCK_record_gc: handle = *LCK_OWNER_HANDLE_ATT(tdbb); break; @@ -704,7 +705,7 @@ bool LCK_lock_opt(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait) } -SLONG LCK_query_data(thread_db* tdbb, enum lck_t lock_type, USHORT aggregate) +SINT64 LCK_query_data(thread_db* tdbb, enum lck_t lock_type, USHORT aggregate) { /************************************** * @@ -725,7 +726,7 @@ SLONG LCK_query_data(thread_db* tdbb, enum lck_t lock_type, USHORT aggregate) } -SLONG LCK_read_data(thread_db* tdbb, Lock* lock) +SINT64 LCK_read_data(thread_db* tdbb, Lock* lock) { /************************************** * @@ -742,9 +743,9 @@ SLONG LCK_read_data(thread_db* tdbb, Lock* lock) fb_assert(LCK_CHECK_LOCK(lock)); - const SLONG data = + const SINT64 data = dbb->dbb_lock_mgr->readData2(lock->lck_type, - (UCHAR*) &lock->lck_key, lock->lck_length, + lock->lck_key.lck_string, lock->lck_length, lock->lck_owner_handle); fb_assert(LCK_CHECK_LOCK(lock)); return data; @@ -815,7 +816,7 @@ void LCK_re_post(thread_db* tdbb, Lock* lock) } -void LCK_write_data(thread_db* tdbb, Lock* lock, SLONG data) +void LCK_write_data(thread_db* tdbb, Lock* lock, SINT64 data) { /************************************** * @@ -916,7 +917,7 @@ static void enqueue(thread_db* tdbb, CheckStatusWrapper* statusVector, Lock* loc fb_assert(LCK_CHECK_LOCK(lock)); lock->lck_id = dbb->dbb_lock_mgr->enqueue(att, statusVector, lock->lck_id, - lock->lck_type, (const UCHAR*) &lock->lck_key, lock->lck_length, + lock->lck_type, lock->lck_key.lck_string, lock->lck_length, level, lock->lck_ast, lock->lck_object, lock->lck_data, wait, lock->lck_owner_handle); @@ -1459,21 +1460,21 @@ static bool internal_enqueue(thread_db* tdbb, CheckStatusWrapper* statusVector, Lock::Lock(thread_db* tdbb, USHORT length, lck_t type, void* object, lock_ast_t ast) : lck_dbb(tdbb->getDatabase()), - lck_attachment(0), - lck_compatible(0), - lck_compatible2(0), + lck_attachment(NULL), + lck_compatible(NULL), + lck_compatible2(NULL), lck_ast(ast), lck_object(object), - lck_next(0), - lck_prior(0), - lck_collision(0), - lck_identical(0), + lck_next(NULL), + lck_prior(NULL), + lck_collision(NULL), + lck_identical(NULL), lck_id(0), lck_owner_handle(get_owner_handle(tdbb, type)), lck_length(length), lck_type(type), - lck_logical(0), - lck_physical(0), + lck_logical(LCK_none), + lck_physical(LCK_none), lck_data(0) { lck_key.lck_long = 0; @@ -1525,7 +1526,6 @@ void Lock::setLockAttachment(thread_db* tdbb, Jrd::Attachment* attachment) lck_prior = NULL; } - // Enlist in new attachment if (attachment) { diff --git a/src/jrd/lck.h b/src/jrd/lck.h index 72ee6e0c38..807f72685b 100644 --- a/src/jrd/lck.h +++ b/src/jrd/lck.h @@ -69,7 +69,9 @@ enum lck_t { LCK_fun_exist, // Function existence lock LCK_rel_rescan, // Relation forced rescan lock LCK_crypt, // Crypt lock for single crypt thread - LCK_crypt_status // Notifies about changed database encryption status + LCK_crypt_status, // Notifies about changed database encryption status + LCK_idx_reserve, // Index reservation lock + LCK_record_gc // Record-level GC lock }; // Lock owner types @@ -129,12 +131,12 @@ public: public: UCHAR lck_logical; // Logical lock level UCHAR lck_physical; // Physical lock level - SLONG lck_data; // Data associated with a lock + SINT64 lck_data; // Data associated with a lock union { UCHAR lck_string[1]; - SLONG lck_long; + SINT64 lck_long; } lck_key; // Lock key string UCHAR lck_tail[1]; // Makes the allocator happy diff --git a/src/jrd/lck_proto.h b/src/jrd/lck_proto.h index f80276cdc5..024d7ffb97 100644 --- a/src/jrd/lck_proto.h +++ b/src/jrd/lck_proto.h @@ -40,11 +40,11 @@ void LCK_fini(Jrd::thread_db*, Jrd::lck_owner_t); void LCK_init(Jrd::thread_db*, Jrd::lck_owner_t); bool LCK_lock(Jrd::thread_db*, Jrd::Lock*, USHORT, SSHORT); bool LCK_lock_opt(Jrd::thread_db*, Jrd::Lock*, USHORT, SSHORT); -SLONG LCK_query_data(Jrd::thread_db*, Jrd::lck_t, USHORT); -SLONG LCK_read_data(Jrd::thread_db*, Jrd::Lock*); +SINT64 LCK_query_data(Jrd::thread_db*, Jrd::lck_t, USHORT); +SINT64 LCK_read_data(Jrd::thread_db*, Jrd::Lock*); void LCK_release(Jrd::thread_db*, Jrd::Lock*); void LCK_re_post(Jrd::thread_db*, Jrd::Lock*); -void LCK_write_data(Jrd::thread_db*, Jrd::Lock*, SLONG); +void LCK_write_data(Jrd::thread_db*, Jrd::Lock*, SINT64); class AutoLock diff --git a/src/jrd/met.epp b/src/jrd/met.epp index 5442e52c7c..22263c1c47 100644 --- a/src/jrd/met.epp +++ b/src/jrd/met.epp @@ -135,14 +135,10 @@ static bool verify_TRG_ignore_perm(thread_db*, const MetaName&); static void release_cached_triggers(thread_db* tdbb, trig_vec* vector) { if (!vector) - { return; - } for (FB_SIZE_T i = 0; i < vector->getCount(); i++) - { (*vector)[i].release(tdbb); - } } @@ -186,9 +182,7 @@ static void inc_int_use_count(JrdStatement* statement) static void post_used_procedures(trig_vec* vector) { if (!vector) - { return; - } for (FB_SIZE_T i = 0; i < vector->getCount(); i++) { @@ -355,7 +349,7 @@ void MET_update_partners(thread_db* tdbb) * **************************************/ SET_TDBB(tdbb); - Attachment* attachment = tdbb->getAttachment(); + Attachment* const attachment = tdbb->getAttachment(); vec* relations = attachment->att_relations; @@ -363,9 +357,8 @@ void MET_update_partners(thread_db* tdbb) for (const vec::const_iterator end = relations->end(); ptr < end; ++ptr) { jrd_rel* relation = *ptr; - if (!relation) { + if (!relation) continue; - } // signal other processes LCK_lock(tdbb, relation->rel_partners_lock, LCK_EX, LCK_WAIT); @@ -706,7 +699,7 @@ void MET_clear_cache(thread_db* tdbb) for (jrd_prc** iter = att->att_procedures.begin(); iter != att->att_procedures.end(); ++iter) { - Routine* routine = *iter; + Routine* const routine = *iter; if (routine && routine->getStatement() && !(routine->flags & Routine::FLAG_OBSOLETE) ) @@ -717,7 +710,7 @@ void MET_clear_cache(thread_db* tdbb) for (Function** iter = att->att_functions.begin(); iter != att->att_functions.end(); ++iter) { - Function* routine = *iter; + Function* const routine = *iter; if (routine && routine->getStatement() && !(routine->flags & Routine::FLAG_OBSOLETE) ) @@ -730,7 +723,7 @@ void MET_clear_cache(thread_db* tdbb) for (jrd_prc** iter = att->att_procedures.begin(); iter != att->att_procedures.end(); ++iter) { - Routine* routine = *iter; + Routine* const routine = *iter; if (routine && routine->getStatement() && !(routine->flags & Routine::FLAG_OBSOLETE) && @@ -742,7 +735,7 @@ void MET_clear_cache(thread_db* tdbb) for (Function** iter = att->att_functions.begin(); iter != att->att_functions.end(); ++iter) { - Function* routine = *iter; + Function* const routine = *iter; if (routine && routine->getStatement() && !(routine->flags & Routine::FLAG_OBSOLETE) && @@ -756,7 +749,7 @@ void MET_clear_cache(thread_db* tdbb) for (jrd_prc** iter = att->att_procedures.begin(); iter != att->att_procedures.end(); ++iter) { - Routine* routine = *iter; + Routine* const routine = *iter; if (routine) { @@ -782,7 +775,7 @@ void MET_clear_cache(thread_db* tdbb) for (Function** iter = att->att_functions.begin(); iter != att->att_functions.end(); ++iter) { - Function* routine = *iter; + Function* const routine = *iter; if (routine) { @@ -831,7 +824,7 @@ bool MET_routine_in_use(thread_db* tdbb, Routine* routine) MET_verify_cache(tdbb); #endif - Attachment* att = tdbb->getAttachment(); + Attachment* const att = tdbb->getAttachment(); vec* relations = att->att_relations; { // scope @@ -2214,9 +2207,7 @@ int MET_lookup_field(thread_db* tdbb, jrd_rel* relation, const MetaName& name) int id = -1; if (relation->rel_flags & REL_deleted) - { return id; - } AutoCacheRequest request(tdbb, irq_l_field, IRQ_REQUESTS); @@ -2521,9 +2512,8 @@ bool MET_lookup_partner(thread_db* tdbb, jrd_rel* relation, index_desc* idx, con SET_TDBB(tdbb); Attachment* attachment = tdbb->getAttachment(); - if (relation->rel_flags & REL_check_partners) { + if (relation->rel_flags & REL_check_partners) scan_partners(tdbb, relation); - } if (idx->idx_flags & idx_foreign) { @@ -2846,7 +2836,7 @@ jrd_rel* MET_lookup_relation_id(thread_db* tdbb, SLONG id, bool return_deleted) * **************************************/ SET_TDBB(tdbb); - Attachment* attachment = tdbb->getAttachment(); + Attachment* const attachment = tdbb->getAttachment(); // System relations are above suspicion @@ -3514,9 +3504,8 @@ jrd_rel* MET_relation(thread_db* tdbb, USHORT id) } // This should check system flag instead. - if (relation->rel_id <= max_sys_rel) { + if (relation->rel_id <= max_sys_rel) return relation; - } { // Scope block. Lock* lock = FB_NEW_RPT(*pool, 0) @@ -3631,9 +3620,7 @@ void MET_scan_partners(thread_db* tdbb, jrd_rel* relation) SET_TDBB(tdbb); if (relation->rel_flags & REL_check_partners) - { scan_partners(tdbb, relation); - } } @@ -3691,9 +3678,8 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation) relation->rel_current_fmt = REL.RDB$FORMAT; vec* vector = relation->rel_fields = vec::newVector(*relation->rel_pool, relation->rel_fields, REL.RDB$FIELD_ID + 1); - if (!REL.RDB$SECURITY_CLASS.NULL) { + if (!REL.RDB$SECURITY_CLASS.NULL) relation->rel_security_name = REL.RDB$SECURITY_CLASS; - } relation->rel_name = REL.RDB$RELATION_NAME; relation->rel_owner_name = REL.RDB$OWNER_NAME; @@ -4595,10 +4581,9 @@ void MET_release_triggers( thread_db* tdbb, trig_vec** vector_ptr) * **************************************/ trig_vec* vector = *vector_ptr; + if (!vector) - { return; - } SET_TDBB(tdbb); diff --git a/src/jrd/ods.cpp b/src/jrd/ods.cpp index a8d06454e9..9282c69877 100644 --- a/src/jrd/ods.cpp +++ b/src/jrd/ods.cpp @@ -24,6 +24,16 @@ #include "../jrd/ods.h" #include "../jrd/ods_proto.h" +using namespace Firebird; + +namespace +{ + const FB_SIZE_T NEXT_INDEX = 0; + const FB_SIZE_T OIT_INDEX = 1; + const FB_SIZE_T OAT_INDEX = 2; + const FB_SIZE_T OST_INDEX = 3; +} + namespace Ods { bool isSupported(USHORT majorVersion, USHORT minorVersion) @@ -34,24 +44,6 @@ bool isSupported(USHORT majorVersion, USHORT minorVersion) if (!isFirebird) return false; -#ifdef ODS_8_TO_CURRENT - // Obsolete: Support InterBase major ODS numbers from 8 to 10 - /* - if (!isFirebird) - { - return (majorVersion >= ODS_VERSION8 && - majorVersion <= ODS_VERSION10); - } - */ - - // This is for future ODS versions - if (majorVersion > ODS_VERSION10 && - majorVersion < ODS_VERSION) - { - return true; - } -#endif - // Support current ODS of the engine if (majorVersion == ODS_VERSION && minorVersion >= ODS_RELEASED && @@ -168,4 +160,97 @@ Firebird::string pagtype(UCHAR type) return rc; } +TraNumber getNT(const header_page* page) +{ + return (TraNumber) page->hdr_tra_high[NEXT_INDEX] << BITS_PER_LONG | page->hdr_next_transaction; +} + +TraNumber getOIT(const header_page* page) +{ + return (TraNumber) page->hdr_tra_high[OIT_INDEX] << BITS_PER_LONG | page->hdr_oldest_transaction; +} + +TraNumber getOAT(const header_page* page) +{ + return (TraNumber) page->hdr_tra_high[OAT_INDEX] << BITS_PER_LONG | page->hdr_oldest_active; +} + +TraNumber getOST(const header_page* page) +{ + return (TraNumber) page->hdr_tra_high[OST_INDEX] << BITS_PER_LONG | page->hdr_oldest_snapshot; +} + +void writeNT(header_page* page, TraNumber number) +{ + page->hdr_next_transaction = (ULONG) (number & MAX_ULONG); + const SLONG high_word = number >> BITS_PER_LONG; + fb_assert(high_word <= MAX_USHORT); + page->hdr_tra_high[NEXT_INDEX] = (USHORT) high_word; +} + +void writeOIT(header_page* page, TraNumber number) +{ + page->hdr_oldest_transaction = (ULONG) (number & MAX_ULONG); + const SLONG high_word = number >> BITS_PER_LONG; + fb_assert(high_word <= MAX_USHORT); + page->hdr_tra_high[OIT_INDEX] = (USHORT) high_word; +} + +void writeOAT(header_page* page, TraNumber number) +{ + page->hdr_oldest_active = (ULONG) (number & MAX_ULONG); + const SLONG high_word = number >> BITS_PER_LONG; + fb_assert(high_word <= MAX_USHORT); + page->hdr_tra_high[OAT_INDEX] = (USHORT) high_word; +} + +void writeOST(header_page* page, TraNumber number) +{ + page->hdr_oldest_snapshot = (ULONG) (number & MAX_ULONG); + const SLONG high_word = number >> BITS_PER_LONG; + fb_assert(high_word <= MAX_USHORT); + page->hdr_tra_high[OST_INDEX] = (USHORT) high_word; +} + +TraNumber getTraNum(const void* ptr) +{ + rhd* const record = (rhd*) ptr; + USHORT high_word = 0; + + if (record->rhd_flags & rhd_long_tranum) + { + high_word = (record->rhd_flags & rhd_incomplete) ? + ((rhdf*) ptr)->rhdf_tra_high : ((rhde*) ptr)->rhde_tra_high; + } + + return ((TraNumber) high_word << BITS_PER_LONG) | record->rhd_transaction; +} + +void writeTraNum(void* ptr, TraNumber number, FB_SIZE_T header_size) +{ + rhd* const record = (rhd*) ptr; + + record->rhd_transaction = (ULONG) (number & MAX_ULONG); + + const SLONG high_word = number >> BITS_PER_LONG; + fb_assert(high_word <= MAX_USHORT); + + if (high_word) + record->rhd_flags |= rhd_long_tranum; + + if (record->rhd_flags & rhd_long_tranum) + { + if (record->rhd_flags & rhd_incomplete) + { + fb_assert(header_size == RHDF_SIZE); + ((rhdf*) ptr)->rhdf_tra_high = (USHORT) high_word; + } + else + { + fb_assert(header_size == RHDE_SIZE); + ((rhde*) ptr)->rhde_tra_high = (USHORT) high_word; + } + } +} + } // namespace diff --git a/src/jrd/ods.h b/src/jrd/ods.h index 934b7496b8..6ada100e81 100644 --- a/src/jrd/ods.h +++ b/src/jrd/ods.h @@ -310,7 +310,7 @@ struct index_root_page struct irt_repeat { ULONG irt_root; // page number of index root - TraNumber irt_transaction; // transaction in progress + ULONG irt_transaction; // transaction in progress (lowest 32 bits) USHORT irt_desc; // offset to key descriptions UCHAR irt_keys; // number of keys in index UCHAR irt_flags; @@ -348,13 +348,13 @@ struct header_page USHORT hdr_ods_version; // Version of on-disk structure ULONG hdr_PAGES; // Page number of PAGES relation ULONG hdr_next_page; // Page number of next hdr page - TraNumber hdr_oldest_transaction; // Oldest interesting transaction - TraNumber hdr_oldest_active; // Oldest transaction thought active - TraNumber hdr_next_transaction; // Next transaction id + ULONG hdr_oldest_transaction; // Oldest interesting transaction + ULONG hdr_oldest_active; // Oldest transaction thought active + ULONG hdr_next_transaction; // Next transaction id USHORT hdr_sequence; // sequence number of file USHORT hdr_flags; // Flag settings, see below SLONG hdr_creation_date[2]; // Date/time of creation - SLONG hdr_attachment_id; // Next attachment id + ULONG hdr_attachment_id; // Next attachment id SLONG hdr_shadow_count; // Event count for shadow synchronization UCHAR hdr_cpu; // CPU database was created on UCHAR hdr_os; // OS database was created under @@ -363,12 +363,13 @@ struct header_page USHORT hdr_ods_minor; // Update version of ODS USHORT hdr_end; // offset of HDR_end in page ULONG hdr_page_buffers; // Page buffers for database cache - TraNumber hdr_oldest_snapshot; // Oldest snapshot of active transactions + ULONG hdr_oldest_snapshot; // Oldest snapshot of active transactions SLONG hdr_backup_pages; // The amount of pages in files locked for backup ULONG hdr_crypt_page; // Page at which processing is in progress ULONG hdr_top_crypt; // Last page to crypt TEXT hdr_crypt_plugin[32]; // Name of plugin used to crypt this DB - SLONG hdr_misc[3]; // Stuff to be named later - reserved for minor changes + SLONG hdr_att_high; // High word of the next attachment counter + USHORT hdr_tra_high[4]; // High words of the transaction counters UCHAR hdr_data[1]; // Misc data }; @@ -527,28 +528,44 @@ struct generator_page struct rhd { - TraNumber rhd_transaction; // transaction id + ULONG rhd_transaction; // transaction id (lowest 32 bits) ULONG rhd_b_page; // back pointer USHORT rhd_b_line; // back line USHORT rhd_flags; // flags, etc UCHAR rhd_format; // format version - UCHAR rhd_data[1]; + UCHAR rhd_data[1]; // record data }; #define RHD_SIZE static_cast(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(offsetof(Ods::rhde, rhde_data[0])) + // Record header for fragmented record struct rhdf { - TraNumber rhdf_transaction; // transaction id + ULONG rhdf_transaction; // transaction id (lowest 32 bits) ULONG rhdf_b_page; // back pointer USHORT rhdf_b_line; // back line USHORT rhdf_flags; // flags, etc - UCHAR rhdf_format; // format version // until here, same than rhd + UCHAR rhdf_format; // format version // until here, same as rhd + USHORT rhdf_tra_high; // higher bits of transaction id ULONG rhdf_f_page; // next fragment page USHORT rhdf_f_line; // next fragment line - UCHAR rhdf_data[1]; // Blob data + UCHAR rhdf_data[1]; // record data }; #define RHDF_SIZE static_cast(offsetof(Ods::rhdf, rhdf_data[0])) @@ -583,12 +600,11 @@ const USHORT rhd_incomplete = 8; // record is incomplete const USHORT rhd_blob = 16; // isn't a record but a blob const USHORT rhd_stream_blob = 32; // blob is a stream mode blob const USHORT rhd_delta = 32; // prior version is differences only - // Tested in validation.cpp's walk_chain but never set const USHORT rhd_large = 64; // object is large const USHORT rhd_damaged = 128; // object is known to be damaged const USHORT rhd_gc_active = 256; // garbage collecting dead record version -//const USHORT rhd_uk_modified = 512; // record key field values are changed - +const USHORT rhd_uk_modified = 512; // record key field values are changed +const USHORT rhd_long_tranum = 1024; // transaction number is 64-bit // This (not exact) copy of class DSC is used to store descriptors on disk. diff --git a/src/jrd/ods_proto.h b/src/jrd/ods_proto.h index ebdfcef4c8..b84cc1bd7c 100644 --- a/src/jrd/ods_proto.h +++ b/src/jrd/ods_proto.h @@ -39,6 +39,19 @@ namespace Ods { ULONG maxRecsPerDP(ULONG page_size); ULONG maxIndices(ULONG page_size); + TraNumber getNT(const header_page* page); + TraNumber getOIT(const header_page* page); + TraNumber getOAT(const header_page* page); + TraNumber getOST(const header_page* page); + + void writeNT(header_page* page, TraNumber number); + void writeOIT(header_page* page, TraNumber number); + void writeOAT(header_page* page, TraNumber number); + void writeOST(header_page* page, TraNumber number); + + TraNumber getTraNum(const void* ptr); + void writeTraNum(void* ptr, TraNumber number, FB_SIZE_T header_size); + } // namespace #endif //ODS_PROTO_H diff --git a/src/jrd/opt.cpp b/src/jrd/opt.cpp index a03e434aa3..f0efa88912 100644 --- a/src/jrd/opt.cpp +++ b/src/jrd/opt.cpp @@ -2647,7 +2647,7 @@ SortedStream* OPT_gen_sort(thread_db* tdbb, CompilerScratch* csb, const StreamLi map_item++; } - // Make fields for record numbers record for all streams + // Make fields for record numbers and transaction ids for all streams map_length = ROUNDUP(map_length, sizeof(SINT64)); for (const StreamType* ptr = streams.begin(); ptr < end_ptr; ptr++, map_item++) @@ -2660,18 +2660,15 @@ SortedStream* OPT_gen_sort(thread_db* tdbb, CompilerScratch* csb, const StreamLi desc->dsc_length = sizeof(SINT64); desc->dsc_address = (UCHAR*)(IPTR) map_length; map_length += desc->dsc_length; - } - // Make fields for transaction id of record for all streams + map_item++; - for (const StreamType* ptr = streams.begin(); ptr < end_ptr; ptr++, map_item++) - { map_item->clear(); map_item->fieldId = SortedStream::ID_TRANS; map_item->stream = *ptr; - dsc* desc = &map_item->desc; - desc->dsc_dtype = dtype_long; - desc->dsc_length = sizeof(SLONG); + desc = &map_item->desc; + desc->dsc_dtype = dtype_int64; + desc->dsc_length = sizeof(SINT64); desc->dsc_address = (UCHAR*)(IPTR) map_length; map_length += desc->dsc_length; } diff --git a/src/jrd/pag.cpp b/src/jrd/pag.cpp index d6bf8ced88..b4280561fc 100644 --- a/src/jrd/pag.cpp +++ b/src/jrd/pag.cpp @@ -834,7 +834,7 @@ static ULONG ensureDiskSpace(thread_db* tdbb, WIN* pip_window, const PageNumber } -SLONG PAG_attachment_id(thread_db* tdbb) +AttNumber PAG_attachment_id(thread_db* tdbb) { /****************************************** * @@ -860,15 +860,18 @@ SLONG PAG_attachment_id(thread_db* tdbb) // Get new attachment id - if (dbb->readOnly()) { + if (dbb->readOnly()) attachment->att_attachment_id = dbb->dbb_attachment_id + dbb->generateAttachmentId(tdbb); - } else { window.win_page = HEADER_PAGE_NUMBER; header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); CCH_MARK(tdbb, &window); - attachment->att_attachment_id = ++header->hdr_attachment_id; + const AttNumber att_id = + ((SINT64) header->hdr_att_high << BITS_PER_LONG | header->hdr_attachment_id) + 1; + attachment->att_attachment_id = att_id; + header->hdr_att_high = att_id >> BITS_PER_LONG; + header->hdr_attachment_id = (ULONG) (att_id & MAX_ULONG); CCH_RELEASE(tdbb, &window); } @@ -960,9 +963,8 @@ void PAG_format_header(thread_db* tdbb) header->hdr_end = HDR_SIZE; header->hdr_data[0] = HDR_end; - if (dbb->dbb_flags & DBB_DB_SQL_dialect_3) { + if (dbb->dbb_flags & DBB_DB_SQL_dialect_3) header->hdr_flags |= hdr_SQL_dialect_3; - } dbb->dbb_ods_version = header->hdr_ods_version & ~ODS_FIREBIRD_FLAG; dbb->dbb_minor_version = header->hdr_ods_minor; @@ -1106,12 +1108,17 @@ void PAG_header(thread_db* tdbb, bool info) try { - if (header->hdr_next_transaction) + const TraNumber next_transaction = Ods::getNT(header); + const TraNumber oldest_transaction = Ods::getOIT(header); + const TraNumber oldest_active = Ods::getOAT(header); + const TraNumber oldest_snapshot = Ods::getOST(header); + + if (next_transaction) { - if (header->hdr_oldest_active > header->hdr_next_transaction) + if (oldest_active > next_transaction) BUGCHECK(266); // next transaction older than oldest active - if (header->hdr_oldest_transaction > header->hdr_next_transaction) + if (oldest_transaction > next_transaction) BUGCHECK(267); // next transaction older than oldest transaction } @@ -1134,17 +1141,16 @@ void PAG_header(thread_db* tdbb, bool info) (*vector)[0] = header->hdr_PAGES; } - dbb->dbb_next_transaction = header->hdr_next_transaction; + dbb->dbb_next_transaction = next_transaction; - if (!info || dbb->dbb_oldest_transaction < header->hdr_oldest_transaction) { - dbb->dbb_oldest_transaction = header->hdr_oldest_transaction; - } - if (!info || dbb->dbb_oldest_active < header->hdr_oldest_active) { - dbb->dbb_oldest_active = header->hdr_oldest_active; - } - if (!info || dbb->dbb_oldest_snapshot < header->hdr_oldest_snapshot) { - dbb->dbb_oldest_snapshot = header->hdr_oldest_snapshot; - } + if (!info || dbb->dbb_oldest_transaction < oldest_transaction) + dbb->dbb_oldest_transaction = oldest_transaction; + + if (!info || dbb->dbb_oldest_active < oldest_active) + dbb->dbb_oldest_active = oldest_active; + + if (!info || dbb->dbb_oldest_snapshot < oldest_snapshot) + dbb->dbb_oldest_snapshot = oldest_snapshot; dbb->dbb_attachment_id = header->hdr_attachment_id; dbb->dbb_creation_date = *(ISC_TIMESTAMP*) header->hdr_creation_date; @@ -2286,7 +2292,8 @@ void PageManager::initTempPageSpace(thread_db* tdbb) if (!attachment->att_temp_pg_lock) { - Lock* lock = FB_NEW_RPT(*attachment->att_pool, 0) Lock(tdbb, sizeof(SLONG), LCK_page_space); + Lock* const lock = FB_NEW_RPT(*attachment->att_pool, 0) + Lock(tdbb, sizeof(SLONG), LCK_page_space); while (true) { diff --git a/src/jrd/pag_proto.h b/src/jrd/pag_proto.h index 18089c7fc8..ddc113d497 100644 --- a/src/jrd/pag_proto.h +++ b/src/jrd/pag_proto.h @@ -45,7 +45,7 @@ bool PAG_add_header_entry(Jrd::thread_db* tdbb, Ods::header_page*, USHORT, USHOR bool PAG_replace_entry_first(Jrd::thread_db* tdbb, Ods::header_page*, USHORT, USHORT, const UCHAR*); Ods::pag* PAG_allocate(Jrd::thread_db* tdbb, Jrd::win*); Ods::pag* PAG_allocate_pages(Jrd::thread_db* tdbb, Jrd::win* window, int cntAlloc, bool aligned); -SLONG PAG_attachment_id(Jrd::thread_db*); +AttNumber PAG_attachment_id(Jrd::thread_db*); bool PAG_delete_clump_entry(Jrd::thread_db* tdbb, USHORT); void PAG_format_header(Jrd::thread_db*); void PAG_format_pip(Jrd::thread_db*, Jrd::PageSpace& pageSpace); diff --git a/src/jrd/recsrc/BufferedStream.cpp b/src/jrd/recsrc/BufferedStream.cpp index 3496ced8cd..ad2bcf0ecc 100644 --- a/src/jrd/recsrc/BufferedStream.cpp +++ b/src/jrd/recsrc/BufferedStream.cpp @@ -68,16 +68,26 @@ BufferedStream::BufferedStream(CompilerScratch* csb, RecordSource* next) fields.add(*desc); } while (accessor.getNext()); } + } - dsc desc; + dsc desc; - desc.makeLong(0); + for (StreamList::iterator i = streams.begin(); i != streams.end(); ++i) + { + const StreamType stream = *i; + + desc.makeInt64(0); m_map.add(FieldMap(FieldMap::TRANSACTION_ID, stream, 0)); fields.add(desc); desc.makeInt64(0); m_map.add(FieldMap(FieldMap::DBKEY_NUMBER, stream, 0)); fields.add(desc); + } + + for (StreamList::iterator i = streams.begin(); i != streams.end(); ++i) + { + const StreamType stream = *i; desc.makeText(1, CS_BINARY); m_map.add(FieldMap(FieldMap::DBKEY_VALID, stream, 0)); @@ -191,7 +201,7 @@ bool BufferedStream::getRecord(thread_db* tdbb) const break; case FieldMap::TRANSACTION_ID: - *reinterpret_cast(to.dsc_address) = rpb->rpb_transaction_nr; + *reinterpret_cast(to.dsc_address) = rpb->rpb_transaction_nr; break; case FieldMap::DBKEY_NUMBER: @@ -258,7 +268,7 @@ bool BufferedStream::getRecord(thread_db* tdbb) const break; case FieldMap::TRANSACTION_ID: - rpb->rpb_transaction_nr = *reinterpret_cast(from.dsc_address); + rpb->rpb_transaction_nr = *reinterpret_cast(from.dsc_address); break; case FieldMap::DBKEY_NUMBER: diff --git a/src/jrd/recsrc/SortedStream.cpp b/src/jrd/recsrc/SortedStream.cpp index 519863b1bf..e2e93d6fc0 100644 --- a/src/jrd/recsrc/SortedStream.cpp +++ b/src/jrd/recsrc/SortedStream.cpp @@ -219,7 +219,7 @@ Sort* SortedStream::init(thread_db* tdbb) const switch (item->fieldId) { case ID_TRANS: - *reinterpret_cast(to.dsc_address) = rpb->rpb_transaction_nr; + *reinterpret_cast(to.dsc_address) = rpb->rpb_transaction_nr; break; case ID_DBKEY: *reinterpret_cast(to.dsc_address) = rpb->rpb_number.getValue(); @@ -353,7 +353,7 @@ void SortedStream::mapData(thread_db* tdbb, jrd_req* request, UCHAR* data) const switch (id) { case ID_TRANS: - rpb->rpb_transaction_nr = *reinterpret_cast(from.dsc_address); + rpb->rpb_transaction_nr = *reinterpret_cast(from.dsc_address); break; case ID_DBKEY: rpb->rpb_number.setValue(*reinterpret_cast(from.dsc_address)); diff --git a/src/jrd/req.h b/src/jrd/req.h index 4f57be314a..b698f7fe53 100644 --- a/src/jrd/req.h +++ b/src/jrd/req.h @@ -62,7 +62,7 @@ struct record_param rpb_f_page(0), rpb_f_line(0), rpb_b_page(0), rpb_b_line(0), rpb_address(NULL), rpb_length(0), rpb_flags(0), rpb_stream_flags(0), - rpb_org_scans(0), + rpb_org_scans(0), rpb_gc_lock(NULL), rpb_window(DB_PAGE_SPACE, -1) { } @@ -90,6 +90,7 @@ struct record_param USHORT rpb_stream_flags; // stream flags USHORT rpb_runtime_flags; // runtime flags SSHORT rpb_org_scans; // relation scan count at stream open + Lock* rpb_gc_lock; // lock for transient record changes inline WIN& getWindow(thread_db* tdbb) { @@ -106,16 +107,17 @@ private: // Record flags must be an exact replica of ODS record header flags -const USHORT rpb_deleted = 1; -const USHORT rpb_chained = 2; -const USHORT rpb_fragment = 4; -const USHORT rpb_incomplete = 8; -const USHORT rpb_blob = 16; -const USHORT rpb_delta = 32; // prior version is a differences record -// rpb_large = 64 is missing -const USHORT rpb_damaged = 128; // record is busted -const USHORT rpb_gc_active = 256; // garbage collecting dead record version -const USHORT rpb_uk_modified= 512; // record key field values are changed +const USHORT rpb_deleted = 1; +const USHORT rpb_chained = 2; +const USHORT rpb_fragment = 4; +const USHORT rpb_incomplete = 8; +const USHORT rpb_blob = 16; +const USHORT rpb_delta = 32; // prior version is a differences record +const USHORT rpb_large = 64; // object is large +const USHORT rpb_damaged = 128; // record is busted +const USHORT rpb_gc_active = 256; // garbage collecting dead record version +const USHORT rpb_uk_modified = 512; // record key field values are changed +const USHORT rpb_long_tranum = 1024; // transaction number is 64-bit // Stream flags @@ -217,7 +219,7 @@ private: public: MemoryPool* req_pool; Attachment* req_attachment; // database attachment - SLONG req_id; // request identifier + StmtNumber req_id; // request identifier USHORT req_incarnation; // incarnation number Firebird::MemoryStats req_memory_stats; diff --git a/src/jrd/sbm.h b/src/jrd/sbm.h index ebaac2ea2e..a5ffe167e4 100644 --- a/src/jrd/sbm.h +++ b/src/jrd/sbm.h @@ -42,6 +42,9 @@ typedef Firebird::SparseBitmap PageBitmap; // Bitmap of generic 32-bit integers typedef Firebird::SparseBitmap UInt32Bitmap; +// Bitmap of transaction numbers +typedef Firebird::SparseBitmap TransactionBitmap; + // Please do not try to turn these macros to inline routines simply. // They are used in very performance-sensitive places and we don't want // pool thread-specific pool pointer be expanded unless necessary. @@ -61,6 +64,10 @@ typedef Firebird::SparseBitmap UInt32Bitmap; #define PBM_SET(POOL_PTR, BITMAP_PPTR, VALUE) \ (*(BITMAP_PPTR) ? *(BITMAP_PPTR) : (*(BITMAP_PPTR) = FB_NEW_POOL(*(POOL_PTR)) Jrd::PageBitmap(*(POOL_PTR))))->set(VALUE) +// Bitmap of transaction numbers +#define TBM_SET(POOL_PTR, BITMAP_PPTR, VALUE) \ + (*(BITMAP_PPTR) ? *(BITMAP_PPTR) : (*(BITMAP_PPTR) = FB_NEW_POOL(*(POOL_PTR)) Jrd::TransactionBitmap(*(POOL_PTR))))->set(VALUE) + } //namespace Jrd #endif // JRD_SBM_H diff --git a/src/jrd/svc.cpp b/src/jrd/svc.cpp index 8a0c65b87f..a1d85e313b 100644 --- a/src/jrd/svc.cpp +++ b/src/jrd/svc.cpp @@ -449,6 +449,21 @@ void Service::putSLong(char tag, SLONG val) enqueue(buf, sizeof buf); } +void Service::putSInt64(char tag, SINT64 val) +{ + UCHAR buf[5]; + buf[0] = tag; + buf[1] = val; + buf[2] = val >> 8; + buf[3] = val >> 16; + buf[4] = val >> 24; + buf[5] = val >> 32; + buf[6] = val >> 40; + buf[7] = val >> 48; + buf[8] = val >> 56; + enqueue(buf, sizeof buf); +} + void Service::putChar(char tag, char val) { UCHAR buf[2]; diff --git a/src/jrd/svc.h b/src/jrd/svc.h index df17b057c6..552b2cabc9 100644 --- a/src/jrd/svc.h +++ b/src/jrd/svc.h @@ -119,6 +119,7 @@ public: // utilities interface with service // put various info items in info buffer virtual void putLine(char tag, const char* val); virtual void putSLong(char tag, SLONG val); + virtual void putSInt64(char tag, SINT64 val); virtual void putChar(char tag, char val); // put raw bytes to svc_stdout virtual void putBytes(const UCHAR*, FB_SIZE_T); diff --git a/src/jrd/tpc.cpp b/src/jrd/tpc.cpp index 9887b2cec0..5ae7fd155b 100644 --- a/src/jrd/tpc.cpp +++ b/src/jrd/tpc.cpp @@ -28,6 +28,7 @@ #include "../jrd/pag.h" #include "../jrd/cch_proto.h" #include "../jrd/lck_proto.h" +#include "../jrd/ods_proto.h" #include "../jrd/tpc_proto.h" #include "../jrd/tra_proto.h" @@ -85,7 +86,7 @@ int TipCache::cacheState(thread_db* tdbb, TraNumber number) // locate the specific TIP cache block for the transaction const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP; - const ULONG base = number - number % trans_per_tip; + const TraNumber base = number - number % trans_per_tip; FB_SIZE_T pos; if (m_cache.find(base, pos)) @@ -142,7 +143,7 @@ TraNumber TipCache::findLimbo(thread_db* tdbb, TraNumber minNumber, TraNumber ma minNumber = tip_cache->tpc_base; const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP; - const ULONG base = minNumber - minNumber % trans_per_tip; + const TraNumber base = minNumber - minNumber % trans_per_tip; // Scan the TIP cache and return the first (i.e. oldest) limbo transaction @@ -232,7 +233,7 @@ void TipCache::setState(TraNumber number, SSHORT state) **************************************/ const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP; - const ULONG base = number - number % trans_per_tip; + const TraNumber base = number - number % trans_per_tip; const ULONG byte = TRANS_OFFSET(number % trans_per_tip); const USHORT shift = TRANS_SHIFT(number); @@ -299,7 +300,7 @@ int TipCache::snapshotState(thread_db* tdbb, TraNumber number) // locate the specific TIP cache block for the transaction const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP; - const ULONG base = number - number % trans_per_tip; + const TraNumber base = number - number % trans_per_tip; FB_SIZE_T pos; if (m_cache.find(base, pos)) @@ -322,7 +323,7 @@ int TipCache::snapshotState(thread_db* tdbb, TraNumber number) // see if we can get a lock on the transaction; if we can't // then we know it is still active - Lock temp_lock(tdbb, sizeof(SLONG), LCK_tra); + Lock temp_lock(tdbb, sizeof(TraNumber), LCK_tra); temp_lock.lck_key.lck_long = number; // If we can't get a lock on the transaction, it must be active. @@ -368,7 +369,7 @@ void TipCache::updateCache(const Ods::tx_inv_page* tip_page, ULONG sequence) **************************************/ const ULONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP; - const TraNumber first_trans = sequence * trans_per_tip; + const TraNumber first_trans = (TraNumber) sequence * trans_per_tip; // while we're in the area we can check to see if there are // any tip cache pages we can release--this is cheaper and @@ -462,8 +463,8 @@ TraNumber TipCache::cacheTransactions(thread_db* tdbb, TraNumber oldest) #else WIN window(HEADER_PAGE_NUMBER); const Ods::header_page* header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header); - const TraNumber top = header->hdr_next_transaction; - const TraNumber hdr_oldest = header->hdr_oldest_transaction; + const TraNumber top = Ods::getNT(header); + const TraNumber hdr_oldest = Ods::getOIT(header); CCH_RELEASE(tdbb, &window); #endif @@ -557,7 +558,8 @@ int TipCache::extendCache(thread_db* tdbb, TraNumber number) // find the right block for this transaction and return the state - const ULONG base = number - number % trans_per_tip; + const TraNumber base = number - number % trans_per_tip; + FB_SIZE_T pos; if (m_cache.find(base, pos)) { @@ -573,6 +575,7 @@ int TipCache::extendCache(thread_db* tdbb, TraNumber number) // we should never get to this point, but if we do the // safest thing to do is return active + fb_assert(false); return tra_active; } diff --git a/src/jrd/tra.cpp b/src/jrd/tra.cpp index 9fc816d802..6c2efccd2b 100644 --- a/src/jrd/tra.cpp +++ b/src/jrd/tra.cpp @@ -228,8 +228,8 @@ void TRA_cleanup(thread_db* tdbb) WIN window(HEADER_PAGE_NUMBER); const header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header); - const TraNumber ceiling = header->hdr_next_transaction; - const TraNumber active = header->hdr_oldest_active; + const TraNumber ceiling = Ods::getNT(header); + const TraNumber active = Ods::getOAT(header); CCH_RELEASE(tdbb, &window); if (ceiling == 0) @@ -246,7 +246,7 @@ void TRA_cleanup(thread_db* tdbb) { window.win_page = inventory_page(tdbb, sequence); tx_inv_page* tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_transactions); - ULONG max = ceiling - (sequence * trans_per_tip); + TraNumber max = ceiling - (TraNumber) sequence * trans_per_tip; if (max > trans_per_tip) max = trans_per_tip - 1; for (; number <= max; number++) @@ -256,7 +256,7 @@ void TRA_cleanup(thread_db* tdbb) const USHORT shift = TRANS_SHIFT(number); const int state = (*byte >> shift) & TRA_MASK; if (state == tra_limbo && limbo == 0) - limbo = sequence * trans_per_tip + number; + limbo = (TraNumber) sequence * trans_per_tip + number; else if (state == tra_active) { CCH_MARK(tdbb, &window); @@ -314,7 +314,7 @@ void TRA_cleanup(thread_db* tdbb) } if (!tip->tip_next) - dbb->dbb_next_transaction = last * trans_per_tip; + dbb->dbb_next_transaction = (TraNumber) last * trans_per_tip; } CCH_RELEASE(tdbb, &window); @@ -579,7 +579,7 @@ void TRA_get_inventory(thread_db* tdbb, UCHAR* bit_vector, TraNumber base, TraNu while (sequence <= last) { - base = sequence * trans_per_tip; + base = (TraNumber) sequence * trans_per_tip; // release the read lock as we go, so that some one else can // commit without having to signal all other transactions. @@ -658,12 +658,17 @@ void TRA_header_write(thread_db* tdbb, Database* dbb, TraNumber number) WIN window(HEADER_PAGE_NUMBER); header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); - if (header->hdr_next_transaction) + const TraNumber next_transaction = Ods::getNT(header); + const TraNumber oldest_active = Ods::getOAT(header); + const TraNumber oldest_transaction = Ods::getOIT(header); + const TraNumber oldest_snapshot = Ods::getOST(header); + + if (next_transaction) { - if (header->hdr_oldest_active > header->hdr_next_transaction) + if (oldest_active > next_transaction) BUGCHECK(266); //next transaction older than oldest active - if (header->hdr_oldest_transaction > header->hdr_next_transaction) + if (oldest_transaction > next_transaction) BUGCHECK(267); // next transaction older than oldest transaction } @@ -674,17 +679,18 @@ void TRA_header_write(thread_db* tdbb, Database* dbb, TraNumber number) if (!number || dbb->dbb_last_header_write < number) { CCH_MARK_MUST_WRITE(tdbb, &window); - if (dbb->dbb_next_transaction > header->hdr_next_transaction) - header->hdr_next_transaction = dbb->dbb_next_transaction; - if (dbb->dbb_oldest_active > header->hdr_oldest_active) - header->hdr_oldest_active = dbb->dbb_oldest_active; + if (dbb->dbb_next_transaction > next_transaction) + Ods::writeNT(header, dbb->dbb_next_transaction); - if (dbb->dbb_oldest_transaction > header->hdr_oldest_transaction) - header->hdr_oldest_transaction = dbb->dbb_oldest_transaction; + if (dbb->dbb_oldest_active > oldest_active) + Ods::writeOAT(header, dbb->dbb_oldest_active); - if (dbb->dbb_oldest_snapshot > header->hdr_oldest_snapshot) - header->hdr_oldest_snapshot = dbb->dbb_oldest_snapshot; + if (dbb->dbb_oldest_transaction > oldest_transaction) + Ods::writeOIT(header, dbb->dbb_oldest_transaction); + + if (dbb->dbb_oldest_snapshot > oldest_snapshot) + Ods::writeOST(header, dbb->dbb_oldest_snapshot); } CCH_RELEASE(tdbb, &window); @@ -905,7 +911,7 @@ bool TRA_precommited(thread_db* tdbb, TraNumber old_number, TraNumber new_number * **************************************/ SET_TDBB(tdbb); - Database* dbb = tdbb->getDatabase(); + Database* const dbb = tdbb->getDatabase(); CHECK_DBB(dbb); Sync sync(&dbb->dbb_pc_sync, "TRA_precommited"); @@ -1104,7 +1110,7 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr * **************************************/ SET_TDBB(tdbb); - Jrd::Attachment* attachment = tdbb->getAttachment(); + Jrd::Attachment* const attachment = tdbb->getAttachment(); if (!transaction->tra_outer) { @@ -1205,7 +1211,7 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr if (trace) trace->finish(ITracePlugin::RESULT_SUCCESS); - // Unlink the transaction from the database block + // Unlink the transaction from the attachment block for (jrd_tra** ptr = &attachment->att_transactions; *ptr; ptr = &(*ptr)->tra_next) { @@ -1548,12 +1554,10 @@ int TRA_snapshot_state(thread_db* tdbb, const jrd_tra* trans, TraNumber number) return state; } - // If the transaction is a commited sub-transction - do the easy lookup. + // If the transaction is a committed sub-transaction - do the easy lookup. - if (trans->tra_commit_sub_trans && UInt32Bitmap::test(trans->tra_commit_sub_trans, number)) - { + if (trans->tra_commit_sub_trans && trans->tra_commit_sub_trans->test(number)) return tra_committed; - } // If the transaction is younger than we are and we are not read committed // or the system transaction, the transaction must be considered active. @@ -1685,7 +1689,7 @@ int TRA_state(const UCHAR* bit_vector, TraNumber oldest, TraNumber number) * to this code make them in the replicated code also. * **************************************/ - const ULONG base = oldest & ~TRA_MASK; + const TraNumber base = oldest & ~TRA_MASK; const ULONG byte = TRANS_OFFSET(number - base); const USHORT shift = TRANS_SHIFT(number); @@ -1779,12 +1783,12 @@ void TRA_sweep(thread_db* tdbb) CCH_flush(tdbb, FLUSH_SWEEP, 0); WIN window(HEADER_PAGE_NUMBER); - header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); + header_page* const header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); - if (header->hdr_oldest_transaction < --transaction_oldest_active) + if (Ods::getOIT(header) < --transaction_oldest_active) { CCH_MARK_MUST_WRITE(tdbb, &window); - header->hdr_oldest_transaction = MIN(active, transaction_oldest_active); + Ods::writeOIT(header, MIN(active, transaction_oldest_active)); } traceSweep.update(header); @@ -1855,7 +1859,7 @@ int TRA_wait(thread_db* tdbb, jrd_tra* trans, TraNumber number, jrd_tra::wait_t if (wait != jrd_tra::tra_no_wait) { - Lock temp_lock(tdbb, sizeof(SLONG), LCK_tra); + Lock temp_lock(tdbb, sizeof(TraNumber), LCK_tra); temp_lock.lck_key.lck_long = number; const SSHORT timeout = (wait == jrd_tra::tra_wait) ? trans->getLockWait() : 0; @@ -1972,23 +1976,29 @@ static header_page* bump_transaction_id(thread_db* tdbb, WIN* window) window->win_page = HEADER_PAGE_NUMBER; header_page* header = (header_page*) CCH_FETCH(tdbb, window, LCK_write, pag_header); + const TraNumber next_transaction = Ods::getNT(header); + const TraNumber oldest_active = Ods::getOAT(header); + const TraNumber oldest_transaction = Ods::getOIT(header); + const TraNumber oldest_snapshot = Ods::getOST(header); + // Before incrementing the next transaction Id, make sure the current one is valid - if (header->hdr_next_transaction) + if (next_transaction) { - if (header->hdr_oldest_active > header->hdr_next_transaction) + if (oldest_active > next_transaction) BUGCHECK(266); //next transaction older than oldest active - if (header->hdr_oldest_transaction > header->hdr_next_transaction) + if (oldest_transaction > next_transaction) BUGCHECK(267); // next transaction older than oldest transaction } - if (header->hdr_next_transaction >= MAX_TRA_NUMBER - 1) + if (next_transaction >= MAX_TRA_NUMBER - 1) { CCH_RELEASE(tdbb, window); ERR_post(Arg::Gds(isc_imp_exc) << Arg::Gds(isc_tra_num_exc)); } - const TraNumber number = header->hdr_next_transaction + 1; + + const TraNumber number = next_transaction + 1; // If this is the first transaction on a TIP, allocate the TIP now. // Note, first TIP page is created with the database itself, @@ -2002,17 +2012,18 @@ static header_page* bump_transaction_id(thread_db* tdbb, WIN* window) // Extend, if necessary, has apparently succeeded. Next, update header page CCH_MARK_MUST_WRITE(tdbb, window); - header->hdr_next_transaction = number; dbb->dbb_next_transaction = number; - if (dbb->dbb_oldest_active > header->hdr_oldest_active) - header->hdr_oldest_active = dbb->dbb_oldest_active; + Ods::writeNT(header, number); - if (dbb->dbb_oldest_transaction > header->hdr_oldest_transaction) - header->hdr_oldest_transaction = dbb->dbb_oldest_transaction; + if (dbb->dbb_oldest_active > oldest_active) + Ods::writeOAT(header, dbb->dbb_oldest_active); - if (dbb->dbb_oldest_snapshot > header->hdr_oldest_snapshot) - header->hdr_oldest_snapshot = dbb->dbb_oldest_snapshot; + if (dbb->dbb_oldest_transaction > oldest_transaction) + Ods::writeOIT(header, dbb->dbb_oldest_transaction); + + if (dbb->dbb_oldest_snapshot > oldest_snapshot) + Ods::writeOST(header, dbb->dbb_oldest_snapshot); return header; } @@ -2233,16 +2244,20 @@ static ULONG inventory_page(thread_db* tdbb, ULONG sequence) while (!vector || sequence >= vector->count()) { DPM_scan_pages(tdbb); + if ((vector = dbb->dbb_t_pages) && sequence < vector->count()) break; + if (!vector) BUGCHECK(165); // msg 165 cannot find tip page + window.win_page = (*vector)[vector->count() - 1]; tx_inv_page* tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_transactions); const ULONG next = tip->tip_next; CCH_RELEASE(tdbb, &window); if (!(window.win_page = next)) BUGCHECK(165); // msg 165 cannot find tip page + // Type check it tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_transactions); CCH_RELEASE(tdbb, &window); @@ -2375,10 +2390,7 @@ static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, i // its snapshot doesn't contain these operations. if (commit) - { - //fb_assert(sizeof(transaction->tra_number) == sizeof(ULONG)); - SBM_SET(tdbb->getDefaultPool(), &transaction->tra_commit_sub_trans, transaction->tra_number); - } + TBM_SET(tdbb->getDefaultPool(), &transaction->tra_commit_sub_trans, transaction->tra_number); // Create a new transaction lock, inheriting oldest active from transaction being committed. @@ -2391,8 +2403,8 @@ static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, i new_number = dbb->dbb_next_transaction + dbb->generateTransactionId(tdbb); else { - const header_page* header = bump_transaction_id(tdbb, &window); - new_number = header->hdr_next_transaction; + const header_page* const header = bump_transaction_id(tdbb, &window); + new_number = Ods::getNT(header); } #endif @@ -2400,7 +2412,7 @@ static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, i Lock* old_lock = transaction->tra_lock; if (old_lock) { - new_lock = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) Lock(tdbb, sizeof(SLONG), LCK_tra); + new_lock = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) Lock(tdbb, sizeof(TraNumber), LCK_tra); new_lock->lck_key.lck_long = new_number; new_lock->lck_data = transaction->tra_lock->lck_data; @@ -3032,11 +3044,12 @@ static void transaction_options(thread_db* tdbb, Lock* lock = (*vector)[id]; if (!lock) continue; + USHORT level = lock->lck_logical; + if (level == LCK_none || LCK_lock(tdbb, lock, level, transaction->getLockWait())) - { continue; - } + for (ULONG l = 0; l < id; l++) { if ( (lock = (*vector)[l]) ) @@ -3046,6 +3059,7 @@ static void transaction_options(thread_db* tdbb, lock->lck_logical = level; } } + id = 0; ERR_punt(); } @@ -3069,7 +3083,7 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans) Jrd::Attachment* const attachment = tdbb->getAttachment(); WIN window(DB_PAGE_SPACE, -1); - Lock* lock = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) Lock(tdbb, sizeof(SLONG), LCK_tra); + Lock* lock = FB_NEW_RPT(*tdbb->getDefaultPool(), 0) Lock(tdbb, sizeof(TraNumber), LCK_tra); // Read header page and allocate transaction number. Since // the transaction inventory page was initialized to zero, it @@ -3095,10 +3109,10 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans) else { const header_page* header = bump_transaction_id(tdbb, &window); - number = header->hdr_next_transaction; - oldest = header->hdr_oldest_transaction; - oldest_active = header->hdr_oldest_active; - oldest_snapshot = header->hdr_oldest_snapshot; + number = Ods::getNT(header); + oldest = Ods::getOIT(header); + oldest_active = Ods::getOAT(header); + oldest_snapshot = Ods::getOST(header); } // oldest (OIT) > oldest_active (OAT) if OIT was advanced by sweep @@ -3179,7 +3193,7 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans) // more complicated by the fact that existing transaction may have oldest // actives older than they are. - Lock temp_lock(tdbb, sizeof(SLONG), LCK_tra, trans); + Lock temp_lock(tdbb, sizeof(TraNumber), LCK_tra, trans); trans->tra_oldest_active = number; base = oldest & ~TRA_MASK; @@ -3197,6 +3211,7 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans) const USHORT shift = TRANS_SHIFT(active); oldest_state = (trans->tra_transactions[byte] >> shift) & TRA_MASK; } + if (oldest_state == tra_active) { temp_lock.lck_key.lck_long = active; diff --git a/src/jrd/tra.h b/src/jrd/tra.h index 3cbaa1ff25..64401263a9 100644 --- a/src/jrd/tra.h +++ b/src/jrd/tra.h @@ -80,12 +80,6 @@ public: int savePoint; }; -//Moved to fb_types.h -//typedef ULONG TraNumber; - -// Moved to constants.h -//const TraNumber MAX_TRA_NUMBER = ~TraNumber(0); - // Blobs active in transaction identified by bli_temp_id. Please keep this // structure small as there can be huge amount of them floating in memory. struct BlobIndex @@ -263,8 +257,8 @@ public: BlobIndexTree* tra_blobs; // pointer to actual list of active blobs ArrayField* tra_arrays; // Linked list of active arrays Lock* tra_lock; // lock for transaction - vec* tra_relation_locks; // locks for relations - UInt32Bitmap* tra_commit_sub_trans; // commited sub-transactions + vec* tra_relation_locks; // locks for relations + TransactionBitmap* tra_commit_sub_trans; // commited sub-transactions Savepoint* tra_save_point; // list of savepoints Savepoint* tra_save_free; // free savepoints SLONG tra_save_point_number; // next save point number to use @@ -433,9 +427,6 @@ const int tra_committed = 3; const int tra_us = 4; // Transaction is us const int tra_precommitted = 5; // Transaction is precommitted -// The highest transaction number possible. This is 0x7fffffff if SLONG is 32 bits. -//#define MAX_TRA_NUMBER (~(1L << (BITS_PER_LONG - 1))) - // Savepoint block class Savepoint : public pool_alloc diff --git a/src/jrd/trace/TraceObjects.cpp b/src/jrd/trace/TraceObjects.cpp index 5192caef07..7ff2f5d5ac 100644 --- a/src/jrd/trace/TraceObjects.cpp +++ b/src/jrd/trace/TraceObjects.cpp @@ -65,7 +65,7 @@ unsigned TraceConnectionImpl::getKind() return KIND_DATABASE; } -int TraceConnectionImpl::getConnectionID() +ISC_INT64 TraceConnectionImpl::getConnectionID() { return m_att->att_attachment_id; //return PAG_attachment_id(JRD_get_thread_data()); @@ -122,7 +122,7 @@ const char* TraceConnectionImpl::getRemoteProcessName() /// TraceTransactionImpl -unsigned TraceTransactionImpl::getTransactionID() +ISC_INT64 TraceTransactionImpl::getTransactionID() { return m_tran->tra_number; } @@ -162,7 +162,7 @@ unsigned TraceTransactionImpl::getIsolation() /// TraceSQLStatementImpl -int TraceSQLStatementImpl::getStmtID() +ISC_INT64 TraceSQLStatementImpl::getStmtID() { if (m_stmt->req_request) return m_stmt->req_request->req_id; diff --git a/src/jrd/trace/TraceObjects.h b/src/jrd/trace/TraceObjects.h index 84d19b9a30..ecd3ce0727 100644 --- a/src/jrd/trace/TraceObjects.h +++ b/src/jrd/trace/TraceObjects.h @@ -35,6 +35,7 @@ #include "../../jrd/ntrace.h" #include "../../common/dsc.h" #include "../../common/isc_s_proto.h" +#include "../../jrd/ods_proto.h" #include "../../jrd/req.h" #include "../../jrd/svc.h" #include "../../jrd/tra.h" @@ -72,7 +73,7 @@ public: const char* getRemoteProcessName(); // TraceDatabaseConnection implementation - int getConnectionID(); + ISC_INT64 getConnectionID(); const char* getDatabaseName(); private: const Attachment* const m_att; @@ -89,7 +90,7 @@ public: {} // TraceTransaction implementation - unsigned getTransactionID(); + ISC_INT64 getTransactionID(); FB_BOOLEAN getReadOnly(); int getWait(); unsigned getIsolation(); @@ -147,7 +148,7 @@ public: m_perf(perf) {} - int getStmtID() { return m_stmt->req_id; } + ISC_INT64 getStmtID() { return m_stmt->req_id; } PerformanceInfo* getPerf() { return m_perf; } private: @@ -163,7 +164,7 @@ public: BLRPrinter(blr, length) {} - int getStmtID() { return 0; } + ISC_INT64 getStmtID() { return 0; } PerformanceInfo* getPerf() { return NULL; } }; @@ -180,7 +181,7 @@ public: {} // TraceSQLStatement implementation - int getStmtID(); + ISC_INT64 getStmtID(); PerformanceInfo* getPerf(); Firebird::ITraceParams* getInputs(); const char* getText(); @@ -234,7 +235,7 @@ public: {} // TraceSQLStatement implementation - int getStmtID() { return 0; } + ISC_INT64 getStmtID() { return 0; } PerformanceInfo* getPerf() { return NULL; } Firebird::ITraceParams* getInputs() { return NULL; } const char* getText() { return m_text.c_str(); } @@ -608,10 +609,10 @@ public: void update(const Ods::header_page* header) { - m_oit = header->hdr_oldest_transaction; - m_ost = header->hdr_oldest_snapshot; - m_oat = header->hdr_oldest_active; - m_next = header->hdr_next_transaction; + m_oit = Ods::getOIT(header); + m_ost = Ods::getOST(header); + m_oat = Ods::getOAT(header); + m_next = Ods::getNT(header); } void setPerf(PerformanceInfo* perf) @@ -619,10 +620,10 @@ public: m_perf = perf; } - ISC_UINT64 getOIT() { return m_oit; }; - ISC_UINT64 getOST() { return m_ost; }; - ISC_UINT64 getOAT() { return m_oat; }; - ISC_UINT64 getNext() { return m_next; }; + ISC_INT64 getOIT() { return m_oit; }; + ISC_INT64 getOST() { return m_ost; }; + ISC_INT64 getOAT() { return m_oat; }; + ISC_INT64 getNext() { return m_next; }; PerformanceInfo* getPerf() { return m_perf; }; private: diff --git a/src/jrd/validation.cpp b/src/jrd/validation.cpp index 2e4cb2aad3..c0dce5b735 100644 --- a/src/jrd/validation.cpp +++ b/src/jrd/validation.cpp @@ -561,6 +561,7 @@ VI. ADDITIONAL NOTES #include "../yvalve/gds_proto.h" #include "../common/isc_proto.h" #include "../jrd/met_proto.h" +#include "../jrd/ods_proto.h" #include "../jrd/tra_proto.h" #include "../jrd/val_proto.h" #include "../jrd/validation.h" @@ -1404,8 +1405,8 @@ static void print_rhd(USHORT length, const rhd* header) **************************************/ if (VAL_debug_level) { - fprintf(stdout, "rhd: len %d TX %d format %d ", - length, header->rhd_transaction, (int) header->rhd_format); + fprintf(stdout, "rhd: len %d TX %"SQUADFORMAT" format %d ", + length, Ods::getTraNum(header), (int) header->rhd_format); fprintf(stdout, "BP %d/%d flags 0x%x ", header->rhd_b_page, header->rhd_b_line, header->rhd_flags); if (header->rhd_flags & rhd_incomplete) @@ -1769,11 +1770,11 @@ Validation::RTN Validation::walk_data_page(jrd_rel* relation, ULONG page_number, RBM_SET(vdr_tdbb->getDefaultPool(), &vdr_rel_records, number.getValue()); else { - int state; - if (header->rhd_transaction < dbb->dbb_oldest_transaction) - state = tra_committed; - else - state = TRA_fetch_state(vdr_tdbb, header->rhd_transaction); + const TraNumber transaction = Ods::getTraNum(header); + + const int state = (transaction < dbb->dbb_oldest_transaction) ? + tra_committed : TRA_fetch_state(vdr_tdbb, transaction); + if (state == tra_committed || state == tra_limbo) RBM_SET(vdr_tdbb->getDefaultPool(), &vdr_rel_records, number.getValue()); } @@ -2626,8 +2627,10 @@ Validation::RTN Validation::walk_record(jrd_rel* relation, const rhd* header, US return rtn_ok; } - if (header->rhd_transaction > vdr_max_transaction) - corrupt(VAL_REC_BAD_TID, relation, number.getValue(), header->rhd_transaction); + const TraNumber transaction = Ods::getTraNum(header); + + if (transaction > vdr_max_transaction) + corrupt(VAL_REC_BAD_TID, relation, number.getValue(), transaction); // If there's a back pointer, verify that it's good diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index cf3496e114..f1fe31e90f 100644 --- a/src/jrd/vio.cpp +++ b/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, - const record_param* rpb, jrd_tra::wait_t wait) +inline int wait(thread_db* tdbb, jrd_tra* transaction, const record_param* rpb) { - const SSHORT timeout = (wait == jrd_tra::tra_wait) ? transaction->getLockWait() : 0; - - if (timeout) + if (transaction->getLockWait()) tdbb->bumpRelStats(RuntimeStatistics::RECORD_WAITS, rpb->rpb_relation->rel_id); - return TRA_wait(tdbb, transaction, rpb->rpb_transaction_nr, wait); + return TRA_wait(tdbb, transaction, rpb->rpb_transaction_nr, jrd_tra::tra_wait); +} + +inline bool checkGCActive(thread_db* tdbb, record_param* rpb, int& state) +{ + Lock temp_lock(tdbb, sizeof(SINT64), LCK_record_gc); + temp_lock.lck_key.lck_long = ((SINT64) rpb->rpb_page << 16) | rpb->rpb_line; + + ThreadStatusGuard temp_status(tdbb); + + if (!LCK_lock(tdbb, &temp_lock, LCK_SR, LCK_NO_WAIT)) + { + rpb->rpb_transaction_nr = LCK_read_data(tdbb, &temp_lock); + state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_active; + return true; + } + + LCK_release(tdbb, &temp_lock); + rpb->rpb_flags &= ~rpb_gc_active; + state = tra_dead; + return false; +} + +inline void waitGCActive(thread_db* tdbb, const record_param* rpb) +{ + Lock temp_lock(tdbb, sizeof(SINT64), LCK_record_gc); + temp_lock.lck_key.lck_long = ((SINT64) rpb->rpb_page << 16) | rpb->rpb_line; + + if (!LCK_lock(tdbb, &temp_lock, LCK_SR, LCK_WAIT)) + ERR_punt(); + + LCK_release(tdbb, &temp_lock); } static const UCHAR gc_tpb[] = @@ -386,7 +414,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction) #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES, - "VIO_backout (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT")\n", + "VIO_backout (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT")\n", rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0); #endif @@ -403,7 +431,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction) #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", temp.rpb_page, temp.rpb_line, temp.rpb_transaction_nr, temp.rpb_flags, temp.rpb_b_page, temp.rpb_b_line, @@ -534,20 +562,35 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction) { DPM_backout_mark(tdbb, rpb, transaction); + // dimitr: We don't need to clear the GC flag on the data page + // as the record version is to be removed. Just ensure + // that the appropriate lock is released at the same time. + + AutoLock gcLockGuard(tdbb, rpb->rpb_gc_lock); + rpb->rpb_gc_lock = NULL; + RecordStack empty_staying; IDX_garbage_collect(tdbb, rpb, going, empty_staying); BLB_garbage_collect(tdbb, going, empty_staying, rpb->rpb_page, relation); going.pop(); if (!DPM_get(tdbb, rpb, LCK_write)) - return; - - if (rpb->rpb_transaction_nr != transaction->tra_number) { + fb_assert(false); + return; + } + + if (rpb->rpb_b_page != temp2.rpb_b_page || rpb->rpb_b_line != temp2.rpb_b_line || + rpb->rpb_transaction_nr != temp2.rpb_transaction_nr) + { + fb_assert(false); CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); return; } + fb_assert(rpb->rpb_flags & rpb_gc_active); + rpb->rpb_flags &= ~rpb_gc_active; + temp2 = *rpb; rpb->rpb_undo = old_data; @@ -581,10 +624,15 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction) clearRecordStack(staying); if (!DPM_get(tdbb, rpb, LCK_write)) - return; - - if (rpb->rpb_transaction_nr != transaction->tra_number) { + fb_assert(false); + return; + } + + if (rpb->rpb_b_page != temp2.rpb_b_page || rpb->rpb_b_line != temp2.rpb_b_line || + rpb->rpb_transaction_nr != temp2.rpb_transaction_nr) + { + fb_assert(false); CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); return; } @@ -624,7 +672,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction) { // There is cleanup to be done. Bring the old version forward first - rpb->rpb_flags &= ~(rpb_fragment | rpb_incomplete | rpb_chained | rpb_gc_active); + rpb->rpb_flags &= ~(rpb_fragment | rpb_incomplete | rpb_chained | rpb_gc_active | rpb_long_tranum); DPM_update(tdbb, rpb, 0, transaction); delete_tail(tdbb, &temp2, rpb->rpb_page, 0, 0); } @@ -672,41 +720,26 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE_ALL, "VIO_chase_record_version (record_param %"QUADFORMAT"d, transaction %" - ULONGFORMAT", pool %p)\n", + SQUADFORMAT", pool %p)\n", rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0, (void*) pool); VIO_trace(DEBUG_TRACE_ALL_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, rpb->rpb_f_line); #endif - // Handle the fast path first. If the record is committed, isn't deleted, - // and doesn't have an old version that is a candidate for garbage collection, - // return without further ado - int state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr); - // Reset the garbage collect active flag if the transaction state is - // in a terminal state. If committed it must have been a precommitted - // transaction that was backing out a dead record version and the - // system crashed. Clear the flag and set the state to tra_dead to - // reattempt the backout. + // Reset (if appropriate) the garbage collect active flag to reattempt the backout if (rpb->rpb_flags & rpb_gc_active) - { - if (!rpb->rpb_transaction_nr) - state = tra_active; + checkGCActive(tdbb, rpb, state); - if (state == tra_committed) - state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead; - - if (state == tra_dead) - rpb->rpb_flags &= ~rpb_gc_active; - } + // Take care about modifications performed by our own transaction rpb->rpb_runtime_flags &= ~(RPB_undo_data | RPB_undo_read); int forceBack = 0; @@ -728,6 +761,10 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, } } + // Handle the fast path first. If the record is committed, isn't deleted, + // and doesn't have an old version that is a candidate for garbage collection, + // return without further ado + if ((state == tra_committed || state == tra_us) && !forceBack && !(rpb->rpb_flags & (rpb_deleted | rpb_damaged)) && (rpb->rpb_b_page == 0 || rpb->rpb_transaction_nr >= oldest_snapshot)) @@ -751,7 +788,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, { #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " chase record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " chase record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -766,7 +803,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, if (state == tra_limbo && !(transaction->tra_flags & TRA_ignore_limbo)) { - state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait); + state = wait(tdbb, transaction, rpb); if (state == tra_active) state = tra_limbo; } @@ -783,7 +820,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, if (state == tra_limbo) { CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); - state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait); + state = wait(tdbb, transaction, rpb); if (!DPM_get(tdbb, rpb, LCK_read)) return false; @@ -814,7 +851,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, // of a dead record version. CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); - state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait); + state = wait(tdbb, transaction, rpb); if (state == tra_precommitted) state = check_precommitted(transaction, rpb); @@ -854,7 +891,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, case tra_dead: #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record's transaction (%"ULONGFORMAT") is dead (my TID - %"ULONGFORMAT")\n", + " record's transaction (%"SQUADFORMAT") is dead (my TID - %"SQUADFORMAT")\n", rpb->rpb_transaction_nr, transaction->tra_number); #endif if (gcPolicyBackground && !(rpb->rpb_flags & rpb_chained) && @@ -942,7 +979,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, case tra_limbo: #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record's transaction (%"ULONGFORMAT") is in limbo (my TID - %"ULONGFORMAT")\n", + " record's transaction (%"SQUADFORMAT") is in limbo (my TID - %"SQUADFORMAT")\n", rpb->rpb_transaction_nr, transaction->tra_number); #endif @@ -957,7 +994,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, if (state == tra_active) { VIO_trace(DEBUG_READS_INFO, - " record's transaction (%"ULONGFORMAT") is active (my TID - %"ULONGFORMAT")\n", + " record's transaction (%"SQUADFORMAT") is active (my TID - %"SQUADFORMAT")\n", rpb->rpb_transaction_nr, transaction->tra_number); } #endif @@ -1065,7 +1102,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, case tra_us: #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record's transaction (%"ULONGFORMAT") is us (my TID - %"ULONGFORMAT")\n", + " record's transaction (%"SQUADFORMAT") is us (my TID - %"SQUADFORMAT")\n", rpb->rpb_transaction_nr, transaction->tra_number); #endif @@ -1103,7 +1140,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, case tra_committed: #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record's transaction (%"ULONGFORMAT") is committed (my TID - %"ULONGFORMAT")\n", + " record's transaction (%"SQUADFORMAT") is committed (my TID - %"SQUADFORMAT")\n", rpb->rpb_transaction_nr, transaction->tra_number); #endif if (rpb->rpb_flags & rpb_deleted) @@ -1184,23 +1221,10 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr); - // Reset the garbage collect active flag if the transaction state is - // in a terminal state. If committed it must have been a precommitted - // transaction that was backing out a dead record version and the - // system crashed. Clear the flag and set the state to tra_dead to - // reattempt the backout. + // Reset (if appropriate) the garbage collect active flag to reattempt the backout if (!(rpb->rpb_flags & rpb_chained) && (rpb->rpb_flags & rpb_gc_active)) - { - if (!rpb->rpb_transaction_nr) - state = tra_active; - - if (state == tra_committed) - state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead; - - if (state == tra_dead) - rpb->rpb_flags &= ~rpb_gc_active; - } + checkGCActive(tdbb, rpb, state); } } @@ -1278,7 +1302,7 @@ void VIO_data(thread_db* tdbb, record_param* rpb, MemoryPool* pool) VIO_trace(DEBUG_READS_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, @@ -1363,7 +1387,7 @@ void VIO_data(thread_db* tdbb, record_param* rpb, MemoryPool* pool) rpb->rpb_number.getValue(), length, format->fmt_length); VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT"d:%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT"d:%d, rpb_trans %"SQUADFORMAT "d, flags %d, back %"SLONGFORMAT"d:%d, fragment %"SLONGFORMAT"d:%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, rpb->rpb_f_line); @@ -1399,11 +1423,11 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES, - "VIO_erase (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT")\n", + "VIO_erase (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT")\n", rpb->rpb_number.getValue(), transaction->tra_number); VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -1937,11 +1961,11 @@ bool VIO_garbage_collect(thread_db* tdbb, record_param* rpb, const jrd_tra* tran #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE, "VIO_garbage_collect (record_param %"QUADFORMAT"d, transaction %" - ULONGFORMAT")\n", + SQUADFORMAT")\n", rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0); VIO_trace(DEBUG_TRACE_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -1966,21 +1990,16 @@ bool VIO_garbage_collect(thread_db* tdbb, record_param* rpb, const jrd_tra* tran int state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr); - // Reset the garbage collect active flag if the transaction state is - // in a terminal state. If committed it must have been a precommitted - // transaction that was backing out a dead record version and the - // system crashed. Clear the flag and set the state to tra_dead to - // reattempt the backout. + // Reset (if appropriate) the garbage collect active flag to reattempt the backout if (rpb->rpb_flags & rpb_gc_active) { - if (state == tra_committed) - state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead; - - if (state == tra_dead) - rpb->rpb_flags &= ~rpb_gc_active; + if (checkGCActive(tdbb, rpb, state)) + return true; } + fb_assert(!(rpb->rpb_flags & rpb_gc_active)); + if (state == tra_precommitted) state = check_precommitted(transaction, rpb); @@ -2076,7 +2095,7 @@ bool VIO_get(thread_db* tdbb, record_param* rpb, jrd_tra* transaction, MemoryPoo #ifdef VIO_DEBUG VIO_trace(DEBUG_READS, - "VIO_get (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT", pool %p)\n", + "VIO_get (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT", pool %p)\n", rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0, (void*) pool); #endif @@ -2095,7 +2114,7 @@ bool VIO_get(thread_db* tdbb, record_param* rpb, jrd_tra* transaction, MemoryPoo #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -2155,7 +2174,7 @@ bool VIO_get_current(thread_db* tdbb, #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE, - "VIO_get_current (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT", pool %p)\n", + "VIO_get_current (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT", pool %p)\n", rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0, (void*) pool); #endif @@ -2173,7 +2192,7 @@ bool VIO_get_current(thread_db* tdbb, #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -2203,26 +2222,23 @@ bool VIO_get_current(thread_db* tdbb, // For now check the state in the tip_cache or tip bitmap. If // record is committed (most cases), this will be faster. - int state = (transaction->tra_flags & TRA_read_committed) ? TPC_cache_state(tdbb, rpb->rpb_transaction_nr) : TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr); - // Reset the garbage collect active flag if the transaction state is - // in a terminal state. If committed it must have been a precommitted - // transaction that was backing out a dead record version and the - // system crashed. Clear the flag and set the state to tra_dead to - // reattempt the backout. + // Reset (if appropriate) the garbage collect active flag to reattempt the backout if (rpb->rpb_flags & rpb_gc_active) { - if (state == tra_committed) - state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead; - - if (state == tra_dead) - rpb->rpb_flags &= ~rpb_gc_active; + if (checkGCActive(tdbb, rpb, state)) + { + waitGCActive(tdbb, rpb); + continue; + } } + fb_assert(!(rpb->rpb_flags & rpb_gc_active)); + if (state == tra_precommitted) state = check_precommitted(transaction, rpb); @@ -2243,10 +2259,6 @@ bool VIO_get_current(thread_db* tdbb, VIO_backout(tdbb, rpb, transaction); } continue; - case tra_precommitted: - Attachment::Checkout cout(attachment, FB_FUNCTION); - Thread::sleep(100); // milliseconds - continue; } // The record belongs to somebody else. Wait for him to commit, rollback, or die. @@ -2254,27 +2266,12 @@ bool VIO_get_current(thread_db* tdbb, const TraNumber tid_fetch = rpb->rpb_transaction_nr; // Wait as long as it takes for an active transaction which has modified - // the record. If an active transaction has used its TID to safely - // backout a fragmented dead record version, spin wait because it will finish shortly. + // the record. - if (!(rpb->rpb_flags & rpb_gc_active)) - { - state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait); + state = wait(tdbb, transaction, rpb); - if (state == tra_precommitted) - state = check_precommitted(transaction, rpb); - } - else - { - state = wait(tdbb, transaction, rpb, jrd_tra::tra_probe); - - if (state == tra_active) - { - Attachment::Checkout cout(attachment, FB_FUNCTION); - Thread::sleep(100); // milliseconds - continue; - } - } + if (state == tra_precommitted) + state = check_precommitted(transaction, rpb); switch (state) { @@ -2496,12 +2493,12 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES, "VIO_modify (org_rpb %"QUADFORMAT"d, new_rpb %"QUADFORMAT"d, " - "transaction %"ULONGFORMAT")\n", + "transaction %"SQUADFORMAT")\n", org_rpb->rpb_number.getValue(), new_rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0); VIO_trace(DEBUG_WRITES_INFO, - " old record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " old record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", org_rpb->rpb_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr, org_rpb->rpb_flags, org_rpb->rpb_b_page, org_rpb->rpb_b_line, @@ -2967,12 +2964,12 @@ bool VIO_next_record(thread_db* tdbb, #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE, - "VIO_next_record (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT", pool %p)\n", + "VIO_next_record (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT", pool %p)\n", rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0, (void*) pool); VIO_trace(DEBUG_TRACE_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -3006,7 +3003,7 @@ bool VIO_next_record(thread_db* tdbb, #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, "VIO_next_record got record %"SLONGFORMAT":%d, rpb_trans %" - ULONGFORMAT", flags %d, back %"SLONGFORMAT":%d, fragment %" + SQUADFORMAT", flags %d, back %"SLONGFORMAT":%d, fragment %" SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -3075,7 +3072,7 @@ bool VIO_refetch_record(thread_db* tdbb, record_param* rpb, jrd_tra* transaction **************************************/ #ifdef VIO_DEBUG VIO_trace(DEBUG_READS, - "VIO_refetch_record (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT")\n", + "VIO_refetch_record (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT")\n", rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0); #endif @@ -3176,7 +3173,7 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES, - "VIO_store (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT + "VIO_store (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT ")\n", rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0); #endif @@ -3528,7 +3525,7 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -3568,7 +3565,7 @@ bool VIO_sweep(thread_db* tdbb, jrd_tra* transaction, TraceSweepEvent* traceSwee #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE, - "VIO_sweep (transaction %"ULONGFORMAT")\n", transaction ? transaction->tra_number : 0); + "VIO_sweep (transaction %"SQUADFORMAT")\n", transaction ? transaction->tra_number : 0); #endif if (transaction->tra_attachment->att_flags & ATT_NO_CLEANUP) @@ -3729,7 +3726,7 @@ void VIO_verb_cleanup(thread_db* tdbb, jrd_tra* transaction) #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE, - "VIO_verb_cleanup (transaction %"ULONGFORMAT")\n", + "VIO_verb_cleanup (transaction %"SQUADFORMAT")\n", transaction ? transaction->tra_number : 0); #endif if (transaction->tra_flags & TRA_system) @@ -3998,11 +3995,11 @@ bool VIO_writelock(thread_db* tdbb, record_param* org_rpb, jrd_tra* transaction) #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES, - "VIO_writelock (org_rpb %"QUADFORMAT"d, transaction %"ULONGFORMAT")\n", + "VIO_writelock (org_rpb %"QUADFORMAT"d, transaction %"SQUADFORMAT")\n", org_rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0); VIO_trace(DEBUG_WRITES_INFO, - " old record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " old record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", org_rpb->rpb_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr, org_rpb->rpb_flags, org_rpb->rpb_b_page, org_rpb->rpb_b_line, @@ -4362,7 +4359,7 @@ static void delete_record(thread_db* tdbb, record_param* rpb, ULONG prior_page, rpb->rpb_number.getValue(), prior_page, (void*) pool); VIO_trace(DEBUG_WRITES_INFO, - " delete_record record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " delete_record record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -4439,7 +4436,7 @@ static UCHAR* delete_tail(thread_db* tdbb, rpb->rpb_number.getValue(), prior_page, tail, tail_end); VIO_trace(DEBUG_WRITES_INFO, - " tail of record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " tail of record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -4523,7 +4520,7 @@ static void expunge(thread_db* tdbb, record_param* rpb, const jrd_tra* transacti #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES, - "expunge (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT + "expunge (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT ", prior_page %"SLONGFORMAT")\n", rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0, prior_page); @@ -4545,7 +4542,7 @@ static void expunge(thread_db* tdbb, record_param* rpb, const jrd_tra* transacti #ifdef VIO_DEBUG VIO_trace(DEBUG_WRITES_INFO, - " expunge record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " expunge record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -4612,7 +4609,7 @@ static void garbage_collect(thread_db* tdbb, record_param* rpb, ULONG prior_page rpb->rpb_number.getValue(), prior_page); VIO_trace(DEBUG_WRITES_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -5462,8 +5459,8 @@ static int prepare_update( thread_db* tdbb, #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE_ALL, - "prepare_update (transaction %"ULONGFORMAT - ", commit_tid read %"ULONGFORMAT", record_param %"QUADFORMAT"d, ", + "prepare_update (transaction %"SQUADFORMAT + ", commit_tid read %"SQUADFORMAT", record_param %"QUADFORMAT"d, ", transaction ? transaction->tra_number : 0, commit_tid_read, rpb ? rpb->rpb_number.getValue() : 0); @@ -5473,7 +5470,7 @@ static int prepare_update( thread_db* tdbb, new_rpb ? new_rpb->rpb_number.getValue() : 0); VIO_trace(DEBUG_TRACE_ALL_INFO, - " old record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " old record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT ":%d, prior %p\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, @@ -5588,21 +5585,20 @@ static int prepare_update( thread_db* tdbb, int state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr); - // Reset the garbage collect active flag if the transaction state is - // in a terminal state. If committed it must have been a precommitted - // transaction that was backing out a dead record version and the - // system crashed. Clear the flag and set the state to tra_dead to - // reattempt the backout. + // Reset (if appropriate) the garbage collect active flag to reattempt the backout if (rpb->rpb_flags & rpb_gc_active) { - if (state == tra_committed) - state = TRA_pc_active(tdbb, rpb->rpb_transaction_nr) ? tra_precommitted : tra_dead; - - if (state == tra_dead) - rpb->rpb_flags &= ~rpb_gc_active; + if (checkGCActive(tdbb, rpb, state)) + { + CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); + waitGCActive(tdbb, rpb); + continue; + } } + fb_assert(!(rpb->rpb_flags & rpb_gc_active)); + if (state == tra_precommitted) state = check_precommitted(transaction, rpb); @@ -5611,8 +5607,8 @@ static int prepare_update( thread_db* tdbb, case tra_committed: #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record's transaction (%"ULONGFORMAT - ") is committed (my TID - %"ULONGFORMAT")\n", + " record's transaction (%"SQUADFORMAT + ") is committed (my TID - %"SQUADFORMAT")\n", rpb->rpb_transaction_nr, transaction->tra_number); #endif if (rpb->rpb_flags & rpb_deleted) @@ -5642,7 +5638,6 @@ static int prepare_update( thread_db* tdbb, // has been updated by another transaction which committed in the // meantime, we cannot proceed further - update conflict error. - if ((transaction->tra_flags & TRA_read_committed) && (commit_tid_read != rpb->rpb_transaction_nr)) { @@ -5672,8 +5667,8 @@ static int prepare_update( thread_db* tdbb, if (state == tra_us) { VIO_trace(DEBUG_READS_INFO, - " record's transaction (%"ULONGFORMAT - ") is us (my TID - %"ULONGFORMAT")\n", + " record's transaction (%"SQUADFORMAT + ") is us (my TID - %"SQUADFORMAT")\n", rpb->rpb_transaction_nr, transaction->tra_number); } #endif @@ -5719,35 +5714,19 @@ static int prepare_update( thread_db* tdbb, case tra_limbo: #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record's transaction (%"ULONGFORMAT") is %s (my TID - %"ULONGFORMAT")\n", + " record's transaction (%"SQUADFORMAT") is %s (my TID - %"SQUADFORMAT")\n", rpb->rpb_transaction_nr, (state == tra_active) ? "active" : "limbo", transaction->tra_number); #endif CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); // Wait as long as it takes for an active transaction which has modified - // the record. If an active transaction has used its TID to safely - // backout a fragmented dead record version, spin wait because it will - // finish shortly. + // the record. - if (!(rpb->rpb_flags & rpb_gc_active)) - { - state = wait(tdbb, transaction, rpb, jrd_tra::tra_wait); + state = wait(tdbb, transaction, rpb); - if (state == tra_precommitted) - state = check_precommitted(transaction, rpb); - } - else - { - state = wait(tdbb, transaction, rpb, jrd_tra::tra_probe); - - if (state == tra_active) - { - Attachment::Checkout cout(attachment, FB_FUNCTION); - Thread::sleep(100); // milliseconds - continue; - } - } + if (state == tra_precommitted) + state = check_precommitted(transaction, rpb); // The snapshot says: transaction was active. The TIP page says: transaction // is committed. Maybe the transaction was rolled back via a transaction @@ -5796,23 +5775,15 @@ static int prepare_update( thread_db* tdbb, break; case tra_dead: - case tra_precommitted: #ifdef VIO_DEBUG VIO_trace(DEBUG_READS_INFO, - " record's transaction (%"ULONGFORMAT") is dead (my TID - %"ULONGFORMAT")\n", + " record's transaction (%"SQUADFORMAT") is dead (my TID - %"SQUADFORMAT")\n", rpb->rpb_transaction_nr, transaction->tra_number); #endif CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); break; } - if (state == tra_precommitted) - { - Attachment::Checkout cout(attachment, FB_FUNCTION); - Thread::sleep(100); // milliseconds - continue; - } - VIO_backout(tdbb, rpb, transaction); } @@ -5909,7 +5880,7 @@ static void purge(thread_db* tdbb, record_param* rpb) "purge (record_param %"QUADFORMAT"d)\n", rpb->rpb_number.getValue()); VIO_trace(DEBUG_TRACE_ALL_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line, @@ -5984,11 +5955,11 @@ static void replace_record(thread_db* tdbb, #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE_ALL, - "replace_record (record_param %"QUADFORMAT"d, transaction %"ULONGFORMAT")\n", + "replace_record (record_param %"QUADFORMAT"d, transaction %"SQUADFORMAT")\n", rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0); VIO_trace(DEBUG_TRACE_ALL_INFO, - " record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT ":%d, prior %p\n", rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, @@ -5997,7 +5968,7 @@ static void replace_record(thread_db* tdbb, #endif record_param temp = *rpb; - rpb->rpb_flags &= ~(rpb_fragment | rpb_incomplete | rpb_chained | rpb_gc_active); + rpb->rpb_flags &= ~(rpb_fragment | rpb_incomplete | rpb_chained | rpb_gc_active | rpb_long_tranum); DPM_update(tdbb, rpb, stack, transaction); delete_tail(tdbb, &temp, rpb->rpb_page, 0, 0); @@ -6136,13 +6107,13 @@ static void update_in_place(thread_db* tdbb, #ifdef VIO_DEBUG VIO_trace(DEBUG_TRACE_ALL, - "update_in_place (transaction %"ULONGFORMAT", org_rpb %"QUADFORMAT"d, " + "update_in_place (transaction %"SQUADFORMAT", org_rpb %"QUADFORMAT"d, " "new_rpb %"QUADFORMAT"d)\n", transaction ? transaction->tra_number : 0, org_rpb->rpb_number.getValue(), new_rpb ? new_rpb->rpb_number.getValue() : 0); VIO_trace(DEBUG_TRACE_ALL_INFO, - " old record %"SLONGFORMAT":%d, rpb_trans %"ULONGFORMAT + " old record %"SLONGFORMAT":%d, rpb_trans %"SQUADFORMAT ", flags %d, back %"SLONGFORMAT":%d, fragment %"SLONGFORMAT":%d\n", org_rpb->rpb_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr, org_rpb->rpb_flags, org_rpb->rpb_b_page, org_rpb->rpb_b_line, diff --git a/src/lock/lock.cpp b/src/lock/lock.cpp index 7b430cb2db..d2b4812436 100644 --- a/src/lock/lock.cpp +++ b/src/lock/lock.cpp @@ -499,7 +499,7 @@ SRQ_PTR LockManager::enqueue(Attachment* attachment, UCHAR type, lock_ast_t ast_routine, void* ast_argument, - SLONG data, + SINT64 data, SSHORT lck_wait, SRQ_PTR owner_offset) { @@ -883,7 +883,7 @@ bool LockManager::cancelWait(SRQ_PTR owner_offset) } -SLONG LockManager::queryData(const USHORT series, const USHORT aggregate) +SINT64 LockManager::queryData(const USHORT series, const USHORT aggregate) { /************************************** * @@ -909,7 +909,7 @@ SLONG LockManager::queryData(const USHORT series, const USHORT aggregate) ++(m_sharedMemory->getHeader()->lhb_query_data); const srq& data_header = m_sharedMemory->getHeader()->lhb_data[series]; - SLONG data = 0, count = 0; + SINT64 data = 0, count = 0; // Simply walk the lock series data queue forward for the minimum // and backward for the maximum -- it's maintained in sorted order. @@ -981,7 +981,7 @@ SLONG LockManager::queryData(const USHORT series, const USHORT aggregate) } -SLONG LockManager::readData(SRQ_PTR request_offset) +SINT64 LockManager::readData(SRQ_PTR request_offset) { /************************************** * @@ -1003,7 +1003,8 @@ SLONG LockManager::readData(SRQ_PTR request_offset) ++(m_sharedMemory->getHeader()->lhb_read_data); const lbl* const lock = (lbl*) SRQ_ABS_PTR(request->lrq_lock); - const SLONG data = lock->lbl_data; + const SINT64 data = lock->lbl_data; + if (lock->lbl_series < LCK_MAX_SERIES) ++(m_sharedMemory->getHeader()->lhb_operations[lock->lbl_series]); else @@ -1013,10 +1014,10 @@ SLONG LockManager::readData(SRQ_PTR request_offset) } -SLONG LockManager::readData2(USHORT series, - const UCHAR* value, - USHORT length, - SRQ_PTR owner_offset) +SINT64 LockManager::readData2(USHORT series, + const UCHAR* value, + USHORT length, + SRQ_PTR owner_offset) { /************************************** * @@ -1049,7 +1050,7 @@ SLONG LockManager::readData2(USHORT series, } -SLONG LockManager::writeData(SRQ_PTR request_offset, SLONG data) +SINT64 LockManager::writeData(SRQ_PTR request_offset, SINT64 data) { /************************************** * diff --git a/src/lock/lock_proto.h b/src/lock/lock_proto.h index 90cb1d4958..16349d4955 100644 --- a/src/lock/lock_proto.h +++ b/src/lock/lock_proto.h @@ -168,7 +168,7 @@ struct lbl srq lbl_requests; // Requests granted srq lbl_lhb_hash; // Collision que for hash table srq lbl_lhb_data; // Lock data que by series - SLONG lbl_data; // User data + SINT64 lbl_data; // User data UCHAR lbl_series; // Lock series UCHAR lbl_flags; // Unused. Misc flags USHORT lbl_pending_lrq_count; // count of lbl_requests with LRQ_pending @@ -186,7 +186,7 @@ struct lrq USHORT lrq_flags; // Misc crud SRQ_PTR lrq_owner; // Owner making request SRQ_PTR lrq_lock; // Lock requested - SLONG lrq_data; // Lock data requested + SINT64 lrq_data; // Lock data requested srq lrq_own_requests; // Locks granted for owner srq lrq_lbl_requests; // Que of requests (active, pending) srq lrq_own_blocks; // Owner block que @@ -405,7 +405,7 @@ public: void shutdownOwner(Attachment*, SRQ_PTR*); SRQ_PTR enqueue(Attachment*, Firebird::CheckStatusWrapper*, SRQ_PTR, const USHORT, - const UCHAR*, const USHORT, UCHAR, lock_ast_t, void*, SLONG, SSHORT, SRQ_PTR); + const UCHAR*, const USHORT, UCHAR, lock_ast_t, void*, SINT64, SSHORT, SRQ_PTR); bool convert(Attachment*, Firebird::CheckStatusWrapper*, SRQ_PTR, UCHAR, SSHORT, lock_ast_t, void*); UCHAR downgrade(Attachment*, Firebird::CheckStatusWrapper*, const SRQ_PTR); bool dequeue(const SRQ_PTR); @@ -413,10 +413,10 @@ public: void repost(Attachment*, lock_ast_t, void*, SRQ_PTR); bool cancelWait(SRQ_PTR); - SLONG queryData(const USHORT, const USHORT); - SLONG readData(SRQ_PTR); - SLONG readData2(USHORT, const UCHAR*, USHORT, SRQ_PTR); - SLONG writeData(SRQ_PTR, SLONG); + SINT64 queryData(const USHORT, const USHORT); + SINT64 readData(SRQ_PTR); + SINT64 readData2(USHORT, const UCHAR*, USHORT, SRQ_PTR); + SINT64 writeData(SRQ_PTR, SINT64); private: explicit LockManager(const Firebird::string&, Firebird::RefPtr); diff --git a/src/lock/print.cpp b/src/lock/print.cpp index c023e229ed..03a81b8584 100644 --- a/src/lock/print.cpp +++ b/src/lock/print.cpp @@ -1209,7 +1209,7 @@ static void prt_lock(OUTFILE outfile, const lhb* LOCK_header, const lbl* lock, U preLock, rel_lock, rel_lock); } FPRINTF(outfile, - "\tSeries: %d, State: %d, Size: %d, Length: %d, Data: %"ULONGFORMAT"\n", + "\tSeries: %d, State: %d, Size: %d, Length: %d, Data: %"SQUADFORMAT"\n", lock->lbl_series, lock->lbl_state, lock->lbl_size, lock->lbl_length, lock->lbl_data); if ((lock->lbl_series == Jrd::LCK_bdb || lock->lbl_series == Jrd::LCK_btr_dont_gc) && diff --git a/src/utilities/fbsvcmgr/fbsvcmgr.cpp b/src/utilities/fbsvcmgr/fbsvcmgr.cpp index 72e601dfea..cb325e568f 100644 --- a/src/utilities/fbsvcmgr/fbsvcmgr.cpp +++ b/src/utilities/fbsvcmgr/fbsvcmgr.cpp @@ -549,17 +549,24 @@ const SvcSwitches actionSwitch[] = bool getLine(string& dest, const char*& p) { - unsigned short length = (unsigned short) isc_vax_integer (p, sizeof(unsigned short)); - p += sizeof (unsigned short); + const USHORT length = (USHORT) isc_vax_integer(p, sizeof(USHORT)); + p += sizeof(USHORT); dest.assign(p, length); p += length; return length > 0; } -int getNumeric(const char*& p) +SLONG getInt(const char*& p) { - unsigned int num = (unsigned int) isc_vax_integer (p, sizeof(unsigned int)); - p += sizeof (unsigned int); + const SLONG num = isc_vax_integer(p, sizeof(SLONG)); + p += sizeof(SLONG); + return num; +} + +SINT64 getInt64(const char*& p) +{ + const SINT64 num = isc_portable_integer(reinterpret_cast(p), sizeof(SINT64)); + p += sizeof(SINT64); return num; } @@ -618,9 +625,14 @@ void printMessage(USHORT number, const SafeArg& arg, bool newLine = true) printf("%s", buffer); } -void printNumeric(const char*& p, int num) +void printInt(const char*& p, SLONG num) { - printf ("%s: %d\n", getMessage(num).c_str(), getNumeric(p)); + printf ("%s: %"SLONGFORMAT"\n", getMessage(num).c_str(), getInt(p)); +} + +void printInt64(const char*& p, SINT64 num) +{ + printf ("%s: %"SQUADFORMAT"\n", getMessage(num).c_str(), getInt64(p)); } const char* capArray[] = { @@ -641,7 +653,7 @@ void printCapabilities(const char*& p) { printMessage(57); - int caps = getNumeric(p); + int caps = getInt(p); bool print = false; for (unsigned i = 0; capArray[i]; ++i) @@ -718,7 +730,7 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq) switch (*p++) { case isc_info_svc_version: - printNumeric(p, 7); + printInt(p, 7); break; case isc_info_svc_server_version: printString(p, 8); @@ -749,10 +761,10 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq) printString(p, 15); break; case isc_spb_num_att: - printNumeric(p, 16); + printInt(p, 16); break; case isc_spb_num_db: - printNumeric(p, 17); + printInt(p, 17); break; default: status_exception::raise(Arg::Gds(isc_fbsvcmgr_info_err) << @@ -814,13 +826,22 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq) } break; case isc_spb_multi_tra_id: - printNumeric(p, 35); + printInt(p, 35); break; case isc_spb_single_tra_id: - printNumeric(p, 34); + printInt(p, 34); break; case isc_spb_tra_id: - printNumeric(p, 37); + printInt(p, 37); + break; + case isc_spb_multi_tra_id_64: + printInt64(p, 35); + break; + case isc_spb_single_tra_id_64: + printInt64(p, 34); + break; + case isc_spb_tra_id_64: + printInt64(p, 37); break; default: status_exception::raise(Arg::Gds(isc_fbsvcmgr_info_err) << @@ -847,13 +868,13 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq) getLine(up.last, p); break; case isc_spb_sec_groupid: - up.gid = getNumeric(p); + up.gid = getInt(p); break; case isc_spb_sec_userid: - up.uid = getNumeric(p); + up.uid = getInt(p); break; case isc_spb_sec_admin: - up.admin = getNumeric(p); + up.admin = getInt(p); break; case isc_info_svc_line: @@ -880,7 +901,7 @@ bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq) break; case isc_info_svc_stdin: - stdinRq = getNumeric(p); + stdinRq = getInt(p); if (stdinRq > 0) { ret = true; diff --git a/src/utilities/gstat/ppg.cpp b/src/utilities/gstat/ppg.cpp index 6e14f019b7..da3d39bceb 100644 --- a/src/utilities/gstat/ppg.cpp +++ b/src/utilities/gstat/ppg.cpp @@ -30,6 +30,7 @@ #include "../common/classes/timestamp.h" #include "../jrd/ibase.h" #include "../jrd/ods.h" +#include "../jrd/ods_proto.h" #include "../common/os/guid.h" #include "../yvalve/gds_proto.h" #include "../common/classes/DbImplementation.h" @@ -58,7 +59,6 @@ void PPG_print_header(const header_page* header, ULONG page, else uSvc->printf(false, "Database overflow header page information:\n"); - if (page == HEADER_PAGE) { uSvc->printf(false, "\tFlags\t\t\t%d\n", header->hdr_header.pag_flags); @@ -68,13 +68,13 @@ void PPG_print_header(const header_page* header, ULONG page, uSvc->printf(false, "\tPage size\t\t%d\n", header->hdr_page_size); uSvc->printf(false, "\tODS version\t\t%d.%d\n", header->hdr_ods_version & ~ODS_FIREBIRD_FLAG, header->hdr_ods_minor); - uSvc->printf(false, "\tOldest transaction\t%"ULONGFORMAT"\n", header->hdr_oldest_transaction); - uSvc->printf(false, "\tOldest active\t\t%"ULONGFORMAT"\n", header->hdr_oldest_active); - uSvc->printf(false, "\tOldest snapshot\t\t%"ULONGFORMAT"\n", header->hdr_oldest_snapshot); - uSvc->printf(false, "\tNext transaction\t%"ULONGFORMAT"\n", header->hdr_next_transaction); + uSvc->printf(false, "\tOldest transaction\t%"SQUADFORMAT"\n", Ods::getOIT(header)); + uSvc->printf(false, "\tOldest active\t\t%"SQUADFORMAT"\n", Ods::getOAT(header)); + uSvc->printf(false, "\tOldest snapshot\t\t%"SQUADFORMAT"\n", Ods::getOST(header)); + uSvc->printf(false, "\tNext transaction\t%"SQUADFORMAT"\n", Ods::getNT(header)); uSvc->printf(false, "\tSequence number\t\t%d\n", header->hdr_sequence); - uSvc->printf(false, "\tNext attachment ID\t%"SLONGFORMAT"\n", header->hdr_attachment_id); + uSvc->printf(false, "\tNext attachment ID\t%"SQUADFORMAT"\n", header->hdr_attachment_id); Firebird::DbImplementation imp(header); uSvc->printf(false, "\tImplementation\t\tHW=%s %s-endian OS=%s CC=%s\n", diff --git a/src/utilities/ntrace/TracePluginImpl.cpp b/src/utilities/ntrace/TracePluginImpl.cpp index be308a07cf..b2723a61fd 100644 --- a/src/utilities/ntrace/TracePluginImpl.cpp +++ b/src/utilities/ntrace/TracePluginImpl.cpp @@ -233,7 +233,7 @@ void TracePluginImpl::logRecord(const char* action) void TracePluginImpl::logRecordConn(const char* action, ITraceDatabaseConnection* connection) { // Lookup connection description - const int conn_id = connection->getConnectionID(); + const AttNumber conn_id = connection->getConnectionID(); bool reg = false; while (true) @@ -251,7 +251,7 @@ void TracePluginImpl::logRecordConn(const char* action, ITraceDatabaseConnection if (reg) { string temp; - temp.printf("\t%s (ATT_%d, )" NEWLINE, + temp.printf("\t%s (ATT_%"SQUADFORMAT", )" NEWLINE, config.db_filename.c_str(), conn_id); record.insert(0, temp); break; @@ -279,7 +279,7 @@ void TracePluginImpl::logRecordConn(const char* action, ITraceDatabaseConnection void TracePluginImpl::logRecordTrans(const char* action, ITraceDatabaseConnection* connection, ITraceTransaction* transaction) { - const unsigned tra_id = transaction->getTransactionID(); + const TraNumber tra_id = transaction->getTransactionID(); bool reg = false; while (true) { @@ -297,7 +297,7 @@ void TracePluginImpl::logRecordTrans(const char* action, ITraceDatabaseConnectio if (reg) { string temp; - temp.printf("\t\t(TRA_%lu, )" NEWLINE, transaction->getTransactionID()); + temp.printf("\t\t(TRA_%"SQUADFORMAT", )" NEWLINE, transaction->getTransactionID()); record.insert(0, temp); break; } @@ -327,7 +327,7 @@ void TracePluginImpl::logRecordProcFunc(const char* action, ITraceDatabaseConnec void TracePluginImpl::logRecordStmt(const char* action, ITraceDatabaseConnection* connection, ITraceTransaction* transaction, ITraceStatement* statement, bool isSQL) { - const int stmt_id = statement->getStmtID(); + const StmtNumber stmt_id = statement->getStmtID(); bool reg = false; bool log = true; @@ -354,7 +354,7 @@ void TracePluginImpl::logRecordStmt(const char* action, ITraceDatabaseConnection if (reg) { string temp; - temp.printf(NEWLINE "Statement %d, :" NEWLINE, stmt_id); + temp.printf(NEWLINE "Statement %"SQUADFORMAT", :" NEWLINE, stmt_id); record.insert(0, temp); break; } @@ -952,7 +952,7 @@ void TracePluginImpl::register_connection(ITraceDatabaseConnection* connection) string tmp(*getDefaultMemoryPool()); - conn_data.description->printf("\t%s (ATT_%d", connection->getDatabaseName(), connection->getConnectionID()); + conn_data.description->printf("\t%s (ATT_%"SQUADFORMAT, connection->getDatabaseName(), connection->getConnectionID()); const char* user = connection->getUserName(); if (user) @@ -1050,7 +1050,7 @@ void TracePluginImpl::register_transaction(ITraceTransaction* transaction) TransactionData trans_data; trans_data.id = transaction->getTransactionID(); trans_data.description = FB_NEW_POOL(*getDefaultMemoryPool()) string(*getDefaultMemoryPool()); - trans_data.description->printf("\t\t(TRA_%lu, ", trans_data.id); + trans_data.description->printf("\t\t(TRA_%"SQUADFORMAT", ", trans_data.id); switch (transaction->getIsolation()) { @@ -1526,7 +1526,7 @@ void TracePluginImpl::register_blr_statement(ITraceBLRStatement* statement) string* description = FB_NEW_POOL(*getDefaultMemoryPool()) string(*getDefaultMemoryPool()); if (statement->getStmtID()) { - description->printf(NEWLINE "Statement %d:" NEWLINE, statement->getStmtID()); + description->printf(NEWLINE "Statement %"SQUADFORMAT":" NEWLINE, statement->getStmtID()); } if (config.print_blr) diff --git a/src/utilities/ntrace/TracePluginImpl.h b/src/utilities/ntrace/TracePluginImpl.h index b5d516e44c..adb58aac78 100644 --- a/src/utilities/ntrace/TracePluginImpl.h +++ b/src/utilities/ntrace/TracePluginImpl.h @@ -55,7 +55,7 @@ public: // Data for tracked (active) connections struct ConnectionData { - int id; + AttNumber id; Firebird::string* description; // Deallocate memory used by objects hanging off this structure @@ -65,19 +65,19 @@ public: description = NULL; } - static const int& generate(const void* /*sender*/, const ConnectionData& item) + static const AttNumber& generate(const void* /*sender*/, const ConnectionData& item) { return item.id; } }; - typedef Firebird::BePlusTree + typedef Firebird::BePlusTree ConnectionsTree; // Data for tracked (active) transactions struct TransactionData { - unsigned id; + TraNumber id; Firebird::string* description; // Deallocate memory used by objects hanging off this structure @@ -87,28 +87,28 @@ public: description = NULL; } - static const unsigned& generate(const void* /*sender*/, const TransactionData& item) + static const TraNumber& generate(const void* /*sender*/, const TransactionData& item) { return item.id; } }; - typedef Firebird::BePlusTree + typedef Firebird::BePlusTree TransactionsTree; // Data for tracked (active) statements struct StatementData { - unsigned int id; + StmtNumber id; Firebird::string* description; // NULL in this field indicates that tracing of this statement is not desired - static const unsigned int& generate(const void* /*sender*/, const StatementData& item) + static const StmtNumber& generate(const void* /*sender*/, const StatementData& item) { return item.id; } }; - typedef Firebird::BePlusTree + typedef Firebird::BePlusTree StatementsTree; typedef void* ServiceId; diff --git a/src/utilities/ntrace/traceplugin.cpp b/src/utilities/ntrace/traceplugin.cpp index 71ac77efb7..739e324f81 100644 --- a/src/utilities/ntrace/traceplugin.cpp +++ b/src/utilities/ntrace/traceplugin.cpp @@ -79,7 +79,7 @@ Firebird::ITracePlugin* TraceFactoryImpl::trace_create(Firebird::CheckStatusWrap if (!config.enabled || (config.connection_id && connection && - (connection->getConnectionID() != SLONG(config.connection_id)))) + (connection->getConnectionID() != config.connection_id))) { return NULL; // Plugin is not needed, no error happened. }