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

Merge B1_5_Remote_LazyPort branch into HEAD

This commit is contained in:
hvlad 2006-05-01 22:23:31 +00:00
parent b196cac010
commit f94b8bd641
14 changed files with 836 additions and 194 deletions

View File

@ -1581,6 +1581,14 @@ ISC_STATUS GDS_DSQL_SQL_INFO_CPP( ISC_STATUS* user_status,
const UCHAR* const end_items = items + item_length;
const UCHAR* const end_info = info + info_length;
UCHAR *start_info;
if (*items == isc_info_length) {
start_info = info;
items++;
}
else {
start_info = 0;
}
// CVC: Is it the idea that this pointer remains with its previous value
// in the loop or should it be made NULL in each iteration?
@ -1760,6 +1768,14 @@ ISC_STATUS GDS_DSQL_SQL_INFO_CPP( ISC_STATUS* user_status,
}
*info++ = isc_info_end;
if (start_info && (end_info - info >= 7))
{
SLONG number = info - start_info;
memmove(start_info + 7, start_info, number);
USHORT length = convert(number, buffer);
put_item(isc_info_length, length, buffer, start_info, end_info);
}
}
catch(const std::exception& ex)
{
@ -3649,6 +3665,7 @@ static USHORT get_plan_info(
SCHAR* plan;
for (int i = 0; i < 2; i++) {
const SCHAR* explain = explain_ptr;
if (*explain++ != isc_info_access_path)
{
// CVC: deallocate memory!

View File

@ -61,6 +61,9 @@ struct sqlda_sup
USHORT dasup_blr_length;
USHORT dasup_blr_buf_len;
USHORT dasup_msg_buf_len;
SCHAR* dasup_info_buf;
USHORT dasup_info_len;
} dasup_clauses[2];
USHORT dasup_dialect; // Dialect associated with statement

View File

@ -77,6 +77,67 @@ static TEXT *DSQL_failures, *DSQL_failures_ptr;
const int DSQL_FAILURE_SPACE = 2048;
/**
Parse response on isc_info_sql_select or isc_info_sql_bind
request. Return pointer to the next byte after successfully
parsed info or NULL if error is encountered or info is truncated
**/
SCHAR* UTLD_skip_sql_info(SCHAR* info)
{
if (*info != isc_info_sql_select &&
*info != isc_info_sql_bind)
return 0;
info++;
if (*info++ != isc_info_sql_describe_vars)
return 0;
get_numeric_info((const SCHAR**) &info);
// Loop over the variables being described
while (true)
{
SCHAR str[256]; // must be big enough to hold metadata name
SCHAR item = *info++;
switch (item)
{
case isc_info_end:
return info;
case isc_info_truncated:
return 0;
case isc_info_sql_select:
case isc_info_sql_bind:
return --info;
case isc_info_sql_describe_end:
break;
case isc_info_sql_sqlda_seq:
case isc_info_sql_type:
case isc_info_sql_sub_type:
case isc_info_sql_scale:
case isc_info_sql_length:
get_numeric_info((const SCHAR**) &info);
break;
case isc_info_sql_field:
case isc_info_sql_relation:
case isc_info_sql_owner:
case isc_info_sql_alias:
get_string_info((const SCHAR**) &info, str, sizeof(str));
break;
default:
return 0;
}
}
return 0;
}
/**

View File

@ -35,6 +35,7 @@ ISC_STATUS UTLD_parse_sql_info(ISC_STATUS*, USHORT, const SCHAR*, XSQLDA*, USHOR
ISC_STATUS UTLD_parse_sqlda(ISC_STATUS*, sqlda_sup* const, USHORT*, USHORT*,
USHORT*, USHORT, XSQLDA*, const USHORT);
void UTLD_save_status_strings(ISC_STATUS*);
SCHAR* UTLD_skip_sql_info(SCHAR*);
#endif // DSQL_UTLD_PROTO_H

View File

@ -106,6 +106,15 @@ int INF_blob_info(const blb* blob,
const SCHAR* const end_items = items + item_length;
const SCHAR* const end = info + output_length;
SCHAR* start_info;
if (*items == isc_info_length) {
start_info = info;
items++;
}
else {
start_info = 0;
}
while (items < end_items && *items != isc_info_end) {
SCHAR item = *items++;
@ -142,6 +151,14 @@ int INF_blob_info(const blb* blob,
*info++ = isc_info_end;
if (start_info && (end - info >= 7))
{
SLONG number = info - start_info;
memmove(start_info + 7, start_info, number);
USHORT length = INF_convert(number, buffer);
INF_put_item(isc_info_length, length, buffer, start_info, end);
}
return TRUE;
}
@ -838,6 +855,16 @@ int INF_request_info(const jrd_req* request,
const SCHAR* const end_items = items + item_length;
const SCHAR* const end = info + output_length;
SCHAR* start_info;
if (*items == isc_info_length) {
start_info = info;
items++;
}
else {
start_info = 0;
}
SCHAR buffer[256];
memset(buffer, 0, sizeof(buffer));
SCHAR* buffer_ptr = buffer;
@ -962,6 +989,14 @@ int INF_request_info(const jrd_req* request,
*info++ = isc_info_end;
if (start_info && (end - info >= 7))
{
SLONG number = info - start_info;
memmove(start_info + 7, start_info, number);
USHORT length = INF_convert(number, buffer);
INF_put_item(isc_info_length, length, buffer, start_info, end);
}
return TRUE;
}
@ -986,6 +1021,15 @@ int INF_transaction_info(const jrd_tra* transaction,
const SCHAR* const end_items = items + item_length;
const SCHAR* const end = info + output_length;
SCHAR* start_info;
if (*items == isc_info_length) {
start_info = info;
items++;
}
else {
start_info = 0;
}
while (items < end_items && *items != isc_info_end) {
SCHAR item = *items++;
@ -1059,6 +1103,14 @@ int INF_transaction_info(const jrd_tra* transaction,
*info++ = isc_info_end;
if (start_info && (end - info >= 7))
{
SLONG number = info - start_info;
memmove(start_info + 7, start_info, number);
USHORT length = INF_convert(number, buffer);
INF_put_item(isc_info_length, length, buffer, start_info, end);
}
return TRUE;
}

View File

@ -33,7 +33,8 @@
#define isc_info_truncated 2
#define isc_info_error 3
#define isc_info_data_not_ready 4
#define isc_info_flag_end 127
#define isc_info_length 126
#define isc_info_flag_end 127
/******************************/
/* Database information items */

View File

@ -829,9 +829,19 @@ ISC_STATUS SVC_query2(Service* service,
/* Process the receive portion of the query now. */
const SCHAR* const end = info + buffer_length;
items = recv_items;
const SCHAR* const end_items2 = items + recv_item_length;
SCHAR* start_info;
if (*items == isc_info_length) {
start_info = info;
items++;
}
else {
start_info = 0;
}
while (items < end_items2 && *items != isc_info_end)
{
/*
@ -1209,6 +1219,13 @@ ISC_STATUS SVC_query2(Service* service,
if (info < end)
*info = isc_info_end;
if (start_info && (end - info >= 7))
{
SLONG number = 1 + (info - start_info);
memmove(start_info + 7, start_info, number);
USHORT length = INF_convert(number, buffer);
INF_put_item(isc_info_length, length, buffer, start_info, end);
}
if (!(service->svc_flags & SVC_thd_running))
{

View File

@ -43,6 +43,7 @@
*/
#include "firebird.h"
#include "memory_routines.h" // needed for get_long
#include <stdlib.h>
#include <string.h>
@ -696,6 +697,39 @@ static const SCHAR describe_bind_info[] =
isc_info_sql_describe_end
};
static const SCHAR sql_prepare_info2[] =
{
isc_info_sql_stmt_type,
// describe_select_info
isc_info_sql_select,
isc_info_sql_describe_vars,
isc_info_sql_sqlda_seq,
isc_info_sql_type,
isc_info_sql_sub_type,
isc_info_sql_scale,
isc_info_sql_length,
isc_info_sql_field,
isc_info_sql_relation,
isc_info_sql_owner,
isc_info_sql_alias,
isc_info_sql_describe_end,
// describe_bind_info
isc_info_sql_bind,
isc_info_sql_describe_vars,
isc_info_sql_sqlda_seq,
isc_info_sql_type,
isc_info_sql_sub_type,
isc_info_sql_scale,
isc_info_sql_length,
isc_info_sql_field,
isc_info_sql_relation,
isc_info_sql_owner,
isc_info_sql_alias,
isc_info_sql_describe_end
};
ISC_STATUS API_ROUTINE GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
SSHORT file_length,
@ -830,13 +864,28 @@ ISC_STATUS API_ROUTINE GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
if (database)
{
database->db_path = (TEXT*) alloc((SLONG) (length + 1));
if (database->db_path)
{
database->db_prepare_buffer =
(SCHAR*) alloc((SLONG) DBB_PREPARE_BUFFER_SIZE);
}
}
if (!database || !database->db_path)
if (!database || !database->db_path || !database->db_prepare_buffer)
{
/* No memory. Make a half-hearted to detach and get out. */
if (database)
release_handle(database);
{
if (database->db_path) {
free_block(database->db_path);
database->db_path = 0;
}
if (database->db_prepare_buffer) {
free_block(database->db_prepare_buffer);
database->db_prepare_buffer = 0;
}
release_handle(database);
}
CALL(PROC_DETACH, n) (ptr, handle);
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
@ -1454,15 +1503,30 @@ ISC_STATUS API_ROUTINE GDS_CREATE_DATABASE(ISC_STATUS* user_status,
if (database)
{
database->db_path = (TEXT *) alloc((SLONG) (length + 1));
if (database->db_path)
{
database->db_prepare_buffer =
(SCHAR*) alloc((SLONG) DBB_PREPARE_BUFFER_SIZE);
}
}
if (!database || !database->db_path)
if (!database || !database->db_path || !database->db_prepare_buffer)
{
/* No memory. Make a half-hearted to drop database. The
database was successfully created but the user wouldn't
be able to tell. */
if (database)
release_handle(database);
{
if (database->db_path) {
free_block(database->db_path);
database->db_path = 0;
}
if (database->db_prepare_buffer) {
free_block(database->db_prepare_buffer);
database->db_prepare_buffer = 0;
}
release_handle(database);
}
CALL(PROC_DROP_DATABASE, n) (ptr, handle);
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
@ -1472,6 +1536,7 @@ ISC_STATUS API_ROUTINE GDS_CREATE_DATABASE(ISC_STATUS* user_status,
fb_assert(database);
fb_assert(database->db_path);
fb_assert(database->db_prepare_buffer);
*public_handle = database->public_handle;
TEXT* p = database->db_path;
@ -1716,8 +1781,14 @@ ISC_STATUS API_ROUTINE GDS_DETACH(ISC_STATUS * user_status,
/* Release associated request handles */
if (dbb->db_path)
if (dbb->db_path) {
free_block(dbb->db_path);
dbb->db_path = 0;
}
if (dbb->db_prepare_buffer) {
free_block(dbb->db_prepare_buffer);
dbb->db_prepare_buffer = 0;
}
while (request = dbb->requests) {
dbb->requests = request->next;
@ -1846,8 +1917,14 @@ ISC_STATUS API_ROUTINE GDS_DROP_DATABASE(ISC_STATUS * user_status,
/* Release associated request handles */
if (dbb->db_path)
free_block(dbb->db_path);
if (dbb->db_path) {
free_block(dbb->db_path);
dbb->db_path = 0;
}
if (dbb->db_prepare_buffer) {
free_block(dbb->db_prepare_buffer);
dbb->db_prepare_buffer = 0;
}
while (request = dbb->requests) {
dbb->requests = request->next;
@ -2050,37 +2127,56 @@ ISC_STATUS API_ROUTINE isc_dsql_describe(ISC_STATUS * user_status,
ISC_STATUS_ARRAY local;
USHORT buffer_len;
SCHAR *buffer, local_buffer[512];
WHY_STMT statement;
GET_STATUS;
TRANSLATE_HANDLE(*stmt_handle, statement, HANDLE_statement, isc_bad_stmt_handle);
if (!(buffer = get_sqlda_buffer(local_buffer, sizeof(local_buffer), sqlda,
dialect, &buffer_len)))
{
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
status[2] = isc_arg_end;
return error2(status, local);
}
sqlda_sup::dasup_clause &clause =
statement->das->dasup_clauses[DASUP_CLAUSE_select];
if (!GDS_DSQL_SQL_INFO( status,
stmt_handle,
sizeof(describe_select_info),
describe_select_info,
buffer_len,
buffer))
if (clause.dasup_info_len && clause.dasup_info_buf)
{
iterative_sql_info( status,
stmt_handle,
sizeof(describe_select_info),
describe_select_info,
buffer_len,
buffer,
clause.dasup_info_len,
clause.dasup_info_buf,
dialect,
sqlda);
}
else
{
if (!(buffer = get_sqlda_buffer(local_buffer, sizeof(local_buffer), sqlda,
dialect, &buffer_len)))
{
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
status[2] = isc_arg_end;
return error2(status, local);
}
if (buffer != local_buffer) {
free_block(buffer);
if (!GDS_DSQL_SQL_INFO( status,
stmt_handle,
sizeof(describe_select_info),
describe_select_info,
buffer_len,
buffer))
{
iterative_sql_info( status,
stmt_handle,
sizeof(describe_select_info),
describe_select_info,
buffer_len,
buffer,
dialect,
sqlda);
}
if (buffer != local_buffer) {
free_block(buffer);
}
}
if (status[1]) {
@ -2111,37 +2207,56 @@ ISC_STATUS API_ROUTINE isc_dsql_describe_bind(ISC_STATUS * user_status,
ISC_STATUS_ARRAY local;
USHORT buffer_len;
SCHAR *buffer, local_buffer[512];
WHY_STMT statement;
GET_STATUS;
TRANSLATE_HANDLE(*stmt_handle, statement, HANDLE_statement, isc_bad_stmt_handle);
if (!(buffer = get_sqlda_buffer(local_buffer, sizeof(local_buffer), sqlda,
dialect, &buffer_len)))
{
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
status[2] = isc_arg_end;
return error2(status, local);
}
sqlda_sup::dasup_clause &clause =
statement->das->dasup_clauses[DASUP_CLAUSE_bind];
if (!GDS_DSQL_SQL_INFO( status,
stmt_handle,
sizeof(describe_bind_info),
describe_bind_info,
buffer_len,
buffer))
if (clause.dasup_info_len && clause.dasup_info_buf)
{
iterative_sql_info( status,
stmt_handle,
sizeof(describe_bind_info),
describe_bind_info,
buffer_len,
buffer,
sizeof(describe_select_info),
describe_select_info,
clause.dasup_info_len,
clause.dasup_info_buf,
dialect,
sqlda);
}
else
{
if (!(buffer = get_sqlda_buffer(local_buffer, sizeof(local_buffer), sqlda,
dialect, &buffer_len)))
{
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
status[2] = isc_arg_end;
return error2(status, local);
}
if (buffer != local_buffer) {
free_block(buffer);
if (!GDS_DSQL_SQL_INFO( status,
stmt_handle,
sizeof(describe_bind_info),
describe_bind_info,
buffer_len,
buffer))
{
iterative_sql_info( status,
stmt_handle,
sizeof(describe_bind_info),
describe_bind_info,
buffer_len,
buffer,
dialect,
sqlda);
}
if (buffer != local_buffer) {
free_block(buffer);
}
}
if (status[1]) {
@ -3242,13 +3357,19 @@ ISC_STATUS API_ROUTINE GDS_DSQL_PREPARE(ISC_STATUS* user_status,
ISC_STATUS *status;
ISC_STATUS_ARRAY local;
USHORT buffer_len;
SCHAR *buffer, local_buffer[BUFFER_MEDIUM];
SCHAR *buffer, *local_buffer;
sqlda_sup* dasup;
GET_STATUS;
if (!(buffer = get_sqlda_buffer(local_buffer, sizeof(local_buffer), sqlda,
dialect, &buffer_len)))
WHY_STMT statement;
TRANSLATE_HANDLE(*stmt_handle, statement, HANDLE_statement, isc_bad_stmt_handle);
WHY_DBB database = statement->parent;
local_buffer = database->db_prepare_buffer;
if (!(buffer = get_sqlda_buffer(local_buffer, DBB_PREPARE_BUFFER_SIZE,
sqlda, dialect, &buffer_len)))
{
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
@ -3262,27 +3383,93 @@ ISC_STATUS API_ROUTINE GDS_DSQL_PREPARE(ISC_STATUS* user_status,
length,
string,
dialect,
sizeof(sql_prepare_info),
sql_prepare_info,
sizeof(sql_prepare_info2),
sql_prepare_info2,
buffer_len,
buffer))
{
WHY_STMT statement = WHY_translate_handle(*stmt_handle);
// WHY_STMT statement = WHY_translate_handle(*stmt_handle);
release_dsql_support(statement->das);
if (!(dasup = (sqlda_sup*) alloc((SLONG) sizeof(sqlda_sup)))) {
if (!(dasup = (sqlda_sup*) alloc((SLONG) sizeof(sqlda_sup))))
{
statement->requests = 0;
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
status[2] = isc_arg_end;
}
else {
else
{
statement->das = dasup;
dasup->dasup_dialect = dialect;
SCHAR* p = buffer;
dasup->dasup_stmt_type = 0;
if (*p == isc_info_sql_stmt_type)
{
const USHORT len = gds__vax_integer((UCHAR*)p + 1, 2);
dasup->dasup_stmt_type = gds__vax_integer((UCHAR*)p + 3, len);
p += 3 + len;
}
sqlda_sup::dasup_clause &das_select = dasup->dasup_clauses[DASUP_CLAUSE_select];
sqlda_sup::dasup_clause &das_bind = dasup->dasup_clauses[DASUP_CLAUSE_bind];
das_select.dasup_info_buf = das_bind.dasup_info_buf = 0;
das_select.dasup_info_len = das_bind.dasup_info_len = 0;
if (*p == isc_info_sql_select)
das_select.dasup_info_buf = p;
das_bind.dasup_info_buf = UTLD_skip_sql_info(p);
p = das_select.dasup_info_buf;
if (p)
{
SCHAR* p2 = das_bind.dasup_info_buf;
if (p2)
{
const SLONG len = p2 - p;
p2 = alloc(len + 1);
memmove(p2, p, len);
p2[len] = isc_info_end;
das_select.dasup_info_buf = p2;
das_select.dasup_info_len = len + 1;
}
else
{
das_select.dasup_info_buf = 0;
das_select.dasup_info_len = 0;
}
}
p = das_bind.dasup_info_buf;
if (p)
{
SCHAR* p2 = UTLD_skip_sql_info(p);
if (p2)
{
const SLONG len = p2 - p;
p2 = alloc(len + 1);
memmove(p2, p, len);
p2[len] = isc_info_end;
das_bind.dasup_info_buf = p2;
das_bind.dasup_info_len = len + 1;
}
else
{
das_bind.dasup_info_buf = 0;
das_bind.dasup_info_len = 0;
}
}
iterative_sql_info(status, stmt_handle, sizeof(sql_prepare_info),
sql_prepare_info, buffer_len, buffer, dialect,
sqlda);
sql_prepare_info, // buffer_len, buffer, dialect,
das_select.dasup_info_len,
das_select.dasup_info_buf,
dialect, sqlda);
}
}
@ -3441,14 +3628,28 @@ ISC_STATUS API_ROUTINE GDS_DSQL_SQL_INFO(ISC_STATUS* user_status,
buffer_length, buffer);
else
#endif
CALL(PROC_DSQL_SQL_INFO, statement->implementation) (status,
{
if (( (item_length == 1) && (items[0] == isc_info_sql_stmt_type) ||
(item_length == 2) && (items[0] == isc_info_sql_stmt_type) &&
(items[1] == isc_info_end || items[1] == 0) ) &&
statement->das && statement->das->dasup_stmt_type)
{
*buffer++ = isc_info_sql_stmt_type;
put_short((UCHAR*) buffer, 4);
buffer += 2;
put_long((UCHAR*) buffer, statement->das->dasup_stmt_type);
}
else
{
CALL(PROC_DSQL_SQL_INFO, statement->implementation) (status,
&statement->
handle,
item_length,
items,
buffer_length,
buffer);
}
}
subsystem_exit();
if (status[1])
@ -5529,6 +5730,9 @@ static SCHAR *get_sqlda_buffer(SCHAR * buffer,
n_variables = ((SQLDA *) sqlda)->sqln;
length = 32 + n_variables * 172;
if (length < local_buffer_length)
length = local_buffer_length;
*buffer_length = (USHORT)((length > 65500L) ? 65500L : length);
if (*buffer_length > local_buffer_length)
buffer = alloc((SLONG) * buffer_length);
@ -5844,13 +6048,17 @@ static void release_dsql_support(sqlda_sup* dasup)
return;
}
/* for C++, add "dasup::" before "dasup_clause" */
/* for C++, add "sqlda_sup::" before "dasup_clause" */
sqlda_sup::dasup_clause* pClauses = dasup->dasup_clauses;
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_bind].dasup_blr);
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_select].dasup_blr);
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_bind].dasup_msg);
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_select].dasup_msg);
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_bind].dasup_info_buf);
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_select].dasup_info_buf);
free_block(dasup);
}

View File

@ -63,6 +63,7 @@ struct why_hndl
FB_API_HANDLE* user_handle;
struct clean* cleanup;
TEXT* db_path;
SCHAR* db_prepare_buffer;
};
typedef why_hndl *WHY_HNDL;
@ -86,4 +87,6 @@ const int HANDLE_TRANSACTION_limbo = 1;
const int HANDLE_BLOB_filter = 2; /* Blob is locally filtered */
const int HANDLE_STATEMENT_local = 4; /* Process DSQL statement locally */
const SLONG DBB_PREPARE_BUFFER_SIZE = 32768; // size of buffer used in isc_dsql_prepare call
#endif // JRD_Y_HANDLE_H

View File

@ -355,7 +355,7 @@ static XDR::xdr_ops inet_ops =
{
inet_getlong,
inet_putlong,
#ifdef SUPERSERVER
#if defined(SUPERSERVER) && !defined(EMBEDDED)
REMOTE_getbytes,
#else
inet_getbytes,
@ -510,7 +510,8 @@ rem_port* INET_analyze(Firebird::PathName& file_name,
static const p_cnct::p_cnct_repeat protocols_to_try1[] =
{
REMOTE_PROTOCOL(PROTOCOL_VERSION8, ptype_rpc, MAX_PTYPE, 1),
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, MAX_PTYPE, 2)
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, MAX_PTYPE, 2),
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, ptype_lazy_send, 3)
#ifdef SCROLLABLE_CURSORS
,
REMOTE_PROTOCOL(PROTOCOL_SCROLLABLE_CURSORS, ptype_rpc, MAX_PTYPE, 3)
@ -618,6 +619,10 @@ rem_port* INET_analyze(Firebird::PathName& file_name,
port->port_flags |= PORT_no_oob;
}
if (packet->p_acpt.p_acpt_type == ptype_lazy_send) {
port->port_flags |= PORT_lazy;
}
return port;
}

View File

@ -185,9 +185,7 @@ static ISC_STATUS send_and_receive(RDB, PACKET *, ISC_STATUS *);
static ISC_STATUS send_blob(ISC_STATUS*, RBL, USHORT, const UCHAR*);
static void send_cancel_event(RVNT);
static bool send_packet(rem_port*, PACKET *, ISC_STATUS *);
#ifdef NOT_USED_OR_REPLACED
static bool send_partial_packet(rem_port*, PACKET *, ISC_STATUS *);
#endif
#ifdef MULTI_THREAD
static void server_death(rem_port*);
#endif
@ -206,6 +204,16 @@ static ULONG remote_event_id = 0;
#define SET_OBJECT(rdb, object, id) REMOTE_set_object (rdb->rdb_port, (struct blk *) object, id)
inline bool defer_packet(rem_port* port, const PACKET* packet, ISC_STATUS* status)
{
rem_que_packet p;
p.packet = *packet;
p.sent = false;
port->port_defered_packets->add(p);
return clear_queue(port, status);
}
#define GDS_ATTACH_DATABASE REM_attach_database
#define GDS_BLOB_INFO REM_blob_info
#define GDS_CANCEL_BLOB REM_cancel_blob
@ -1225,26 +1233,35 @@ ISC_STATUS GDS_DSQL_ALLOCATE(ISC_STATUS* user_status,
if (rdb->rdb_port->port_protocol < PROTOCOL_VERSION7)
return unsupported(user_status);
PACKET* packet = &rdb->rdb_packet;
packet->p_operation = op_allocate_statement;
packet->p_rlse.p_rlse_object = rdb->rdb_id;
RSR statement;
if (rdb->rdb_port->port_flags & PORT_lazy) {
*stmt_handle = statement = (RSR) ALLR_block(type_rsr, 0);
statement->rsr_rdb = rdb;
statement->rsr_id = INVALID_OBJECT;
statement->rsr_flags |= RSR_lazy;
}
else {
PACKET* packet = &rdb->rdb_packet;
packet->p_operation = op_allocate_statement;
packet->p_rlse.p_rlse_object = rdb->rdb_id;
if (send_and_receive(rdb, packet, user_status))
return error(user_status);
if (send_and_receive(rdb, packet, user_status))
return error(user_status);
/* Allocate SQL request block */
/* Allocate SQL request block */
statement = (RSR) ALLR_block(type_rsr, 0);
*stmt_handle = statement;
statement->rsr_rdb = rdb;
statement->rsr_id = packet->p_resp.p_resp_object;
/* register the object */
SET_OBJECT(rdb, statement, statement->rsr_id);
}
RSR statement = (RSR) ALLR_block(type_rsr, 0);
*stmt_handle = statement;
statement->rsr_rdb = rdb;
statement->rsr_id = packet->p_resp.p_resp_object;
statement->rsr_next = rdb->rdb_sql_requests;
rdb->rdb_sql_requests = statement;
/* register the object */
SET_OBJECT(rdb, statement, statement->rsr_id);
}
catch (const std::exception& ex)
{
@ -1988,14 +2005,45 @@ ISC_STATUS GDS_DSQL_FREE(ISC_STATUS * user_status, RSR * stmt_handle, USHORT opt
return unsupported(user_status);
}
if (statement->rsr_flags & RSR_lazy) {
if (option == DSQL_drop) {
release_sql_request(statement);
*stmt_handle = NULL;
}
else {
statement->rsr_flags &= ~RSR_fetched;
statement->rsr_rtr = NULL;
if (!clear_queue(rdb->rdb_port, user_status))
return error(user_status);
REMOTE_reset_statement(statement);
}
return return_success(rdb);
}
PACKET* packet = &rdb->rdb_packet;
packet->p_operation = op_free_statement;
P_SQLFREE* free_stmt = &packet->p_sqlfree;
free_stmt->p_sqlfree_statement = statement->rsr_id;
free_stmt->p_sqlfree_option = option;
if (send_and_receive(rdb, packet, user_status)) {
return error(user_status);
if (rdb->rdb_port->port_flags & PORT_lazy) {
if (!defer_packet(rdb->rdb_port, packet, user_status))
return error(user_status);
if (option == DSQL_drop) {
packet->p_resp.p_resp_object = INVALID_OBJECT;
}
else {
packet->p_resp.p_resp_object = statement->rsr_id;
}
}
else {
if (send_and_receive(rdb, packet, user_status)) {
return error(user_status);
}
}
statement->rsr_handle = (FB_API_HANDLE) (IPTR) packet->p_resp.p_resp_object;
@ -2096,6 +2144,15 @@ ISC_STATUS GDS_DSQL_INSERT(ISC_STATUS * user_status,
/* set up the packet for the other guy... */
PACKET* packet = &rdb->rdb_packet;
if (statement->rsr_flags & RSR_lazy) {
packet->p_operation = op_allocate_statement;
packet->p_rlse.p_rlse_object = rdb->rdb_id;
if (!send_partial_packet(rdb->rdb_port, packet, user_status))
return error(user_status);
}
packet->p_operation = op_insert;
P_SQLDATA* sqldata = &packet->p_sqldata;
sqldata->p_sqldata_statement = statement->rsr_id;
@ -2110,6 +2167,16 @@ ISC_STATUS GDS_DSQL_INSERT(ISC_STATUS * user_status,
message->msg_address = NULL;
if (statement->rsr_flags & RSR_lazy) {
if (!receive_response(rdb, packet))
return error(user_status);
statement->rsr_id = packet->p_resp.p_resp_object;
SET_OBJECT(rdb, statement, statement->rsr_id);
statement->rsr_flags &= ~RSR_lazy;
}
if (!receive_response(rdb, packet)) {
return error(user_status);
}
@ -2185,6 +2252,15 @@ ISC_STATUS GDS_DSQL_PREPARE(ISC_STATUS * user_status, RTR * rtr_handle, RSR * st
/* set up the packet for the other guy... */
PACKET* packet = &rdb->rdb_packet;
if (statement->rsr_flags & RSR_lazy) {
packet->p_operation = op_allocate_statement;
packet->p_rlse.p_rlse_object = rdb->rdb_id;
if (!send_partial_packet(rdb->rdb_port, packet, user_status))
return error(user_status);
}
packet->p_operation = op_prepare_statement;
P_SQLST* prepare = &packet->p_sqlst;
prepare->p_sqlst_transaction = (transaction) ? transaction->rtr_id : 0;
@ -2204,6 +2280,16 @@ ISC_STATUS GDS_DSQL_PREPARE(ISC_STATUS * user_status, RTR * rtr_handle, RSR * st
/* Set up for the response packet. */
if (statement->rsr_flags & RSR_lazy) {
if (!receive_response(rdb, packet))
return error(user_status);
statement->rsr_id = packet->p_resp.p_resp_object;
SET_OBJECT(rdb, statement, statement->rsr_id);
statement->rsr_flags &= ~RSR_lazy;
}
P_RESP* response = &packet->p_resp;
CSTRING temp = response->p_resp_data;
response->p_resp_data.cstr_allocated = buffer_length;
@ -5252,6 +5338,18 @@ static void disconnect( rem_port* port)
RDB rdb = port->port_context;
if (rdb) {
PACKET* packet = &rdb->rdb_packet;
// Deliver the pending defered packets
for (rem_que_packet* p = port->port_defered_packets->begin();
p < port->port_defered_packets->end(); p++)
{
if (!p->sent) {
port->send(&p->packet);
}
}
/* BAND-AID:
It seems as if we are disconnecting the port
on both the server and client side. For now
@ -5263,7 +5361,6 @@ static void disconnect( rem_port* port)
*/
PACKET* packet = &rdb->rdb_packet;
if (port->port_type != port_pipe) {
packet->p_operation = op_disconnect;
port->send(packet);
@ -5271,6 +5368,10 @@ static void disconnect( rem_port* port)
REMOTE_free_packet(port, packet);
}
// Cleanup the queue
delete port->port_defered_packets;
// Clear context reference for the associated event handler
// to avoid SEGV during shutdown
@ -5745,6 +5846,9 @@ static bool init(ISC_STATUS* user_status,
RDB rdb = port->port_context;
PACKET* packet = &rdb->rdb_packet;
MemoryPool& pool = *getDefaultMemoryPool();
port->port_defered_packets = FB_NEW(pool) PacketQueue(pool);
/* Make attach packet */
P_ATCH* attach = &packet->p_atch;
@ -6104,6 +6208,18 @@ static bool receive_packet_noqueue(rem_port* port,
user_status[1] = isc_net_read_err;
user_status[2] = isc_arg_end;
// Receive responses for all defered packets that were already sent
while (port->port_defered_packets->getCount())
{
rem_que_packet* p = port->port_defered_packets->begin();
if (!p->sent)
break;
if (!port->receive(packet))
return FALSE;
port->port_defered_packets->remove(p);
}
return (port->receive(packet));
}
@ -6302,7 +6418,20 @@ static bool release_object(RDB rdb,
packet->p_operation = op;
packet->p_rlse.p_rlse_object = id;
if (!send_packet(rdb->rdb_port, packet, rdb->rdb_status_vector))
ISC_STATUS* status = rdb->rdb_status_vector;
if (rdb->rdb_port->port_flags & PORT_lazy) {
switch (op) {
case op_close_blob:
case op_cancel_blob:
case op_release:
return defer_packet(rdb->rdb_port, packet, status);
default:
break;
}
}
if (!send_packet(rdb->rdb_port, packet, status))
return false;
return receive_response(rdb, packet);
@ -6801,10 +6930,21 @@ static bool send_packet(rem_port* port,
user_status[1] = isc_net_write_err;
user_status[2] = isc_arg_end;
// Send packets that were defered
for (rem_que_packet* p = port->port_defered_packets->begin();
p < port->port_defered_packets->end(); p++)
{
if (!p->sent) {
if (!port->send_partial(&p->packet))
return FALSE;
p->sent = true;
}
}
return (port->send(packet));
}
#ifdef NOT_USED_OR_REPLACED
static bool send_partial_packet(rem_port* port,
PACKET* packet,
ISC_STATUS* user_status)
@ -6834,13 +6974,20 @@ static bool send_partial_packet(rem_port* port,
user_status[1] = isc_net_write_err;
user_status[2] = isc_arg_end;
if (!port->send_partial(packet)) {
return false;
// Send packets that were defered
for (rem_que_packet* p = port->port_defered_packets->begin();
p < port->port_defered_packets->end(); p++)
{
if (!p->sent) {
if (!port->send_partial(&p->packet))
return FALSE;
p->sent = true;
}
}
return true;
return (port->send_partial(packet));
}
#endif
#ifdef MULTI_THREAD
static void server_death(rem_port* port)

View File

@ -142,6 +142,7 @@ const USHORT ptype_page = 1; /* Page server protocol */
const USHORT ptype_rpc = 2; /* Simple remote procedure call */
const USHORT ptype_batch_send = 3; /* Batch sends, no asynchrony */
const USHORT ptype_out_of_band = 4; /* Batch sends w/ out of band notification */
const USHORT ptype_lazy_send = 5; /* Defered packets delivery */
/* Generic object id */

View File

@ -298,6 +298,7 @@ const USHORT RSR_eof = 2; /* End-of-stream encountered */
const USHORT RSR_blob = 4; /* Statement relates to blob op */
const USHORT RSR_no_batch = 8; /* Do not batch fetch rows */
const USHORT RSR_stream_err = 16; /* There is an error pending in the batched rows */
const USHORT RSR_lazy = 32; /* To be allocated at the first reference */
enum blk_t
@ -353,6 +354,18 @@ typedef int HANDLE;
struct p_cnct;
struct rmtque;
/* Queue of defered packets */
struct rem_que_packet
{
PACKET packet;
bool sent;
};
typedef Firebird::Array<rem_que_packet> PacketQueue;
/* Port itself */
class port_interface
{
public:
@ -422,6 +435,8 @@ struct rem_port
USHORT port_iosb[4];
#endif
void* port_xcc; /* interprocess structure */
PacketQueue* port_defered_packets; /* queue of defered packets */
OBJCT port_last_object_id; /* cached last id */
#ifdef SUPERSERVER
Firebird::ObjectsArray< Firebird::Array< char > >* port_queue;
size_t port_qoffset; // current packet in the queue
@ -472,7 +487,7 @@ struct rem_port
ISC_STATUS receive_msg(P_DATA*, PACKET*);
ISC_STATUS seek_blob(P_SEEK*, PACKET*);
ISC_STATUS send_msg(P_DATA*, PACKET*);
ISC_STATUS send_response(PACKET*, OBJCT, USHORT, const ISC_STATUS*);
ISC_STATUS send_response(PACKET*, OBJCT, USHORT, const ISC_STATUS*, bool);
ISC_STATUS service_attach(P_ATCH*, PACKET*);
ISC_STATUS service_end(P_RLSE*, PACKET*);
ISC_STATUS service_start(P_INFO*, PACKET*);
@ -498,7 +513,8 @@ const USHORT PORT_not_trusted = 256; /* Connection is from an untrusted node */
// This is tested only in wnet.cpp but never set.
//const USHORT PORT_impersonate = 512; // A remote user is being impersonated
const USHORT PORT_dummy_pckt_set= 1024; /* A dummy packet interval is set */
const USHORT PORT_partial_data = 2048; /* Physical packet doesn't contain all API packet */
const USHORT PORT_partial_data = 2048; /* Physical packet doesn't contain all API packet */
const USHORT PORT_lazy = 4096; /* Defered operations are allowed */
/* Misc declarations */

View File

@ -74,6 +74,10 @@
#define CHECK_HANDLE(blk, cast, type, id, err) \
{ \
if ((port->port_flags & PORT_lazy) && id == INVALID_OBJECT) \
{ \
id = port->port_last_object_id; \
} \
if (id >= port->port_object_vector->vec_count || \
!(blk = (cast) port->port_objects [id]) || \
((BLK) blk)->blk_type != (UCHAR) type) \
@ -81,12 +85,17 @@
status_vector [0] = isc_arg_gds; \
status_vector [1] = err; \
status_vector [2] = isc_arg_end; \
return port->send_response(sendL, 0, 0, status_vector); \
return port->send_response(send, 0, 0, status_vector, \
false); \
} \
}
#define CHECK_HANDLE_MEMBER(blk, cast, type, id, err) \
{ \
if ((this->port_flags & PORT_lazy) && id == INVALID_OBJECT) \
{ \
id = this->port_last_object_id; \
} \
if (id >= this->port_object_vector->vec_count || \
!(blk = (cast) this->port_objects [id]) || \
((BLK) blk)->blk_type != (UCHAR) type) \
@ -94,7 +103,8 @@
status_vector [0] = isc_arg_gds; \
status_vector [1] = err; \
status_vector [2] = isc_arg_end; \
return this->send_response(sendL, 0, 0, status_vector); \
return this->send_response(sendL, 0, 0, status_vector, \
false); \
} \
}
@ -576,7 +586,7 @@ void SRVR_multi_thread( rem_port* main_port, USHORT flags)
#endif
*/
port->send_response(&request->req_send, 0, 0,
status_vector);
status_vector, false);
port->disconnect(&request->req_send, &request->req_receive);
}
else {
@ -676,7 +686,7 @@ static bool accept_connection(rem_port* port,
weight = protocol->p_cnct_weight;
version = protocol->p_cnct_version;
architecture = protocol->p_cnct_architecture;
type = MIN(protocol->p_cnct_max_type, ptype_out_of_band);
type = MIN(protocol->p_cnct_max_type, ptype_lazy_send);
send->p_operation = op_accept;
}
}
@ -707,6 +717,9 @@ static bool accept_connection(rem_port* port,
if (type != ptype_out_of_band)
port->port_flags |= PORT_no_oob;
if (type == ptype_lazy_send)
port->port_flags |= PORT_lazy;
port->send(send);
return true;
@ -731,7 +744,7 @@ static ISC_STATUS allocate_statement( rem_port* port, P_RLSE * allocate, PACKET*
if (bad_db(status_vector, rdb))
{
return port->send_response(send, 0, 0, status_vector);
return port->send_response(send, 0, 0, status_vector, true);
}
FB_API_HANDLE handle = 0;
@ -767,7 +780,7 @@ static ISC_STATUS allocate_statement( rem_port* port, P_RLSE * allocate, PACKET*
}
}
return port->send_response(send, object, 0, status_vector);
return port->send_response(send, object, 0, status_vector, true);
}
@ -957,7 +970,7 @@ static ISC_STATUS attach_database(
rdb->rdb_handle = handle;
}
return port->send_response(send, 0, 0, status_vector);
return port->send_response(send, 0, 0, status_vector, false);
}
@ -1023,7 +1036,8 @@ static void aux_request( rem_port* port, P_REQ * request, PACKET* send)
}
port->send_response(send, rdb->rdb_id,
send->p_resp.p_resp_data.cstr_length, status_vector);
send->p_resp.p_resp_data.cstr_length,
status_vector, false);
if (status_vector[1]) {
/* restore the port status vector */
@ -1064,7 +1078,7 @@ static ISC_STATUS cancel_events( rem_port* port, P_EVENT * stuff, PACKET* send)
RDB rdb = port->port_context;
if (bad_db(status_vector, rdb))
{
return port->send_response(send, 0, 0, status_vector);
return port->send_response(send, 0, 0, status_vector, false);
}
/* Find the event */
@ -1077,7 +1091,7 @@ static ISC_STATUS cancel_events( rem_port* port, P_EVENT * stuff, PACKET* send)
/* If no event found, pretend it was cancelled */
if (!event)
return port->send_response(send, 0, 0, status_vector);
return port->send_response(send, 0, 0, status_vector, false);
/* cancel the event */
@ -1095,7 +1109,7 @@ static ISC_STATUS cancel_events( rem_port* port, P_EVENT * stuff, PACKET* send)
/* return response */
return port->send_response(send, 0, 0, status_vector);
return port->send_response(send, 0, 0, status_vector, false);
}
@ -1232,7 +1246,7 @@ ISC_STATUS rem_port::compile(P_CMPL* compileL, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
FB_API_HANDLE handle = 0;
@ -1245,7 +1259,7 @@ ISC_STATUS rem_port::compile(P_CMPL* compileL, PACKET* sendL)
THREAD_ENTER();
if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
/* Parse the request to find the messages */
@ -1281,7 +1295,7 @@ ISC_STATUS rem_port::compile(P_CMPL* compileL, PACKET* sendL)
status_vector[0] = isc_arg_gds;
status_vector[1] = isc_too_many_handles;
status_vector[2] = isc_arg_end;
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
while (message) {
@ -1300,7 +1314,7 @@ ISC_STATUS rem_port::compile(P_CMPL* compileL, PACKET* sendL)
message = next;
}
return this->send_response(sendL, object, 0, status_vector);
return this->send_response(sendL, object, 0, status_vector, false);
}
@ -1328,7 +1342,7 @@ ISC_STATUS rem_port::ddl(P_DDL* ddlL, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
const UCHAR* blr = ddlL->p_ddl_blr.cstr_address;
@ -1339,7 +1353,7 @@ ISC_STATUS rem_port::ddl(P_DDL* ddlL, PACKET* sendL)
blr_length, reinterpret_cast<const char*>(blr));
THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -1529,7 +1543,7 @@ void rem_port::drop_database(P_RLSE* release, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
this->send_response(sendL, 0, 0, status_vector);
this->send_response(sendL, 0, 0, status_vector, false);
return;
}
@ -1540,7 +1554,7 @@ void rem_port::drop_database(P_RLSE* release, PACKET* sendL)
if (status_vector[1]
&& (status_vector[1] != isc_drdb_completed_with_errs))
{
this->send_response(sendL, 0, 0, status_vector);
this->send_response(sendL, 0, 0, status_vector, false);
return;
}
@ -1559,7 +1573,7 @@ void rem_port::drop_database(P_RLSE* release, PACKET* sendL)
if (this->port_statement)
release_statement(&this->port_statement);
this->send_response(sendL, 0, 0, status_vector);
this->send_response(sendL, 0, 0, status_vector, false);
}
@ -1625,7 +1639,7 @@ ISC_STATUS rem_port::end_blob(P_OP operation, P_RLSE * release, PACKET* sendL)
release_blob(blob);
}
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -1646,7 +1660,7 @@ ISC_STATUS rem_port::end_database(P_RLSE * release, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
THREAD_EXIT();
@ -1654,7 +1668,7 @@ ISC_STATUS rem_port::end_database(P_RLSE * release, PACKET* sendL)
THREAD_ENTER();
if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
while (rdb->rdb_events)
release_event(rdb->rdb_events);
@ -1671,7 +1685,7 @@ ISC_STATUS rem_port::end_database(P_RLSE * release, PACKET* sendL)
if (this->port_statement)
release_statement(&this->port_statement);
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -1703,7 +1717,7 @@ ISC_STATUS rem_port::end_request(P_RLSE * release, PACKET* sendL)
if (!status_vector[1])
release_request(requestL);
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, true);
}
@ -1735,7 +1749,7 @@ ISC_STATUS rem_port::end_statement(P_SQLFREE* free_stmt, PACKET* sendL)
THREAD_ENTER();
if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, true);
if (!statement->rsr_handle) {
release_sql_request(statement);
@ -1750,7 +1764,7 @@ ISC_STATUS rem_port::end_statement(P_SQLFREE* free_stmt, PACKET* sendL)
const USHORT object = (statement) ? statement->rsr_id : INVALID_OBJECT;
return this->send_response(sendL, object, 0, status_vector);
return this->send_response(sendL, object, 0, status_vector, true);
}
@ -1807,7 +1821,7 @@ ISC_STATUS rem_port::end_transaction(P_OP operation, P_RLSE * release, PACKET* s
release_transaction(transaction);
}
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -1831,7 +1845,7 @@ ISC_STATUS rem_port::execute_immediate(P_OP op, P_SQLST * exnow, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
/** Do not call CHECK_HANDLE if this is the start of a transaction **/
@ -1956,7 +1970,8 @@ ISC_STATUS rem_port::execute_immediate(P_OP op, P_SQLST * exnow, PACKET* sendL)
return this->send_response( sendL,
(OBJCT) (transaction ? transaction->rtr_id : 0),
0,
status_vector);
status_vector,
false);
}
@ -2072,7 +2087,8 @@ ISC_STATUS rem_port::execute_statement(P_OP op, P_SQLDATA* sqldata, PACKET* send
return this->send_response( sendL,
(OBJCT) (transaction ? transaction->rtr_id : 0),
0,
status_vector);
status_vector,
false);
}
@ -2159,7 +2175,8 @@ ISC_STATUS rem_port::fetch(P_SQLDATA * sqldata, PACKET* sendL)
{
statement->rsr_flags &= ~RSR_stream_err;
return this->send_response(sendL, 0, 0,
statement->rsr_status_vector);
statement->rsr_status_vector,
false);
}
message = statement->rsr_buffer;
@ -2190,7 +2207,7 @@ ISC_STATUS rem_port::fetch(P_SQLDATA * sqldata, PACKET* sendL)
break;
}
else {
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
}
message->msg_address = message->msg_buffer;
@ -2343,7 +2360,7 @@ ISC_STATUS rem_port::fetch_blob(P_SQLDATA * sqldata, PACKET* sendL)
message->msg_address = NULL;
}
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -2382,13 +2399,15 @@ OBJCT rem_port::get_id(BLK block)
{
if (!*p) {
*p = block;
return (OBJCT) (p - vector->vec_object);
this->port_last_object_id = (OBJCT) (p - vector->vec_object);
return this->port_last_object_id;
}
}
/* Vector is full -- somebody will need to expand it */
return REMOTE_set_object(this, block, (OBJCT) vector->vec_count);
return (this->port_last_object_id =
REMOTE_set_object(this, block, (OBJCT) vector->vec_count));
}
@ -2501,7 +2520,7 @@ ISC_STATUS rem_port::get_segment(P_SGMT* segment, PACKET* sendL)
reinterpret_cast<char*>(buffer));
THREAD_ENTER();
const ISC_STATUS status =
this->send_response(sendL, blob->rbl_id, length, status_vector);
this->send_response(sendL, blob->rbl_id, length, status_vector, false);
#ifdef DEBUG_REMOTE_MEMORY
printf("get_segment(server) free buffer %x\n", buffer);
#endif
@ -2553,7 +2572,8 @@ ISC_STATUS rem_port::get_segment(P_SGMT* segment, PACKET* sendL)
const ISC_STATUS status = this->send_response(sendL,
(OBJCT)state,
(USHORT) (p - buffer),
status_vector);
status_vector,
false);
#ifdef DEBUG_REMOTE_MEMORY
printf("get_segment(server) free buffer %x\n", buffer);
@ -2588,7 +2608,7 @@ ISC_STATUS rem_port::get_slice(P_SLC * stuff, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
CHECK_HANDLE_MEMBER(transaction,
@ -2628,7 +2648,7 @@ ISC_STATUS rem_port::get_slice(P_SLC * stuff, PACKET* sendL)
ISC_STATUS status;
if (status_vector[1])
status = this->send_response(sendL, 0, 0, status_vector);
status = this->send_response(sendL, 0, 0, status_vector, false);
else {
sendL->p_operation = op_slice;
response->p_slr_slice.lstr_address = slice;
@ -2673,28 +2693,60 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
/* Make sure there is a suitable temporary blob buffer */
UCHAR* const buffer = ALLR_alloc((SLONG) stuff->p_info_buffer_length);
UCHAR* const buffer = ALLR_alloc(stuff->p_info_buffer_length);
memset(buffer, 0, stuff->p_info_buffer_length);
#ifdef DEBUG_REMOTE_MEMORY
printf("info(server) allocate buffer %x\n", buffer);
#endif
SCHAR info[1024], *info_buffer;
SSHORT info_len;
UCHAR temp[1024];
UCHAR* temp_buffer;
if (op == op_info_database && stuff->p_info_buffer_length > sizeof(temp)) {
temp_buffer = ALLR_alloc((SLONG) stuff->p_info_buffer_length);
temp_buffer = temp;
if (op == op_info_database)
{
info_len = 0;
info_buffer = 0;
if (stuff->p_info_buffer_length > sizeof(temp))
{
temp_buffer = ALLR_alloc((SLONG) stuff->p_info_buffer_length);
#ifdef DEBUG_REMOTE_MEMORY
printf("info(server) allocate buffer %x\n", temp_buffer);
printf("info(server) allocate buffer %x\n", temp_buffer);
#endif
}
}
else
temp_buffer = temp;
{
// stuff isc_info_length in front of info items buffer
CSTRING* info_string = (op == op_service_info) ?
&stuff->p_info_recv_items : &stuff->p_info_items;
info_len = 1 + info_string->cstr_length;
if (info_len > sizeof(info))
{
info_buffer = (SCHAR*) ALLR_alloc((SLONG) info_len);
#ifdef DEBUG_REMOTE_MEMORY
ib_printf("info(server) allocate buffer %x\n", info_buffer);
#endif
}
else {
info_buffer = info;
}
*info_buffer = isc_info_length;
memmove(info_buffer + 1, info_string->cstr_address, info_len-1);
}
USHORT info_db_len = 0;
switch (op) {
case op_info_blob:
CHECK_HANDLE_MEMBER(blob,
@ -2704,8 +2756,8 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
isc_bad_segstr_handle);
THREAD_EXIT();
isc_blob_info(status_vector, &blob->rbl_handle,
stuff->p_info_items.cstr_length,
reinterpret_cast<char*>(stuff->p_info_items.cstr_address),
info_len,
info_buffer,
stuff->p_info_buffer_length,
reinterpret_cast<char*>(buffer));
THREAD_ENTER();
@ -2720,9 +2772,9 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
reinterpret_cast<char*>(temp_buffer) /*temp*/);
if (!status_vector[1]) {
TEXT version[256];
sprintf(version, "%s/%s", GDS_VERSION,
this->port_version->str_data);
MERGE_database_info(temp_buffer /*temp*/, buffer, stuff->p_info_buffer_length,
sprintf(version, "%s/%s", GDS_VERSION, this->port_version->str_data);
info_db_len = MERGE_database_info(temp_buffer /*temp*/,
buffer, stuff->p_info_buffer_length,
IMPLEMENTATION, 4, 1,
reinterpret_cast<const UCHAR*>(version),
reinterpret_cast<UCHAR*>(this->port_host->str_data),
@ -2742,8 +2794,8 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
THREAD_EXIT();
isc_request_info(status_vector, &requestL->rrq_handle,
stuff->p_info_incarnation,
stuff->p_info_items.cstr_length,
reinterpret_cast<const char*>(stuff->p_info_items.cstr_address),
info_len,
info_buffer,
stuff->p_info_buffer_length,
reinterpret_cast<char*>(buffer));
THREAD_ENTER();
@ -2758,8 +2810,8 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
isc_bad_trans_handle);
THREAD_EXIT();
isc_transaction_info(status_vector, &transaction->rtr_handle,
stuff->p_info_items.cstr_length,
reinterpret_cast<const char*>(stuff->p_info_items.cstr_address),
info_len,
info_buffer,
stuff->p_info_buffer_length,
reinterpret_cast < char *>(buffer));
THREAD_ENTER();
@ -2773,9 +2825,8 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
stuff->p_info_items.cstr_length,
reinterpret_cast<
const char*>(stuff->p_info_items.cstr_address),
stuff->p_info_recv_items.cstr_length,
reinterpret_cast<
const char*>(stuff->p_info_recv_items.cstr_address),
info_len,
info_buffer,
stuff->p_info_buffer_length,
reinterpret_cast<char*>(buffer));
THREAD_ENTER();
@ -2787,12 +2838,13 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
type_rsr,
stuff->p_info_object,
isc_bad_req_handle);
THREAD_EXIT();
GDS_DSQL_SQL_INFO(status_vector,
&statement->rsr_handle,
stuff->p_info_items.cstr_length,
reinterpret_cast<
const char*>(stuff->p_info_items.cstr_address),
info_len,
info_buffer,
stuff->p_info_buffer_length,
reinterpret_cast < char *>(buffer));
THREAD_ENTER();
@ -2806,12 +2858,34 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
ALLR_free(temp_buffer);
}
if (info_buffer && (info_buffer != info)) {
#ifdef DEBUG_REMOTE_MEMORY
printf ("info(server) free buffer %x\n", info_buffer);
#endif
ALLR_free(info_buffer);
}
/* Send a response that includes the segment. */
sendL->p_resp.p_resp_data.cstr_address = buffer;
USHORT response_len =
info_db_len ? info_db_len : stuff->p_info_buffer_length;
SSHORT skip_len = 0;
if (*buffer == isc_info_length)
{
skip_len = gds__vax_integer(buffer + 1, 2);
SLONG val = gds__vax_integer(buffer + 3, skip_len);
skip_len += 3;
if (val && val <= response_len) {
response_len = val;
}
}
sendL->p_resp.p_resp_data.cstr_address = buffer + skip_len;
const ISC_STATUS status = this->send_response(sendL, stuff->p_info_object,
response_len, status_vector, false);
const ISC_STATUS status = this->send_response(sendL, stuff->p_info_object,
stuff->p_info_buffer_length, status_vector);
#ifdef DEBUG_REMOTE_MEMORY
printf("info(server) free buffer %x\n", buffer);
#endif
@ -2864,7 +2938,7 @@ ISC_STATUS rem_port::insert(P_SQLDATA * sqldata, PACKET* sendL)
reinterpret_cast<const char*>(msg));
THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -2921,7 +2995,7 @@ ISC_STATUS rem_port::open_blob(P_OP op, P_BLOB* stuff, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
FB_API_HANDLE handle = 0;
@ -2976,7 +3050,7 @@ ISC_STATUS rem_port::open_blob(P_OP op, P_BLOB* stuff, PACKET* sendL)
}
}
return this->send_response(sendL, object, 0, status_vector);
return this->send_response(sendL, object, 0, status_vector, false);
}
@ -3010,7 +3084,7 @@ ISC_STATUS rem_port::prepare(P_PREP * stuff, PACKET* sendL)
}
THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -3046,12 +3120,24 @@ ISC_STATUS rem_port::prepare_statement(P_SQLST * prepareL, PACKET* sendL)
isc_bad_req_handle);
UCHAR local_buffer[1024];
UCHAR *info, info_buffer[1024];
UCHAR* buffer;
if (prepareL->p_sqlst_buffer_length > sizeof(local_buffer))
buffer = ALLR_alloc((SLONG) prepareL->p_sqlst_buffer_length);
else
buffer = local_buffer;
// stuff isc_info_length in front of info items buffer
if (prepareL->p_sqlst_items.cstr_length + 1 > sizeof(info_buffer)) {
info = ALLR_alloc((SLONG) prepareL->p_sqlst_items.cstr_length + 1);
}
else {
info = info_buffer;
}
*info = isc_info_length;
memmove(info + 1, prepareL->p_sqlst_items.cstr_address,
prepareL->p_sqlst_items.cstr_length);
FB_API_HANDLE handle = (transaction) ? transaction->rtr_handle : 0;
@ -3084,16 +3170,20 @@ ISC_STATUS rem_port::prepare_statement(P_SQLST * prepareL, PACKET* sendL)
reinterpret_cast<const char*>(prepareL->p_sqlst_SQL_str.cstr_address),
(USHORT) ((prepareL->p_sqlst_SQL_dialect * 10) +
parser_version),
prepareL->p_sqlst_items.cstr_length,
reinterpret_cast<const char*>(prepareL->p_sqlst_items.cstr_address),
prepareL->p_sqlst_items.cstr_length + 1,
reinterpret_cast<const char*> (info),
prepareL->p_sqlst_buffer_length,
reinterpret_cast<char*>(buffer));
THREAD_ENTER();
if (info != info_buffer) {
ALLR_free(info);
}
if (status_vector[1]) {
if (buffer != local_buffer)
ALLR_free(buffer);
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
REMOTE_reset_statement(statement);
@ -3108,13 +3198,26 @@ ISC_STATUS rem_port::prepare_statement(P_SQLST * prepareL, PACKET* sendL)
/* Send a response that includes the info requested. */
sendL->p_resp.p_resp_data.cstr_address = buffer;
USHORT response_len = prepareL->p_sqlst_buffer_length;
SSHORT skip_len = 0;
if (*buffer == isc_info_length)
{
skip_len = gds__vax_integer(buffer + 1, 2);
SLONG val = gds__vax_integer(buffer + 3, skip_len);
skip_len += 3;
if (val && val <= response_len) {
response_len = val;
}
}
sendL->p_resp.p_resp_data.cstr_address = buffer + skip_len;
const ISC_STATUS status =
this->send_response(sendL,
state,
prepareL->p_sqlst_buffer_length,
status_vector);
response_len,
status_vector,
false);
if (buffer != local_buffer) {
ALLR_free(buffer);
@ -3418,7 +3521,7 @@ bool process_packet(rem_port* port,
gds__log_status("unknown, SERVER/process_packet", status_ptr);
/* It would be nice to log an error to the user, instead of just terminating them! */
port->send_response(sendL, 0, 0, status_ptr);
port->send_response(sendL, 0, 0, status_ptr, false);
port->disconnect(sendL, receive); /* Well, how about this... */
ThreadData::restoreSpecific();
@ -3462,7 +3565,7 @@ ISC_STATUS rem_port::put_segment(P_OP op, P_SGMT * segment, PACKET* sendL)
isc_put_segment(status_vector, &blob->rbl_handle, length,
reinterpret_cast<const char*>(p));
THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
/* We've got a batch of segments. This is only slightly more complicated */
@ -3477,11 +3580,11 @@ ISC_STATUS rem_port::put_segment(P_OP op, P_SGMT * segment, PACKET* sendL)
reinterpret_cast<const char*>(p));
THREAD_ENTER();
if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
p += length;
}
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -3509,7 +3612,7 @@ ISC_STATUS rem_port::put_slice(P_SLC * stuff, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
THREAD_EXIT();
@ -3524,7 +3627,7 @@ ISC_STATUS rem_port::put_slice(P_SLC * stuff, PACKET* sendL)
stuff->p_slc_slice.lstr_address);
THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -3544,7 +3647,7 @@ ISC_STATUS rem_port::que_events(P_EVENT * stuff, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
/* Find unused event block or, if necessary, a new one */
@ -3592,7 +3695,7 @@ ISC_STATUS rem_port::que_events(P_EVENT * stuff, PACKET* sendL)
event->rvnt_id = 0;
}
return this->send_response(sendL, (OBJCT) id, 0, status_vector);
return this->send_response(sendL, (OBJCT) id, 0, status_vector, false);
}
@ -3625,7 +3728,7 @@ ISC_STATUS rem_port::receive_after_start( P_DATA* data,
USHORT msg_number;
if (!get_next_msg_no(requestL, level, &msg_number)) {
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
sendL->p_operation = op_response_piggyback;
@ -3699,7 +3802,7 @@ ISC_STATUS rem_port::receive_msg(P_DATA * data, PACKET* sendL)
status_vector[0] = isc_arg_gds;
status_vector[1] = isc_badmsgnum;
status_vector[2] = isc_arg_end;
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
rrq::rrq_repeat* tail = requestL->rrq_rpt + msg_number;
const rem_fmt* format = tail->rrq_format;
@ -3751,7 +3854,8 @@ ISC_STATUS rem_port::receive_msg(P_DATA * data, PACKET* sendL)
if (requestL->rrq_status_vector[1]) {
const ISC_STATUS res =
this->send_response(sendL, 0, 0,
requestL->rrq_status_vector);
requestL->rrq_status_vector,
false);
memset(requestL->rrq_status_vector, 0,
sizeof(requestL->rrq_status_vector));
return res;
@ -3768,7 +3872,7 @@ ISC_STATUS rem_port::receive_msg(P_DATA * data, PACKET* sendL)
#endif
THREAD_ENTER();
if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
#ifdef SCROLLABLE_CURSORS
/* set the appropriate flags according to the way we just scrolled
@ -4248,7 +4352,7 @@ ISC_STATUS rem_port::seek_blob(P_SEEK * seek, PACKET* sendL)
sendL->p_resp.p_resp_blob_id.bid_number = result;
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -4280,7 +4384,7 @@ ISC_STATUS rem_port::send_msg(P_DATA * data, PACKET* sendL)
status_vector[0] = isc_arg_gds;
status_vector[1] = isc_badmsgnum;
status_vector[2] = isc_arg_end;
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
REM_MSG message = requestL->rrq_rpt[number].rrq_message;
const rem_fmt* format = requestL->rrq_rpt[number].rrq_format;
@ -4292,14 +4396,15 @@ ISC_STATUS rem_port::send_msg(P_DATA * data, PACKET* sendL)
message->msg_address = NULL;
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
ISC_STATUS rem_port::send_response( PACKET* sendL,
OBJCT object,
USHORT length,
const ISC_STATUS* status_vector)
const ISC_STATUS* status_vector,
bool defer_flag)
{
/**************************************
*
@ -4429,7 +4534,12 @@ ISC_STATUS rem_port::send_response( PACKET* sendL,
response->p_resp_status_vector = new_vector;
response->p_resp_data.cstr_length = length;
this->send(sendL);
if ((this->port_flags & PORT_lazy) && defer_flag) {
this->send_partial(sendL);
}
else {
this->send(sendL);
}
return exit_code;
}
@ -4535,7 +4645,7 @@ ISC_STATUS rem_port::service_attach(P_ATCH* attach, PACKET* sendL)
rdb->rdb_flags |= RDB_service;
}
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -4556,14 +4666,14 @@ ISC_STATUS rem_port::service_end(P_RLSE * release, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_service(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
THREAD_EXIT();
isc_service_detach(status_vector, &rdb->rdb_handle);
THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -4584,7 +4694,7 @@ ISC_STATUS rem_port::service_start(P_INFO * stuff, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_service(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
THREAD_EXIT();
@ -4596,7 +4706,7 @@ ISC_STATUS rem_port::service_start(P_INFO * stuff, PACKET* sendL)
reinterpret_cast<char*>(stuff->p_info_items.cstr_address));
THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -4628,7 +4738,7 @@ ISC_STATUS rem_port::set_cursor(P_SQLCUR * sqlcur, PACKET* sendL)
sqlcur->p_sqlcur_type);
THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -4708,7 +4818,7 @@ ISC_STATUS rem_port::start(P_OP operation, P_DATA * data, PACKET* sendL)
return this->receive_after_start(data, sendL, status_vector);
}
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -4748,7 +4858,7 @@ ISC_STATUS rem_port::start_and_send(P_OP operation,
status_vector[0] = isc_arg_gds;
status_vector[1] = isc_badmsgnum;
status_vector[2] = isc_arg_end;
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
REM_MSG message = requestL->rrq_rpt[number].rrq_message;
const rem_fmt* format = requestL->rrq_rpt[number].rrq_format;
@ -4769,7 +4879,7 @@ ISC_STATUS rem_port::start_and_send(P_OP operation,
}
}
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
@ -4790,7 +4900,7 @@ ISC_STATUS rem_port::start_transaction(P_OP operation, P_STTR * stuff, PACKET* s
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
FB_API_HANDLE handle = 0;
@ -4849,7 +4959,7 @@ ISC_STATUS rem_port::start_transaction(P_OP operation, P_STTR * stuff, PACKET* s
}
}
return this->send_response(sendL, object, 0, status_vector);
return this->send_response(sendL, object, 0, status_vector, false);
}
@ -5103,7 +5213,7 @@ ISC_STATUS rem_port::transact_request(P_TRRQ* trrq, PACKET* sendL)
RDB rdb = this->port_context;
if (bad_db(status_vector, rdb))
{
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
}
const UCHAR* blr = trrq->p_trrq_blr.cstr_address;
@ -5131,7 +5241,7 @@ ISC_STATUS rem_port::transact_request(P_TRRQ* trrq, PACKET* sendL)
THREAD_ENTER();
if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector);
return this->send_response(sendL, 0, 0, status_vector, false);
P_DATA* data = &sendL->p_data;
sendL->p_operation = op_transact_response;