8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 04:43:03 +01:00
This commit is contained in:
asfernandes 2009-02-02 03:35:52 +00:00
parent 4c47e58544
commit 612c108e3e
22 changed files with 375 additions and 268 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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
{

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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());
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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++;
}
}

View File

@ -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

View File

@ -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)),

View File

@ -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(&times);

View File

@ -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);

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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;
}