8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 03:23:04 +01:00

1) Remove REPLAY_OSRI_API_CALLS_SUBSYSTEM code

2) Remove internal y-valve function INTERNAL_COMPILE_REQUEST
3) Go direct to engine internals from DSQL, without need to exit/enter the attachment lock and check exceptions in status vector
This commit is contained in:
asfernandes 2008-03-07 15:23:21 +00:00
parent 23d7643d80
commit 0b6ecafe1b
26 changed files with 455 additions and 1737 deletions

View File

@ -34,7 +34,7 @@ JRD_ServerFiles= blob_filter.cpp dpm.epp dyn.epp dyn_def.epp \
event.cpp evl.cpp exe.cpp ext.cpp \
execute_statement.cpp filters.cpp flu.cpp functions.cpp \
idx.cpp inf.cpp intl.cpp intl_builtin.cpp IntlManager.cpp IntlUtil.cpp \
jrd.cpp Database.cpp lck.cpp log.cpp \
jrd.cpp Database.cpp lck.cpp \
mov.cpp nav.cpp opt.cpp Optimizer.cpp pag.cpp par.cpp \
ods.cpp plugin_manager.cpp pwd.cpp RandomGenerator.cpp Relation.cpp rlck.cpp \
rpb_chain.cpp rse.cpp \

View File

@ -362,10 +362,6 @@ SOURCE=..\..\..\src\jrd\lck.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\mov.cpp
# End Source File
# Begin Source File
@ -1048,18 +1044,6 @@ SOURCE=..\..\..\src\jrd\lnmdef.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log2.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log_proto.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\map_proto.h
# End Source File
# Begin Source File

View File

@ -353,10 +353,6 @@ SOURCE=..\..\..\src\jrd\lck.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\mov.cpp
# End Source File
# Begin Source File
@ -1017,18 +1013,6 @@ SOURCE=..\..\..\src\jrd\lnmdef.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log2.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log_proto.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\map_proto.h
# End Source File
# Begin Source File

View File

@ -341,10 +341,6 @@ SOURCE=..\..\..\src\jrd\lck.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\gen\jrd\met.cpp
# End Source File
# Begin Source File
@ -1021,18 +1017,6 @@ SOURCE=..\..\..\src\jrd\lnmdef.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log2.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\log_proto.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\jrd\map_proto.h
# End Source File
# Begin Source File

View File

@ -291,9 +291,6 @@
<File
RelativePath="..\..\..\src\jrd\lck.cpp">
</File>
<File
RelativePath="..\..\..\src\jrd\log.cpp">
</File>
<File
RelativePath="..\..\..\gen\jrd\met.cpp">
</File>
@ -778,15 +775,6 @@
<File
RelativePath="..\..\..\src\jrd\lnmdef.h">
</File>
<File
RelativePath="..\..\..\src\jrd\log.h">
</File>
<File
RelativePath="..\..\..\src\jrd\log2.h">
</File>
<File
RelativePath="..\..\..\src\jrd\log_proto.h">
</File>
<File
RelativePath="..\..\..\src\jrd\map_proto.h">
</File>

View File

@ -291,9 +291,6 @@
<File
RelativePath="..\..\..\src\jrd\lck.cpp">
</File>
<File
RelativePath="..\..\..\src\jrd\log.cpp">
</File>
<File
RelativePath="..\..\..\gen\jrd\met.cpp">
</File>
@ -778,15 +775,6 @@
<File
RelativePath="..\..\..\src\jrd\lnmdef.h">
</File>
<File
RelativePath="..\..\..\src\jrd\log.h">
</File>
<File
RelativePath="..\..\..\src\jrd\log2.h">
</File>
<File
RelativePath="..\..\..\src\jrd\log_proto.h">
</File>
<File
RelativePath="..\..\..\src\jrd\map_proto.h">
</File>

View File

@ -295,9 +295,6 @@
<File
RelativePath="..\..\..\src\jrd\lck.cpp">
</File>
<File
RelativePath="..\..\..\src\jrd\log.cpp">
</File>
<File
RelativePath="..\..\..\gen\jrd\met.cpp">
</File>
@ -779,15 +776,6 @@
<File
RelativePath="..\..\..\src\jrd\lnmdef.h">
</File>
<File
RelativePath="..\..\..\src\jrd\log.h">
</File>
<File
RelativePath="..\..\..\src\jrd\log2.h">
</File>
<File
RelativePath="..\..\..\src\jrd\log_proto.h">
</File>
<File
RelativePath="..\..\..\src\jrd\map_proto.h">
</File>

View File

@ -490,10 +490,6 @@
RelativePath="..\..\..\src\jrd\lck.cpp"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log.cpp"
>
</File>
<File
RelativePath="..\..\..\gen\$(PlatformName)\jrd\met.cpp"
>
@ -1142,18 +1138,6 @@
RelativePath="..\..\..\src\jrd\lnmdef.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log2.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log_proto.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\map_proto.h"
>

View File

@ -490,10 +490,6 @@
RelativePath="..\..\..\src\jrd\lck.cpp"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log.cpp"
>
</File>
<File
RelativePath="..\..\..\gen\$(PlatformName)\jrd\met.cpp"
>
@ -1142,18 +1138,6 @@
RelativePath="..\..\..\src\jrd\lnmdef.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log2.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log_proto.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\map_proto.h"
>

View File

@ -494,10 +494,6 @@
RelativePath="..\..\..\src\jrd\lck.cpp"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log.cpp"
>
</File>
<File
RelativePath="..\..\..\gen\$(PlatformName)\jrd\met.cpp"
>
@ -1142,18 +1138,6 @@
RelativePath="..\..\..\src\jrd\lnmdef.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log2.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\log_proto.h"
>
</File>
<File
RelativePath="..\..\..\src\jrd\map_proto.h"
>

View File

@ -944,28 +944,25 @@ static void close_cursor(dsql_req* request)
if (request->req_request)
{
if (request->req_type == REQ_GET_SEGMENT ||
request->req_type == REQ_PUT_SEGMENT)
{
ISC_STATUS* const old_status = tdbb->tdbb_status_vector;
ISC_STATUS* const old_status = tdbb->tdbb_status_vector;
tdbb->tdbb_status_vector = status_vector;
try
tdbb->tdbb_status_vector = status_vector;
try
{
if (request->req_type == REQ_GET_SEGMENT ||
request->req_type == REQ_PUT_SEGMENT)
{
BLB_close(tdbb, request->req_blob->blb_blob);
request->req_blob->blb_blob = NULL;
}
catch (Firebird::Exception&)
{
}
tdbb->tdbb_status_vector = old_status;
else
JRD_unwind_request(tdbb, request->req_request, 0);
}
else
catch (Firebird::Exception&)
{
Database::Checkout dcoHolder(request->req_dbb->dbb_database);
jrd8_unwind_request(status_vector, &request->req_request, 0);
}
tdbb->tdbb_status_vector = old_status;
}
request->req_flags &= ~REQ_cursor_open;
@ -1251,62 +1248,32 @@ static void execute_request(thread_db* tdbb,
switch (request->req_type)
{
case REQ_START_TRANS:
{
Database::Checkout dcoHolder(request->req_dbb->dbb_database);
if (jrd8_start_transaction(tdbb->tdbb_status_vector,
&request->req_transaction,
1,
&request->req_dbb->dbb_attachment,
request->req_blr_data.getCount(),
request->req_blr_data.begin()))
{
Firebird::status_exception::raise(tdbb->tdbb_status_vector);
}
*tra_handle = request->req_transaction;
return;
}
JRD_start_transaction(tdbb,
&request->req_transaction,
1,
&request->req_dbb->dbb_attachment,
request->req_blr_data.getCount(),
request->req_blr_data.begin());
*tra_handle = request->req_transaction;
return;
case REQ_COMMIT:
{
Database::Checkout dcoHolder(request->req_dbb->dbb_database);
if (jrd8_commit_transaction(tdbb->tdbb_status_vector, &request->req_transaction))
{
Firebird::status_exception::raise(tdbb->tdbb_status_vector);
}
*tra_handle = NULL;
return;
}
JRD_commit_transaction(tdbb, &request->req_transaction);
*tra_handle = NULL;
return;
case REQ_COMMIT_RETAIN:
{
Database::Checkout dcoHolder(request->req_dbb->dbb_database);
if (jrd8_commit_retaining(tdbb->tdbb_status_vector, &request->req_transaction))
{
Firebird::status_exception::raise(tdbb->tdbb_status_vector);
}
return;
}
JRD_commit_retaining(tdbb, &request->req_transaction);
return;
case REQ_ROLLBACK:
{
Database::Checkout dcoHolder(request->req_dbb->dbb_database);
if (jrd8_rollback_transaction(tdbb->tdbb_status_vector, &request->req_transaction))
{
Firebird::status_exception::raise(tdbb->tdbb_status_vector);
}
*tra_handle = NULL;
return;
}
JRD_rollback_transaction(tdbb, &request->req_transaction);
*tra_handle = NULL;
return;
case REQ_ROLLBACK_RETAIN:
{
Database::Checkout dcoHolder(request->req_dbb->dbb_database);
if (jrd8_rollback_retaining(tdbb->tdbb_status_vector, &request->req_transaction))
{
Firebird::status_exception::raise(tdbb->tdbb_status_vector);
}
return;
}
JRD_rollback_retaining(tdbb, &request->req_transaction);
return;
case REQ_CREATE_DB:
case REQ_DDL:
@ -1357,17 +1324,13 @@ static void execute_request(thread_db* tdbb,
in_blr_length, in_blr,
in_msg_length, const_cast<UCHAR*>(in_msg));
Database::Checkout dcoHolder(request->req_dbb->dbb_database);
if (jrd8_start_and_send(tdbb->tdbb_status_vector,
&request->req_request,
&request->req_transaction,
message->msg_number,
message->msg_length,
reinterpret_cast<SCHAR*>(message->msg_buffer),
0))
{
Firebird::status_exception::raise(tdbb->tdbb_status_vector);
}
JRD_start_and_send(tdbb,
request->req_request,
request->req_transaction,
message->msg_number,
message->msg_length,
reinterpret_cast<SCHAR*>(message->msg_buffer),
0);
}
ISC_STATUS_ARRAY local_status = {0};
@ -2714,17 +2677,21 @@ static dsql_req* prepare(thread_db* tdbb,
ISC_STATUS status = FB_SUCCESS;
{ // scope
Database::Checkout dcoHolder(request->req_dbb->dbb_database);
status = jrd8_internal_compile_request(tdbb->tdbb_status_vector,
&request->req_dbb->dbb_attachment,
&request->req_request,
length,
(const char*)(request->req_blr_data.begin()),
string_length,
string,
request->req_debug_data.getCount(),
request->req_debug_data.begin());
try
{
JRD_internal_compile(tdbb,
request->req_dbb->dbb_attachment,
&request->req_request,
length,
(const char*)(request->req_blr_data.begin()),
string_length,
string,
request->req_debug_data.getCount(),
request->req_debug_data.begin());
}
catch (const Firebird::Exception&)
{
status = tdbb->tdbb_status_vector[1];
}
// restore warnings (if there are any)

View File

@ -372,11 +372,6 @@ public:
crypt_routine dbb_encrypt; // External encryption routine
crypt_routine dbb_decrypt; // External decryption routine
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
class blb_map *dbb_blob_map; // mapping of blobs for REPLAY
struct log *dbb_log; // log file for REPLAY
#endif
Firebird::Array<CharSetContainer*> dbb_charsets; // intl character set descriptions
TxPageCache* dbb_tip_cache; // cache of latest known state of all transactions in system
vcl* dbb_pc_transactions; // active precommitted transactions

View File

@ -91,9 +91,6 @@ static void delete_blob_id(thread_db*, const bid*, SLONG, jrd_rel*);
static ArrayField* find_array(jrd_tra*, const bid*);
static BlobFilter* find_filter(thread_db*, SSHORT, SSHORT);
static blob_page* get_next_page(thread_db*, blb*, WIN *);
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
static void get_replay_blob(thread_db*, const bid*);
#endif
static void insert_page(thread_db*, blb*);
static void move_from_string(Jrd::thread_db*, const dsc*, dsc*, Jrd::jrd_nod*);
static void move_to_string(Jrd::thread_db*, dsc*, dsc*);
@ -954,40 +951,6 @@ SLONG BLB_lseek(blb* blob, USHORT mode, SLONG offset)
}
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
void BLB_map_blobs(thread_db* tdbb, blb* old_blob, blb* new_blob)
{
/**************************************
*
* B L B _ m a p _ b l o b s
*
**************************************
*
* Functional description
* Form a mapping between two blobs.
* Since the blobs have been newly created
* in this session, only the second part of
* the blob id is significant. At the moment
* this is intended solely for REPLAY, when
* replaying a log.
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
blb_map* new_map = FB_NEW(*dbb->dbb_permanent) blb_map();
new_map->map_old_blob = old_blob;
new_map->map_new_blob = new_blob;
new_map->map_next = dbb->dbb_blob_map;
dbb->dbb_blob_map = new_map;
}
#endif // REPLAY_OSRI_API_CALLS_SUBSYSTEM
// This function can't take from_desc as const because it may call store_array,
// which in turn calls BLB_create2 that writes in the blob id. Although the
// compiler allows to modify from_desc->dsc_address' contents when from_desc is
@ -1131,12 +1094,6 @@ void BLB_move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, jrd_nod* field)
return;
}
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
// for REPLAY, map blob id's from the original session
get_replay_blob(tdbb, source);
#endif
// If the source is a permanent blob, then the blob must be copied.
// Otherwise find the temporary blob referenced.
@ -1327,12 +1284,6 @@ blb* BLB_open2(thread_db* tdbb,
blb* blob = allocate_blob(tdbb, transaction);
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
/* for REPLAY, map blob id's from the original session */
get_replay_blob(tdbb, blob_id);
#endif
bool try_relations = false;
BlobIndex* current = NULL;
@ -2404,43 +2355,6 @@ static blob_page* get_next_page(thread_db* tdbb, blb* blob, WIN * window)
}
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
static void get_replay_blob(thread_db* tdbb, bid* blob_id)
{
/**************************************
*
* g e t _ r e p l a y _ b l o b
*
**************************************
*
* Functional description
* Replace the blob id passed with the
* blob id used in the original session.
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
/* we're only interested in newly created blobs */
if (blob_id->bid_internal.bid_relation_id != 0)
return;
/* search the linked list for the old blob id */
for (map* map_ptr = dbb->dbb_blob_map; map_ptr; map_ptr = map_ptr->map_next)
{
if (blob_id->bid_temp_id() == map_ptr->map_old_blob)
{
blob_id->bid_temp_id() = map_ptr->map_new_blob;
break;
}
}
}
#endif
static void insert_page(thread_db* tdbb, blb* blob)
{
/**************************************

View File

@ -208,16 +208,6 @@ const int BLB_large_scan = 128; /* Blob is larger than page buffer cache */
2 large blob -- blob "record" is pointer to pages of pointers
*/
// mapping blob ids for REPLAY
// Useful only with REPLAY_OSRI_API_CALLS_SUBSYSTEM defined.
class blb_map : public pool_alloc<type_map>
{
public:
blb_map* map_next;
blb* map_old_blob;
blb* map_new_blob;
};
} //namespace Jrd
#endif // JRD_BLB_H

View File

@ -58,10 +58,6 @@ void BLB_release_array(Jrd::ArrayField*);
void BLB_scalar(Jrd::thread_db*, Jrd::jrd_tra*, const Jrd::bid*, USHORT, const SLONG*, Jrd::impure_value*);
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
void BLB_map_blobs(Jrd::thread_db*, Jrd::blb*, Jrd::blb*);
#endif
class AutoBlb
{
public:

View File

@ -49,9 +49,6 @@
#include "../jrd/ext.h"
#include "../jrd/met.h"
#include "../jrd/sdw.h"
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
#include "../jrd/log.h"
#endif
#include "../jrd/intl.h"
#include "../jrd/intl_classes.h"
#include "../jrd/fil.h"
@ -358,9 +355,6 @@ static TEXT_PTR VerbAction[] = { "VERB", 0};
static TEXT_PTR BlobFilter[] = { "BLOB FILTER", 0};
static TEXT_PTR ArrayField[] = { "ARRAY DESCRIPTION", 0};
static TEXT_PTR blb_map[] = { "MAP BLOCK", 0};
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
static TEXT_PTR fblog[] = { "LOG BLOCK", 0};
#endif
static TEXT_PTR dir_list[] = { "DIR LIST BLOCK", 0};
static TEXT_PTR jrd_prc[] =
{

View File

@ -208,9 +208,6 @@ ENTRYPOINT( jrd8_rollback_retaining,
ENTRYPOINT( jrd8_cancel_operation,
/* REM_cancel_operation */ no_entrypoint)
ENTRYPOINT( jrd8_internal_compile_request,
/* REM_internal_compile_request */ no_entrypoint)
ENTRYPOINT( jrd8_shutdown_all,
/* REM_shutdown_all */ no_entrypoint)

File diff suppressed because it is too large Load Diff

View File

@ -74,11 +74,6 @@ ISC_STATUS jrd8_ddl(ISC_STATUS*, Jrd::Attachment**, Jrd::jrd_tra**,
USHORT, const SCHAR*);
ISC_STATUS jrd8_detach_database(ISC_STATUS *, Jrd::Attachment**);
ISC_STATUS jrd8_drop_database(ISC_STATUS *, Jrd::Attachment**);
ISC_STATUS jrd8_internal_compile_request(ISC_STATUS*, Jrd::Attachment**,
Jrd::jrd_req**,
SSHORT, const SCHAR*,
USHORT, const char*,
USHORT, const UCHAR*);
ISC_STATUS jrd8_get_segment(ISC_STATUS *, Jrd::blb**, USHORT *,
USHORT, UCHAR *);
ISC_STATUS jrd8_get_slice(ISC_STATUS*, Jrd::Attachment**,
@ -227,5 +222,22 @@ void JRD_request_info(Jrd::thread_db* tdbb, Jrd::jrd_req* request, SSHORT level,
const SCHAR* items, SSHORT buffer_length, SCHAR* buffer);
void JRD_start(Jrd::thread_db* tdbb, Jrd::jrd_req* request, Jrd::jrd_tra* transaction, SSHORT level);
void JRD_commit_transaction(Jrd::thread_db* tdbb, Jrd::jrd_tra** transaction);
void JRD_commit_retaining(Jrd::thread_db* tdbb, Jrd::jrd_tra** transaction);
void JRD_rollback_transaction(Jrd::thread_db* tdbb, Jrd::jrd_tra** transaction);
void JRD_rollback_retaining(Jrd::thread_db* tdbb, Jrd::jrd_tra** transaction);
void JRD_start_and_send(Jrd::thread_db* tdbb, Jrd::jrd_req* request, Jrd::jrd_tra* transaction,
USHORT msg_type, USHORT msg_length, SCHAR* msg, SSHORT level);
void JRD_start_multiple(Jrd::thread_db* tdbb, Jrd::jrd_tra** tra_handle, USHORT count, Jrd::teb* vector);
void JRD_start_transaction(Jrd::thread_db* tdbb, Jrd::jrd_tra** transaction, SSHORT count, ...);
void JRD_unwind_request(Jrd::thread_db* tdbb, Jrd::jrd_req* request, SSHORT level);
void JRD_internal_compile(Jrd::thread_db* tdbb,
Jrd::Attachment* attachment,
Jrd::jrd_req** req_handle,
SSHORT blr_length,
const SCHAR* blr,
USHORT string_length, const char* string,
USHORT dbginfo_length, const UCHAR* dbginfo);
#endif /* JRD_JRD_PROTO_H */

View File

@ -1,616 +0,0 @@
/*
* PROGRAM: JRD Access Method
* MODULE: log.cpp
* DESCRIPTION: Log all OSRI calls
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#include "firebird.h"
#include <stdio.h>
#include <string.h>
#include "../jrd/common.h"
#include <stdarg.h>
#include "../jrd/jrd.h"
#include "../jrd/log.h"
#include "../jrd/ods.h"
#include "../jrd/gds_proto.h"
#include "../jrd/log_proto.h"
#include "../jrd/pag_proto.h"
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
#include "../jrd/log2.h"
/*
Documentation on the REPLAY_OSRI_API_CALLS_SUBSYSTEM.
This is currently removed as
a) It is currently not used for any customers
b) it doesn't work in 4.0
c) Has a slight performance impact.
d) It needs work to cover the full range of 4.0 API calls
This is a valuable function to re-activate in the product, but
until it is I've #ifdef'ed it out under REPLAY_OSRI_API_CALLS_SUBSYSTEM.
I've also embedded the notes on how it works into log.cpp so they
can serve as a reference to a future completion of implementation.
Not reviewed, removal & documentation only
1996-Nov-07 David Schnepper
================= dialogue history ================
From ccaro@wpo.borland.com Thu Nov 7 10:23 PST 1996
I think we should keep REPLAY in the product..
I think it will be an invaluable tool for debugging complex
SuperServer interactions. While the CLASSIC architecture is well-tested,
multi-user interactions will only become more frenetic as the multi-user
server evolves to higher levels of SMP support.
------------ and ----------
From bkarwin@interbase.borland.com Thu Nov 7 13:19 PST 1996
I do not know of any customers sites who use REPLAY. It is likely that
only Motorola knows of its existance.
This is the first I've heard of this feature, at least that I recall.
I believe the rest of support also did not know of this feature. So it
may be safe to say that none of us use it. :-)
It sounds like a good feature. In fact, a customer asked recently if
there was a server-side feature akin to Delphi's "SQL Monitor" (which
logs all BDE and InterBase API calls), and we had to say no. Even if
we had known about the REPLAY feature, I think we would have said no,
since it is uncertified.
I think we should keep it in the product, and even do some development
on it, to eventually make it a supported feature that can be used
for diagnostics.
-Bill Karwin
-----------------------
Documentation on the REPLAY_OSRI_API_CALLS_SUBSYSTEM.
-----------
From deej@borland.com Thu Nov 7 09:48 PST 1996
I'll confess to having written the REPLAY feature.
I used to say that I wrote it to avoid going to Phoenix
in August, when Motorola was having a problem that we
could only reproduce by running their application.
For whatever reason it was impossible to get the
application inhouse.
But I really wrote it as a general purpose diagnostic tool
that would allow us to recreate customer problems without
sending an engineer to a customer site, and without the
necessity of figuring out a complex application.
Here's the way it works: the customer makes a copy of their
database to tape. They start REPLAY logging, then run their
application per usual. When the error occurs, they stop
logging. They send the original database and the REPLAY log
to us, and we re-run the log inhouse. It's like a tape recorder
which records all the API calls their application makes.
The feature worked beautifully in the Motorola case, and I
was able to reproduce two weeks' worth of the customer's
operations in an hour, enabling me to fix the bug within a
day when it might have taken several weeks at the customer
site.
Unfortunately, new API calls or parameters have been added
and the REPLAY feature has not been updated. At some point during
the 4.0 cycle I updated REPLAY to take care of the new calls
added to that point. But REPLAY has never been maintained
as a full-blown feature, meaning it was only tested on one platform,
and certainly never had full testing to certify that it works
for all API calls.
I think it is best if we leave this as a latent feature, which
can be dusted off if really needed in a future customer situation.
At that time we can generate a t-kit with the feature turned on,
so there is no need to maintain it as a fully supported feature.
To be sure, InterBase is a much more reliable database than it
was in 1990 and these types of situations occur less often.
And the cost of fully productizing this particular feature is
frightening.
At 04:58 PM 11/6/96 -0800, David Schnepper wrote:
>
>Does anyone still use the REPLAY facility?
>
>For those that don't know, InterBase had the ability to record all API calls
>in a log file, with the idea being to make an audit trail for debugging
>problems found in the field.
>
>There also was (apparently) the ability to replay the log to see if the
>trouble still reproduced.
>
>The reason I ask is I have found that REPLAY for Blobs (at least) doesn't
>function in 4.O - there is a private API call gds__map_blobs() which was
>used for the replay function that calls into the engine in an unsafe way.
>
>I would like to turn REPLAY off, by turning off the #ifdef in common.h - but
>would like to check on whether anyone in-house is using it - or if
>it is likely that any knowledgable customer is using it.
>
>Aside: we'll get a slight performance gain on each API call by turning
>it off as well.
>
>Dave
>
*/
static void error(const TEXT*);
static void log_char(SCHAR);
static void log_flush(void);
static void log_long(SLONG);
static void log_pointer(const SCHAR*);
static void log_short(SSHORT);
static void log_string(SSHORT, const SCHAR*);
static void log_teb(SSHORT, const TEB*);
static void open_log(const TEXT*, SSHORT, const SCHAR*);
void LOG_call(enum log_t call_type, ...)
{
/**************************************
*
* L O G _ c a l l
*
**************************************
*
* Functional description
* Log an OSRI call for later replay. This is intended
* for use as a debugging utility to ease fixing
* bugs in a production environment.
*
**************************************/
SSHORT number;
SLONG long_number;
const SCHAR *pointer;
const SLONG *long_pointer;
va_list ptr;
Database* dbb = GET_DBB();
if (!dbb || !dbb->dbb_log || !dbb->dbb_log->log_file)
return;
log_char((SCHAR) call_type);
va_start(ptr, call_type);
/* using the argument types described in the table,
pop the arguments off the call stack and put
them into the log file */
for (const char* arg_type = arg_types1[(int) call_type]; *arg_type; arg_type++)
{
switch (*arg_type) {
case 'o':
case 's':
number = va_arg(ptr, int);
log_short(number);
break;
case 'l':
long_number = va_arg(ptr, SLONG);
log_long(long_number);
break;
case 'p':
pointer = va_arg(ptr, SCHAR *);
log_pointer(pointer);
break;
case 'r':
pointer = va_arg(ptr, SCHAR *);
break;
case 'b':
pointer = va_arg(ptr, SCHAR *);
log_string(number, pointer);
break;
case 'f':
number = 0;
case 'n':
pointer = va_arg(ptr, SCHAR *);
if (!number)
number = strlen(pointer) + 1;
log_string(number, pointer);
break;
case 't':
pointer = va_arg(ptr, SCHAR *);
log_teb(number, pointer);
break;
case 'd':
long_pointer = va_arg(ptr, SLONG *);
log_long(long_pointer[0]);
log_long(long_pointer[1]);
break;
default:
error("argument type not known");
}
}
va_end(ptr);
log_flush();
}
void LOG_disable(void)
{
/**************************************
*
* L O G _ d i s a b l e
*
**************************************
*
* Functional description
* Disable logging.
*
**************************************/
Database* dbb = GET_DBB();
/* Get header page and look for logging entry */
PAG_delete_clump_entry(HEADER_PAGE, HDR_log_name);
/* Next, if logging was really enabled, close the file */
if (dbb->dbb_log && dbb->dbb_log->log_file)
LOG_fini();
}
void LOG_enable(const TEXT* log_file_name, USHORT l_length)
{
/**************************************
*
* L O G _ e n a b l e
*
**************************************
*
* Functional description
* Enable replay logging for the database.
*
**************************************/
Database* dbb = GET_DBB();
/* if we are already enabled for another file, get rid of it */
if (dbb->dbb_log)
LOG_disable();
/* Get database header page and add the log name */
PAG_add_clump(HEADER_PAGE, HDR_log_name, l_length, log_file_name,
CLUMP_ADD, 0);
/* open the log file for write to make sure that this
is the first entry in the file, and write the version number */
open_log(log_file_name, l_length, MODE_WRITE);
log_short(LOG_VERSION3);
LOG_fini();
/* now reopen for append to be a good citizen */
open_log(log_file_name, l_length, MODE_APPEND);
}
void LOG_fini(void)
{
/**************************************
*
* L O G _ f i n i
*
**************************************
*
* Functional description
* Close down the log file for replay logging.
*
**************************************/
Database* dbb = GET_DBB();
fblog* log;
if (dbb && (log = dbb->dbb_log)) {
if (log->log_file) {
log_flush();
fclose(log->log_file);
}
ALL_release(log->log_string);
ALL_release(log);
dbb->dbb_log = NULL;
}
}
void LOG_init(const TEXT* name, USHORT length)
{
/**************************************
*
* L O G _ i n i t
*
**************************************
*
* Functional description
* Initialize the REPLAY logging system.
* Check the database to see if logging
* is enabled. If so, open the file to
* append to.
*
**************************************/
TEXT file_name[MAXPATHLEN];
USHORT log_length = sizeof(file_name);
/* Get header page and look for logging entry */
if (!PAG_get_clump(HEADER_PAGE, HDR_log_name, &log_length, file_name))
return;
if (log_length >= sizeof(file_name))
log_length = sizeof(file_name) - 1; // We can't handle more for now.
file_name[log_length] = 0;
open_log(file_name, log_length, MODE_APPEND);
}
static void error(const TEXT* error_string)
{
/**************************************
*
* e r r o r
*
**************************************
*
* Functional description
* Report a failure of the logging system,
* both to the terminal and to the log.
*
**************************************/
Database* dbb = GET_DBB();
printf("ERROR in logging system: %s\n", error_string);
if (dbb->dbb_log && dbb->dbb_log->log_file) {
log_short(log_error);
const SSHORT length = strlen(error_string);
log_short(length);
}
}
static void log_char(SCHAR c)
{
/**************************************
*
* l o g _ c h a r
*
**************************************
*
* Functional description
* Log a character to the fill buffer
* for later flushing to the log.
*
**************************************/
Database* dbb = GET_DBB();
fblog* log = dbb->dbb_log;
*log->log_ptr++ = c;
/* this log flush could be done in the middle of an OSRI
call and hence could be non multiuser compatible -- it
is important that the log buffer be large enough that
this doesn't happen very often */
if ((log->log_ptr - log->log_buffer) >= (LOG_BUFFER_LENGTH - 1))
log_flush();
}
static void log_flush(void)
{
/**************************************
*
* l o g _ f l u s h
*
**************************************
*
* Functional description
* Flush the contents of the log buffer to
* the file and do a file flush while we're
* at it.
*
**************************************/
Database* dbb = GET_DBB();
fblog* log = dbb->dbb_log;
if (!(log->log_ptr - log->log_buffer))
return;
const UCHAR* buffer = log->log_buffer;
fwrite(buffer, sizeof(*buffer), log->log_ptr - log->log_buffer,
log->log_file);
log->log_ptr = log->log_buffer;
fflush(log->log_file);
}
static void log_long(SLONG number)
{
/**************************************
*
* l o g _ l o n g
*
**************************************
*
* Functional description
* Log a longword.
*
**************************************/
const SLONG vax_number = gds__vax_integer(&number, sizeof(number));
const char* p = (SCHAR *) & vax_number;
for (int i = 0; i < sizeof(number); i++)
log_char(*p++);
}
static void log_pointer(const SCHAR* pointer)
{
/**************************************
*
* l o g _ p o i n t e r
*
**************************************
*
* Functional description
* Log a pointer.
*
**************************************/
const char* p = (SCHAR *) & pointer;
for (int i = 0; i < sizeof(pointer); i++)
log_char(*p++);
}
static void log_short(SSHORT number)
{
/**************************************
*
* l o g _ s h o r t
*
**************************************
*
* Functional description
* Log a shortword.
*
**************************************/
const USHORT vax_number = (USHORT) gds__vax_integer(&number, sizeof(number));
const char* p = (SCHAR *) & vax_number;
for (int i = 0; i < sizeof(number); i++)
log_char(*p++);
}
static void log_string(SSHORT buffer_size, const SCHAR* buffer)
{
/**************************************
*
* l o g _ s t r i n g
*
**************************************
*
* Functional description
* Log a buffer of unknown content.
*
**************************************/
while (buffer_size--)
log_char(*buffer++);
}
static void log_teb(SSHORT count, const TEB* vector)
{
/**************************************
*
* l o g _ t e b
*
**************************************
*
* Functional description
* Log a transaction element block.
*
**************************************/
if (count < 0)
return;
for (TEB* const end = vector + count; vector < end; vector++) {
log_pointer(*vector->teb_database);
log_long((SLONG) vector->teb_tpb_length);
log_string(vector->teb_tpb_length, vector->teb_tpb);
}
}
static void open_log(const TEXT* file_name, SSHORT file_length,
const SCHAR* mode)
{
/**************************************
*
* o p e n _ l o g
*
**************************************
*
* Functional description
* Open the log file.
*
**************************************/
Database* dbb = GET_DBB();
if (dbb->dbb_log)
LOG_fini();
SCHAR buffer[MAXPATHLEN];
const SCHAR* log_name;
if (file_length)
log_name = file_name;
else {
gds__prefix(buffer, LOG_FILE_NAME);
log_name = buffer;
}
const int mask = umask(0111);
void* log_file = fopen(log_name, mode);
umask(mask);
if (!log_file)
error("can't open log file");
else {
fblog* log = FB_NEW(*dbb->dbb_permanent) fblog();
dbb->dbb_log = log;
log->log_file = log_file;
log->log_string = FB_NEW_RPT(*dbb->dbb_permanent, LOG_BUFFER_LENGTH) str();
log->log_ptr = log->log_buffer = log->log_string->str_data;
}
}
#endif // REPLAY_OSRI_API_CALLS_SUBSYSTEM

View File

@ -1,119 +0,0 @@
/*
* PROGRAM: REPLAY Debugging Utility
* MODULE: log.h
* DESCRIPTION: Definitions for logging OSRI calls
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#ifndef JRD_LOG_H
#define JRD_LOG_H
//const int LOG_VERSION1 = 1; // version to correspond with v2.5 access method
//const int LOG_VERSION2 = 2; // version to correspond with v3.0 access method
const int LOG_VERSION3 = 3; // version to correspond with v4.0 access method
/* the log buffer length should be long enough to fit
any OSRI call atomically to prevent multiuser bugs */
const int LOG_BUFFER_LENGTH = 1024;
/* replay log block */
class str;
class fblog : public pool_alloc<type_log>
{
public:
str* log_string; /* string block allocated to hold log buffer */
UCHAR* log_buffer; /* points to beginning of string data */
UCHAR* log_ptr; /* current end of buffer for logging */
void* log_file; /* db-specific file to write */
};
/* this table is the possible log file entries */
enum log_t {
log_attach = 0, /* V2 OSRI calls */
log_blob_info,
log_cancel_blob,
log_close_blob,
log_commit,
log_compile,
log_create_blob,
log_create_database,
log_database_info,
log_detach,
log_get_segment,
log_open_blob,
log_prepare,
log_put_segment,
log_receive,
log_reconnect,
log_release_request,
log_request_info,
log_rollback,
log_send,
log_start_and_send,
log_start,
log_start_multiple,
log_transaction_info,
log_unwind,
log_handle_returned, /* handle returned from a call */
log_statistics, /* stats for sanity checking */
log_error, /* error from logging system */
/* the following are V3 OSRI calls -- note that calls which
are even slightly changed are given a new number even if
the name of the call didn't change, such as attach. This
is to achieve upward compatibility of the log files. */
log_attach2,
log_cancel_events,
log_commit_retaining,
log_create_blob2,
log_create_database2,
log_get_slice,
log_open_blob2,
log_prepare2,
log_put_slice,
log_que_events,
log_blob_seek,
/* the following are the same as the above calls but they stop recording
buffers that are supposed to be returned by the access method */
log_get_segment2,
log_get_slice2,
log_receive2,
log_blob_info2,
log_database_info2,
log_request_info2,
log_transaction_info2,
log_ddl,
log_transact_request,
log_drop_database,
log_max
};
#endif // JRD_LOG_H

View File

@ -1,127 +0,0 @@
/*
* PROGRAM: REPLAY Debugging Utility
* MODULE: log2.h
* DESCRIPTION: Arguments for OSRI calls
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
* 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
*
*/
#ifndef JRD_LOG2_H
#define JRD_LOG2_H
/* This table will be used to pull off the argument types
for recording in the log. The status vector is assumed
as the first argument
Key to datatypes:
s = short by value
l = long by value
p = pointer
r = short by reference
b = buffer which has been preceded by a length of type s
n = possibly null-terminated buffer if preceding value is 0
f = definitely null-terminated buffer, no preceding length
d = double long, such as a blob id
t = transaction existence block
o = short which requires a buffer of the specified size to
be generated, to be filled in by the call
*/
static const SCHAR arg_types1[log_max][10] = {
"snpsbs", /* attach_database */
"psbsb", /* blob_info */
"p", /* cancel_blob */
"p", /* close_blob */
"p", /* commit */
"ppsb", /* compile */
"pppd", /* create_blob */
"snpsbs", /* create_database */
"psbsb", /* database_info */
"p", /* detach */
"prsb", /* get_segment */
"pppd", /* open_blob */
"p", /* prepare */
"psb", /* put_segment */
"pssbs", /* receive */
"ppsb", /* reconnect */
"p", /* release_request */
"pssbsb", /* request_info */
"p", /* rollback */
"pssbs", /* send */
"ppssbs", /* start_and_send */
"pps", /* start */
"pst", /* start_multiple */
"psbsb", /* transaction_info */
"ps", /* unwind */
"p", /* handle_returned */
"lll", /* statistics */
"", /* error */
"snpsbf", /* attach2 */
"pp", /* cancel_events */
"p", /* commit_retaining */
"pppdsb", /* create_blob2 */
"snpsbsf", /* create_database2 */
"pppsbsbsb", /* get_slice */
"pppdsb", /* open_blob2 */
"psb", /* prepare2 */
"pppsbsbsb", /* put_slice */
"psb", /* que_events */
"psl", /* blob_seek */
"pro", /* get_segment2 */
"pppsbsbo", /* get_slice2 */
"psos", /* receive2 */
"psbo", /* blob_info2 */
"psbo", /* database_info2 */
"pssbo", /* request_info2 */
"psbo", /* transaction_info2 */
"ppsb", /* ddl */
"ppsbsbs", /* transact_request */
"p" /* drop_database */
};
/* this is the replay log filename definition */
#ifdef WIN_NT
static const char* LOG_FILE_NAME = "replay.log";
#else
static const char* LOG_FILE_NAME = FB_PREFIX "/replay.log";
#endif
/* these are the modes for opening the log file */
#if (defined WIN_NT)
static const char* MODE_READ = "rb";
static const char* MODE_WRITE = "wb";
static const char* MODE_APPEND = "ab";
#else
static const char* MODE_READ = "r";
static const char* MODE_WRITE = "w";
static const char* MODE_APPEND = "a";
#endif
#endif // JRD_LOG2_H

View File

@ -1,37 +0,0 @@
/*
* PROGRAM: JRD Access method
* MODULE: log_proto.h
* DESCRIPTION: Prototype Header file for log.cpp
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#ifndef JRD_LOG_PROTO_H
#define JRD_LOG_PROTO_H
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
void LOG_call(enum log_t, ...);
void LOG_disable(void);
void LOG_enable(const TEXT*, USHORT);
void LOG_fini(void);
void LOG_init(const TEXT*, USHORT);
#endif /* REPLAY_OSRI_API_CALLS_SUBSYSTEM */
#endif // JRD_LOG_PROTO_H

View File

@ -55,9 +55,6 @@
#include "../jrd/event.h"
#include "../jrd/gds_proto.h"
#include "../jrd/utl_proto.h"
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
#include "../jrd/blb_proto.h"
#endif
#include "../jrd/constants.h"
#include "../common/classes/ClumpletWriter.h"
#include "../common/utils_proto.h"
@ -902,36 +899,6 @@ int API_ROUTINE isc_get_client_minor_version()
}
void API_ROUTINE gds__map_blobs(int* handle1, int* handle2)
{
/**************************************
*
* g d s _ $ m a p _ b l o b s
*
**************************************
*
* Functional description
* Map an old blob to a new blob.
* This call is intended for use by REPLAY,
* and is probably not generally useful
* for anyone else.
*
**************************************/
#ifdef REPLAY_OSRI_API_CALLS_SUBSYSTEM
#ifndef SUPERCLIENT
/* Note: gds__map_blobs is almost like an API call,
it needs a thread_db structure setup for it in order
to function properly. This currently does
not function.
1996-Nov-06 David Schnepper */
deliberate_compile_error++;
BLB_map_blobs(NULL, handle1, handle2);
#endif
#endif
}
void API_ROUTINE isc_set_debug(int value)
{
/**************************************

View File

@ -944,7 +944,6 @@ namespace
#define GDS_DETACH isc_detach_database
#define GDS_DROP_DATABASE isc_drop_database
//#define GDS_EVENT_WAIT gds__event_wait
#define GDS_INTERNAL_COMPILE gds__internal_compile_request
#define GDS_GET_SEGMENT isc_get_segment
#define GDS_GET_SLICE isc_get_slice
#define GDS_OPEN_BLOB isc_open_blob
@ -1072,11 +1071,10 @@ const int PROC_SERVICE_START = 51;
const int PROC_ROLLBACK_RETAINING = 52;
const int PROC_CANCEL_OPERATION = 53;
const int PROC_INTERNAL_COMPILE = 54; // internal call
const int PROC_SHUTDOWN = 55;
const int PROC_SHUTDOWN = 54;
const int PROC_count = 56;
const int PROC_count = 55;
/* Define complicated table for multi-subsystem world */
@ -3684,51 +3682,6 @@ ISC_STATUS API_ROUTINE isc_wait_for_event(ISC_STATUS * user_status,
}
ISC_STATUS API_ROUTINE GDS_INTERNAL_COMPILE(ISC_STATUS* user_status,
FB_API_HANDLE* db_handle,
FB_API_HANDLE* req_handle,
USHORT blr_length,
const SCHAR* blr,
USHORT string_length,
const char* string,
USHORT dbginfo_length,
const UCHAR* dbginfo)
{
YEntry status(user_status);
Attachment* dbb = NULL;
StoredReq* rq = NULL;
try
{
dbb = translate<Attachment>(db_handle);
status.setPrimaryHandle(dbb);
nullCheck(req_handle, isc_bad_req_handle);
if (CALL(PROC_INTERNAL_COMPILE, dbb->implementation) (status, &dbb->handle,
&rq, blr_length,
blr,
string_length, string,
dbginfo_length, dbginfo))
{
return status[1];
}
new Request(rq, req_handle, dbb);
}
catch (const Firebird::Exception& e)
{
*req_handle = 0;
if (dbb && rq)
{
CALL(PROC_RELEASE_REQUEST, dbb->implementation) (status, rq);
}
e.stuff_exception(status);
}
return status[1];
}
ISC_STATUS API_ROUTINE GDS_GET_SEGMENT(ISC_STATUS * user_status,
FB_API_HANDLE * blob_handle,
USHORT * length,

View File

@ -269,10 +269,6 @@ ISC_STATUS API_ROUTINE isc_database_cleanup(ISC_STATUS*, FB_API_HANDLE*,
int API_ROUTINE gds__disable_subsystem(TEXT*);
int API_ROUTINE gds__enable_subsystem(TEXT*);
ISC_STATUS API_ROUTINE gds__internal_compile_request(
ISC_STATUS*, FB_API_HANDLE*, FB_API_HANDLE*, USHORT,
const SCHAR*, USHORT, const char*, USHORT, const UCHAR*);
ISC_STATUS API_ROUTINE gds__transaction_cleanup(ISC_STATUS*, FB_API_HANDLE*,
TransactionCleanupRoutine*, void*);
void WHY_cleanup_transaction(struct why_hndl* transaction);