mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 02:03:04 +01:00
Misc
This commit is contained in:
parent
4c47e58544
commit
612c108e3e
@ -194,7 +194,7 @@
|
||||
|
||||
# ----------------------------
|
||||
# Maximum summary size of each user trace session's log files in MB.
|
||||
# When log files size reach this limit trace session automatically
|
||||
# When log files size reach this limit, trace session automatically
|
||||
# suspends until interactive user service read and delete some log files.
|
||||
#
|
||||
# Type: integer
|
||||
|
@ -471,7 +471,7 @@ ISC_STATUS DSQL_fetch(thread_db* tdbb,
|
||||
dsql_msg* message = (dsql_msg*) request->req_receive;
|
||||
|
||||
// Set up things for tracing this call
|
||||
Attachment *att = request->req_dbb->dbb_attachment;
|
||||
Attachment* att = request->req_dbb->dbb_attachment;
|
||||
TraceDSQLFetch trace(att, request);
|
||||
|
||||
/* Insure that the blr for the message is parsed, regardless of
|
||||
@ -1268,18 +1268,17 @@ static void execute_request(thread_db* tdbb,
|
||||
// If there is no data required, just start the request
|
||||
|
||||
dsql_msg* message = request->req_send;
|
||||
if (message) {
|
||||
if (message)
|
||||
map_in_out(request, message, in_blr_length, in_blr, in_msg_length, NULL, in_msg);
|
||||
}
|
||||
|
||||
// we need to map_in_out before tracing of execution start to let trace
|
||||
// manager know statement parameters values
|
||||
TraceDSQLExecute trace(request->req_dbb->dbb_attachment, request);
|
||||
|
||||
if (!message) {
|
||||
if (!message)
|
||||
JRD_start(tdbb, request->req_request, request->req_transaction, 0);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
JRD_start_and_send(tdbb, request->req_request, request->req_transaction, message->msg_number,
|
||||
message->msg_length, reinterpret_cast<SCHAR*>(message->msg_buffer),
|
||||
0);
|
||||
@ -2570,7 +2569,8 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
|
||||
if (!node)
|
||||
return statement;
|
||||
|
||||
statement->req_traced = statement->req_type != REQ_COMMIT &&
|
||||
statement->req_traced =
|
||||
statement->req_type != REQ_COMMIT &&
|
||||
statement->req_type != REQ_COMMIT_RETAIN &&
|
||||
statement->req_type != REQ_ROLLBACK &&
|
||||
statement->req_type != REQ_ROLLBACK_RETAIN &&
|
||||
@ -2666,7 +2666,6 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
|
||||
trace.prepare(status == isc_no_priv ? res_unauthorized : res_failed);
|
||||
}
|
||||
|
||||
|
||||
// restore warnings (if there are any)
|
||||
if (local_status[2] == isc_arg_warning)
|
||||
{
|
||||
@ -2690,9 +2689,10 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
|
||||
|
||||
if (status)
|
||||
Firebird::status_exception::raise(tdbb->tdbb_status_vector);
|
||||
|
||||
|
||||
// Notify Trace API manager about new request cooked.
|
||||
trace.prepare(res_successful);
|
||||
|
||||
return statement;
|
||||
|
||||
}
|
||||
@ -2997,7 +2997,7 @@ static void sql_info(thread_db* tdbb,
|
||||
// larger size if it is not big enough
|
||||
|
||||
UCHAR* buffer_ptr = buffer;
|
||||
length = DSQL_get_plan_info(tdbb, request,
|
||||
length = DSQL_get_plan_info(tdbb, request,
|
||||
(SSHORT) sizeof(buffer), reinterpret_cast<SCHAR**>(&buffer_ptr));
|
||||
|
||||
if (length) {
|
||||
@ -3293,4 +3293,3 @@ static UCHAR* var_info(dsql_msg* message,
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -43,9 +43,10 @@ void RuntimeStatistics::bumpValue(StatType index, SLONG relation_id)
|
||||
fb_assert(index >= 0);
|
||||
|
||||
RelationCountsTree::Accessor accessor(&rel_counts);
|
||||
if (accessor.locate(relation_id)) {
|
||||
if (accessor.locate(relation_id))
|
||||
accessor.current().rlc_counter[index]++;
|
||||
} else {
|
||||
else
|
||||
{
|
||||
RelationCounts counts;
|
||||
memset(&counts, 0, sizeof(counts));
|
||||
counts.rlc_relation_id = relation_id;
|
||||
@ -54,15 +55,16 @@ void RuntimeStatistics::bumpValue(StatType index, SLONG relation_id)
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeStatistics::addRelCounts(const RelationCountsTree &other, bool add)
|
||||
void RuntimeStatistics::addRelCounts(const RelationCountsTree& other, bool add)
|
||||
{
|
||||
RelationCountsTree::Accessor first(&rel_counts);
|
||||
RelationCountsTree::ConstAccessor second(&other);
|
||||
|
||||
if (second.getFirst())
|
||||
{
|
||||
do
|
||||
{
|
||||
const RelationCounts &src = second.current();
|
||||
const RelationCounts& src = second.current();
|
||||
|
||||
if (!first.locate(src.rlc_relation_id))
|
||||
{
|
||||
@ -74,18 +76,18 @@ void RuntimeStatistics::addRelCounts(const RelationCountsTree &other, bool add)
|
||||
first.locate(src.rlc_relation_id);
|
||||
}
|
||||
|
||||
RelationCounts &dst = first.current();
|
||||
RelationCounts& dst = first.current();
|
||||
fb_assert(src.rlc_relation_id == dst.rlc_relation_id);
|
||||
|
||||
for (int index = 0; index < sizeof(src.rlc_counter) / sizeof(src.rlc_counter[0]); index++)
|
||||
for (int index = 0; index < FB_NELEM(src.rlc_counter); index++)
|
||||
{
|
||||
if (add)
|
||||
dst.rlc_counter[index] += src.rlc_counter[index];
|
||||
else
|
||||
dst.rlc_counter[index] -= src.rlc_counter[index];
|
||||
}
|
||||
|
||||
} while(second.getNext());
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeStatistics::reset()
|
||||
@ -95,13 +97,13 @@ void RuntimeStatistics::reset()
|
||||
}
|
||||
|
||||
|
||||
PerformanceInfo *RuntimeStatistics::computeDifference(
|
||||
Database *dbb, const RuntimeStatistics& new_stat, PerformanceInfo &dest, TraceCountsArray& temp)
|
||||
PerformanceInfo* RuntimeStatistics::computeDifference(
|
||||
Database* dbb, const RuntimeStatistics& new_stat, PerformanceInfo& dest, TraceCountsArray& temp)
|
||||
{
|
||||
// NOTE: we do not initialize dest.pin_time. This must be done by the caller
|
||||
|
||||
// Calculate database-level statistics
|
||||
for(int i = 0; i < TOTAL_ITEMS; i++)
|
||||
for (int i = 0; i < TOTAL_ITEMS; i++)
|
||||
values[i] = new_stat.values[i] - values[i];
|
||||
|
||||
dest.pin_counters = values;
|
||||
@ -114,55 +116,59 @@ PerformanceInfo *RuntimeStatistics::computeDifference(
|
||||
|
||||
// This loop assumes that base array is smaller than new one
|
||||
bool base_found = base_acc.getFirst();
|
||||
if (new_acc.getFirst())
|
||||
do {
|
||||
const RelationCounts *counts = &new_acc.current();
|
||||
if (base_found && base_acc.current().rlc_relation_id == counts->rlc_relation_id)
|
||||
|
||||
if (new_acc.getFirst())
|
||||
{
|
||||
do
|
||||
{
|
||||
RelationCounts *base_counts = &base_acc.current();
|
||||
bool all_zeros = true;
|
||||
for (int i = 0; i < DBB_max_rel_count; i++) {
|
||||
if ((base_counts->rlc_counter[i] = counts->rlc_counter[i] - base_counts->rlc_counter[i]))
|
||||
all_zeros = false;
|
||||
}
|
||||
|
||||
// Point TraceCounts to counts array from baseline object
|
||||
if (!all_zeros)
|
||||
const RelationCounts* counts = &new_acc.current();
|
||||
if (base_found && base_acc.current().rlc_relation_id == counts->rlc_relation_id)
|
||||
{
|
||||
jrd_rel *relation =
|
||||
counts->rlc_relation_id < dbb->dbb_relations->count() ?
|
||||
(*dbb->dbb_relations)[counts->rlc_relation_id] :
|
||||
NULL;
|
||||
RelationCounts* base_counts = &base_acc.current();
|
||||
bool all_zeros = true;
|
||||
for (int i = 0; i < DBB_max_rel_count; i++)
|
||||
{
|
||||
if ((base_counts->rlc_counter[i] = counts->rlc_counter[i] - base_counts->rlc_counter[i]))
|
||||
all_zeros = false;
|
||||
}
|
||||
|
||||
// Point TraceCounts to counts array from baseline object
|
||||
if (!all_zeros)
|
||||
{
|
||||
jrd_rel* relation = counts->rlc_relation_id < dbb->dbb_relations->count() ?
|
||||
(*dbb->dbb_relations)[counts->rlc_relation_id] : NULL;
|
||||
TraceCounts traceCounts;
|
||||
traceCounts.trc_relation_id = counts->rlc_relation_id;
|
||||
traceCounts.trc_counters = base_counts->rlc_counter;
|
||||
traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL;
|
||||
temp.add(traceCounts);
|
||||
}
|
||||
|
||||
base_found = base_acc.getNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
jrd_rel* relation = counts->rlc_relation_id < dbb->dbb_relations->count() ?
|
||||
(*dbb->dbb_relations)[counts->rlc_relation_id] : NULL;
|
||||
|
||||
// Point TraceCounts to counts array from object with updated counters
|
||||
TraceCounts traceCounts;
|
||||
traceCounts.trc_relation_id = counts->rlc_relation_id;
|
||||
traceCounts.trc_counters = base_counts->rlc_counter;
|
||||
traceCounts.trc_counters = counts->rlc_counter;
|
||||
traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL;
|
||||
temp.add(traceCounts);
|
||||
}
|
||||
base_found = base_acc.getNext();
|
||||
} else
|
||||
{
|
||||
jrd_rel *relation =
|
||||
counts->rlc_relation_id < dbb->dbb_relations->count() ?
|
||||
(*dbb->dbb_relations)[counts->rlc_relation_id] :
|
||||
NULL;
|
||||
|
||||
// Point TraceCounts to counts array from object with updated counters
|
||||
TraceCounts traceCounts;
|
||||
traceCounts.trc_relation_id = counts->rlc_relation_id;
|
||||
traceCounts.trc_counters = counts->rlc_counter;
|
||||
traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL;
|
||||
temp.add(traceCounts);
|
||||
}
|
||||
} while (new_acc.getNext());
|
||||
} while (new_acc.getNext());
|
||||
}
|
||||
|
||||
dest.pin_count = temp.getCount();
|
||||
dest.pin_tables = temp.begin();
|
||||
|
||||
return &dest;
|
||||
}
|
||||
|
||||
|
||||
/* hvlad: i've commented out this two operators as they not used and not take
|
||||
/* hvlad: I've commented out this two operators as they're not used and not take
|
||||
in account relation's counters
|
||||
bool RuntimeStatistics::operator==(const RuntimeStatistics& other) const
|
||||
{
|
||||
|
@ -40,13 +40,15 @@ struct RelationCounts
|
||||
SLONG rlc_relation_id; // Relation ID
|
||||
SINT64 rlc_counter[DBB_max_rel_count];
|
||||
|
||||
inline static const SLONG& generate(const void* sender, const RelationCounts& item)
|
||||
{ return item.rlc_relation_id; }
|
||||
inline static const SLONG& generate(const void* sender, const RelationCounts& item)
|
||||
{
|
||||
return item.rlc_relation_id;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Firebird::BePlusTree<RelationCounts, SLONG, Firebird::MemoryPool, RelationCounts> RelationCountsTree;
|
||||
|
||||
typedef Firebird::HalfStaticArray<TraceCounts, 5> TraceCountsArray;
|
||||
typedef Firebird::HalfStaticArray<TraceCounts, 5> TraceCountsArray;
|
||||
|
||||
// Runtime statistics class
|
||||
|
||||
@ -88,21 +90,23 @@ public:
|
||||
{
|
||||
return values[index];
|
||||
}
|
||||
|
||||
void reset();
|
||||
|
||||
void bumpValue(const StatType index)
|
||||
{
|
||||
++values[index];
|
||||
}
|
||||
|
||||
void bumpValue(StatType index, SLONG relation_id);
|
||||
|
||||
// Calculate difference between counts stored in this object and current
|
||||
// Calculate difference between counts stored in this object and current
|
||||
// counts of given request. Counts stored in object are destroyed.
|
||||
PerformanceInfo *computeDifference(Database *dbb, const RuntimeStatistics& new_stat,
|
||||
PerformanceInfo &dest, TraceCountsArray& temp);
|
||||
PerformanceInfo* computeDifference(Database* dbb, const RuntimeStatistics& new_stat,
|
||||
PerformanceInfo& dest, TraceCountsArray& temp);
|
||||
|
||||
// bool operator==(const RuntimeStatistics& other) const;
|
||||
// bool operator!=(const RuntimeStatistics& other) const;
|
||||
// bool operator==(const RuntimeStatistics& other) const;
|
||||
// bool operator!=(const RuntimeStatistics& other) const;
|
||||
|
||||
RuntimeStatistics& operator+=(const RuntimeStatistics& other)
|
||||
{
|
||||
@ -128,7 +132,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void addRelCounts(const RelationCountsTree &other, bool add);
|
||||
void addRelCounts(const RelationCountsTree& other, bool add);
|
||||
|
||||
SINT64 values[TOTAL_ITEMS];
|
||||
RelationCountsTree rel_counts;
|
||||
|
@ -1776,7 +1776,7 @@ static jrd_req* execute_triggers(thread_db* tdbb,
|
||||
trigger->req_timestamp = timestamp;
|
||||
|
||||
trigger->req_trigger_action = trigger_action;
|
||||
|
||||
|
||||
TraceTrigExecute trace(tdbb, trigger, which_trig);
|
||||
|
||||
EXE_start(tdbb, trigger, transaction);
|
||||
@ -1788,7 +1788,8 @@ static jrd_req* execute_triggers(thread_db* tdbb,
|
||||
const bool ok = (trigger->req_operation != jrd_req::req_unwind);
|
||||
trace.finish(ok ? res_successful : res_failed);
|
||||
|
||||
if (!ok) {
|
||||
if (!ok)
|
||||
{
|
||||
result = trigger;
|
||||
break;
|
||||
}
|
||||
|
@ -311,11 +311,11 @@ static SLONG set_context(const vary* ns_vary, const vary* name_vary, const vary*
|
||||
|
||||
const Firebird::string ns_str(ns_vary->vary_string, ns_vary->vary_length);
|
||||
const Firebird::string name_str(name_vary->vary_string, name_vary->vary_length);
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
Attachment *att = tdbb->getAttachment();
|
||||
jrd_tra* tra = tdbb->getTransaction();
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
Attachment* att = tdbb->getAttachment();
|
||||
jrd_tra* tra = tdbb->getTransaction();
|
||||
|
||||
Firebird::StringMap *context_vars = NULL;
|
||||
Firebird::StringMap* context_vars = NULL;
|
||||
|
||||
bool result = false;
|
||||
|
||||
@ -364,18 +364,17 @@ static SLONG set_context(const vary* ns_vary, const vary* name_vary, const vary*
|
||||
TraceConnectionImpl conn(att);
|
||||
TraceTransactionImpl tran(tra);
|
||||
|
||||
Firebird::string *value_str = NULL;
|
||||
if (value_vary) {
|
||||
Firebird::string* value_str = NULL;
|
||||
if (value_vary)
|
||||
value_str = att->att_context_vars.get(name_str);
|
||||
}
|
||||
|
||||
TraceContextVarImpl ctxvar(ns_str.c_str(), name_str.c_str(),
|
||||
value_str ? value_str->c_str() : NULL );
|
||||
value_str ? value_str->c_str() : NULL);
|
||||
|
||||
att->att_trace_manager->event_set_context(&conn, &tran, &ctxvar);
|
||||
}
|
||||
|
||||
return result;
|
||||
return (SLONG) result;
|
||||
}
|
||||
|
||||
static int test(const long* n, char *result)
|
||||
|
@ -447,7 +447,7 @@ public:
|
||||
class TraceFailedConnection : public TraceConnection
|
||||
{
|
||||
public:
|
||||
TraceFailedConnection(const char* filename, const DatabaseOptions *options) :
|
||||
TraceFailedConnection(const char* filename, const DatabaseOptions* options) :
|
||||
m_filename(filename),
|
||||
m_options(options)
|
||||
{}
|
||||
@ -455,6 +455,7 @@ public:
|
||||
virtual int getConnectionID() { return 0; }
|
||||
virtual int getProcessID() { return m_options->dpb_remote_pid; }
|
||||
virtual const char* getDatabaseName() { return m_filename; }
|
||||
|
||||
virtual const char* getUserName()
|
||||
{
|
||||
if (m_options->dpb_user_name.empty())
|
||||
@ -470,7 +471,7 @@ public:
|
||||
virtual const char* getRemoteProcessName() { return m_options->dpb_remote_process.c_str(); }
|
||||
|
||||
private:
|
||||
const DatabaseOptions *m_options;
|
||||
const DatabaseOptions* m_options;
|
||||
const char* m_filename;
|
||||
};
|
||||
|
||||
@ -720,7 +721,7 @@ void trace_failed_attach(TraceManager* traceManager, const char* filename, const
|
||||
}
|
||||
}
|
||||
|
||||
ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
const TEXT* filename,
|
||||
Attachment** handle,
|
||||
SSHORT dpb_length,
|
||||
@ -1646,7 +1647,7 @@ ISC_STATUS GDS_COMPILE(ISC_STATUS* user_status,
|
||||
try
|
||||
{
|
||||
ThreadContextHolder tdbb(user_status);
|
||||
|
||||
|
||||
Attachment* const attachment = *db_handle;
|
||||
validateHandle(tdbb, attachment);
|
||||
DatabaseContextHolder dbbHolder(tdbb);
|
||||
@ -3107,7 +3108,7 @@ ISC_STATUS GDS_SERVICE_QUERY(ISC_STATUS* user_status,
|
||||
memcpy(tdbb->tdbb_status_vector, service->getStatus(), sizeof(ISC_STATUS) * len);
|
||||
// Empty out the service status vector
|
||||
memset(service->getStatus(), 0, sizeof(ISC_STATUS_ARRAY));
|
||||
return user_status[1];
|
||||
return user_status[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3732,7 +3733,7 @@ ISC_STATUS GDS_DSQL_FETCH(ISC_STATUS* user_status,
|
||||
check_database(tdbb);
|
||||
|
||||
return_code = DSQL_fetch(tdbb, statement, blr_length, reinterpret_cast<const UCHAR*>(blr),
|
||||
msg_type, msg_length, reinterpret_cast<UCHAR*>(dsql_msg_buf)
|
||||
msg_type, msg_length, reinterpret_cast<UCHAR*>(dsql_msg_buf)
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
, direction, offset
|
||||
#endif
|
||||
@ -3763,10 +3764,8 @@ ISC_STATUS GDS_DSQL_FREE(ISC_STATUS* user_status,
|
||||
DSQL_free_statement(tdbb, statement, option);
|
||||
|
||||
if (option & DSQL_drop)
|
||||
{
|
||||
*stmt_handle = NULL;
|
||||
}
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
return ex.stuff_exception(user_status);
|
||||
@ -4008,7 +4007,7 @@ bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt)
|
||||
!(attachment->att_flags & ATT_cancel_disable))
|
||||
{
|
||||
if ((!request ||
|
||||
!(request->req_flags & (req_internal | req_sys_trigger))) &&
|
||||
!(request->req_flags & (req_internal | req_sys_trigger))) &&
|
||||
(!transaction || !(transaction->tra_flags & TRA_system)))
|
||||
{
|
||||
attachment->att_flags &= ~ATT_cancel_raise;
|
||||
@ -4129,7 +4128,7 @@ static void check_database(thread_db* tdbb)
|
||||
}
|
||||
|
||||
if ((attachment->att_flags & ATT_shutdown) ||
|
||||
((dbb->dbb_ast_flags & DBB_shutdown) &&
|
||||
((dbb->dbb_ast_flags & DBB_shutdown) &&
|
||||
((dbb->dbb_ast_flags & DBB_shutdown_full) || !attachment->locksmith())))
|
||||
{
|
||||
if (dbb->dbb_ast_flags & DBB_shutdown)
|
||||
@ -5020,7 +5019,7 @@ static void release_attachment(thread_db* tdbb, Attachment* attachment, ISC_STAT
|
||||
}
|
||||
#endif
|
||||
|
||||
for (vcl** vector = attachment->att_counts; vector < attachment->att_counts + DBB_max_count;
|
||||
for (vcl** vector = attachment->att_counts; vector < attachment->att_counts + DBB_max_count;
|
||||
++vector)
|
||||
{
|
||||
delete *vector;
|
||||
@ -5959,7 +5958,7 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options)
|
||||
|
||||
if (name.length() > USERNAME_LENGTH)
|
||||
{
|
||||
status_exception::raise(Arg::Gds(isc_long_login) << Arg::Num(name.length())
|
||||
status_exception::raise(Arg::Gds(isc_long_login) << Arg::Num(name.length())
|
||||
<< Arg::Num(USERNAME_LENGTH));
|
||||
}
|
||||
|
||||
@ -6372,8 +6371,6 @@ void JRD_start_multiple(thread_db* tdbb, jrd_tra** tra_handle, USHORT count, TEB
|
||||
|
||||
// run ON TRANSACTION START triggers
|
||||
EXE_execute_db_triggers(tdbb, transaction, jrd_req::req_trigger_trans_start);
|
||||
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
}
|
||||
|
||||
*tra_handle = transaction;
|
||||
@ -6496,7 +6493,7 @@ namespace {
|
||||
class DatabaseDirectoryList : public DirectoryList
|
||||
{
|
||||
private:
|
||||
const PathName getConfigString() const
|
||||
const PathName getConfigString() const
|
||||
{
|
||||
return PathName(Config::getDatabaseAccess());
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ public:
|
||||
Firebird::Mutex att_strings_mutex; // mutex for this buffer access
|
||||
|
||||
EDS::Connection* att_ext_connection; // external connection executed by this attachment
|
||||
TraceManager* att_trace_manager; // Trace API manager
|
||||
TraceManager* att_trace_manager; // Trace API manager
|
||||
|
||||
bool locksmith() const;
|
||||
|
||||
|
@ -58,12 +58,13 @@ public:
|
||||
virtual const char* getRemoteProcessName() = 0;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
enum ntrace_tra_isolation_t
|
||||
{
|
||||
tra_iso_consistency = 1,
|
||||
tra_iso_concurrency,
|
||||
tra_iso_read_committed_recver,
|
||||
tra_iso_read_committed_norecver
|
||||
} ntrace_tra_isolation_t;
|
||||
};
|
||||
|
||||
class TraceTransaction
|
||||
{
|
||||
@ -177,17 +178,19 @@ typedef unsigned char ntrace_byte_t;
|
||||
|
||||
|
||||
/* Event completion: 0 - successful, 1 - unsuccessful, 2 - unauthorized access */
|
||||
typedef enum {
|
||||
enum ntrace_result_t
|
||||
{
|
||||
res_successful = 0,
|
||||
res_failed = 1,
|
||||
res_unauthorized = 2
|
||||
} ntrace_result_t;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
enum ntrace_trigger_type_t
|
||||
{
|
||||
trg_all = 0,
|
||||
trg_before = 1,
|
||||
trg_after = 2
|
||||
} ntrace_trigger_type_t;
|
||||
};
|
||||
|
||||
const int DBB_max_rel_count = 8; // must be the same as DBB_max_count from jrd.h
|
||||
|
||||
@ -202,7 +205,8 @@ enum {
|
||||
};
|
||||
|
||||
/* Performance counters for individual table */
|
||||
struct TraceCounts {
|
||||
struct TraceCounts
|
||||
{
|
||||
ntrace_relation_t trc_relation_id; /* Relation ID */
|
||||
const char* trc_relation_name; /* Relation name */
|
||||
const ntrace_counter_t* trc_counters; /* Pointer to allow easy addition of new counters */
|
||||
@ -212,10 +216,10 @@ struct TraceCounts {
|
||||
struct PerformanceInfo
|
||||
{
|
||||
ntrace_counter_t pin_time; /* Total operation time in milliseconds */
|
||||
ntrace_counter_t *pin_counters; /* Pointer to allow easy addition of new counters */
|
||||
ntrace_counter_t* pin_counters; /* Pointer to allow easy addition of new counters */
|
||||
|
||||
size_t pin_count; /* Number of relations involved in analysis */
|
||||
struct TraceCounts *pin_tables; /* Pointer to array with table stats */
|
||||
struct TraceCounts* pin_tables; /* Pointer to array with table stats */
|
||||
|
||||
ntrace_counter_t pin_records_fetched; // records fetched from statement/procedure
|
||||
};
|
||||
@ -359,4 +363,4 @@ public:
|
||||
/* Trace API plugin entrypoint type */
|
||||
typedef ntrace_boolean_t (*ntrace_attach_t)(const TraceInitInfo* initInfo, const TracePlugin** plugin);
|
||||
|
||||
#endif
|
||||
#endif // FIREBIRD_NTRACE_H
|
||||
|
@ -261,10 +261,10 @@ public:
|
||||
ULONG req_flags; /* misc request flags */
|
||||
Savepoint* req_proc_sav_point; /* procedure savepoint list */
|
||||
Firebird::TimeStamp req_timestamp; /* Start time of request */
|
||||
Firebird::RefStrPtr req_sql_text;
|
||||
Firebird::Array<UCHAR> req_blr;
|
||||
Firebird::RefStrPtr req_sql_text; // SQL text
|
||||
Firebird::Array<UCHAR> req_blr; // BLR for non-SQL query
|
||||
|
||||
Firebird::AutoPtr<Jrd::RuntimeStatistics> req_fetch_baseline; //!< State of request performance counters when we reported it last time
|
||||
Firebird::AutoPtr<Jrd::RuntimeStatistics> req_fetch_baseline; // State of request performance counters when we reported it last time
|
||||
SINT64 req_fetch_elapsed; // Number of clock ticks spent while fetching rows for this request since we reported it last time
|
||||
SINT64 req_fetch_rowcount; // Total number of rows returned by this request
|
||||
jrd_req* req_proc_caller; // Procedure's caller request
|
||||
|
@ -708,7 +708,7 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d
|
||||
|
||||
// Since this moment we should remove this service from allServices in case of error thrown
|
||||
try
|
||||
{
|
||||
{
|
||||
// If the service name begins with a slash, ignore it.
|
||||
if (*service_name == '/' || *service_name == '\\') {
|
||||
service_name++;
|
||||
@ -857,7 +857,7 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d
|
||||
ISC_STATUS_ARRAY status_vector;
|
||||
|
||||
// Use created trace manager if it's possible
|
||||
const bool hasTrace = svc_trace_manager;
|
||||
const bool hasTrace = svc_trace_manager != NULL;
|
||||
if (hasTrace)
|
||||
trace_manager = svc_trace_manager;
|
||||
else
|
||||
@ -872,12 +872,13 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d
|
||||
trace_manager->event_service_attach(&service, no_priv ? res_unauthorized : res_failed);
|
||||
}
|
||||
|
||||
if ( !hasTrace)
|
||||
if (!hasTrace)
|
||||
delete trace_manager;
|
||||
|
||||
removeFromAllServices();
|
||||
throw;
|
||||
}
|
||||
|
||||
if (svc_trace_manager->needs().event_service_attach)
|
||||
{
|
||||
TraceServiceImpl service(this);
|
||||
@ -1834,7 +1835,7 @@ void Service::query(USHORT send_item_length,
|
||||
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 attachment has not been created
|
||||
// Report to Trace API that query failed
|
||||
TraceServiceImpl service(this);
|
||||
svc_trace_manager->event_service_query(&service,
|
||||
send_item_length, reinterpret_cast<const UCHAR*>(send_items),
|
||||
@ -1855,6 +1856,7 @@ void Service::query(USHORT send_item_length,
|
||||
recv_item_length, reinterpret_cast<const UCHAR*>(recv_items),
|
||||
res_successful);
|
||||
}
|
||||
|
||||
finish(SVC_finished);
|
||||
}
|
||||
}
|
||||
@ -2022,6 +2024,7 @@ void Service::start(USHORT spb_length, const UCHAR* spb_data)
|
||||
{
|
||||
status_exception::raise(Arg::Gds(isc_svcnotdef) << Arg::Str(serv->serv_name));
|
||||
}
|
||||
|
||||
} // try
|
||||
catch (const Firebird::Exception& ex)
|
||||
{
|
||||
@ -2216,7 +2219,7 @@ void Service::get(SCHAR* buffer, USHORT length, USHORT flags, USHORT timeout, US
|
||||
time(&end_time);
|
||||
const time_t elapsed_time = end_time - start_time;
|
||||
#endif
|
||||
if ((timeout) && (elapsed_time >= timeout))
|
||||
if (timeout && elapsed_time >= timeout)
|
||||
{
|
||||
MutexLockGuard guard(svc_mutex);
|
||||
svc_flags |= SVC_timeout;
|
||||
@ -2600,7 +2603,6 @@ bool Service::process_switches(ClumpletReader& spb, string& switches)
|
||||
case isc_action_svc_trace_suspend:
|
||||
case isc_action_svc_trace_resume:
|
||||
case isc_action_svc_trace_list:
|
||||
{
|
||||
if (!found)
|
||||
{
|
||||
if (!get_action_svc_parameter(svc_action, trace_action_in_sw_table, switches)) {
|
||||
@ -2629,7 +2631,6 @@ bool Service::process_switches(ClumpletReader& spb, string& switches)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
@ -134,7 +134,7 @@ public: // utilities interface with service
|
||||
|
||||
virtual bool finished()
|
||||
{
|
||||
return (svc_flags & (SVC_finished | SVC_detached));
|
||||
return (svc_flags & (SVC_finished | SVC_detached)) != 0;
|
||||
}
|
||||
|
||||
public: // external interface with service
|
||||
@ -170,6 +170,7 @@ public: // external interface with service
|
||||
else
|
||||
return svc_username;
|
||||
}
|
||||
|
||||
const Firebird::string& getNetworkProtocol() const { return svc_network_protocol; }
|
||||
const Firebird::string& getRemoteAddress() const { return svc_remote_address; }
|
||||
const Firebird::string& getRemoteProcess() const { return svc_remote_process; }
|
||||
@ -236,8 +237,8 @@ private:
|
||||
ULONG svc_stdout_tail;
|
||||
UCHAR svc_stdout[SVC_STDOUT_BUFFER_SIZE]; // output from service
|
||||
Firebird::Semaphore svcStart;
|
||||
const serv_entry* svc_service; // attached service's enrty
|
||||
const serv_entry* svc_service_run; // running service's enrty
|
||||
const serv_entry* svc_service; // attached service's entry
|
||||
const serv_entry* svc_service_run; // running service's entry
|
||||
Firebird::Array<UCHAR> svc_resp_alloc;
|
||||
UCHAR* svc_resp_buf;
|
||||
const UCHAR* svc_resp_ptr;
|
||||
|
@ -1225,7 +1225,8 @@ void TRA_rollback(thread_db* tdbb, jrd_tra* transaction, const bool retaining_fl
|
||||
MET_update_transaction(tdbb, transaction, false);
|
||||
|
||||
/* If force flag is true, get rid of all savepoints to mark the transaction as dead */
|
||||
if (force_flag) {
|
||||
if (force_flag)
|
||||
{
|
||||
// Free all savepoint data
|
||||
// We can do it in reverse order because nothing except simple deallocation
|
||||
// of memory is really done in VIO_verb_cleanup when we pass NULL as sav_next
|
||||
@ -1569,6 +1570,7 @@ jrd_tra* TRA_start(thread_db* tdbb, ULONG flags, SSHORT lock_timeout, Jrd::jrd_t
|
||||
attachment->att_trace_manager->event_transaction_start(&conn,
|
||||
&tran, 0, NULL, res_successful);
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
@ -1612,6 +1614,7 @@ jrd_tra* TRA_start(thread_db* tdbb, int tpb_length, const UCHAR* tpb, Jrd::jrd_t
|
||||
attachment->att_trace_manager->event_transaction_start(&conn,
|
||||
&tran, tpb_length, tpb, res_successful);
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ void TraceCfgReader::readConfig()
|
||||
}
|
||||
|
||||
bool defDB = false, defSvc = false, exactMatch = false;
|
||||
const Element *section = cfgFile->getObjects()->children;
|
||||
const Element* section = cfgFile->getObjects()->children;
|
||||
for (; section && !exactMatch; section = section->sibling)
|
||||
{
|
||||
const bool isDatabase = (section->name == "database");
|
||||
@ -89,7 +89,8 @@ void TraceCfgReader::readConfig()
|
||||
{
|
||||
if (isDatabase)
|
||||
{
|
||||
if (defDB) {
|
||||
if (defDB)
|
||||
{
|
||||
fatal_exception::raiseFmt("line %d: second default database section is not allowed",
|
||||
section->lineNumber + 1);
|
||||
}
|
||||
@ -99,7 +100,8 @@ void TraceCfgReader::readConfig()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (defSvc) {
|
||||
if (defSvc)
|
||||
{
|
||||
fatal_exception::raiseFmt("line %d: second default service section is not allowed",
|
||||
section->lineNumber + 1);
|
||||
}
|
||||
@ -109,9 +111,8 @@ void TraceCfgReader::readConfig()
|
||||
}
|
||||
else if (isDatabase && !m_databaseName.empty())
|
||||
{
|
||||
if (m_databaseName == pattern.c_str()) {
|
||||
if (m_databaseName == pattern.c_str())
|
||||
match = exactMatch = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
regex_t matcher;
|
||||
@ -142,16 +143,17 @@ void TraceCfgReader::readConfig()
|
||||
|
||||
if (errorCode == 0)
|
||||
match = exactMatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!match)
|
||||
continue;
|
||||
|
||||
const Element *el = section->children;
|
||||
const Element* el = section->children;
|
||||
for (; el; el = el->sibling)
|
||||
{
|
||||
if (!el->getAttributes()) {
|
||||
if (!el->getAttributes())
|
||||
{
|
||||
fatal_exception::raiseFmt("line %d: element \"%s\" have no attribute value set",
|
||||
el->lineNumber + 1, el->name.c_str());
|
||||
}
|
||||
@ -170,7 +172,8 @@ void TraceCfgReader::readConfig()
|
||||
#undef SERVICE_PARAMS
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (!found)
|
||||
{
|
||||
fatal_exception::raiseFmt("line %d: element \"%s\" is unknown",
|
||||
el->lineNumber + 1, el->name.c_str());
|
||||
}
|
||||
@ -213,12 +216,11 @@ void TraceCfgReader::expandPattern(string& valueToExpand)
|
||||
string::char_type c = valueToExpand[pos];
|
||||
if (c == '$')
|
||||
{
|
||||
if (pos + 1 >= valueToExpand.length()) {
|
||||
if (pos + 1 >= valueToExpand.length())
|
||||
fatal_exception::raiseFmt("pattern is invalid");
|
||||
}
|
||||
|
||||
c = valueToExpand[pos+1];
|
||||
if (c == '$')
|
||||
c = valueToExpand[pos + 1];
|
||||
if (c == '$')
|
||||
{
|
||||
// Kill one of the dollar signs and loop again
|
||||
valueToExpand.erase(pos, 1);
|
||||
@ -227,7 +229,7 @@ void TraceCfgReader::expandPattern(string& valueToExpand)
|
||||
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
regmatch_t *subpattern = m_subpatterns + (c - '0');
|
||||
regmatch_t* subpattern = m_subpatterns + (c - '0');
|
||||
// Replace value with piece of database name
|
||||
valueToExpand.erase(pos, 2);
|
||||
if (subpattern->rm_eo != -1 && subpattern->rm_so != -1)
|
||||
@ -250,9 +252,10 @@ void TraceCfgReader::expandPattern(string& valueToExpand)
|
||||
pos += filename.length();
|
||||
continue;
|
||||
}
|
||||
|
||||
fatal_exception::raiseFmt("pattern is invalid");
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
#define TRACE_CONFIGURATION
|
||||
|
||||
#include "firebird.h"
|
||||
|
||||
#include "../../common/classes/auto.h"
|
||||
#include "../../common/classes/fb_string.h"
|
||||
#include "../../config/ConfigFile.h"
|
||||
@ -42,16 +41,14 @@
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
|
||||
using Firebird::string;
|
||||
using Firebird::PathName;
|
||||
|
||||
class TraceCfgReader
|
||||
{
|
||||
public:
|
||||
static void readTraceConfiguration(const char* text, const PathName& databaseName, TracePluginConfig& config);
|
||||
static void readTraceConfiguration(const char* text, const Firebird::PathName& databaseName, TracePluginConfig& config);
|
||||
|
||||
private:
|
||||
TraceCfgReader(const char* text, const PathName& databaseName, TracePluginConfig& config) :
|
||||
TraceCfgReader(const char* text, const Firebird::PathName& databaseName, TracePluginConfig& config) :
|
||||
m_text(text),
|
||||
m_databaseName(databaseName),
|
||||
m_config(config)
|
||||
@ -59,14 +56,14 @@ private:
|
||||
|
||||
void readConfig();
|
||||
|
||||
void expandPattern(string& valueToExpand);
|
||||
bool parseBoolean(const string& value) const;
|
||||
ULONG parseUInteger(const string& value) const;
|
||||
void expandPattern(Firebird::string& valueToExpand);
|
||||
bool parseBoolean(const Firebird::string& value) const;
|
||||
ULONG parseUInteger(const Firebird::string& value) const;
|
||||
|
||||
const char* m_text;
|
||||
const PathName& m_databaseName;
|
||||
regmatch_t m_subpatterns[10];
|
||||
TracePluginConfig& m_config;
|
||||
const char* m_text;
|
||||
const Firebird::PathName& m_databaseName;
|
||||
regmatch_t m_subpatterns[10];
|
||||
TracePluginConfig& m_config;
|
||||
};
|
||||
|
||||
#endif // TRACE_CONFIGURATION
|
||||
|
@ -30,9 +30,10 @@
|
||||
|
||||
#include "../../common/classes/fb_string.h"
|
||||
|
||||
enum LogFormat {lfText = 0, lfBinary = 1};
|
||||
enum LogFormat { lfText = 0, lfBinary = 1 };
|
||||
|
||||
struct TracePluginConfig {
|
||||
struct TracePluginConfig
|
||||
{
|
||||
#define DATABASE_PARAMS
|
||||
#define SERVICE_PARAMS
|
||||
|
||||
@ -47,7 +48,6 @@ struct TracePluginConfig {
|
||||
#undef UINT_PARAMETER
|
||||
Firebird::PathName db_filename;
|
||||
|
||||
|
||||
// Default constructor. Pass pool to all string parameters, initialize everything to defaults
|
||||
TracePluginConfig() :
|
||||
#define PATH_PARAMETER(NAME, VALUE) NAME(*getDefaultMemoryPool(), VALUE, strlen(VALUE)),
|
||||
|
@ -50,12 +50,12 @@ TracePlugin* TracePluginImpl::createSkeletalPlugin()
|
||||
return plugin_ptr;
|
||||
}
|
||||
|
||||
TracePlugin* TracePluginImpl::createFullPlugin(const TracePluginConfig &configuration, TraceInitInfo* initInfo)
|
||||
TracePlugin* TracePluginImpl::createFullPlugin(const TracePluginConfig& configuration, TraceInitInfo* initInfo)
|
||||
{
|
||||
TracePlugin* plugin_ptr = createSkeletalPlugin();
|
||||
try
|
||||
{
|
||||
TracePluginImpl *pluginImpl = FB_NEW(*getDefaultMemoryPool()) TracePluginImpl(configuration, initInfo);
|
||||
TracePluginImpl* pluginImpl = FB_NEW(*getDefaultMemoryPool()) TracePluginImpl(configuration, initInfo);
|
||||
plugin_ptr->tpl_object = pluginImpl;
|
||||
|
||||
plugin_ptr->tpl_event_attach = ntrace_event_attach;
|
||||
@ -79,11 +79,13 @@ 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;
|
||||
} catch(const Firebird::Exception&)
|
||||
}
|
||||
catch(const Firebird::Exception&)
|
||||
{
|
||||
plugin_ptr->tpl_shutdown(plugin_ptr);
|
||||
throw;
|
||||
}
|
||||
|
||||
return plugin_ptr;
|
||||
}
|
||||
|
||||
@ -104,13 +106,13 @@ TracePluginImpl::TracePluginImpl(const TracePluginConfig &configuration, TraceIn
|
||||
statements(getDefaultMemoryPool()),
|
||||
services(getDefaultMemoryPool())
|
||||
{
|
||||
const char *ses_name = initInfo->getTraceSessionName();
|
||||
const char* ses_name = initInfo->getTraceSessionName();
|
||||
session_name = ses_name && *ses_name ? ses_name : " ";
|
||||
|
||||
if (!logWriter)
|
||||
{
|
||||
logFile = FB_NEW (*getDefaultMemoryPool())
|
||||
FileObject (*getDefaultMemoryPool(), configuration.log_filename, fo_rdwr | fo_append | fo_creat);
|
||||
FileObject(*getDefaultMemoryPool(), configuration.log_filename, fo_rdwr | fo_append | fo_creat);
|
||||
}
|
||||
|
||||
// Compile filtering regular expressions
|
||||
@ -151,21 +153,33 @@ TracePluginImpl::~TracePluginImpl()
|
||||
|
||||
if (operational)
|
||||
{
|
||||
if (connections.getFirst()) do {
|
||||
connections.current().deallocate_references();
|
||||
} while (connections.getNext());
|
||||
if (connections.getFirst())
|
||||
{
|
||||
do {
|
||||
connections.current().deallocate_references();
|
||||
} while (connections.getNext());
|
||||
}
|
||||
|
||||
if (transactions.getFirst()) do {
|
||||
transactions.current().deallocate_references();
|
||||
} while (transactions.getNext());
|
||||
if (transactions.getFirst())
|
||||
{
|
||||
do {
|
||||
transactions.current().deallocate_references();
|
||||
} while (transactions.getNext());
|
||||
}
|
||||
|
||||
if (statements.getFirst()) do {
|
||||
delete statements.current().description;
|
||||
} while (statements.getNext());
|
||||
if (statements.getFirst())
|
||||
{
|
||||
do {
|
||||
delete statements.current().description;
|
||||
} while (statements.getNext());
|
||||
}
|
||||
|
||||
if (services.getFirst()) do {
|
||||
services.current().deallocate_references();
|
||||
} while (services.getNext());
|
||||
if (services.getFirst())
|
||||
{
|
||||
do {
|
||||
services.current().deallocate_references();
|
||||
} while (services.getNext());
|
||||
}
|
||||
|
||||
log_finalize();
|
||||
}
|
||||
@ -173,7 +187,7 @@ TracePluginImpl::~TracePluginImpl()
|
||||
|
||||
bool TracePluginImpl::need_rotate(size_t added_bytes_length)
|
||||
{
|
||||
return logFile->size() + added_bytes_length >= config.max_log_size*1048576;
|
||||
return logFile->size() + added_bytes_length >= config.max_log_size * 1048576;
|
||||
}
|
||||
|
||||
|
||||
@ -199,7 +213,9 @@ void TracePluginImpl::rotateLog(size_t added_bytes_length)
|
||||
newName.printf("%s.%04d-%02d-%02dT%02d-%02d-%02d", config.log_filename.c_str(), times.tm_year + 1900,
|
||||
times.tm_mon + 1, times.tm_mday, times.tm_hour, times.tm_min, times.tm_sec);
|
||||
}
|
||||
|
||||
logFile->reopen();
|
||||
|
||||
if (logFile->size() + added_bytes_length > config.max_log_size*1048576 || !added_bytes_length) {
|
||||
logFile->renameFile(newName);
|
||||
}
|
||||
@ -236,9 +252,7 @@ void TracePluginImpl::logRecord(const char* action, string& line)
|
||||
// line.adjustLineBreaks();
|
||||
|
||||
if (logWriter)
|
||||
{
|
||||
logWriter->write(line.c_str(), line.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (config.max_log_size && need_rotate(line.length()))
|
||||
@ -253,6 +267,7 @@ void TracePluginImpl::logRecordConn(const char* action, TraceConnection* connect
|
||||
// Lookup connection description
|
||||
const int conn_id = connection->getConnectionID();
|
||||
bool reg = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
@ -443,7 +458,7 @@ void TracePluginImpl::logRecordServ(const char* action, TraceService* service,
|
||||
logRecord(action, line);
|
||||
}
|
||||
|
||||
void TracePluginImpl::appendGlobalCounts(PerformanceInfo *info, string& line)
|
||||
void TracePluginImpl::appendGlobalCounts(PerformanceInfo* info, string& line)
|
||||
{
|
||||
string temp;
|
||||
|
||||
@ -452,22 +467,26 @@ void TracePluginImpl::appendGlobalCounts(PerformanceInfo *info, string& line)
|
||||
|
||||
ntrace_counter_t cnt;
|
||||
|
||||
if ((cnt = info->pin_counters[RuntimeStatistics::PAGE_READS]) != 0) {
|
||||
if ((cnt = info->pin_counters[RuntimeStatistics::PAGE_READS]) != 0)
|
||||
{
|
||||
temp.printf(", %d read(s)", cnt);
|
||||
line.append(temp);
|
||||
}
|
||||
|
||||
if ((cnt = info->pin_counters[RuntimeStatistics::PAGE_WRITES]) != 0) {
|
||||
if ((cnt = info->pin_counters[RuntimeStatistics::PAGE_WRITES]) != 0)
|
||||
{
|
||||
temp.printf(", %d write(s)", cnt);
|
||||
line.append(temp);
|
||||
}
|
||||
|
||||
if ((cnt = info->pin_counters[RuntimeStatistics::PAGE_FETCHES]) != 0) {
|
||||
if ((cnt = info->pin_counters[RuntimeStatistics::PAGE_FETCHES]) != 0)
|
||||
{
|
||||
temp.printf(", %d fetch(es)", cnt);
|
||||
line.append(temp);
|
||||
}
|
||||
|
||||
if ((cnt = info->pin_counters[RuntimeStatistics::PAGE_MARKS]) != 0) {
|
||||
if ((cnt = info->pin_counters[RuntimeStatistics::PAGE_MARKS]) != 0)
|
||||
{
|
||||
temp.printf(", %d mark(s)", cnt);
|
||||
line.append(temp);
|
||||
}
|
||||
@ -484,7 +503,9 @@ void TracePluginImpl::appendTableCounts(PerformanceInfo *info, string& line)
|
||||
"Table Natural Index Update Insert Delete Backout Purge Expunge" NEWLINE
|
||||
"***************************************************************************************************************" NEWLINE );
|
||||
|
||||
TraceCounts *trc, *trc_end;
|
||||
TraceCounts* trc;
|
||||
TraceCounts* trc_end;
|
||||
|
||||
for (trc = info->pin_tables, trc_end = trc + info->pin_count; trc < trc_end; trc++)
|
||||
{
|
||||
line.append(trc->trc_relation_name);
|
||||
@ -520,13 +541,17 @@ void int_to_quoted_str(SINT64 value, int scale, string& str)
|
||||
else if (scale > 0)
|
||||
{
|
||||
// Append needed amount of zeros in the beginning of string as necessary
|
||||
if (value >= 0) {
|
||||
if (value >= 0)
|
||||
{
|
||||
if (str.length() < static_cast<size_t>(scale + 1))
|
||||
str.insert((string::size_type) 0, scale - str.length() + 1, '0');
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (str.length() < static_cast<size_t>(scale + 2))
|
||||
str.insert(1, scale - str.length(), '0');
|
||||
}
|
||||
|
||||
str.insert(str.length() - scale, "0");
|
||||
}
|
||||
|
||||
@ -552,7 +577,7 @@ void TracePluginImpl::formatStringArgument(string& result, const UCHAR* str, siz
|
||||
}
|
||||
|
||||
|
||||
void TracePluginImpl::appendParams(TraceParams *params, Firebird::string& line)
|
||||
void TracePluginImpl::appendParams(TraceParams* params, Firebird::string& line)
|
||||
{
|
||||
size_t paramcount = params->getCount();
|
||||
if (!paramcount)
|
||||
@ -679,34 +704,34 @@ void TracePluginImpl::appendParams(TraceParams *params, Firebird::string& line)
|
||||
}
|
||||
|
||||
case dtype_short:
|
||||
int_to_quoted_str(*(SSHORT*)parameters->dsc_address, parameters->dsc_scale, paramvalue);
|
||||
int_to_quoted_str(*(SSHORT*) parameters->dsc_address, parameters->dsc_scale, paramvalue);
|
||||
break;
|
||||
|
||||
case dtype_long:
|
||||
int_to_quoted_str(*(SLONG*)parameters->dsc_address, parameters->dsc_scale, paramvalue);
|
||||
int_to_quoted_str(*(SLONG*) parameters->dsc_address, parameters->dsc_scale, paramvalue);
|
||||
break;
|
||||
|
||||
case dtype_int64:
|
||||
int_to_quoted_str(*(SINT64*)parameters->dsc_address, parameters->dsc_scale, paramvalue);
|
||||
int_to_quoted_str(*(SINT64*) parameters->dsc_address, parameters->dsc_scale, paramvalue);
|
||||
break;
|
||||
|
||||
case dtype_real:
|
||||
if (!parameters->dsc_scale) {
|
||||
paramvalue.printf("\"%f\"", *(float*)parameters->dsc_address);
|
||||
paramvalue.printf("\"%f\"", *(float*) parameters->dsc_address);
|
||||
}
|
||||
else {
|
||||
paramvalue.printf("\"%f\"",
|
||||
*(float*)parameters->dsc_address * pow((float)10, -parameters->dsc_scale));
|
||||
*(float*) parameters->dsc_address * pow(10.0f, -parameters->dsc_scale));
|
||||
}
|
||||
break;
|
||||
|
||||
case dtype_double:
|
||||
if (!parameters->dsc_scale) {
|
||||
paramvalue.printf("\"%f\"", *(double*)parameters->dsc_address);
|
||||
paramvalue.printf("\"%f\"", *(double*) parameters->dsc_address);
|
||||
}
|
||||
else {
|
||||
paramvalue.printf("\"%f\"",
|
||||
*(double*)parameters->dsc_address * pow((double)10, -parameters->dsc_scale));
|
||||
*(double*) parameters->dsc_address * pow(10.0, -parameters->dsc_scale));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -720,7 +745,7 @@ void TracePluginImpl::appendParams(TraceParams *params, Firebird::string& line)
|
||||
case dtype_sql_time:
|
||||
{
|
||||
int hours, minutes, seconds, fractions;
|
||||
Firebird::TimeStamp::decode_time(*(ISC_TIME*)parameters->dsc_address,
|
||||
Firebird::TimeStamp::decode_time(*(ISC_TIME*) parameters->dsc_address,
|
||||
&hours, &minutes, &seconds, &fractions);
|
||||
|
||||
paramvalue.printf("\"%02d:%02d:%02d.%04d\"", hours, minutes, seconds, fractions);
|
||||
@ -728,7 +753,7 @@ void TracePluginImpl::appendParams(TraceParams *params, Firebird::string& line)
|
||||
}
|
||||
case dtype_timestamp:
|
||||
{
|
||||
Firebird::TimeStamp ts(*(ISC_TIMESTAMP*)parameters->dsc_address);
|
||||
Firebird::TimeStamp ts(*(ISC_TIMESTAMP*) parameters->dsc_address);
|
||||
struct tm times;
|
||||
|
||||
ts.decode(×);
|
||||
|
@ -38,7 +38,8 @@
|
||||
#define NEWLINE "\n"
|
||||
#endif
|
||||
|
||||
enum FileOpenFlags {
|
||||
enum FileOpenFlags
|
||||
{
|
||||
fo_rdonly = 0x0000, /* open for reading only */
|
||||
fo_wronly = 0x0001, /* open for writing only */
|
||||
fo_rdwr = 0x0002, /* open for reading and writing */
|
||||
@ -49,32 +50,31 @@ enum FileOpenFlags {
|
||||
fo_excl = 0x0400, /* open only if file doesn't already exist */
|
||||
|
||||
/* Temporary file bit - file is deleted when last handle is closed */
|
||||
|
||||
fo_temporary = 0x0040, /* temporary file bit */
|
||||
|
||||
/* temporary access hint */
|
||||
|
||||
fo_short_lived = 0x1000, /* temporary storage file, try not to flush */
|
||||
|
||||
/* sequential/random access hints */
|
||||
|
||||
fo_sequential = 0x0020, /* file access is primarily sequential */
|
||||
fo_random = 0x0010 /* file access is primarily random */
|
||||
};
|
||||
|
||||
enum SeekOrigin {
|
||||
enum SeekOrigin
|
||||
{
|
||||
so_from_beginning,
|
||||
so_from_current,
|
||||
so_from_end
|
||||
};
|
||||
|
||||
class FileObject : public Firebird::AutoStorage {
|
||||
class FileObject : public Firebird::AutoStorage
|
||||
{
|
||||
public:
|
||||
FileObject(const Firebird::PathName& afilename, int flags, int pflags = 0666) :
|
||||
filename(getPool(), afilename),
|
||||
filename(getPool(), afilename),
|
||||
#ifdef WIN_NT
|
||||
file(INVALID_HANDLE_VALUE),
|
||||
append_mutex(INVALID_HANDLE_VALUE)
|
||||
file(INVALID_HANDLE_VALUE),
|
||||
append_mutex(INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
file(-1)
|
||||
#endif
|
||||
@ -102,24 +102,30 @@ public:
|
||||
void writeHeader(const void* buffer, size_t bytesToWrite);
|
||||
SINT64 seek(SINT64 offset, SeekOrigin origin);
|
||||
FB_UINT64 size();
|
||||
|
||||
//This method used when log file was renamed by another process
|
||||
void reopen();
|
||||
bool renameFile(const Firebird::PathName new_filename);
|
||||
|
||||
// Generic stuff. Let it be inline for the moment.
|
||||
// If there will be a more than a few such methods we need to use inheritance
|
||||
bool readLine(Firebird::string &dest) {
|
||||
// This method is not very efficient, but is still much better then
|
||||
bool readLine(Firebird::string& dest)
|
||||
{
|
||||
// This method is not very efficient, but is still much better than
|
||||
// reading characters one-by-one. Plus it can handle line breaks in
|
||||
// Windows, Linux and Macintosh format nicely on all platforms
|
||||
char buffer[100];
|
||||
size_t bytesRead;
|
||||
dest.resize(0);
|
||||
bool prevCR = false;
|
||||
do {
|
||||
|
||||
do
|
||||
{
|
||||
bytesRead = blockRead(buffer, sizeof(buffer));
|
||||
for (int pos = 0; pos < bytesRead; pos++) {
|
||||
switch(buffer[pos]) {
|
||||
for (int pos = 0; pos < bytesRead; pos++)
|
||||
{
|
||||
switch (buffer[pos])
|
||||
{
|
||||
case '\n':
|
||||
dest.append(buffer, pos);
|
||||
// Adjust file pointer
|
||||
@ -132,7 +138,8 @@ public:
|
||||
prevCR = true;
|
||||
break;
|
||||
default:
|
||||
if (prevCR) {
|
||||
if (prevCR)
|
||||
{
|
||||
dest.append(buffer, pos);
|
||||
// Adjust file pointer
|
||||
seek(pos - bytesRead, so_from_current);
|
||||
@ -142,13 +149,16 @@ public:
|
||||
}
|
||||
dest.append(buffer, bytesRead);
|
||||
} while (bytesRead == sizeof(buffer));
|
||||
|
||||
// Kill trailing CR if present
|
||||
if (prevCR)
|
||||
dest.resize(dest.length() - 1);
|
||||
|
||||
return dest.length() || bytesRead;
|
||||
}
|
||||
|
||||
void writeLine(const Firebird::string &from) {
|
||||
void writeLine(const Firebird::string& from)
|
||||
{
|
||||
// Line should be written in a single BlockWrite call to handle file append properly
|
||||
Firebird::string temp = from.substr(0, from.max_length() - 2) + NEWLINE;
|
||||
blockWrite(temp.c_str(), temp.length());
|
||||
@ -156,8 +166,8 @@ public:
|
||||
|
||||
private:
|
||||
// Forbid copy and assignment operators
|
||||
FileObject(const FileObject &);
|
||||
FileObject& operator= (const FileObject &);
|
||||
FileObject(const FileObject&);
|
||||
FileObject& operator =(const FileObject&);
|
||||
|
||||
void open(int flags, int pflags);
|
||||
|
||||
|
@ -25,8 +25,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../../include/firebird.h"
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../FileObject.h"
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
@ -37,11 +36,13 @@
|
||||
using namespace Firebird;
|
||||
Firebird::Mutex open_mutex;
|
||||
|
||||
void FileObject::open(int flags, int pflags) {
|
||||
void FileObject::open(int flags, int pflags)
|
||||
{
|
||||
open_mutex.enter();
|
||||
int oflags = 0;
|
||||
|
||||
switch (flags & (fo_rdonly | fo_wronly | fo_rdwr)) {
|
||||
switch (flags & (fo_rdonly | fo_wronly | fo_rdwr))
|
||||
{
|
||||
case fo_rdonly:
|
||||
oflags = O_RDONLY;
|
||||
break;
|
||||
@ -67,6 +68,7 @@ void FileObject::open(int flags, int pflags) {
|
||||
|
||||
file = ::open(filename.c_str(), oflags, pflags);
|
||||
open_mutex.leave();
|
||||
|
||||
if (file < 0)
|
||||
fatal_exception::raiseFmt("Error (%d) opening file: %s", errno, filename.c_str());
|
||||
|
||||
@ -74,12 +76,14 @@ void FileObject::open(int flags, int pflags) {
|
||||
unlink(filename.c_str());
|
||||
}
|
||||
|
||||
FileObject::~FileObject() {
|
||||
FileObject::~FileObject()
|
||||
{
|
||||
close(file);
|
||||
}
|
||||
|
||||
//Size of file, given by descriptor
|
||||
FB_UINT64 FileObject::size() {
|
||||
FB_UINT64 FileObject::size()
|
||||
{
|
||||
off_t nFileLen = 0;
|
||||
struct stat file_stat;
|
||||
if (!fstat(file, &file_stat))
|
||||
@ -90,16 +94,21 @@ FB_UINT64 FileObject::size() {
|
||||
return nFileLen;
|
||||
}
|
||||
|
||||
size_t FileObject::blockRead(void* buffer, size_t bytesToRead) {
|
||||
size_t FileObject::blockRead(void* buffer, size_t bytesToRead)
|
||||
{
|
||||
ssize_t bytesDone = read(file, buffer, bytesToRead);
|
||||
if (bytesDone < 0)
|
||||
{
|
||||
fatal_exception::raiseFmt("IO error (%d) reading file: %s",
|
||||
errno,
|
||||
filename.c_str());
|
||||
}
|
||||
|
||||
return bytesDone;
|
||||
}
|
||||
|
||||
void FileObject::blockWrite(const void* buffer, size_t bytesToWrite) {
|
||||
void FileObject::blockWrite(const void* buffer, size_t bytesToWrite)
|
||||
{
|
||||
ssize_t bytesDone = write(file, buffer, bytesToWrite);
|
||||
if (bytesDone != static_cast<ssize_t>(bytesToWrite))
|
||||
{
|
||||
@ -110,9 +119,11 @@ void FileObject::blockWrite(const void* buffer, size_t bytesToWrite) {
|
||||
}
|
||||
|
||||
// Write data to header only if file is empty
|
||||
void FileObject::writeHeader(const void* buffer, size_t bytesToWrite) {
|
||||
void FileObject::writeHeader(const void* buffer, size_t bytesToWrite)
|
||||
{
|
||||
if (seek(0, so_from_end) != 0)
|
||||
return;
|
||||
|
||||
ssize_t bytesDone = write(file, buffer, bytesToWrite);
|
||||
if (bytesDone != static_cast<ssize_t>(bytesToWrite))
|
||||
{
|
||||
@ -122,14 +133,16 @@ void FileObject::writeHeader(const void* buffer, size_t bytesToWrite) {
|
||||
}
|
||||
}
|
||||
|
||||
void FileObject::reopen() {
|
||||
void FileObject::reopen()
|
||||
{
|
||||
if (file >= 0)
|
||||
close(file);
|
||||
open(fo_rdwr | fo_append | fo_creat, 0666);
|
||||
// fchmod(file, PMASK);
|
||||
//fchmod(file, PMASK);
|
||||
}
|
||||
|
||||
bool FileObject::renameFile(const Firebird::PathName new_filename) {
|
||||
bool FileObject::renameFile(const Firebird::PathName new_filename)
|
||||
{
|
||||
if (rename(filename.c_str(), new_filename.c_str()))
|
||||
{
|
||||
int rename_err = errno;
|
||||
@ -146,8 +159,10 @@ bool FileObject::renameFile(const Firebird::PathName new_filename) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SINT64 FileObject::seek(SINT64 newOffset, SeekOrigin origin) {
|
||||
if (newOffset != (SINT64) LSEEK_OFFSET_CAST newOffset) {
|
||||
SINT64 FileObject::seek(SINT64 newOffset, SeekOrigin origin)
|
||||
{
|
||||
if (newOffset != (SINT64) LSEEK_OFFSET_CAST newOffset)
|
||||
{
|
||||
fatal_exception::raiseFmt(
|
||||
"Attempt to seek file %s past platform size limit",
|
||||
filename.c_str());
|
||||
@ -155,7 +170,8 @@ SINT64 FileObject::seek(SINT64 newOffset, SeekOrigin origin) {
|
||||
|
||||
int moveMethod;
|
||||
|
||||
switch(origin) {
|
||||
switch(origin)
|
||||
{
|
||||
case so_from_beginning:
|
||||
moveMethod = SEEK_SET;
|
||||
break;
|
||||
@ -175,5 +191,6 @@ SINT64 FileObject::seek(SINT64 newOffset, SeekOrigin origin) {
|
||||
errno,
|
||||
filename.c_str());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
|
||||
#include "../platform.h"
|
||||
#include "../common/classes/fb_tls.h"
|
||||
#include <sys/types.h>
|
||||
@ -35,29 +34,36 @@
|
||||
#define TEST
|
||||
//#undef TEST
|
||||
#ifndef TEST
|
||||
class MallocClear {
|
||||
class MallocClear
|
||||
{
|
||||
public:
|
||||
static void clear(char* error_string) {
|
||||
static void clear(char* error_string)
|
||||
{
|
||||
free(error_string);
|
||||
}
|
||||
};
|
||||
|
||||
Firebird::TlsValue<char*, MallocClear> error_value;
|
||||
|
||||
const char* get_error_string() {
|
||||
const char* get_error_string()
|
||||
{
|
||||
return error_value.get();
|
||||
}
|
||||
|
||||
void set_error_string(const char* str) {
|
||||
void set_error_string(const char* str)
|
||||
{
|
||||
char* org_str = error_value.get();
|
||||
if (org_str) {
|
||||
if (org_str)
|
||||
{
|
||||
free(org_str);
|
||||
error_value.set(NULL);
|
||||
}
|
||||
if (str) {
|
||||
if (str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
char* new_str = (char*) malloc(len + 1);
|
||||
if (new_str) {
|
||||
if (new_str)
|
||||
{
|
||||
memcpy(new_str, str, len + 1);
|
||||
error_value.set(new_str);
|
||||
}
|
||||
@ -65,26 +71,32 @@ void set_error_string(const char* str) {
|
||||
}
|
||||
#else
|
||||
TLS_DECLARE(char*, error_string);
|
||||
const char* get_error_string(){
|
||||
const char* get_error_string()
|
||||
{
|
||||
return TLS_GET(error_string);
|
||||
}
|
||||
|
||||
void set_error_string(const char* str){
|
||||
void set_error_string(const char* str)
|
||||
{
|
||||
char* org_str = TLS_GET(error_string);
|
||||
if (org_str){
|
||||
if (org_str)
|
||||
{
|
||||
free(org_str);
|
||||
TLS_SET(error_string,NULL);
|
||||
}
|
||||
if (str){
|
||||
if (str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
char* new_str = (char*) malloc(len + 1);
|
||||
if (new_str) {
|
||||
if (new_str)
|
||||
{
|
||||
memcpy(new_str, str, len + 1);
|
||||
TLS_SET(error_string, new_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
SLONG get_process_id() {
|
||||
SLONG get_process_id()
|
||||
{
|
||||
return getpid();
|
||||
}
|
||||
|
@ -26,19 +26,20 @@
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
|
||||
#include "../FileObject.h"
|
||||
|
||||
using namespace Firebird;
|
||||
Firebird::Mutex open_mutex;
|
||||
|
||||
void FileObject::open(int flags, int pflags) {
|
||||
void FileObject::open(int flags, int pflags)
|
||||
{
|
||||
open_mutex.enter();
|
||||
DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
DWORD filecreate = 0;
|
||||
DWORD desiredAccess = 0;
|
||||
|
||||
switch (flags & (fo_rdonly | fo_wronly | fo_rdwr)) {
|
||||
switch (flags & (fo_rdonly | fo_wronly | fo_rdwr))
|
||||
{
|
||||
case fo_rdonly:
|
||||
desiredAccess = GENERIC_READ;
|
||||
break;
|
||||
@ -49,29 +50,34 @@ void FileObject::open(int flags, int pflags) {
|
||||
desiredAccess = GENERIC_READ | GENERIC_WRITE;
|
||||
}
|
||||
|
||||
if (flags & fo_append) {
|
||||
if (flags & fo_append)
|
||||
{
|
||||
// This is going to be tricky. Need to use global named mutex to achieve
|
||||
// multi-process happiness
|
||||
string temp(filename.c_str());
|
||||
for (string::size_type i = 0; i < temp.length(); i++)
|
||||
switch (temp[i]) {
|
||||
{
|
||||
switch (temp[i])
|
||||
{
|
||||
case '\\':
|
||||
case '/':
|
||||
case ':':
|
||||
temp[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
temp.append("_mutex");
|
||||
append_mutex = CreateMutex(NULL, FALSE, temp.c_str());
|
||||
if (append_mutex == NULL) {
|
||||
if (append_mutex == NULL)
|
||||
{
|
||||
append_mutex = INVALID_HANDLE_VALUE;
|
||||
system_call_failed::raise("CreateMutex");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* decode open/create method flags
|
||||
*/
|
||||
switch ( flags & (fo_creat | fo_excl | fo_trunc) ) {
|
||||
// decode open/create method flags
|
||||
switch ( flags & (fo_creat | fo_excl | fo_trunc) )
|
||||
{
|
||||
case 0:
|
||||
case fo_excl: // ignore EXCL w/o CREAT
|
||||
filecreate = OPEN_EXISTING;
|
||||
@ -118,17 +124,21 @@ void FileObject::open(int flags, int pflags) {
|
||||
NULL,
|
||||
filecreate,
|
||||
flagsAndAttributes, NULL);
|
||||
|
||||
open_mutex.leave();
|
||||
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
fatal_exception::raiseFmt("Error (%d) opening file: %s", GetLastError(), filename.c_str());
|
||||
}
|
||||
|
||||
FileObject::~FileObject() {
|
||||
FileObject::~FileObject()
|
||||
{
|
||||
CloseHandle(file);
|
||||
CloseHandle(append_mutex);
|
||||
}
|
||||
|
||||
UINT64 FileObject::size() {
|
||||
UINT64 FileObject::size()
|
||||
{
|
||||
UINT64 nFileLen = 0;
|
||||
if (file != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
@ -152,21 +162,28 @@ void FileObject::reopen()
|
||||
FlushFileBuffers(file);
|
||||
}
|
||||
|
||||
size_t FileObject::blockRead(void* buffer, size_t bytesToRead) {
|
||||
size_t FileObject::blockRead(void* buffer, size_t bytesToRead)
|
||||
{
|
||||
DWORD bytesDone;
|
||||
if (!ReadFile(file, buffer, bytesToRead, &bytesDone, NULL))
|
||||
{
|
||||
fatal_exception::raiseFmt("IO error (%d) reading file: %s",
|
||||
GetLastError(),
|
||||
filename.c_str());
|
||||
}
|
||||
|
||||
return bytesDone;
|
||||
}
|
||||
|
||||
void FileObject::blockWrite(const void* buffer, size_t bytesToWrite) {
|
||||
if (append_mutex != INVALID_HANDLE_VALUE) {
|
||||
void FileObject::blockWrite(const void* buffer, size_t bytesToWrite)
|
||||
{
|
||||
if (append_mutex != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (WaitForSingleObject(append_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||
system_call_failed::raise("WaitForSingleObject");
|
||||
seek(0, so_from_end);
|
||||
}
|
||||
|
||||
DWORD bytesDone;
|
||||
if (!WriteFile(file, buffer, bytesToWrite, &bytesDone, NULL) ||
|
||||
bytesDone != bytesToWrite)
|
||||
@ -177,24 +194,30 @@ void FileObject::blockWrite(const void* buffer, size_t bytesToWrite) {
|
||||
GetLastError(),
|
||||
filename.c_str());
|
||||
}
|
||||
|
||||
if (append_mutex != INVALID_HANDLE_VALUE)
|
||||
ReleaseMutex(append_mutex);
|
||||
}
|
||||
|
||||
// Write data to header only if file is empty
|
||||
void FileObject::writeHeader(const void* buffer, size_t bytesToWrite) {
|
||||
if (append_mutex != INVALID_HANDLE_VALUE) {
|
||||
void FileObject::writeHeader(const void* buffer, size_t bytesToWrite)
|
||||
{
|
||||
if (append_mutex != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (WaitForSingleObject(append_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||
system_call_failed::raise("WaitForSingleObject");
|
||||
}
|
||||
|
||||
if (seek(0, so_from_end) != 0)
|
||||
return;
|
||||
|
||||
DWORD bytesDone;
|
||||
if (!WriteFile(file, buffer, bytesToWrite, &bytesDone, NULL) ||
|
||||
bytesDone != bytesToWrite)
|
||||
{
|
||||
if (append_mutex != INVALID_HANDLE_VALUE)
|
||||
ReleaseMutex(append_mutex);
|
||||
|
||||
fatal_exception::raiseFmt("IO error (%d) writing file: %s",
|
||||
GetLastError(),
|
||||
filename.c_str());
|
||||
@ -204,35 +227,46 @@ void FileObject::writeHeader(const void* buffer, size_t bytesToWrite) {
|
||||
ReleaseMutex(append_mutex);
|
||||
}
|
||||
|
||||
bool FileObject::renameFile(const Firebird::PathName new_filename) {
|
||||
if (append_mutex != INVALID_HANDLE_VALUE)
|
||||
bool FileObject::renameFile(const Firebird::PathName new_filename)
|
||||
{
|
||||
if (append_mutex != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (WaitForSingleObject(append_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||
system_call_failed::raise("WaitForSingleObject");
|
||||
if (!MoveFile(filename.c_str(), new_filename.c_str())) {
|
||||
}
|
||||
|
||||
if (!MoveFile(filename.c_str(), new_filename.c_str()))
|
||||
{
|
||||
DWORD rename_err = GetLastError();
|
||||
if (rename_err == ERROR_ALREADY_EXISTS || rename_err == ERROR_FILE_NOT_FOUND) {
|
||||
if (rename_err == ERROR_ALREADY_EXISTS || rename_err == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
// Another process renames our file just now. Open new it.
|
||||
reopen();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (append_mutex != INVALID_HANDLE_VALUE)
|
||||
ReleaseMutex(append_mutex);
|
||||
|
||||
fatal_exception::raiseFmt("IO error (%d) renaming file: %s",
|
||||
rename_err,
|
||||
filename.c_str());
|
||||
}
|
||||
else
|
||||
reopen();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SINT64 FileObject::seek(SINT64 newOffset, SeekOrigin origin) {
|
||||
SINT64 FileObject::seek(SINT64 newOffset, SeekOrigin origin)
|
||||
{
|
||||
LARGE_INTEGER offset;
|
||||
offset.QuadPart = newOffset;
|
||||
DWORD error;
|
||||
DWORD moveMethod;
|
||||
|
||||
switch(origin) {
|
||||
switch(origin)
|
||||
{
|
||||
case so_from_beginning:
|
||||
moveMethod = FILE_BEGIN;
|
||||
break;
|
||||
@ -244,14 +278,14 @@ SINT64 FileObject::seek(SINT64 newOffset, SeekOrigin origin) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((offset.LowPart = SetFilePointer(file, offset.LowPart,
|
||||
&offset.HighPart, moveMethod)) == INVALID_SET_FILE_POINTER
|
||||
&&
|
||||
(error = GetLastError()) != NO_ERROR)
|
||||
if ((offset.LowPart = SetFilePointer(file, offset.LowPart,
|
||||
&offset.HighPart, moveMethod)) == INVALID_SET_FILE_POINTER &&
|
||||
(error = GetLastError()) != NO_ERROR)
|
||||
{
|
||||
fatal_exception::raiseFmt("IO error (%d) seeking file: %s",
|
||||
error,
|
||||
filename.c_str());
|
||||
}
|
||||
|
||||
return offset.QuadPart;
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include "../platform.h"
|
||||
#include "../common/classes/fb_tls.h"
|
||||
@ -46,7 +45,8 @@ void set_error_string(const char* str)
|
||||
LocalFree(org_str);
|
||||
TLS_SET(error_string, NULL);
|
||||
}
|
||||
if (str)
|
||||
|
||||
if (str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
char* new_str = (char*) LocalAlloc(LMEM_FIXED, len + 1);
|
||||
@ -64,11 +64,7 @@ SLONG get_process_id()
|
||||
}
|
||||
|
||||
|
||||
BOOL WINAPI DllMain(
|
||||
HINSTANCE hinstDLL,
|
||||
DWORD fdwReason,
|
||||
LPVOID lpvReserved
|
||||
)
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
if (fdwReason == DLL_THREAD_DETACH)
|
||||
{
|
||||
@ -81,5 +77,3 @@ BOOL WINAPI DllMain(
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user