mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 12:03:02 +01:00
Merge B1_5_Remote_LazyPort branch into HEAD
This commit is contained in:
parent
b196cac010
commit
f94b8bd641
@ -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!
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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))
|
||||
{
|
||||
|
324
src/jrd/why.cpp
324
src/jrd/why.cpp
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user