diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index da4bcd5ac3..ffd66454b4 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -482,7 +482,7 @@ private: /// trace manager support -class TraceFailedConnection : public TraceConnection +class TraceFailedConnection : public TraceDatabaseConnection { public: TraceFailedConnection(const char* filename, const DatabaseOptions* options) : @@ -502,6 +502,7 @@ public: return m_options->dpb_user_name.c_str(); } + virtual ntrace_connection_kind_t getKind() { return connection_database; } virtual const char* getRoleName() { return m_options->dpb_role_name.c_str(); } virtual const char* getCharSet() { return m_options->dpb_lc_ctype.c_str(); } virtual const char* getRemoteProtocol() { return m_options->dpb_network_protocol.c_str(); } @@ -712,6 +713,7 @@ const char SINGLE_QUOTE = '\''; #define GDS_DSQL_SET_CURSOR jrd8_set_cursor #define GDS_DSQL_SQL_INFO jrd8_sql_info +#define ENTRYPOINT_NAME(func) STRINGIZE(func) // External hook definitions @@ -728,31 +730,75 @@ static const char* ENCRYPT = "encrypt"; static const char* DECRYPT = "decrypt"; -void trace_failed_attach(TraceManager* traceManager, const char* filename, - const DatabaseOptions& options, bool create, bool no_priv) +static ISC_STATUS trace_error(thread_db* tdbb, const Exception& ex, ISC_STATUS* user_status, const char* func) +{ + const ISC_STATUS ret = ex.stuff_exception(user_status); + + Attachment* att = tdbb->getAttachment(); + if (ret == isc_bad_db_handle || !att) + return ret; + + if (att->att_trace_manager->needs().event_error) + { + TraceConnectionImpl conn(att); + TraceStatusVectorImpl traceStatus(user_status); + + att->att_trace_manager->event_error(&conn, &traceStatus, func); + } + + return ret; +} + +static void trace_warning(thread_db* tdbb, ISC_STATUS* user_status, const char* func) +{ + Attachment* att = tdbb->getAttachment(); + if (!att) + return; + + if (att->att_trace_manager->needs().event_error) + { + TraceStatusVectorImpl traceStatus(user_status); + + if (traceStatus.hasWarning()) + { + TraceConnectionImpl conn(att); + att->att_trace_manager->event_error(&conn, &traceStatus, func); + } + } +} + +static void trace_failed_attach(TraceManager* traceManager, const char* filename, + const DatabaseOptions& options, bool create, ISC_STATUS* status) { // Report to Trace API that attachment has not been created const char* origFilename = filename; if (options.dpb_org_filename.hasData()) origFilename = options.dpb_org_filename.c_str(); + TraceFailedConnection conn(origFilename, &options); + TraceStatusVectorImpl traceStatus(status); + + const bool no_priv = (status[1] == isc_login || status[1] == isc_no_priv); + const char* func = create ? ENTRYPOINT_NAME(GDS_CREATE_DATABASE) : + ENTRYPOINT_NAME(GDS_ATTACH_DATABASE); + if (!traceManager) { TraceManager tempMgr(origFilename); if (tempMgr.needs().event_attach) - { - TraceFailedConnection conn(origFilename, &options); tempMgr.event_attach(&conn, create, no_priv ? res_unauthorized : res_failed); - } + + if (tempMgr.needs().event_error) + tempMgr.event_error(&conn, &traceStatus, func); } else { if (traceManager->needs().event_attach) - { - TraceFailedConnection conn(origFilename, &options); traceManager->event_attach(&conn, create, no_priv ? res_unauthorized : res_failed); - } + + if (traceManager->needs().event_error) + traceManager->event_error(&conn, &traceStatus, func); } } @@ -837,22 +883,24 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status, } catch (const DelayFailedLogin& ex) { - trace_failed_attach(NULL, filename, options, false, true); + const ISC_STATUS ret = ex.stuff_exception(user_status); + trace_failed_attach(NULL, filename, options, false, user_status); ex.sleep(); - return ex.stuff_exception(user_status); + return ret; } catch (const Exception& ex) { - trace_failed_attach(NULL, filename, options, false, true); - return ex.stuff_exception(user_status); + const ISC_STATUS ret = ex.stuff_exception(user_status); + trace_failed_attach(NULL, filename, options, false, user_status); + return ret; } // Check database against conf file. const VdnResult vdn = verifyDatabaseName(expanded_name, user_status, is_alias); if (!is_alias && vdn == VDN_FAIL) { - trace_failed_attach(NULL, filename, options, false, false); + trace_failed_attach(NULL, filename, options, false, user_status); return user_status[1]; } @@ -1420,10 +1468,9 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status, } // try catch (const Exception& ex) { - const ISC_LONG exc = ex.stuff_exception(user_status); - const bool no_priv = (exc == isc_login || exc == isc_no_priv); + ex.stuff_exception(user_status); trace_failed_attach(attachment ? attachment->att_trace_manager : NULL, - filename, options, false, no_priv); + filename, options, false, user_status); return unwindAttach(ex, user_status, tdbb, attachment, dbb); } @@ -1456,11 +1503,18 @@ ISC_STATUS GDS_BLOB_INFO(ISC_STATUS* user_status, blb* const blob = *blob_handle; validateHandle(tdbb, blob); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - const UCHAR* items2 = reinterpret_cast(items); - UCHAR* buffer2 = reinterpret_cast(buffer); - INF_blob_info(blob, items2, item_length, buffer2, buffer_length); + const UCHAR* items2 = reinterpret_cast(items); + UCHAR* buffer2 = reinterpret_cast(buffer); + INF_blob_info(blob, items2, item_length, buffer2, buffer_length); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_BLOB_INFO)); + } } catch (const Exception& ex) { @@ -1490,10 +1544,17 @@ ISC_STATUS GDS_CANCEL_BLOB(ISC_STATUS* user_status, blb** blob_handle) blb* const blob = *blob_handle; validateHandle(tdbb, blob); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - BLB_cancel(tdbb, blob); - *blob_handle = NULL; + BLB_cancel(tdbb, blob); + *blob_handle = NULL; + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_CANCEL_BLOB)); + } } catch (const Exception& ex) { @@ -1522,13 +1583,20 @@ ISC_STATUS GDS_CANCEL_EVENTS(ISC_STATUS* user_status, Attachment** handle, SLONG validateHandle(tdbb, *handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); - - Database* const dbb = tdbb->getDatabase(); - - if (dbb->dbb_event_mgr) + try { - dbb->dbb_event_mgr->cancelEvents(*id); + check_database(tdbb); + + Database* const dbb = tdbb->getDatabase(); + + if (dbb->dbb_event_mgr) + { + dbb->dbb_event_mgr->cancelEvents(*id); + } + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_CANCEL_EVENTS)); } } catch (const Exception& ex) @@ -1617,10 +1685,17 @@ ISC_STATUS GDS_CLOSE_BLOB(ISC_STATUS* user_status, blb** blob_handle) blb* const blob = *blob_handle; validateHandle(tdbb, blob); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - BLB_close(tdbb, blob); - *blob_handle = NULL; + BLB_close(tdbb, blob); + *blob_handle = NULL; + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_CLOSE_BLOB)); + } } catch (const Exception& ex) { @@ -1649,9 +1724,16 @@ ISC_STATUS GDS_COMMIT(ISC_STATUS* user_status, jrd_tra** tra_handle) validateHandle(tdbb, *tra_handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - JRD_commit_transaction(tdbb, tra_handle); + JRD_commit_transaction(tdbb, tra_handle); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_COMMIT)); + } } catch (const Exception& ex) { @@ -1680,9 +1762,16 @@ ISC_STATUS GDS_COMMIT_RETAINING(ISC_STATUS* user_status, jrd_tra** tra_handle) validateHandle(tdbb, *tra_handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - JRD_commit_retaining(tdbb, tra_handle); + JRD_commit_retaining(tdbb, tra_handle); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_COMMIT_RETAINING)); + } } catch (const Exception& ex) { @@ -1733,7 +1822,7 @@ ISC_STATUS GDS_COMPILE(ISC_STATUS* user_status, const bool no_priv = (exc == isc_no_priv); trace.finish(NULL, no_priv ? res_unauthorized : res_failed); - return exc; + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_COMPILE)); } } catch (const Exception& ex) @@ -1775,11 +1864,18 @@ ISC_STATUS GDS_CREATE_BLOB2(ISC_STATUS* user_status, validateHandle(tdbb, *db_handle); validateHandle(tdbb, *tra_handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - jrd_tra* const transaction = find_transaction(tdbb, isc_segstr_wrong_db); + jrd_tra* const transaction = find_transaction(tdbb, isc_segstr_wrong_db); - *blob_handle = BLB_create2(tdbb, transaction, blob_id, bpb_length, bpb); + *blob_handle = BLB_create2(tdbb, transaction, blob_id, bpb_length, bpb); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_CREATE_BLOB2)); + } } catch (const Exception& ex) { @@ -1872,15 +1968,17 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status, } catch (const DelayFailedLogin& ex) { - trace_failed_attach(NULL, filename, options, true, true); + const ISC_STATUS ret = ex.stuff_exception(user_status); + trace_failed_attach(NULL, filename, options, true, user_status); ex.sleep(); - return ex.stuff_exception(user_status); + return ret; } catch (const Exception& ex) { - trace_failed_attach(NULL, filename, options, true, true); - return ex.stuff_exception(user_status); + const ISC_STATUS ret = ex.stuff_exception(user_status); + trace_failed_attach(NULL, filename, options, true, user_status); + return ret; } // Check database against conf file. @@ -2160,10 +2258,9 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status, } // try catch (const Exception& ex) { - const ISC_LONG exc = ex.stuff_exception(user_status); - const bool no_priv = (exc == isc_login || exc == isc_no_priv); + ex.stuff_exception(user_status); trace_failed_attach(attachment ? attachment->att_trace_manager : NULL, - filename, options, true, no_priv); + filename, options, true, user_status); return unwindAttach(ex, user_status, tdbb, attachment, dbb); } @@ -2196,11 +2293,18 @@ ISC_STATUS GDS_DATABASE_INFO(ISC_STATUS* user_status, Attachment* const attachment = *handle; validateHandle(tdbb, attachment); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - const UCHAR* items2 = reinterpret_cast(items); - UCHAR* buffer2 = reinterpret_cast(buffer); - INF_database_info(items2, item_length, buffer2, buffer_length); + const UCHAR* items2 = reinterpret_cast(items); + UCHAR* buffer2 = reinterpret_cast(buffer); + INF_database_info(items2, item_length, buffer2, buffer_length); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DATABASE_INFO)); + } } catch (const Exception& ex) { @@ -2250,7 +2354,7 @@ ISC_STATUS GDS_DDL(ISC_STATUS* user_status, const ISC_STATUS exc = ex.stuff_exception(user_status); trace.finish(exc == FB_SUCCESS ? res_successful : res_failed); - return exc; + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DDL)); } } catch (const Exception& ex) { @@ -2341,94 +2445,100 @@ ISC_STATUS GDS_DROP_DATABASE(ISC_STATUS* user_status, Attachment** handle) Attachment* const attachment = *handle; validateHandle(tdbb, attachment); DatabaseContextHolder dbbHolder(tdbb); - - Database* const dbb = tdbb->getDatabase(); - - const PathName& file_name = attachment->att_filename; - - if (!attachment->locksmith()) + try { - ERR_post(Arg::Gds(isc_no_priv) << Arg::Str("drop") << - Arg::Str("database") << - Arg::Str(file_name)); - } + Database* const dbb = tdbb->getDatabase(); - if (attachment->att_flags & ATT_shutdown) - { - if (dbb->dbb_ast_flags & DBB_shutdown) + const PathName& file_name = attachment->att_filename; + + if (!attachment->locksmith()) { - ERR_post(Arg::Gds(isc_shutdown) << Arg::Str(file_name)); + ERR_post(Arg::Gds(isc_no_priv) << Arg::Str("drop") << + Arg::Str("database") << + Arg::Str(file_name)); } - else + + if (attachment->att_flags & ATT_shutdown) { - ERR_post(Arg::Gds(isc_att_shutdown)); + if (dbb->dbb_ast_flags & DBB_shutdown) + { + ERR_post(Arg::Gds(isc_shutdown) << Arg::Str(file_name)); + } + else + { + ERR_post(Arg::Gds(isc_att_shutdown)); + } + } + + if (!CCH_exclusive(tdbb, LCK_PW, WAIT_PERIOD)) + { + ERR_post(Arg::Gds(isc_lock_timeout) << + Arg::Gds(isc_obj_in_use) << Arg::Str(file_name)); + } + + // Check if same process has more attachments + + if (dbb->dbb_attachments && dbb->dbb_attachments->att_next) + { + ERR_post(Arg::Gds(isc_no_meta_update) << + Arg::Gds(isc_obj_in_use) << Arg::Str("DATABASE")); + } + + // Forced release of all transactions + purge_transactions(tdbb, attachment, true, attachment->att_flags); + + attachment->att_flags |= ATT_cancel_disable; + + // Here we have database locked in exclusive mode. + // Just mark the header page with an 0 ods version so that no other + // process can attach to this database once we release our exclusive + // lock and start dropping files. + + WIN window(HEADER_PAGE_NUMBER); + Ods::header_page* header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); + CCH_MARK_MUST_WRITE(tdbb, &window); + header->hdr_ods_version = 0; + CCH_RELEASE(tdbb, &window); + + // This point on database is useless + // mark the dbb unusable + + dbb->dbb_flags |= DBB_not_in_use; + *handle = NULL; + + PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE); + const jrd_file* file = pageSpace->file; + const Shadow* shadow = dbb->dbb_shadow; + + // Notify Trace API manager about successful drop of database + if (attachment->att_trace_manager->needs().event_detach) + { + TraceConnectionImpl conn(attachment); + attachment->att_trace_manager->event_detach(&conn, true); + } + + // Unlink attachment from database + release_attachment(tdbb, attachment); + + shutdown_database(dbb, false); + + // drop the files here + bool err = drop_files(file); + for (; shadow; shadow = shadow->sdw_next) + { + err = err || drop_files(shadow->sdw_file); + } + + tdbb->setDatabase(NULL); + Database::destroy(dbb); + + if (err) { + ERR_build_status(user_status, Arg::Gds(isc_drdb_completed_with_errs)); } } - - if (!CCH_exclusive(tdbb, LCK_PW, WAIT_PERIOD)) + catch (const Exception& ex) { - ERR_post(Arg::Gds(isc_lock_timeout) << - Arg::Gds(isc_obj_in_use) << Arg::Str(file_name)); - } - - // Check if same process has more attachments - - if (dbb->dbb_attachments && dbb->dbb_attachments->att_next) - { - ERR_post(Arg::Gds(isc_no_meta_update) << - Arg::Gds(isc_obj_in_use) << Arg::Str("DATABASE")); - } - - // Forced release of all transactions - purge_transactions(tdbb, attachment, true, attachment->att_flags); - - attachment->att_flags |= ATT_cancel_disable; - - // Here we have database locked in exclusive mode. - // Just mark the header page with an 0 ods version so that no other - // process can attach to this database once we release our exclusive - // lock and start dropping files. - - WIN window(HEADER_PAGE_NUMBER); - Ods::header_page* header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); - CCH_MARK_MUST_WRITE(tdbb, &window); - header->hdr_ods_version = 0; - CCH_RELEASE(tdbb, &window); - - // This point on database is useless - // mark the dbb unusable - - dbb->dbb_flags |= DBB_not_in_use; - *handle = NULL; - - PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE); - const jrd_file* file = pageSpace->file; - const Shadow* shadow = dbb->dbb_shadow; - - // Notify Trace API manager about successful drop of database - if (attachment->att_trace_manager->needs().event_detach) - { - TraceConnectionImpl conn(attachment); - attachment->att_trace_manager->event_detach(&conn, true); - } - - // Unlink attachment from database - release_attachment(tdbb, attachment); - - shutdown_database(dbb, false); - - // drop the files here - bool err = drop_files(file); - for (; shadow; shadow = shadow->sdw_next) - { - err = err || drop_files(shadow->sdw_file); - } - - tdbb->setDatabase(NULL); - Database::destroy(dbb); - - if (err) { - ERR_build_status(user_status, Arg::Gds(isc_drdb_completed_with_errs)); + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DROP_DATABASE)); } } catch (const Exception& ex) @@ -2463,9 +2573,19 @@ ISC_STATUS GDS_GET_SEGMENT(ISC_STATUS* user_status, blb* const blob = *blob_handle; validateHandle(tdbb, blob); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - *length = BLB_get_segment(tdbb, blob, buffer, buffer_length); + *length = BLB_get_segment(tdbb, blob, buffer, buffer_length); + + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_GET_SEGMENT)); + } + + // Don't trace errors below as it is not real errors but kind of return value if (blob->blb_flags & BLB_eof) { status_exception::raise(Arg::Gds(isc_segstr_eof)); @@ -2512,19 +2632,26 @@ ISC_STATUS GDS_GET_SLICE(ISC_STATUS* user_status, validateHandle(tdbb, *db_handle); validateHandle(tdbb, *tra_handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); - - jrd_tra* const transaction = find_transaction(tdbb, isc_segstr_wrong_db); - - if (!array_id->gds_quad_low && !array_id->gds_quad_high) + try { - MOVE_CLEAR(slice, slice_length); - *return_length = 0; + check_database(tdbb); + + jrd_tra* const transaction = find_transaction(tdbb, isc_segstr_wrong_db); + + if (!array_id->gds_quad_low && !array_id->gds_quad_high) + { + MOVE_CLEAR(slice, slice_length); + *return_length = 0; + } + else + { + *return_length = BLB_get_slice(tdbb, transaction, reinterpret_cast(array_id), + sdl, param_length, param, slice_length, slice); + } } - else + catch (const Exception& ex) { - *return_length = BLB_get_slice(tdbb, transaction, reinterpret_cast(array_id), - sdl, param_length, param, slice_length, slice); + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_GET_SLICE)); } } catch (const Exception& ex) @@ -2566,11 +2693,18 @@ ISC_STATUS GDS_OPEN_BLOB2(ISC_STATUS* user_status, validateHandle(tdbb, *db_handle); validateHandle(tdbb, *tra_handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - jrd_tra* const transaction = find_transaction(tdbb, isc_segstr_wrong_db); + jrd_tra* const transaction = find_transaction(tdbb, isc_segstr_wrong_db); - *blob_handle = BLB_open2(tdbb, transaction, blob_id, bpb_length, bpb, true); + *blob_handle = BLB_open2(tdbb, transaction, blob_id, bpb_length, bpb, true); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_OPEN_BLOB2)); + } } catch (const Exception& ex) { @@ -2601,9 +2735,16 @@ ISC_STATUS GDS_PREPARE(ISC_STATUS* user_status, jrd_tra** tra_handle, USHORT len jrd_tra* const transaction = *tra_handle; validateHandle(tdbb, transaction); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - prepare(tdbb, transaction, length, msg); + prepare(tdbb, transaction, length, msg); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_PREPARE)); + } } catch (const Exception& ex) { @@ -2636,9 +2777,16 @@ ISC_STATUS GDS_PUT_SEGMENT(ISC_STATUS* user_status, blb* const blob = *blob_handle; validateHandle(tdbb, blob); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - BLB_put_segment(tdbb, blob, buffer, buffer_length); + BLB_put_segment(tdbb, blob, buffer, buffer_length); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_PUT_SEGMENT)); + } } catch (const Exception& ex) { @@ -2677,12 +2825,19 @@ ISC_STATUS GDS_PUT_SLICE(ISC_STATUS* user_status, validateHandle(tdbb, *db_handle); validateHandle(tdbb, *tra_handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - jrd_tra* const transaction = find_transaction(tdbb, isc_segstr_wrong_db); + jrd_tra* const transaction = find_transaction(tdbb, isc_segstr_wrong_db); - BLB_put_slice(tdbb, transaction, reinterpret_cast(array_id), - sdl, param_length, param, slice_length, slice); + BLB_put_slice(tdbb, transaction, reinterpret_cast(array_id), + sdl, param_length, param, slice_length, slice); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_PUT_SLICE)); + } } catch (const Exception& ex) { @@ -2718,17 +2873,24 @@ ISC_STATUS GDS_QUE_EVENTS(ISC_STATUS* user_status, Attachment* const attachment = *handle; validateHandle(tdbb, attachment); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - Database* const dbb = tdbb->getDatabase(); - Lock* const lock = dbb->dbb_lock; + Database* const dbb = tdbb->getDatabase(); + Lock* const lock = dbb->dbb_lock; - EventManager::init(attachment); + EventManager::init(attachment); - *id = dbb->dbb_event_mgr->queEvents(attachment->att_event_session, - lock->lck_length, (const TEXT*) &lock->lck_key, - length, items, - ast, arg); + *id = dbb->dbb_event_mgr->queEvents(attachment->att_event_session, + lock->lck_length, (const TEXT*) &lock->lck_key, + length, items, + ast, arg); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_QUE_EVENTS)); + } } catch (const Exception& ex) { @@ -2768,14 +2930,21 @@ ISC_STATUS GDS_RECEIVE(ISC_STATUS* user_status, jrd_req* const request = *req_handle; validateHandle(tdbb, request); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); - check_transaction(tdbb, request->req_transaction); + try + { + check_database(tdbb); + check_transaction(tdbb, request->req_transaction); - JRD_receive(tdbb, request, msg_type, msg_length, reinterpret_cast(msg), level + JRD_receive(tdbb, request, msg_type, msg_length, reinterpret_cast(msg), level #ifdef SCROLLABLE_CURSORS - , direction, offset + , direction, offset #endif - ); + ); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_RECEIVE)); + } } catch (const Exception& ex) { @@ -2814,9 +2983,16 @@ ISC_STATUS GDS_RECONNECT(ISC_STATUS* user_status, Attachment* const attachment = *db_handle; validateHandle(tdbb, attachment); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - *tra_handle = TRA_reconnect(tdbb, id, length); + *tra_handle = TRA_reconnect(tdbb, id, length); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_RECONNECT)); + } } catch (const Exception& ex) { @@ -2846,10 +3022,17 @@ ISC_STATUS GDS_RELEASE_REQUEST(ISC_STATUS* user_status, jrd_req** req_handle) jrd_req* const request = *req_handle; validateHandle(tdbb, request); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - CMP_release(tdbb, request); - *req_handle = NULL; + CMP_release(tdbb, request); + *req_handle = NULL; + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_RELEASE_REQUEST)); + } } catch (const Exception& ex) { @@ -2885,13 +3068,20 @@ ISC_STATUS GDS_REQUEST_INFO(ISC_STATUS* user_status, jrd_req* const request = *req_handle; validateHandle(tdbb, request); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - // I can't change the GDS_REQUEST_INFO's signature, so I do the casts here. - const UCHAR* items2 = reinterpret_cast(items); - UCHAR* buffer2 = reinterpret_cast(buffer); - SLONG buffer_length2 = (ULONG)(USHORT) buffer_length; - JRD_request_info(tdbb, request, level, item_length, items2, buffer_length2, buffer2); + // I can't change the GDS_REQUEST_INFO's signature, so I do the casts here. + const UCHAR* items2 = reinterpret_cast(items); + UCHAR* buffer2 = reinterpret_cast(buffer); + SLONG buffer_length2 = (ULONG)(USHORT) buffer_length; + JRD_request_info(tdbb, request, level, item_length, items2, buffer_length2, buffer2); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_REQUEST_INFO)); + } } catch (const Exception& ex) { @@ -2920,9 +3110,16 @@ ISC_STATUS GDS_ROLLBACK_RETAINING(ISC_STATUS* user_status, jrd_tra** tra_handle) validateHandle(tdbb, *tra_handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - JRD_rollback_retaining(tdbb, tra_handle); + JRD_rollback_retaining(tdbb, tra_handle); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_ROLLBACK_RETAINING)); + } } catch (const Exception& ex) { @@ -2951,9 +3148,16 @@ ISC_STATUS GDS_ROLLBACK(ISC_STATUS* user_status, jrd_tra** tra_handle) validateHandle(tdbb, *tra_handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - JRD_rollback_transaction(tdbb, tra_handle); + JRD_rollback_transaction(tdbb, tra_handle); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_ROLLBACK)); + } } catch (const Exception& ex) { @@ -2987,9 +3191,16 @@ ISC_STATUS GDS_SEEK_BLOB(ISC_STATUS* user_status, blb* const blob = *blob_handle; validateHandle(tdbb, blob); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - *result = BLB_lseek(blob, mode, offset); + *result = BLB_lseek(blob, mode, offset); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_SEEK_BLOB)); + } } catch (const Exception& ex) { @@ -3024,19 +3235,26 @@ ISC_STATUS GDS_SEND(ISC_STATUS* user_status, jrd_req* request = *req_handle; validateHandle(tdbb, request); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); - check_transaction(tdbb, request->req_transaction); - - verify_request_synchronization(request, level); - - EXE_send(tdbb, request, msg_type, msg_length, reinterpret_cast(msg)); - - check_autocommit(request, tdbb); - - if (request->req_flags & req_warning) + try { - request->req_flags &= ~req_warning; - ERR_punt(); + check_database(tdbb); + check_transaction(tdbb, request->req_transaction); + + verify_request_synchronization(request, level); + + EXE_send(tdbb, request, msg_type, msg_length, reinterpret_cast(msg)); + + check_autocommit(request, tdbb); + + if (request->req_flags & req_warning) + { + request->req_flags &= ~req_warning; + ERR_punt(); + } + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_SEND)); } } catch (const Exception& ex) @@ -3263,27 +3481,34 @@ ISC_STATUS GDS_START_AND_SEND(ISC_STATUS* user_status, validateHandle(tdbb, request); validateHandle(tdbb, *tra_handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); - check_transaction(tdbb, request->req_transaction); - - jrd_tra* const transaction = find_transaction(tdbb, isc_req_wrong_db); - - TraceBlrExecute trace(tdbb, request); try { - JRD_start_and_send(tdbb, request, transaction, msg_type, - msg_length, reinterpret_cast(msg), level); + check_database(tdbb); + check_transaction(tdbb, request->req_transaction); - // Notify Trace API about blr execution - trace.finish(res_successful); + jrd_tra* const transaction = find_transaction(tdbb, isc_req_wrong_db); + + TraceBlrExecute trace(tdbb, request); + try + { + JRD_start_and_send(tdbb, request, transaction, msg_type, + msg_length, reinterpret_cast(msg), level); + + // Notify Trace API about blr execution + trace.finish(res_successful); + } + catch (const Exception& ex) + { + const ISC_LONG exc = ex.stuff_exception(user_status); + const bool no_priv = (exc == isc_login || exc == isc_no_priv); + trace.finish(no_priv ? res_unauthorized : res_failed); + + throw; + } } catch (const Exception& ex) { - const ISC_LONG exc = ex.stuff_exception(user_status); - const bool no_priv = (exc == isc_login || exc == isc_no_priv); - trace.finish(no_priv ? res_unauthorized : res_failed); - - return exc; + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_START_AND_SEND)); } } catch (const Exception& ex) @@ -3315,24 +3540,31 @@ ISC_STATUS GDS_START(ISC_STATUS* user_status, jrd_req** req_handle, jrd_tra** tr validateHandle(tdbb, request); validateHandle(tdbb, *tra_handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); - check_transaction(tdbb, request->req_transaction); - - jrd_tra* const transaction = find_transaction(tdbb, isc_req_wrong_db); - - TraceBlrExecute trace(tdbb, request); try { - JRD_start(tdbb, request, transaction, level); - trace.finish(res_successful); + check_database(tdbb); + check_transaction(tdbb, request->req_transaction); + + jrd_tra* const transaction = find_transaction(tdbb, isc_req_wrong_db); + + TraceBlrExecute trace(tdbb, request); + try + { + JRD_start(tdbb, request, transaction, level); + trace.finish(res_successful); + } + catch (const Exception& ex) + { + const ISC_LONG exc = stuff_exception(user_status, ex); + const bool no_priv = (exc == isc_login || exc == isc_no_priv); + trace.finish(no_priv ? res_unauthorized : res_failed); + + throw; + } } catch (const Exception& ex) { - const ISC_LONG exc = stuff_exception(user_status, ex); - const bool no_priv = (exc == isc_login || exc == isc_no_priv); - trace.finish(no_priv ? res_unauthorized : res_failed); - - return exc; + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_START)); } } catch (const Exception& ex) @@ -3506,101 +3738,108 @@ ISC_STATUS GDS_TRANSACT_REQUEST(ISC_STATUS* user_status, validateHandle(tdbb, attachment); validateHandle(tdbb, *tra_handle); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); - - Database* const dbb = tdbb->getDatabase(); - - jrd_tra* const transaction = find_transaction(tdbb, isc_req_wrong_db); - - jrd_nod* in_message = NULL; - jrd_nod* out_message = NULL; - - jrd_req* request = NULL; - MemoryPool* new_pool = dbb->createPool(); - try { - Jrd::ContextPoolHolder context(tdbb, new_pool); + check_database(tdbb); - AutoPtr csb; - PAR_parse(tdbb, csb, reinterpret_cast(blr), blr_length, false); + Database* const dbb = tdbb->getDatabase(); - request = CMP_make_request(tdbb, csb, false); - CMP_verify_access(tdbb, request); + jrd_tra* const transaction = find_transaction(tdbb, isc_req_wrong_db); - jrd_nod* node; - for (size_t i = 0; i < csb->csb_rpt.getCount(); i++) + jrd_nod* in_message = NULL; + jrd_nod* out_message = NULL; + + jrd_req* request = NULL; + MemoryPool* new_pool = dbb->createPool(); + + try { - if ( (node = csb->csb_rpt[i].csb_message) ) + Jrd::ContextPoolHolder context(tdbb, new_pool); + + AutoPtr csb; + PAR_parse(tdbb, csb, reinterpret_cast(blr), blr_length, false); + + request = CMP_make_request(tdbb, csb, false); + CMP_verify_access(tdbb, request); + + jrd_nod* node; + for (size_t i = 0; i < csb->csb_rpt.getCount(); i++) { - if ((int) (IPTR) node->nod_arg[e_msg_number] == 0) + if ( (node = csb->csb_rpt[i].csb_message) ) { - in_message = node; - } - else if ((int) (IPTR) node->nod_arg[e_msg_number] == 1) - { - out_message = node; + if ((int) (IPTR) node->nod_arg[e_msg_number] == 0) + { + in_message = node; + } + else if ((int) (IPTR) node->nod_arg[e_msg_number] == 1) + { + out_message = node; + } } } } - } - catch (const Exception&) - { - if (request) - CMP_release(tdbb, request); - else - dbb->deletePool(new_pool); - - throw; - } - - request->req_attachment = attachment; - - USHORT len; - if (in_msg_length) - { - if (in_message) + catch (const Exception&) { - const Format* format = (Format*) in_message->nod_arg[e_msg_format]; + if (request) + CMP_release(tdbb, request); + else + dbb->deletePool(new_pool); + + throw; + } + + request->req_attachment = attachment; + + USHORT len; + if (in_msg_length) + { + if (in_message) + { + const Format* format = (Format*) in_message->nod_arg[e_msg_format]; + len = format->fmt_length; + } + else { + len = 0; + } + + if (in_msg_length != len) + { + ERR_post(Arg::Gds(isc_port_len) << Arg::Num(in_msg_length) << + Arg::Num(len)); + } + + memcpy((SCHAR*) request + in_message->nod_impure, in_msg, in_msg_length); + } + + EXE_start(tdbb, request, transaction); + + if (out_message) + { + const Format* format = (Format*) out_message->nod_arg[e_msg_format]; len = format->fmt_length; } else { len = 0; } - if (in_msg_length != len) + if (out_msg_length != len) { - ERR_post(Arg::Gds(isc_port_len) << Arg::Num(in_msg_length) << + ERR_post(Arg::Gds(isc_port_len) << Arg::Num(out_msg_length) << Arg::Num(len)); } - memcpy((SCHAR*) request + in_message->nod_impure, in_msg, in_msg_length); + if (out_msg_length) { + memcpy(out_msg, (SCHAR*) request + out_message->nod_impure, out_msg_length); + } + + check_autocommit(request, tdbb); + + CMP_release(tdbb, request); } - - EXE_start(tdbb, request, transaction); - - if (out_message) + catch (const Exception& ex) { - const Format* format = (Format*) out_message->nod_arg[e_msg_format]; - len = format->fmt_length; + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_TRANSACT_REQUEST)); } - else { - len = 0; - } - - if (out_msg_length != len) - { - ERR_post(Arg::Gds(isc_port_len) << Arg::Num(out_msg_length) << - Arg::Num(len)); - } - - if (out_msg_length) { - memcpy(out_msg, (SCHAR*) request + out_message->nod_impure, out_msg_length); - } - - check_autocommit(request, tdbb); - - CMP_release(tdbb, request); } catch (const Exception& ex) { @@ -3635,11 +3874,18 @@ ISC_STATUS GDS_TRANSACTION_INFO(ISC_STATUS* user_status, jrd_tra* const transaction = *tra_handle; validateHandle(tdbb, transaction); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - const UCHAR* items2 = reinterpret_cast(items); - UCHAR* buffer2 = reinterpret_cast(buffer); - INF_transaction_info(transaction, items2, item_length, buffer2, buffer_length); + const UCHAR* items2 = reinterpret_cast(items); + UCHAR* buffer2 = reinterpret_cast(buffer); + INF_transaction_info(transaction, items2, item_length, buffer2, buffer_length); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_TRANSACTION_INFO)); + } } catch (const Exception& ex) { @@ -3670,9 +3916,16 @@ ISC_STATUS GDS_UNWIND(ISC_STATUS* user_status, jrd_req** req_handle, SSHORT leve jrd_req* const request = *req_handle; validateHandle(tdbb, request); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - JRD_unwind_request(tdbb, request, level); + JRD_unwind_request(tdbb, request, level); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_UNWIND)); + } } catch (const Exception& ex) { @@ -3697,9 +3950,17 @@ ISC_STATUS GDS_DSQL_ALLOCATE(ISC_STATUS* user_status, Attachment** db_handle, ds Attachment* const attachment = *db_handle; validateHandle(tdbb, attachment); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - *stmt_handle = DSQL_allocate_statement(tdbb, attachment); + *stmt_handle = DSQL_allocate_statement(tdbb, attachment); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DSQL_ALLOCATE)); + } + trace_warning(tdbb, user_status, ENTRYPOINT_NAME(GDS_DSQL_ALLOCATE)); } catch (const Exception& ex) { @@ -3729,13 +3990,21 @@ ISC_STATUS GDS_DSQL_EXECUTE(ISC_STATUS* user_status, validateHandle(tdbb, *tra_handle); } DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - DSQL_execute(tdbb, tra_handle, statement, - in_blr_length, reinterpret_cast(in_blr), - in_msg_type, in_msg_length, reinterpret_cast(in_msg), - out_blr_length, reinterpret_cast(out_blr), - /*out_msg_type,*/ out_msg_length, reinterpret_cast(out_msg)); + DSQL_execute(tdbb, tra_handle, statement, + in_blr_length, reinterpret_cast(in_blr), + in_msg_type, in_msg_length, reinterpret_cast(in_msg), + out_blr_length, reinterpret_cast(out_blr), + /*out_msg_type,*/ out_msg_length, reinterpret_cast(out_msg)); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DSQL_EXECUTE)); + } + trace_warning(tdbb, user_status, ENTRYPOINT_NAME(GDS_DSQL_EXECUTE)); } catch (const Exception& ex) { @@ -3766,14 +4035,22 @@ ISC_STATUS GDS_DSQL_EXECUTE_IMMEDIATE(ISC_STATUS* user_status, validateHandle(tdbb, *tra_handle); } DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - DSQL_execute_immediate(tdbb, attachment, tra_handle, - length, string, dialect, - in_blr_length, reinterpret_cast(in_blr), - /*in_msg_type,*/ in_msg_length, reinterpret_cast(in_msg), - out_blr_length, reinterpret_cast(out_blr), - /*out_msg_type,*/ out_msg_length, reinterpret_cast(out_msg)); + DSQL_execute_immediate(tdbb, attachment, tra_handle, + length, string, dialect, + in_blr_length, reinterpret_cast(in_blr), + /*in_msg_type,*/ in_msg_length, reinterpret_cast(in_msg), + out_blr_length, reinterpret_cast(out_blr), + /*out_msg_type,*/ out_msg_length, reinterpret_cast(out_msg)); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DSQL_EXECUTE_IMMEDIATE)); + } + trace_warning(tdbb, user_status, ENTRYPOINT_NAME(GDS_DSQL_EXECUTE_IMMEDIATE)); } catch (const Exception& ex) { @@ -3803,14 +4080,22 @@ ISC_STATUS GDS_DSQL_FETCH(ISC_STATUS* user_status, validateHandle(tdbb, statement); validateHandle(tdbb, statement->req_transaction); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - return_code = DSQL_fetch(tdbb, statement, blr_length, reinterpret_cast(blr), - /*msg_type,*/ msg_length, reinterpret_cast(dsql_msg_buf) + return_code = DSQL_fetch(tdbb, statement, blr_length, reinterpret_cast(blr), + /*msg_type,*/ msg_length, reinterpret_cast(dsql_msg_buf) #ifdef SCROLLABLE_CURSORS - , direction, offset + , direction, offset #endif - ); + ); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DSQL_FETCH)); + } + trace_warning(tdbb, user_status, ENTRYPOINT_NAME(GDS_DSQL_FETCH)); } catch (const Exception& ex) { @@ -3830,12 +4115,20 @@ ISC_STATUS GDS_DSQL_FREE(ISC_STATUS* user_status, dsql_req** stmt_handle, USHORT dsql_req* const statement = *stmt_handle; validateHandle(tdbb, statement); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - DSQL_free_statement(tdbb, statement, option); + DSQL_free_statement(tdbb, statement, option); - if (option & DSQL_drop) - *stmt_handle = NULL; + if (option & DSQL_drop) + *stmt_handle = NULL; + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DSQL_FREE)); + } + trace_warning(tdbb, user_status, ENTRYPOINT_NAME(GDS_DSQL_FREE)); } catch (const Exception& ex) { @@ -3858,10 +4151,18 @@ ISC_STATUS GDS_DSQL_INSERT(ISC_STATUS* user_status, dsql_req* const statement = *stmt_handle; validateHandle(tdbb, statement); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - DSQL_insert(tdbb, statement, blr_length, reinterpret_cast(blr), - /*msg_type,*/ msg_length, reinterpret_cast(dsql_msg_buf)); + DSQL_insert(tdbb, statement, blr_length, reinterpret_cast(blr), + /*msg_type,*/ msg_length, reinterpret_cast(dsql_msg_buf)); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DSQL_INSERT)); + } + trace_warning(tdbb, user_status, ENTRYPOINT_NAME(GDS_DSQL_INSERT)); } catch (const Exception& ex) { @@ -3890,11 +4191,19 @@ ISC_STATUS GDS_DSQL_PREPARE(ISC_STATUS* user_status, validateHandle(tdbb, *tra_handle); } DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - DSQL_prepare(tdbb, *tra_handle, stmt_handle, length, string, dialect, - item_length, reinterpret_cast(items), - buffer_length, reinterpret_cast(buffer)); + DSQL_prepare(tdbb, *tra_handle, stmt_handle, length, string, dialect, + item_length, reinterpret_cast(items), + buffer_length, reinterpret_cast(buffer)); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DSQL_PREPARE)); + } + trace_warning(tdbb, user_status, ENTRYPOINT_NAME(GDS_DSQL_PREPARE)); } catch (const Exception& ex) { @@ -3917,9 +4226,17 @@ ISC_STATUS GDS_DSQL_SET_CURSOR(ISC_STATUS* user_status, dsql_req* const statement = *stmt_handle; validateHandle(tdbb, statement); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - DSQL_set_cursor(tdbb, statement, cursor); //, type); + DSQL_set_cursor(tdbb, statement, cursor); //, type); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DSQL_SET_CURSOR)); + } + trace_warning(tdbb, user_status, ENTRYPOINT_NAME(GDS_DSQL_SET_CURSOR)); } catch (const Exception& ex) { @@ -3942,11 +4259,19 @@ ISC_STATUS GDS_DSQL_SQL_INFO(ISC_STATUS* user_status, dsql_req* const statement = *stmt_handle; validateHandle(tdbb, statement); DatabaseContextHolder dbbHolder(tdbb); - check_database(tdbb); + try + { + check_database(tdbb); - DSQL_sql_info(tdbb, statement, - item_length, reinterpret_cast(items), - info_length, reinterpret_cast(info)); + DSQL_sql_info(tdbb, statement, + item_length, reinterpret_cast(items), + info_length, reinterpret_cast(info)); + } + catch (const Exception& ex) + { + return trace_error(tdbb, ex, user_status, ENTRYPOINT_NAME(GDS_DSQL_SQL_INFO)); + } + trace_warning(tdbb, user_status, ENTRYPOINT_NAME(GDS_DSQL_SQL_INFO)); } catch (const Exception& ex) { @@ -6568,18 +6893,28 @@ void JRD_start_multiple(thread_db* tdbb, jrd_tra** tra_handle, USHORT count, TEB check_database(tdbb); } - if (v->teb_tpb_length < 0 || (v->teb_tpb_length > 0 && v->teb_tpb == NULL)) + try { - status_exception::raise(Arg::Gds(isc_bad_tpb_form)); + if (v->teb_tpb_length < 0 || (v->teb_tpb_length > 0 && v->teb_tpb == NULL)) + { + status_exception::raise(Arg::Gds(isc_bad_tpb_form)); + } + + transaction = TRA_start(tdbb, v->teb_tpb_length, v->teb_tpb); + + transaction->tra_sibling = prior; + prior = transaction; + + // run ON TRANSACTION START triggers + EXE_execute_db_triggers(tdbb, transaction, jrd_req::req_trigger_trans_start); } + catch(const Exception& ex) + { + ISC_STATUS_ARRAY temp = {0}; + trace_error(tdbb, ex, temp, ENTRYPOINT_NAME(GDS_START_TRANSACTION)); - transaction = TRA_start(tdbb, v->teb_tpb_length, v->teb_tpb); - - transaction->tra_sibling = prior; - prior = transaction; - - // run ON TRANSACTION START triggers - EXE_execute_db_triggers(tdbb, transaction, jrd_req::req_trigger_trans_start); + throw; + } } *tra_handle = transaction; diff --git a/src/jrd/ntrace.h b/src/jrd/ntrace.h index 8cc74a8309..cb19abea00 100644 --- a/src/jrd/ntrace.h +++ b/src/jrd/ntrace.h @@ -34,7 +34,7 @@ #include "../jrd/common.h" /* Version of API, used for version fields in TracePlugin structure */ -#define NTRACE_VERSION 2 +#define NTRACE_VERSION 3 // plugin entry point static const char* const NTRACE_ATTACH = "trace_create"; @@ -43,11 +43,16 @@ static const char* const NTRACE_ATTACH = "trace_create"; struct PerformanceInfo; -class TraceConnection +enum ntrace_connection_kind_t +{ + connection_database = 1, + connection_service +}; + +class TraceBaseConnection { public: - virtual int getConnectionID() = 0; - virtual const char* getDatabaseName() = 0; + virtual ntrace_connection_kind_t getKind() = 0; virtual int getProcessID() = 0; virtual const char* getUserName() = 0; @@ -57,8 +62,13 @@ public: virtual const char* getRemoteAddress() = 0; virtual int getRemoteProcessID() = 0; virtual const char* getRemoteProcessName() = 0; +}; - virtual ~TraceConnection() { } +class TraceDatabaseConnection : public TraceBaseConnection +{ +public: + virtual int getConnectionID() = 0; + virtual const char* getDatabaseName() = 0; }; enum ntrace_tra_isolation_t @@ -77,8 +87,6 @@ public: virtual int getWait() = 0; virtual ntrace_tra_isolation_t getIsolation() = 0; virtual PerformanceInfo* getPerf() = 0; - - virtual ~TraceTransaction() { } }; typedef int ntrace_relation_t; @@ -88,8 +96,6 @@ class TraceParams public: virtual size_t getCount() = 0; virtual const struct dsc* getParam(size_t idx) = 0; - - virtual ~TraceParams() { } }; class TraceStatement @@ -97,8 +103,6 @@ class TraceStatement public: virtual int getStmtID() = 0; virtual PerformanceInfo* getPerf() = 0; - - virtual ~TraceStatement() { } }; class TraceSQLStatement : public TraceStatement @@ -124,8 +128,6 @@ public: virtual const unsigned char* getData() = 0; virtual size_t getDataLength() = 0; virtual const char* getText() = 0; - - virtual ~TraceDYNRequest() { } }; class TraceContextVariable @@ -134,8 +136,6 @@ public: virtual const char* getNameSpace() = 0; virtual const char* getVarName() = 0; virtual const char* getVarValue() = 0; - - virtual ~TraceContextVariable() { } }; class TraceProcedure @@ -144,8 +144,6 @@ public: virtual const char* getProcName() = 0; virtual TraceParams* getInputs() = 0; virtual PerformanceInfo* getPerf() = 0; - - virtual ~TraceProcedure() { } }; class TraceTrigger @@ -156,30 +154,26 @@ public: virtual int getAction() = 0; virtual int getWhich() = 0; virtual PerformanceInfo* getPerf() = 0; - - virtual ~TraceTrigger() { } }; typedef void* ntrace_service_t; -class TraceService +class TraceServiceConnection : public TraceBaseConnection { public: virtual ntrace_service_t getServiceID() = 0; virtual const char* getServiceMgr() = 0; virtual const char* getServiceName() = 0; - - virtual int getProcessID() = 0; - virtual const char* getUserName() = 0; - virtual const char* getRoleName() = 0; - virtual const char* getRemoteProtocol() = 0; - virtual const char* getRemoteAddress() = 0; - virtual int getRemoteProcessID() = 0; - virtual const char* getRemoteProcessName() = 0; - - virtual ~TraceService() { } }; +class TraceStatusVector +{ +public: + virtual bool hasError() = 0; + virtual bool hasWarning() = 0; + virtual const ISC_STATUS* getStatus() = 0; + virtual const char* getText() = 0; +}; /* Plugin-specific argument. Passed by the engine to each hook */ typedef void* ntrace_object_t; @@ -252,67 +246,71 @@ typedef ntrace_boolean_t (*ntrace_shutdown_t)(const struct TracePlugin* tpl_plug /* Create/close attachment */ typedef ntrace_boolean_t (*ntrace_event_attach_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, ntrace_boolean_t create_db, ntrace_result_t att_result); + TraceDatabaseConnection* connection, ntrace_boolean_t create_db, ntrace_result_t att_result); typedef ntrace_boolean_t (*ntrace_event_detach_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, ntrace_boolean_t drop_db); + TraceDatabaseConnection* connection, ntrace_boolean_t drop_db); /* Start/end transaction */ typedef ntrace_boolean_t (*ntrace_event_transaction_start_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, size_t tpb_length, const ntrace_byte_t* tpb, ntrace_result_t tra_result); typedef ntrace_boolean_t (*ntrace_event_transaction_end_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, ntrace_boolean_t commit, ntrace_boolean_t retain_context, ntrace_result_t tra_result); /* Assignment to context variables */ typedef ntrace_boolean_t (*ntrace_event_set_context_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, TraceContextVariable* variable); + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceContextVariable* variable); /* Stored procedure and triggers executing */ typedef ntrace_boolean_t (*ntrace_event_proc_execute_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure, bool started, ntrace_result_t proc_result); typedef ntrace_boolean_t (*ntrace_event_trigger_execute_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger, bool started, ntrace_result_t trig_result); /* DSQL statement lifecycle */ typedef ntrace_boolean_t (*ntrace_event_dsql_prepare_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result); typedef ntrace_boolean_t (*ntrace_event_dsql_free_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceSQLStatement* statement, unsigned short option); + TraceDatabaseConnection* connection, TraceSQLStatement* statement, unsigned short option); typedef ntrace_boolean_t (*ntrace_event_dsql_execute_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, bool started, ntrace_result_t req_result); /* BLR requests */ typedef ntrace_boolean_t (*ntrace_event_blr_compile_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result); typedef ntrace_boolean_t (*ntrace_event_blr_execute_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_result_t req_result); /* DYN requests */ typedef ntrace_boolean_t (*ntrace_event_dyn_execute_t)(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceDYNRequest* request, ntrace_counter_t time_millis, ntrace_result_t req_result); /* Using the services */ typedef ntrace_boolean_t (*ntrace_event_service_attach_t)(const struct TracePlugin* tpl_plugin, - TraceService* service, ntrace_result_t att_result); + TraceServiceConnection* service, ntrace_result_t att_result); typedef ntrace_boolean_t (*ntrace_event_service_start_t)(const struct TracePlugin* tpl_plugin, - TraceService* service, size_t switches_length, const char* switches, + TraceServiceConnection* service, size_t switches_length, const char* switches, ntrace_result_t start_result); typedef ntrace_boolean_t (*ntrace_event_service_query_t)(const struct TracePlugin* tpl_plugin, - TraceService* service, size_t send_item_length, + TraceServiceConnection* service, size_t send_item_length, const ntrace_byte_t* send_items, size_t recv_item_length, const ntrace_byte_t* recv_items, ntrace_result_t query_result); typedef ntrace_boolean_t (*ntrace_event_service_detach_t)(const struct TracePlugin* tpl_plugin, - TraceService* service, ntrace_result_t detach_result); + TraceServiceConnection* service, ntrace_result_t detach_result); + +/* Errors happened */ +typedef ntrace_boolean_t (*ntrace_event_error_t)(const struct TracePlugin* tpl_plugin, + TraceBaseConnection* connection, TraceStatusVector* status, const char* function); /* API of trace plugin. Used to deliver notifications for each database */ @@ -353,9 +351,11 @@ struct TracePlugin ntrace_event_service_query_t tpl_event_service_query; ntrace_event_service_detach_t tpl_event_service_detach; + ntrace_event_error_t tpl_event_error; + /* Some space for future extension of Trace API interface, must be zero-initialized by the plugin */ - void* reserved_for_interface[24]; + void* reserved_for_interface[23]; /* Some space which may be freely used by Trace API driver. If driver needs more space it may allocate and return larger TracePlugin structure. */ @@ -379,7 +379,7 @@ public: virtual const char* getTraceSessionName() = 0; virtual const char* getFirebirdRootDirectory() = 0; virtual const char* getDatabaseName() = 0; - virtual TraceConnection* getConnection() = 0; + virtual TraceDatabaseConnection* getConnection() = 0; virtual TraceLogWriter* getLogWriter() = 0; virtual ~TraceInitInfo() { } diff --git a/src/jrd/svc.cpp b/src/jrd/svc.cpp index 2bb8a52511..96618a7431 100644 --- a/src/jrd/svc.cpp +++ b/src/jrd/svc.cpp @@ -962,13 +962,24 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d else trace_manager = FB_NEW(*getDefaultMemoryPool()) TraceManager(this); - if (trace_manager->needs().event_service_attach) + if (trace_manager->needs().event_service_attach || + trace_manager->needs().event_error) { const ISC_LONG exc = ex.stuff_exception(status_vector); const bool no_priv = (exc == isc_login || exc == isc_no_priv); TraceServiceImpl service(this); - trace_manager->event_service_attach(&service, no_priv ? res_unauthorized : res_failed); + + if (trace_manager->needs().event_service_attach) + { + trace_manager->event_service_attach(&service, no_priv ? res_unauthorized : res_failed); + } + + if (trace_manager->needs().event_error) + { + TraceStatusVectorImpl traceStatus(status_vector); + trace_manager->event_error(&service, &traceStatus, "jrd8_service_attach"); + } } if (!hasTrace) @@ -1611,19 +1622,38 @@ ISC_STATUS Service::query2(thread_db* tdbb, { ISC_STATUS_ARRAY status_vector; - if (svc_trace_manager->needs().event_service_query) + if (svc_trace_manager->needs().event_service_query || + svc_trace_manager->needs().event_error) { const ISC_LONG exc = ex.stuff_exception(status_vector); const bool no_priv = (exc == isc_login || exc == isc_no_priv || exc == isc_insufficient_svc_privileges); TraceServiceImpl service(this); - svc_trace_manager->event_service_query(&service, send_item_length, send_items, - recv_item_length, recv_items, (no_priv ? res_unauthorized : res_failed)); + + if (svc_trace_manager->needs().event_service_query) + { + svc_trace_manager->event_service_query(&service, send_item_length, send_items, + recv_item_length, recv_items, (no_priv ? res_unauthorized : res_failed)); + } + + if (svc_trace_manager->needs().event_error) + { + TraceStatusVectorImpl traceStatus(status_vector); + svc_trace_manager->event_error(&service, &traceStatus, "jrd8_service_query"); + } } throw; } + if (svc_status[1] && svc_trace_manager->needs().event_error) + { + TraceServiceImpl service(this); + TraceStatusVectorImpl traceStatus(svc_status); + + svc_trace_manager->event_error(&service, &traceStatus, "jrd8_service_query"); + } + if (!(svc_flags & SVC_thd_running)) { finish(SVC_finished); @@ -1997,15 +2027,26 @@ void Service::query(USHORT send_item_length, { ISC_STATUS_ARRAY status_vector; - if (svc_trace_manager->needs().event_service_query) + if (svc_trace_manager->needs().event_service_query || + svc_trace_manager->needs().event_error) { const ISC_LONG exc = ex.stuff_exception(status_vector); const bool no_priv = (exc == isc_login || exc == isc_no_priv); - // Report to Trace API that query failed TraceServiceImpl service(this); - svc_trace_manager->event_service_query(&service, send_item_length, send_items, - recv_item_length, recv_items, (no_priv ? res_unauthorized : res_failed)); + + // Report to Trace API that query failed + if (svc_trace_manager->needs().event_service_query) + { + svc_trace_manager->event_service_query(&service, send_item_length, send_items, + recv_item_length, recv_items, (no_priv ? res_unauthorized : res_failed)); + } + + if (svc_trace_manager->needs().event_error) + { + TraceStatusVectorImpl traceStatus(status_vector); + svc_trace_manager->event_error(&service, &traceStatus, "jrd8_service_query"); + } } throw; } @@ -2202,16 +2243,27 @@ void Service::start(USHORT spb_length, const UCHAR* spb_data) } // try catch (const Firebird::Exception& ex) { - if (svc_trace_manager->needs().event_service_start) + if (svc_trace_manager->needs().event_service_start || + svc_trace_manager->needs().event_error) { ISC_STATUS_ARRAY status_vector; const ISC_LONG exc = ex.stuff_exception(status_vector); const bool no_priv = (exc == isc_login || exc == isc_no_priv); TraceServiceImpl service(this); - svc_trace_manager->event_service_start(&service, - this->svc_switches.length(), this->svc_switches.c_str(), - no_priv ? res_unauthorized : res_failed); + + if (svc_trace_manager->needs().event_service_start) + { + svc_trace_manager->event_service_start(&service, + this->svc_switches.length(), this->svc_switches.c_str(), + no_priv ? res_unauthorized : res_failed); + } + + if (svc_trace_manager->needs().event_error) + { + TraceStatusVectorImpl traceStatus(status_vector); + svc_trace_manager->event_error(&service, &traceStatus, "jrd8_service_start"); + } } throw; } diff --git a/src/jrd/trace/TraceDSQLHelpers.h b/src/jrd/trace/TraceDSQLHelpers.h index d60bce3585..82afff325c 100644 --- a/src/jrd/trace/TraceDSQLHelpers.h +++ b/src/jrd/trace/TraceDSQLHelpers.h @@ -147,7 +147,7 @@ public: } TraceRuntimeStats stats(m_attachment->att_database, m_request->req_fetch_baseline, - &m_request->req_request->req_stats, + &m_request->req_request ? &m_request->req_request->req_stats : NULL, fb_utils::query_performance_counter() - m_start_clock, m_request->req_fetch_rowcount); @@ -211,7 +211,8 @@ public: } TraceRuntimeStats stats(m_attachment->att_database, m_request->req_fetch_baseline, - &m_request->req_request->req_stats, m_request->req_fetch_elapsed, + m_request->req_request ? &m_request->req_request->req_stats : NULL, + m_request->req_fetch_elapsed, m_request->req_fetch_rowcount); TraceSQLStatementImpl stmt(m_request, stats.getPerf()); diff --git a/src/jrd/trace/TraceManager.cpp b/src/jrd/trace/TraceManager.cpp index 57d98ed901..59c5968b04 100644 --- a/src/jrd/trace/TraceManager.cpp +++ b/src/jrd/trace/TraceManager.cpp @@ -322,6 +322,8 @@ void TraceManager::update_session(const TraceSession& session) trace_needs.event_service_detach = true; if (plugin->tpl_event_trigger_execute) trace_needs.event_trigger_execute = true; + if (plugin->tpl_event_error) + trace_needs.event_error = true; } } } @@ -387,19 +389,19 @@ void TraceManager::event_dsql_execute(Attachment* att, jrd_tra* transaction, } -void TraceManager::event_attach(TraceConnection* connection, +void TraceManager::event_attach(TraceDatabaseConnection* connection, bool create_db, ntrace_result_t att_result) { EXECUTE_HOOKS(tpl_event_attach, (plug_info->plugin, connection, create_db, att_result)); } -void TraceManager::event_detach(TraceConnection* connection, bool drop_db) +void TraceManager::event_detach(TraceDatabaseConnection* connection, bool drop_db) { EXECUTE_HOOKS(tpl_event_detach, (plug_info->plugin, connection, drop_db)); } -void TraceManager::event_transaction_start(TraceConnection* connection, +void TraceManager::event_transaction_start(TraceDatabaseConnection* connection, TraceTransaction* transaction, size_t tpb_length, const ntrace_byte_t* tpb, ntrace_result_t tra_result) { @@ -407,7 +409,7 @@ void TraceManager::event_transaction_start(TraceConnection* connection, (plug_info->plugin, connection, transaction, tpb_length, tpb, tra_result)); } -void TraceManager::event_transaction_end(TraceConnection* connection, +void TraceManager::event_transaction_end(TraceDatabaseConnection* connection, TraceTransaction* transaction, bool commit, bool retain_context, ntrace_result_t tra_result) { @@ -415,28 +417,28 @@ void TraceManager::event_transaction_end(TraceConnection* connection, (plug_info->plugin, connection, transaction, commit, retain_context, tra_result)); } -void TraceManager::event_set_context(TraceConnection* connection, +void TraceManager::event_set_context(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceContextVariable* variable) { EXECUTE_HOOKS(tpl_event_set_context, (plug_info->plugin, connection, transaction, variable)); } - void TraceManager::event_proc_execute(TraceConnection* connection, TraceTransaction* transaction, + void TraceManager::event_proc_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure, bool started, ntrace_result_t proc_result) { EXECUTE_HOOKS(tpl_event_proc_execute, (plug_info->plugin, connection, transaction, procedure, started, proc_result)); } -void TraceManager::event_trigger_execute(TraceConnection* connection, TraceTransaction* transaction, +void TraceManager::event_trigger_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger, bool started, ntrace_result_t trig_result) { EXECUTE_HOOKS(tpl_event_trigger_execute, (plug_info->plugin, connection, transaction, trigger, started, trig_result)); } -void TraceManager::event_dsql_prepare(TraceConnection* connection, TraceTransaction* transaction, +void TraceManager::event_dsql_prepare(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result) { EXECUTE_HOOKS(tpl_event_dsql_prepare, @@ -444,14 +446,14 @@ void TraceManager::event_dsql_prepare(TraceConnection* connection, TraceTransact time_millis, req_result)); } -void TraceManager::event_dsql_free(TraceConnection* connection, +void TraceManager::event_dsql_free(TraceDatabaseConnection* connection, TraceSQLStatement* statement, unsigned short option) { EXECUTE_HOOKS(tpl_event_dsql_free, (plug_info->plugin, connection, statement, option)); } -void TraceManager::event_dsql_execute(TraceConnection* connection, TraceTransaction* transaction, +void TraceManager::event_dsql_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, bool started, ntrace_result_t req_result) { EXECUTE_HOOKS(tpl_event_dsql_execute, @@ -459,7 +461,7 @@ void TraceManager::event_dsql_execute(TraceConnection* connection, TraceTransact } -void TraceManager::event_blr_compile(TraceConnection* connection, +void TraceManager::event_blr_compile(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result) { @@ -468,7 +470,7 @@ void TraceManager::event_blr_compile(TraceConnection* connection, time_millis, req_result)); } -void TraceManager::event_blr_execute(TraceConnection* connection, +void TraceManager::event_blr_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_result_t req_result) { @@ -476,7 +478,7 @@ void TraceManager::event_blr_execute(TraceConnection* connection, (plug_info->plugin, connection, transaction, statement, req_result)); } -void TraceManager::event_dyn_execute(TraceConnection* connection, +void TraceManager::event_dyn_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceDYNRequest* request, ntrace_counter_t time_millis, ntrace_result_t req_result) { @@ -485,13 +487,13 @@ void TraceManager::event_dyn_execute(TraceConnection* connection, req_result)); } -void TraceManager::event_service_attach(TraceService* service, ntrace_result_t att_result) +void TraceManager::event_service_attach(TraceServiceConnection* service, ntrace_result_t att_result) { EXECUTE_HOOKS(tpl_event_service_attach, (plug_info->plugin, service, att_result)); } -void TraceManager::event_service_start(TraceService* service, +void TraceManager::event_service_start(TraceServiceConnection* service, size_t switches_length, const char* switches, ntrace_result_t start_result) { @@ -499,7 +501,7 @@ void TraceManager::event_service_start(TraceService* service, (plug_info->plugin, service, switches_length, switches, start_result)); } -void TraceManager::event_service_query(TraceService* service, +void TraceManager::event_service_query(TraceServiceConnection* service, size_t send_item_length, const ntrace_byte_t* send_items, size_t recv_item_length, const ntrace_byte_t* recv_items, ntrace_result_t query_result) @@ -509,10 +511,17 @@ void TraceManager::event_service_query(TraceService* service, recv_item_length, recv_items, query_result)); } -void TraceManager::event_service_detach(TraceService* service, ntrace_result_t detach_result) +void TraceManager::event_service_detach(TraceServiceConnection* service, ntrace_result_t detach_result) { EXECUTE_HOOKS(tpl_event_service_detach, (plug_info->plugin, service, detach_result)); } + +void TraceManager::event_error(TraceBaseConnection* connection, TraceStatusVector* status, const char* function) +{ + EXECUTE_HOOKS(tpl_event_error, + (plug_info->plugin, connection, status, function)); +} + } diff --git a/src/jrd/trace/TraceManager.h b/src/jrd/trace/TraceManager.h index dad1ee34b1..9a58e064cf 100644 --- a/src/jrd/trace/TraceManager.h +++ b/src/jrd/trace/TraceManager.h @@ -62,51 +62,53 @@ public: static size_t pluginsCount() { return modules->getCount(); } - void event_attach(TraceConnection* connection, bool create_db, + void event_attach(TraceDatabaseConnection* connection, bool create_db, ntrace_result_t att_result); - void event_detach(TraceConnection* connection, bool drop_db); + void event_detach(TraceDatabaseConnection* connection, bool drop_db); /* Start/end transaction */ - void event_transaction_start(TraceConnection* connection, TraceTransaction* transaction, + void event_transaction_start(TraceDatabaseConnection* connection, TraceTransaction* transaction, size_t tpb_length, const ntrace_byte_t* tpb, ntrace_result_t tra_result); - void event_transaction_end(TraceConnection* connection, TraceTransaction* transaction, + void event_transaction_end(TraceDatabaseConnection* connection, TraceTransaction* transaction, bool commit, bool retain_context, ntrace_result_t tra_result); - void event_set_context(TraceConnection* connection, + void event_set_context(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceContextVariable* variable); - void event_proc_execute(TraceConnection* connection, TraceTransaction* transaction, + void event_proc_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure, bool started, ntrace_result_t proc_result); - void event_trigger_execute(TraceConnection* connection, TraceTransaction* transaction, + void event_trigger_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger, bool started, ntrace_result_t trig_result); - void event_blr_compile(TraceConnection* connection, + void event_blr_compile(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result); - void event_blr_execute(TraceConnection* connection, + void event_blr_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_result_t req_result); - void event_dyn_execute(TraceConnection* connection, + void event_dyn_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceDYNRequest* request, ntrace_counter_t time_millis, ntrace_result_t req_result); - void event_service_attach(TraceService* service, ntrace_result_t att_result); + void event_service_attach(TraceServiceConnection* service, ntrace_result_t att_result); - void event_service_start(TraceService* service, + void event_service_start(TraceServiceConnection* service, size_t switches_length, const char* switches, ntrace_result_t start_result); - void event_service_query(TraceService* service, + void event_service_query(TraceServiceConnection* service, size_t send_item_length, const ntrace_byte_t* send_items, size_t recv_item_length, const ntrace_byte_t* recv_items, ntrace_result_t query_result); - void event_service_detach(TraceService* service, ntrace_result_t detach_result); + void event_service_detach(TraceServiceConnection* service, ntrace_result_t detach_result); + + void event_error(TraceBaseConnection* connection, TraceStatusVector* status, const char* function); struct NotificationNeeds { @@ -128,6 +130,7 @@ public: bool event_service_start; bool event_service_query; bool event_service_detach; + bool event_error; }; inline const NotificationNeeds& needs() @@ -194,14 +197,14 @@ private: bool check_result(const TracePlugin* plugin, const char* module, const char* function, bool result); /* DSQL statement lifecycle. To be moved to public and used directly when DSQL becomes a part of JRD */ - void event_dsql_prepare(TraceConnection* connection, TraceTransaction* transaction, + void event_dsql_prepare(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result); - void event_dsql_free(TraceConnection* connection, + void event_dsql_free(TraceDatabaseConnection* connection, TraceSQLStatement* statement, unsigned short option); - void event_dsql_execute(TraceConnection* connection, TraceTransaction* transaction, + void event_dsql_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, bool started, ntrace_result_t req_result); diff --git a/src/jrd/trace/TraceObjects.cpp b/src/jrd/trace/TraceObjects.cpp index 8a1d3f68a0..b58d8c3f6c 100644 --- a/src/jrd/trace/TraceObjects.cpp +++ b/src/jrd/trace/TraceObjects.cpp @@ -71,6 +71,11 @@ int TraceConnectionImpl::getProcessID() return getpid(); } +ntrace_connection_kind_t TraceConnectionImpl::getKind() +{ + return connection_database; +} + const char* TraceConnectionImpl::getDatabaseName() { return m_att->att_filename.c_str(); @@ -553,6 +558,11 @@ const char* TraceServiceImpl::getServiceName() return m_svc->getServiceName(); } +ntrace_connection_kind_t TraceServiceImpl::getKind() +{ + return connection_service; +} + int TraceServiceImpl::getProcessID() { return getpid(); @@ -568,6 +578,11 @@ const char* TraceServiceImpl::getRoleName() return NULL; } +const char* TraceServiceImpl::getCharSet() +{ + return NULL; +} + const char* TraceServiceImpl::getRemoteProtocol() { return m_svc->getNetworkProtocol().c_str(); @@ -607,6 +622,38 @@ TraceRuntimeStats::TraceRuntimeStats(Database* dbb, RuntimeStatistics* baseline, } } -SINT64 TraceRuntimeStats::m_dummy_counts[DBB_max_dbb_count] = {0}; +SINT64 TraceRuntimeStats::m_dummy_counts[RuntimeStatistics::TOTAL_ITEMS] = {0}; + + +/// TraceStatusVectorImpl + +const char* TraceStatusVectorImpl::getText() +{ + if (m_error.isEmpty() && (hasError() || hasWarning())) + { + char buff[1024]; + const ISC_STATUS* p = m_status; + const ISC_STATUS* end = m_status + ISC_STATUS_LENGTH; + + while (p < end - 1) + { + if (p[0] == isc_arg_gds && p[1] == 0) + { + p += 2; + continue; + } + + const ISC_STATUS code = *p ? p[1] : 0; + if (!fb_interpret(buff, sizeof(buff), &p)) + break; + + string s; + s.printf("%9lu : %s\n", code, buff); + m_error += s; + } + } + + return m_error.c_str(); +} } // namespace Jrd diff --git a/src/jrd/trace/TraceObjects.h b/src/jrd/trace/TraceObjects.h index 8d1f3abf06..60e098ec91 100644 --- a/src/jrd/trace/TraceObjects.h +++ b/src/jrd/trace/TraceObjects.h @@ -47,7 +47,7 @@ class Database; class Attachment; class jrd_tra; -class TraceConnectionImpl : public TraceConnection +class TraceConnectionImpl : public TraceDatabaseConnection { public: TraceConnectionImpl(const Attachment* att) : @@ -56,6 +56,8 @@ public: virtual int getConnectionID(); virtual int getProcessID(); + + virtual ntrace_connection_kind_t getKind(); virtual const char* getDatabaseName(); virtual const char* getUserName(); virtual const char* getRoleName(); @@ -311,7 +313,7 @@ private: }; -class TraceServiceImpl : public TraceService +class TraceServiceImpl : public TraceServiceConnection { public: TraceServiceImpl(const Service* svc) : @@ -321,9 +323,12 @@ public: virtual ntrace_service_t getServiceID(); virtual const char* getServiceMgr(); virtual const char* getServiceName(); + + virtual ntrace_connection_kind_t getKind(); + virtual int getProcessID(); virtual const char* getUserName(); virtual const char* getRoleName(); - virtual int getProcessID(); + virtual const char* getCharSet(); virtual const char* getRemoteProtocol(); virtual const char* getRemoteAddress(); virtual int getRemoteProcessID(); @@ -345,7 +350,7 @@ public: private: PerformanceInfo m_info; TraceCountsArray m_counts; - static SINT64 m_dummy_counts[DBB_max_dbb_count]; // Zero-initialized array with zero counts + static SINT64 m_dummy_counts[RuntimeStatistics::TOTAL_ITEMS]; // Zero-initialized array with zero counts }; @@ -372,7 +377,7 @@ public: virtual const char* getFirebirdRootDirectory(); virtual const char* getDatabaseName() { return m_filename; } - virtual TraceConnection* getConnection() + virtual TraceDatabaseConnection* getConnection() { if (m_attachment) return &m_trace_conn; @@ -391,6 +396,36 @@ private: }; +class TraceStatusVectorImpl : public TraceStatusVector +{ +public: + TraceStatusVectorImpl(const ISC_STATUS* status) : + m_status(status) + { + } + + virtual bool hasError() + { + return m_status && (m_status[1] != 0); + } + + virtual bool hasWarning() + { + return m_status && (m_status[1] == 0) && (m_status[2] == isc_arg_warning); + } + + virtual const ISC_STATUS* getStatus() + { + return m_status; + } + + virtual const char* getText(); + +private: + const ISC_STATUS* m_status; + Firebird::string m_error; +}; + } // namespace Jrd #endif // JRD_TRACE_OBJECTS_H diff --git a/src/utilities/ntrace/TracePluginImpl.cpp b/src/utilities/ntrace/TracePluginImpl.cpp index 3b07f98233..a134f1f77f 100644 --- a/src/utilities/ntrace/TracePluginImpl.cpp +++ b/src/utilities/ntrace/TracePluginImpl.cpp @@ -91,6 +91,8 @@ TracePlugin* TracePluginImpl::createFullPlugin(const TracePluginConfig& configur plugin_ptr->tpl_event_service_start = ntrace_event_service_start; plugin_ptr->tpl_event_service_query = ntrace_event_service_query; plugin_ptr->tpl_event_service_detach = ntrace_event_service_detach; + + plugin_ptr->tpl_event_error = ntrace_event_error; } catch(const Firebird::Exception&) { @@ -266,7 +268,7 @@ void TracePluginImpl::logRecord(const char* action) record = ""; } -void TracePluginImpl::logRecordConn(const char* action, TraceConnection* connection) +void TracePluginImpl::logRecordConn(const char* action, TraceDatabaseConnection* connection) { // Lookup connection description const int conn_id = connection->getConnectionID(); @@ -312,7 +314,7 @@ void TracePluginImpl::logRecordConn(const char* action, TraceConnection* connect logRecord(action); } -void TracePluginImpl::logRecordTrans(const char* action, TraceConnection* connection, +void TracePluginImpl::logRecordTrans(const char* action, TraceDatabaseConnection* connection, TraceTransaction* transaction) { const int tra_id = transaction->getTransactionID(); @@ -345,7 +347,7 @@ void TracePluginImpl::logRecordTrans(const char* action, TraceConnection* connec logRecordConn(action, connection); } -void TracePluginImpl::logRecordProc(const char* action, TraceConnection* connection, +void TracePluginImpl::logRecordProc(const char* action, TraceDatabaseConnection* connection, TraceTransaction* transaction, const char* proc_name) { string temp; @@ -360,7 +362,7 @@ void TracePluginImpl::logRecordProc(const char* action, TraceConnection* connect } } -void TracePluginImpl::logRecordStmt(const char* action, TraceConnection* connection, +void TracePluginImpl::logRecordStmt(const char* action, TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceStatement* statement, bool isSQL) { const int stmt_id = statement->getStmtID(); @@ -430,7 +432,7 @@ void TracePluginImpl::logRecordStmt(const char* action, TraceConnection* connect } } -void TracePluginImpl::logRecordServ(const char* action, TraceService* service) +void TracePluginImpl::logRecordServ(const char* action, TraceServiceConnection* service) { const ntrace_service_t svc_id = service->getServiceID(); bool reg = false; @@ -464,6 +466,34 @@ void TracePluginImpl::logRecordServ(const char* action, TraceService* service) logRecord(action); } +void TracePluginImpl::logRecordError(const char* action, TraceBaseConnection* connection, + TraceStatusVector* status) +{ + const char* err = status->getText(); + + record = ""; + record.insert(0, err); + + if (connection) + { + switch (connection->getKind()) + { + case connection_database: + logRecordConn(action, (TraceDatabaseConnection*) connection); + break; + + case connection_service: + logRecordServ(action, (TraceServiceConnection*) connection); + break; + + default: + break; + } + } + else + logRecord(action); +} + void TracePluginImpl::appendGlobalCounts(const PerformanceInfo* info) { string temp; @@ -497,6 +527,24 @@ void TracePluginImpl::appendGlobalCounts(const PerformanceInfo* info) record.append(temp); } + if ((cnt = info->pin_counters[RuntimeStatistics::SORTS]) != 0) + { + temp.printf(", %"QUADFORMAT"d sort(s)", cnt); + record.append(temp); + } + + if ((cnt = info->pin_counters[RuntimeStatistics::SORT_GETS]) != 0) + { + temp.printf(", %"QUADFORMAT"d sort get(s)", cnt); + record.append(temp); + } + + if ((cnt = info->pin_counters[RuntimeStatistics::SORT_PUTS]) != 0) + { + temp.printf(", %"QUADFORMAT"d sort put(s)", cnt); + record.append(temp); + } + record.append(NEWLINE); } @@ -939,7 +987,7 @@ void TracePluginImpl::log_finalize() logWriter = NULL; } -void TracePluginImpl::register_connection(TraceConnection* connection) +void TracePluginImpl::register_connection(TraceDatabaseConnection* connection) { ConnectionData conn_data; conn_data.id = connection->getConnectionID(); @@ -997,7 +1045,7 @@ void TracePluginImpl::register_connection(TraceConnection* connection) } } -void TracePluginImpl::log_event_attach(TraceConnection* connection, +void TracePluginImpl::log_event_attach(TraceDatabaseConnection* connection, ntrace_boolean_t create_db, ntrace_result_t att_result) { if (config.log_connections) @@ -1024,7 +1072,7 @@ void TracePluginImpl::log_event_attach(TraceConnection* connection, } } -void TracePluginImpl::log_event_detach(TraceConnection* connection, ntrace_boolean_t drop_db) +void TracePluginImpl::log_event_detach(TraceDatabaseConnection* connection, ntrace_boolean_t drop_db) { if (config.log_connections) { @@ -1100,7 +1148,7 @@ void TracePluginImpl::register_transaction(TraceTransaction* transaction) } -void TracePluginImpl::log_event_transaction_start(TraceConnection* connection, +void TracePluginImpl::log_event_transaction_start(TraceDatabaseConnection* connection, TraceTransaction* transaction, size_t /*tpb_length*/, const ntrace_byte_t* /*tpb*/, ntrace_result_t tra_result) { @@ -1126,7 +1174,7 @@ void TracePluginImpl::log_event_transaction_start(TraceConnection* connection, } } -void TracePluginImpl::log_event_transaction_end(TraceConnection* connection, +void TracePluginImpl::log_event_transaction_end(TraceDatabaseConnection* connection, TraceTransaction* transaction, ntrace_boolean_t commit, ntrace_boolean_t retain_context, ntrace_result_t tra_result) { @@ -1176,7 +1224,7 @@ void TracePluginImpl::log_event_transaction_end(TraceConnection* connection, } } -void TracePluginImpl::log_event_set_context(TraceConnection* connection, +void TracePluginImpl::log_event_set_context(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceContextVariable* variable) { const char* ns = variable->getNameSpace(); @@ -1199,7 +1247,7 @@ void TracePluginImpl::log_event_set_context(TraceConnection* connection, } } -void TracePluginImpl::log_event_proc_execute(TraceConnection* connection, TraceTransaction* transaction, +void TracePluginImpl::log_event_proc_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure, bool started, ntrace_result_t proc_result) { if (!config.log_procedure_start && started) @@ -1342,7 +1390,7 @@ void TracePluginImpl::register_sql_statement(TraceSQLStatement* statement) } } -void TracePluginImpl::log_event_dsql_prepare(TraceConnection* connection, +void TracePluginImpl::log_event_dsql_prepare(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result) { @@ -1369,7 +1417,7 @@ void TracePluginImpl::log_event_dsql_prepare(TraceConnection* connection, } } -void TracePluginImpl::log_event_dsql_free(TraceConnection* connection, +void TracePluginImpl::log_event_dsql_free(TraceDatabaseConnection* connection, TraceSQLStatement* statement, unsigned short option) { if (config.log_statement_free) @@ -1389,7 +1437,7 @@ void TracePluginImpl::log_event_dsql_free(TraceConnection* connection, } } -void TracePluginImpl::log_event_dsql_execute(TraceConnection* connection, +void TracePluginImpl::log_event_dsql_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, bool started, ntrace_result_t req_result) { @@ -1486,7 +1534,7 @@ void TracePluginImpl::register_blr_statement(TraceBLRStatement* statement) statements.add(stmt_data); } -void TracePluginImpl::log_event_blr_compile(TraceConnection* connection, +void TracePluginImpl::log_event_blr_compile(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result) { @@ -1522,7 +1570,7 @@ void TracePluginImpl::log_event_blr_compile(TraceConnection* connection, } } -void TracePluginImpl::log_event_blr_execute(TraceConnection* connection, +void TracePluginImpl::log_event_blr_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_result_t req_result) { @@ -1558,7 +1606,7 @@ void TracePluginImpl::log_event_blr_execute(TraceConnection* connection, } } -void TracePluginImpl::log_event_dyn_execute(TraceConnection* connection, +void TracePluginImpl::log_event_dyn_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceDYNRequest* request, ntrace_counter_t time_millis, ntrace_result_t req_result) { @@ -1617,7 +1665,7 @@ void TracePluginImpl::log_event_dyn_execute(TraceConnection* connection, } -void TracePluginImpl::register_service(TraceService* service) +void TracePluginImpl::register_service(TraceServiceConnection* service) { string username(service->getUserName()); string remote_address; @@ -1660,7 +1708,7 @@ void TracePluginImpl::register_service(TraceService* service) } -bool TracePluginImpl::checkServiceFilter(TraceService* service, bool started) +bool TracePluginImpl::checkServiceFilter(TraceServiceConnection* service, bool started) { ReadLockGuard lock(servicesLock); @@ -1698,7 +1746,7 @@ bool TracePluginImpl::checkServiceFilter(TraceService* service, bool started) } -void TracePluginImpl::log_event_service_attach(TraceService* service, +void TracePluginImpl::log_event_service_attach(TraceServiceConnection* service, ntrace_result_t att_result) { if (config.log_services) @@ -1724,7 +1772,7 @@ void TracePluginImpl::log_event_service_attach(TraceService* service, } } -void TracePluginImpl::log_event_service_start(TraceService* service, +void TracePluginImpl::log_event_service_start(TraceServiceConnection* service, size_t switches_length, const char* switches, ntrace_result_t start_result) { if (config.log_services) @@ -1776,7 +1824,7 @@ void TracePluginImpl::log_event_service_start(TraceService* service, } } -void TracePluginImpl::log_event_service_query(TraceService* service, +void TracePluginImpl::log_event_service_query(TraceServiceConnection* service, size_t send_item_length, const ntrace_byte_t* send_items, size_t recv_item_length, const ntrace_byte_t* recv_items, ntrace_result_t query_result) @@ -1814,7 +1862,7 @@ void TracePluginImpl::log_event_service_query(TraceService* service, } } -void TracePluginImpl::log_event_service_detach(TraceService* service, ntrace_result_t detach_result) +void TracePluginImpl::log_event_service_detach(TraceServiceConnection* service, ntrace_result_t detach_result) { if (config.log_services) { @@ -1848,7 +1896,7 @@ void TracePluginImpl::log_event_service_detach(TraceService* service, ntrace_res } } -void TracePluginImpl::log_event_trigger_execute(TraceConnection* connection, TraceTransaction* transaction, +void TracePluginImpl::log_event_trigger_execute(TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger, bool started, ntrace_result_t trig_result) { if (!config.log_trigger_start && started) @@ -1953,6 +2001,22 @@ void TracePluginImpl::log_event_trigger_execute(TraceConnection* connection, Tra logRecordTrans(event_type, connection, transaction); } +void TracePluginImpl::log_event_error(TraceBaseConnection* connection, TraceStatusVector* status, const char* function) +{ + if (!config.log_errors) + return; + + string event_type; + if (status->hasError()) + event_type.printf("ERROR AT %s", function); + else if (status->hasWarning()) + event_type.printf("WARNING AT %s", function); + else + return; + + logRecordError(event_type.c_str(), connection, status); +} + //***************************** PLUGIN INTERFACE ******************************** ntrace_boolean_t TracePluginImpl::ntrace_shutdown(const TracePlugin* tpl_plugin) @@ -1975,7 +2039,7 @@ const char* TracePluginImpl::ntrace_get_error(const TracePlugin* /*tpl_plugin*/) // Create/close attachment ntrace_boolean_t TracePluginImpl::ntrace_event_attach(const TracePlugin* tpl_plugin, - TraceConnection* connection, ntrace_boolean_t create_db, + TraceDatabaseConnection* connection, ntrace_boolean_t create_db, ntrace_result_t att_result) { try @@ -1992,7 +2056,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_attach(const TracePlugin* tpl_plu } ntrace_boolean_t TracePluginImpl::ntrace_event_detach(const TracePlugin* tpl_plugin, - TraceConnection* connection, ntrace_boolean_t drop_db) + TraceDatabaseConnection* connection, ntrace_boolean_t drop_db) { try { @@ -2008,7 +2072,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_detach(const TracePlugin* tpl_plu // Start/end transaction ntrace_boolean_t TracePluginImpl::ntrace_event_transaction_start(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, size_t tpb_length, const ntrace_byte_t* tpb, ntrace_result_t tra_result) { try @@ -2025,7 +2089,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_transaction_start(const TracePlug } ntrace_boolean_t TracePluginImpl::ntrace_event_transaction_end(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, ntrace_boolean_t commit, ntrace_boolean_t retain_context, ntrace_result_t tra_result) { try @@ -2043,7 +2107,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_transaction_end(const TracePlugin // Assignment to context variables ntrace_boolean_t TracePluginImpl::ntrace_event_set_context(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceContextVariable* variable) { try @@ -2061,7 +2125,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_set_context(const struct TracePlu // Stored procedure executing ntrace_boolean_t TracePluginImpl::ntrace_event_proc_execute(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure, bool started, ntrace_result_t proc_result) { try @@ -2078,7 +2142,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_proc_execute(const struct TracePl } ntrace_boolean_t TracePluginImpl::ntrace_event_trigger_execute(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger, bool started, ntrace_result_t trig_result) { try @@ -2097,7 +2161,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_trigger_execute(const TracePlugin // DSQL statement lifecycle ntrace_boolean_t TracePluginImpl::ntrace_event_dsql_prepare(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result) { try @@ -2114,7 +2178,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_dsql_prepare(const TracePlugin* t } ntrace_boolean_t TracePluginImpl::ntrace_event_dsql_free(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceSQLStatement* statement, unsigned short option) + TraceDatabaseConnection* connection, TraceSQLStatement* statement, unsigned short option) { try { @@ -2130,7 +2194,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_dsql_free(const TracePlugin* tpl_ } ntrace_boolean_t TracePluginImpl::ntrace_event_dsql_execute(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, bool started, ntrace_result_t req_result) { try @@ -2149,7 +2213,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_dsql_execute(const TracePlugin* t // BLR requests ntrace_boolean_t TracePluginImpl::ntrace_event_blr_compile(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result) { try @@ -2166,7 +2230,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_blr_compile(const TracePlugin* tp } ntrace_boolean_t TracePluginImpl::ntrace_event_blr_execute(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_result_t req_result) { try @@ -2184,7 +2248,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_blr_execute(const TracePlugin* tp // DYN requests ntrace_boolean_t TracePluginImpl::ntrace_event_dyn_execute(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceDYNRequest* request, ntrace_counter_t time_millis, ntrace_result_t req_result) { try @@ -2202,7 +2266,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_dyn_execute(const TracePlugin* tp // Using the services ntrace_boolean_t TracePluginImpl::ntrace_event_service_attach(const TracePlugin* tpl_plugin, - TraceService* service, ntrace_result_t att_result) + TraceServiceConnection* service, ntrace_result_t att_result) { try { @@ -2218,7 +2282,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_service_attach(const TracePlugin* } ntrace_boolean_t TracePluginImpl::ntrace_event_service_start(const TracePlugin* tpl_plugin, - TraceService* service, size_t switches_length, const char* switches, + TraceServiceConnection* service, size_t switches_length, const char* switches, ntrace_result_t start_result) { try @@ -2235,7 +2299,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_service_start(const TracePlugin* } ntrace_boolean_t TracePluginImpl::ntrace_event_service_query(const TracePlugin* tpl_plugin, - TraceService* service, size_t send_item_length, + TraceServiceConnection* service, size_t send_item_length, const ntrace_byte_t* send_items, size_t recv_item_length, const ntrace_byte_t* recv_items, ntrace_result_t query_result) { @@ -2255,7 +2319,7 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_service_query(const TracePlugin* } ntrace_boolean_t TracePluginImpl::ntrace_event_service_detach(const TracePlugin* tpl_plugin, - TraceService* service, ntrace_result_t detach_result) + TraceServiceConnection* service, ntrace_result_t detach_result) { try { @@ -2269,3 +2333,19 @@ ntrace_boolean_t TracePluginImpl::ntrace_event_service_detach(const TracePlugin* return false; } } + +ntrace_boolean_t TracePluginImpl::ntrace_event_error(const TracePlugin* tpl_plugin, + TraceBaseConnection* connection, TraceStatusVector* status, const char* function) +{ + try + { + static_cast(tpl_plugin->tpl_object)->log_event_error( + connection, status, function); + return true; + } + catch(const Firebird::Exception& ex) + { + marshal_exception(ex); + return false; + } +} diff --git a/src/utilities/ntrace/TracePluginImpl.h b/src/utilities/ntrace/TracePluginImpl.h index ea149172d4..bc9a3b5da7 100644 --- a/src/utilities/ntrace/TracePluginImpl.h +++ b/src/utilities/ntrace/TracePluginImpl.h @@ -178,83 +178,86 @@ private: void formatStringArgument(Firebird::string& result, const UCHAR* str, size_t len); // register various objects - void register_connection(TraceConnection* connection); + void register_connection(TraceDatabaseConnection* connection); void register_transaction(TraceTransaction* transaction); void register_sql_statement(TraceSQLStatement* statement); void register_blr_statement(TraceBLRStatement* statement); - void register_service(TraceService* service); + void register_service(TraceServiceConnection* service); - bool checkServiceFilter(TraceService* service, bool started); + bool checkServiceFilter(TraceServiceConnection* service, bool started); // Write message to text log file void logRecord(const char* action); - void logRecordConn(const char* action, TraceConnection* connection); - void logRecordTrans(const char* action, TraceConnection* connection, + void logRecordConn(const char* action, TraceDatabaseConnection* connection); + void logRecordTrans(const char* action, TraceDatabaseConnection* connection, TraceTransaction* transaction); - void logRecordProc(const char* action, TraceConnection* connection, + void logRecordProc(const char* action, TraceDatabaseConnection* connection, TraceTransaction* transaction, const char* proc_name); - void logRecordStmt(const char* action, TraceConnection* connection, + void logRecordStmt(const char* action, TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceStatement* statement, bool isSQL); - void logRecordServ(const char* action, TraceService* service); + void logRecordServ(const char* action, TraceServiceConnection* service); + void logRecordError(const char* action, TraceBaseConnection* connection, TraceStatusVector* status); /* Methods which do logging of events to file */ void log_init(); void log_finalize(); void log_event_attach( - TraceConnection* connection, ntrace_boolean_t create_db, + TraceDatabaseConnection* connection, ntrace_boolean_t create_db, ntrace_result_t att_result); void log_event_detach( - TraceConnection* connection, ntrace_boolean_t drop_db); + TraceDatabaseConnection* connection, ntrace_boolean_t drop_db); void log_event_transaction_start( - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, size_t tpb_length, const ntrace_byte_t* tpb, ntrace_result_t tra_result); void log_event_transaction_end( - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, ntrace_boolean_t commit, ntrace_boolean_t retain_context, ntrace_result_t tra_result); void log_event_set_context( - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceContextVariable* variable); void log_event_proc_execute( - TraceConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure, bool started, ntrace_result_t proc_result); void log_event_trigger_execute( - TraceConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger, bool started, ntrace_result_t trig_result); void log_event_dsql_prepare( - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result); void log_event_dsql_free( - TraceConnection* connection, TraceSQLStatement* statement, unsigned short option); + TraceDatabaseConnection* connection, TraceSQLStatement* statement, unsigned short option); void log_event_dsql_execute( - TraceConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, bool started, ntrace_result_t req_result); void log_event_blr_compile( - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result); void log_event_blr_execute( - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_result_t req_result); void log_event_dyn_execute( - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceDYNRequest* request, ntrace_counter_t time_millis, ntrace_result_t req_result); - void log_event_service_attach(TraceService* service, ntrace_result_t att_result); - void log_event_service_start(TraceService* service, size_t switches_length, const char* switches, + void log_event_service_attach(TraceServiceConnection* service, ntrace_result_t att_result); + void log_event_service_start(TraceServiceConnection* service, size_t switches_length, const char* switches, ntrace_result_t start_result); - void log_event_service_query(TraceService* service, size_t send_item_length, + void log_event_service_query(TraceServiceConnection* service, size_t send_item_length, const ntrace_byte_t* send_items, size_t recv_item_length, const ntrace_byte_t* recv_items, ntrace_result_t query_result); - void log_event_service_detach(TraceService* service, ntrace_result_t detach_result); + void log_event_service_detach(TraceServiceConnection* service, ntrace_result_t detach_result); + + void log_event_error(TraceBaseConnection* connection, TraceStatusVector* status, const char* function); /* Finalize plugin. Called when database is closed by the engine */ static ntrace_boolean_t ntrace_shutdown(const TracePlugin* tpl_plugin); @@ -264,69 +267,72 @@ private: /* Create/close attachment */ static ntrace_boolean_t ntrace_event_attach(const TracePlugin* tpl_plugin, - TraceConnection* connection, ntrace_boolean_t create_db, + TraceDatabaseConnection* connection, ntrace_boolean_t create_db, ntrace_result_t att_result); static ntrace_boolean_t ntrace_event_detach(const TracePlugin* tpl_plugin, - TraceConnection* connection, ntrace_boolean_t drop_db); + TraceDatabaseConnection* connection, ntrace_boolean_t drop_db); /* Start/end transaction */ static ntrace_boolean_t ntrace_event_transaction_start(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, size_t tpb_length, const ntrace_byte_t* tpb, ntrace_result_t tra_result); static ntrace_boolean_t ntrace_event_transaction_end(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, ntrace_boolean_t commit, ntrace_boolean_t retain_context, ntrace_result_t tra_result); /* Assignment to context variables */ static ntrace_boolean_t ntrace_event_set_context(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceContextVariable* variable); /* Stored procedure executing */ static ntrace_boolean_t ntrace_event_proc_execute(const struct TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure, bool started, ntrace_result_t proc_result); static ntrace_boolean_t ntrace_event_trigger_execute(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger, bool started, ntrace_result_t trig_result); /* DSQL statement lifecycle */ static ntrace_boolean_t ntrace_event_dsql_prepare(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result); static ntrace_boolean_t ntrace_event_dsql_free(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceSQLStatement* statement, unsigned short option); + TraceDatabaseConnection* connection, TraceSQLStatement* statement, unsigned short option); static ntrace_boolean_t ntrace_event_dsql_execute(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement, bool started, ntrace_result_t req_result); /* BLR requests */ static ntrace_boolean_t ntrace_event_blr_compile(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result); static ntrace_boolean_t ntrace_event_blr_execute(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceBLRStatement* statement, ntrace_result_t req_result); /* DYN requests */ static ntrace_boolean_t ntrace_event_dyn_execute(const TracePlugin* tpl_plugin, - TraceConnection* connection, TraceTransaction* transaction, + TraceDatabaseConnection* connection, TraceTransaction* transaction, TraceDYNRequest* request, ntrace_counter_t time_millis, ntrace_result_t req_result); /* Using the services */ static ntrace_boolean_t ntrace_event_service_attach(const TracePlugin* tpl_plugin, - TraceService* service, ntrace_result_t att_result); + TraceServiceConnection* service, ntrace_result_t att_result); static ntrace_boolean_t ntrace_event_service_start(const TracePlugin* tpl_plugin, - TraceService* service, size_t switches_length, const char* switches, + TraceServiceConnection* service, size_t switches_length, const char* switches, ntrace_result_t start_result); static ntrace_boolean_t ntrace_event_service_query(const TracePlugin* tpl_plugin, - TraceService* service, size_t send_item_length, + TraceServiceConnection* service, size_t send_item_length, const ntrace_byte_t* send_items, size_t recv_item_length, const ntrace_byte_t* recv_items, ntrace_result_t query_result); static ntrace_boolean_t ntrace_event_service_detach(const TracePlugin* tpl_plugin, - TraceService* service, ntrace_result_t detach_result); + TraceServiceConnection* service, ntrace_result_t detach_result); + + static ntrace_boolean_t ntrace_event_error(const struct TracePlugin* tpl_plugin, + TraceBaseConnection* connection, TraceStatusVector* status, const char* function); }; #endif // TRACEPLUGINIMPL_H diff --git a/src/utilities/ntrace/fbtrace.conf b/src/utilities/ntrace/fbtrace.conf index 40620d4317..4c8f7da860 100644 --- a/src/utilities/ntrace/fbtrace.conf +++ b/src/utilities/ntrace/fbtrace.conf @@ -84,6 +84,9 @@ # Put context variable change records (RDB$SET_CONTEXT) #log_context false + # Put errors happened + #log_errors false + # Print access path (plan) with sql statement print_plan false @@ -178,6 +181,9 @@ # Put service query records log_service_query false + + # Put errors happened + #log_errors false diff --git a/src/utilities/ntrace/paramtable.h b/src/utilities/ntrace/paramtable.h index a3c37f040e..16890a33bd 100644 --- a/src/utilities/ntrace/paramtable.h +++ b/src/utilities/ntrace/paramtable.h @@ -35,6 +35,7 @@ STR_PARAMETER(include_filter, "") STR_PARAMETER(exclude_filter, "") PATH_PARAMETER(log_filename, "") +BOOL_PARAMETER(log_errors, false) BOOL_PARAMETER(enabled, false) UINT_PARAMETER(max_log_size, 0) diff --git a/src/utilities/ntrace/traceplugin.cpp b/src/utilities/ntrace/traceplugin.cpp index 2d5e306f39..c7f3411f9a 100644 --- a/src/utilities/ntrace/traceplugin.cpp +++ b/src/utilities/ntrace/traceplugin.cpp @@ -45,7 +45,7 @@ FB_DLL_EXPORT ntrace_boolean_t trace_create(TraceInitInfo* initInfo, const Trace dbname ? dbname : "", config); - TraceConnection* connection = initInfo->getConnection(); + TraceDatabaseConnection* connection = initInfo->getConnection(); if (!config.enabled || (config.connection_id && connection && (connection->getConnectionID() != config.connection_id))) {