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

Implemented methods to manage blobs cache size at client side and maximum size of blob to transfer inline.

This commit is contained in:
Vlad Khorsun 2024-11-23 13:51:16 +02:00
parent 6cab8f2532
commit f5032b5557
13 changed files with 648 additions and 23 deletions

View File

@ -521,6 +521,11 @@ version: // 3.0 => 4.0
version: // 3.0.7 => 3.0.8, 4.0.0 => 4.0.1
[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedFree(status) endif]
void free(Status status);
version: // 6.0
// Inline blob transfer
uint getMaxInlineBlobSize(Status status);
void setMaxInlineBlobSize(Status status, uint size);
}
interface Batch : ReferenceCounted
@ -713,6 +718,15 @@ version: // 3.0.7 => 3.0.8, 4.0.0 => 4.0.1
void detach(Status status);
[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedDropDatabase(status) endif]
void dropDatabase(Status status);
version: // 6.0
// Blob caching by client
uint getMaxBlobCacheSize(Status status);
void setMaxBlobCacheSize(Status status, uint size);
// Inline blob transfer
uint getMaxInlineBlobSize(Status status);
void setMaxInlineBlobSize(Status status, uint size);
}
interface Service : ReferenceCounted

View File

@ -1869,7 +1869,7 @@ namespace Firebird
}
};
#define FIREBIRD_ISTATEMENT_VERSION 5u
#define FIREBIRD_ISTATEMENT_VERSION 6u
class IStatement : public IReferenceCounted
{
@ -1891,6 +1891,8 @@ namespace Firebird
void (CLOOP_CARG *setTimeout)(IStatement* self, IStatus* status, unsigned timeOut) CLOOP_NOEXCEPT;
IBatch* (CLOOP_CARG *createBatch)(IStatement* self, IStatus* status, IMessageMetadata* inMetadata, unsigned parLength, const unsigned char* par) CLOOP_NOEXCEPT;
void (CLOOP_CARG *free)(IStatement* self, IStatus* status) CLOOP_NOEXCEPT;
unsigned (CLOOP_CARG *getMaxInlineBlobSize)(IStatement* self, IStatus* status) CLOOP_NOEXCEPT;
void (CLOOP_CARG *setMaxInlineBlobSize)(IStatement* self, IStatus* status, unsigned size) CLOOP_NOEXCEPT;
};
protected:
@ -2064,6 +2066,33 @@ namespace Firebird
static_cast<VTable*>(this->cloopVTable)->free(this, status);
StatusType::checkException(status);
}
template <typename StatusType> unsigned getMaxInlineBlobSize(StatusType* status)
{
if (cloopVTable->version < 6)
{
StatusType::setVersionError(status, "IStatement", cloopVTable->version, 6);
StatusType::checkException(status);
return 0;
}
StatusType::clearException(status);
unsigned ret = static_cast<VTable*>(this->cloopVTable)->getMaxInlineBlobSize(this, status);
StatusType::checkException(status);
return ret;
}
template <typename StatusType> void setMaxInlineBlobSize(StatusType* status, unsigned size)
{
if (cloopVTable->version < 6)
{
StatusType::setVersionError(status, "IStatement", cloopVTable->version, 6);
StatusType::checkException(status);
return;
}
StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->setMaxInlineBlobSize(this, status, size);
StatusType::checkException(status);
}
};
#define FIREBIRD_IBATCH_VERSION 4u
@ -2499,7 +2528,7 @@ namespace Firebird
}
};
#define FIREBIRD_IATTACHMENT_VERSION 5u
#define FIREBIRD_IATTACHMENT_VERSION 6u
class IAttachment : public IReferenceCounted
{
@ -2532,6 +2561,10 @@ namespace Firebird
IReplicator* (CLOOP_CARG *createReplicator)(IAttachment* self, IStatus* status) CLOOP_NOEXCEPT;
void (CLOOP_CARG *detach)(IAttachment* self, IStatus* status) CLOOP_NOEXCEPT;
void (CLOOP_CARG *dropDatabase)(IAttachment* self, IStatus* status) CLOOP_NOEXCEPT;
unsigned (CLOOP_CARG *getMaxBlobCacheSize)(IAttachment* self, IStatus* status) CLOOP_NOEXCEPT;
void (CLOOP_CARG *setMaxBlobCacheSize)(IAttachment* self, IStatus* status, unsigned size) CLOOP_NOEXCEPT;
unsigned (CLOOP_CARG *getMaxInlineBlobSize)(IAttachment* self, IStatus* status) CLOOP_NOEXCEPT;
void (CLOOP_CARG *setMaxInlineBlobSize)(IAttachment* self, IStatus* status, unsigned size) CLOOP_NOEXCEPT;
};
protected:
@ -2800,6 +2833,60 @@ namespace Firebird
static_cast<VTable*>(this->cloopVTable)->dropDatabase(this, status);
StatusType::checkException(status);
}
template <typename StatusType> unsigned getMaxBlobCacheSize(StatusType* status)
{
if (cloopVTable->version < 6)
{
StatusType::setVersionError(status, "IAttachment", cloopVTable->version, 6);
StatusType::checkException(status);
return 0;
}
StatusType::clearException(status);
unsigned ret = static_cast<VTable*>(this->cloopVTable)->getMaxBlobCacheSize(this, status);
StatusType::checkException(status);
return ret;
}
template <typename StatusType> void setMaxBlobCacheSize(StatusType* status, unsigned size)
{
if (cloopVTable->version < 6)
{
StatusType::setVersionError(status, "IAttachment", cloopVTable->version, 6);
StatusType::checkException(status);
return;
}
StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->setMaxBlobCacheSize(this, status, size);
StatusType::checkException(status);
}
template <typename StatusType> unsigned getMaxInlineBlobSize(StatusType* status)
{
if (cloopVTable->version < 6)
{
StatusType::setVersionError(status, "IAttachment", cloopVTable->version, 6);
StatusType::checkException(status);
return 0;
}
StatusType::clearException(status);
unsigned ret = static_cast<VTable*>(this->cloopVTable)->getMaxInlineBlobSize(this, status);
StatusType::checkException(status);
return ret;
}
template <typename StatusType> void setMaxInlineBlobSize(StatusType* status, unsigned size)
{
if (cloopVTable->version < 6)
{
StatusType::setVersionError(status, "IAttachment", cloopVTable->version, 6);
StatusType::checkException(status);
return;
}
StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->setMaxInlineBlobSize(this, status, size);
StatusType::checkException(status);
}
};
#define FIREBIRD_ISERVICE_VERSION 5u
@ -10525,6 +10612,8 @@ namespace Firebird
this->setTimeout = &Name::cloopsetTimeoutDispatcher;
this->createBatch = &Name::cloopcreateBatchDispatcher;
this->free = &Name::cloopfreeDispatcher;
this->getMaxInlineBlobSize = &Name::cloopgetMaxInlineBlobSizeDispatcher;
this->setMaxInlineBlobSize = &Name::cloopsetMaxInlineBlobSizeDispatcher;
}
} vTable;
@ -10751,6 +10840,35 @@ namespace Firebird
}
}
static unsigned CLOOP_CARG cloopgetMaxInlineBlobSizeDispatcher(IStatement* self, IStatus* status) CLOOP_NOEXCEPT
{
StatusType status2(status);
try
{
return static_cast<Name*>(self)->Name::getMaxInlineBlobSize(&status2);
}
catch (...)
{
StatusType::catchException(&status2);
return static_cast<unsigned>(0);
}
}
static void CLOOP_CARG cloopsetMaxInlineBlobSizeDispatcher(IStatement* self, IStatus* status, unsigned size) CLOOP_NOEXCEPT
{
StatusType status2(status);
try
{
static_cast<Name*>(self)->Name::setMaxInlineBlobSize(&status2, size);
}
catch (...)
{
StatusType::catchException(&status2);
}
}
static void CLOOP_CARG cloopaddRefDispatcher(IReferenceCounted* self) CLOOP_NOEXCEPT
{
try
@ -10805,6 +10923,8 @@ namespace Firebird
virtual void setTimeout(StatusType* status, unsigned timeOut) = 0;
virtual IBatch* createBatch(StatusType* status, IMessageMetadata* inMetadata, unsigned parLength, const unsigned char* par) = 0;
virtual void free(StatusType* status) = 0;
virtual unsigned getMaxInlineBlobSize(StatusType* status) = 0;
virtual void setMaxInlineBlobSize(StatusType* status, unsigned size) = 0;
};
template <typename Name, typename StatusType, typename Base>
@ -11630,6 +11750,10 @@ namespace Firebird
this->createReplicator = &Name::cloopcreateReplicatorDispatcher;
this->detach = &Name::cloopdetachDispatcher;
this->dropDatabase = &Name::cloopdropDatabaseDispatcher;
this->getMaxBlobCacheSize = &Name::cloopgetBlobCacheSizeDispatcher;
this->setMaxBlobCacheSize = &Name::cloopsetBlobCacheSizeDispatcher;
this->getMaxInlineBlobSize = &Name::cloopgetMaxInlineBlobSizeDispatcher;
this->setMaxInlineBlobSize = &Name::cloopsetMaxInlineBlobSizeDispatcher;
}
} vTable;
@ -12014,6 +12138,64 @@ namespace Firebird
}
}
static unsigned CLOOP_CARG cloopgetBlobCacheSizeDispatcher(IAttachment* self, IStatus* status) CLOOP_NOEXCEPT
{
StatusType status2(status);
try
{
return static_cast<Name*>(self)->Name::getMaxBlobCacheSize(&status2);
}
catch (...)
{
StatusType::catchException(&status2);
return static_cast<unsigned>(0);
}
}
static void CLOOP_CARG cloopsetBlobCacheSizeDispatcher(IAttachment* self, IStatus* status, unsigned size) CLOOP_NOEXCEPT
{
StatusType status2(status);
try
{
static_cast<Name*>(self)->Name::setMaxBlobCacheSize(&status2, size);
}
catch (...)
{
StatusType::catchException(&status2);
}
}
static unsigned CLOOP_CARG cloopgetMaxInlineBlobSizeDispatcher(IAttachment* self, IStatus* status) CLOOP_NOEXCEPT
{
StatusType status2(status);
try
{
return static_cast<Name*>(self)->Name::getMaxInlineBlobSize(&status2);
}
catch (...)
{
StatusType::catchException(&status2);
return static_cast<unsigned>(0);
}
}
static void CLOOP_CARG cloopsetMaxInlineBlobSizeDispatcher(IAttachment* self, IStatus* status, unsigned size) CLOOP_NOEXCEPT
{
StatusType status2(status);
try
{
static_cast<Name*>(self)->Name::setMaxInlineBlobSize(&status2, size);
}
catch (...)
{
StatusType::catchException(&status2);
}
}
static void CLOOP_CARG cloopaddRefDispatcher(IReferenceCounted* self) CLOOP_NOEXCEPT
{
try
@ -12079,6 +12261,10 @@ namespace Firebird
virtual IReplicator* createReplicator(StatusType* status) = 0;
virtual void detach(StatusType* status) = 0;
virtual void dropDatabase(StatusType* status) = 0;
virtual unsigned getMaxBlobCacheSize(StatusType* status) = 0;
virtual void setMaxBlobCacheSize(StatusType* status, unsigned size) = 0;
virtual unsigned getMaxInlineBlobSize(StatusType* status) = 0;
virtual void setMaxInlineBlobSize(StatusType* status, unsigned size) = 0;
};
template <typename Name, typename StatusType, typename Base>

View File

@ -358,6 +358,8 @@ type
IStatement_setTimeoutPtr = procedure(this: IStatement; status: IStatus; timeOut: Cardinal); cdecl;
IStatement_createBatchPtr = function(this: IStatement; status: IStatus; inMetadata: IMessageMetadata; parLength: Cardinal; par: BytePtr): IBatch; cdecl;
IStatement_freePtr = procedure(this: IStatement; status: IStatus); cdecl;
IStatement_getMaxInlineBlobSizePtr = function(this: IStatement; status: IStatus): Cardinal; cdecl;
IStatement_setMaxInlineBlobSizePtr = procedure(this: IStatement; status: IStatus; size: Cardinal); cdecl;
IBatch_addPtr = procedure(this: IBatch; status: IStatus; count: Cardinal; inBuffer: Pointer); cdecl;
IBatch_addBlobPtr = procedure(this: IBatch; status: IStatus; length: Cardinal; inBuffer: Pointer; blobId: ISC_QUADPtr; parLength: Cardinal; par: BytePtr); cdecl;
IBatch_appendBlobDataPtr = procedure(this: IBatch; status: IStatus; length: Cardinal; inBuffer: Pointer); cdecl;
@ -414,6 +416,10 @@ type
IAttachment_createReplicatorPtr = function(this: IAttachment; status: IStatus): IReplicator; cdecl;
IAttachment_detachPtr = procedure(this: IAttachment; status: IStatus); cdecl;
IAttachment_dropDatabasePtr = procedure(this: IAttachment; status: IStatus); cdecl;
IAttachment_getMaxBlobCacheSizePtr = function(this: IAttachment; status: IStatus): Cardinal; cdecl;
IAttachment_setMaxBlobCacheSizePtr = procedure(this: IAttachment; status: IStatus; size: Cardinal); cdecl;
IAttachment_getMaxInlineBlobSizePtr = function(this: IAttachment; status: IStatus): Cardinal; cdecl;
IAttachment_setMaxInlineBlobSizePtr = procedure(this: IAttachment; status: IStatus; size: Cardinal); cdecl;
IService_deprecatedDetachPtr = procedure(this: IService; status: IStatus); cdecl;
IService_queryPtr = procedure(this: IService; status: IStatus; sendLength: Cardinal; sendItems: BytePtr; receiveLength: Cardinal; receiveItems: BytePtr; bufferLength: Cardinal; buffer: BytePtr); cdecl;
IService_startPtr = procedure(this: IService; status: IStatus; spbLength: Cardinal; spb: BytePtr); cdecl;
@ -1523,10 +1529,12 @@ type
setTimeout: IStatement_setTimeoutPtr;
createBatch: IStatement_createBatchPtr;
free: IStatement_freePtr;
getMaxInlineBlobSize: IStatement_getMaxInlineBlobSizePtr;
setMaxInlineBlobSize: IStatement_setMaxInlineBlobSizePtr;
end;
IStatement = class(IReferenceCounted)
const VERSION = 5;
const VERSION = 6;
const PREPARE_PREFETCH_NONE = Cardinal($0);
const PREPARE_PREFETCH_TYPE = Cardinal($1);
const PREPARE_PREFETCH_INPUT_PARAMETERS = Cardinal($2);
@ -1557,6 +1565,8 @@ type
procedure setTimeout(status: IStatus; timeOut: Cardinal);
function createBatch(status: IStatus; inMetadata: IMessageMetadata; parLength: Cardinal; par: BytePtr): IBatch;
procedure free(status: IStatus);
function getMaxInlineBlobSize(status: IStatus): Cardinal;
procedure setMaxInlineBlobSize(status: IStatus; size: Cardinal);
end;
IStatementImpl = class(IStatement)
@ -1579,6 +1589,8 @@ type
procedure setTimeout(status: IStatus; timeOut: Cardinal); virtual; abstract;
function createBatch(status: IStatus; inMetadata: IMessageMetadata; parLength: Cardinal; par: BytePtr): IBatch; virtual; abstract;
procedure free(status: IStatus); virtual; abstract;
function getMaxInlineBlobSize(status: IStatus): Cardinal; virtual; abstract;
procedure setMaxInlineBlobSize(status: IStatus; size: Cardinal); virtual; abstract;
end;
BatchVTable = class(ReferenceCountedVTable)
@ -1792,10 +1804,14 @@ type
createReplicator: IAttachment_createReplicatorPtr;
detach: IAttachment_detachPtr;
dropDatabase: IAttachment_dropDatabasePtr;
getMaxBlobCacheSize: IAttachment_getMaxBlobCacheSizePtr;
setMaxBlobCacheSize: IAttachment_setMaxBlobCacheSizePtr;
getMaxInlineBlobSize: IAttachment_getMaxInlineBlobSizePtr;
setMaxInlineBlobSize: IAttachment_setMaxInlineBlobSizePtr;
end;
IAttachment = class(IReferenceCounted)
const VERSION = 5;
const VERSION = 6;
procedure getInfo(status: IStatus; itemsLength: Cardinal; items: BytePtr; bufferLength: Cardinal; buffer: BytePtr);
function startTransaction(status: IStatus; tpbLength: Cardinal; tpb: BytePtr): ITransaction;
@ -1823,6 +1839,10 @@ type
function createReplicator(status: IStatus): IReplicator;
procedure detach(status: IStatus);
procedure dropDatabase(status: IStatus);
function getMaxBlobCacheSize(status: IStatus): Cardinal;
procedure setMaxBlobCacheSize(status: IStatus; size: Cardinal);
function getMaxInlineBlobSize(status: IStatus): Cardinal;
procedure setMaxInlineBlobSize(status: IStatus; size: Cardinal);
end;
IAttachmentImpl = class(IAttachment)
@ -1856,6 +1876,10 @@ type
function createReplicator(status: IStatus): IReplicator; virtual; abstract;
procedure detach(status: IStatus); virtual; abstract;
procedure dropDatabase(status: IStatus); virtual; abstract;
function getMaxBlobCacheSize(status: IStatus): Cardinal; virtual; abstract;
procedure setMaxBlobCacheSize(status: IStatus; size: Cardinal); virtual; abstract;
function getMaxInlineBlobSize(status: IStatus): Cardinal; virtual; abstract;
procedure setMaxInlineBlobSize(status: IStatus; size: Cardinal); virtual; abstract;
end;
ServiceVTable = class(ReferenceCountedVTable)
@ -7220,6 +7244,29 @@ begin
FbException.checkException(status);
end;
function IStatement.getMaxInlineBlobSize(status: IStatus): Cardinal;
begin
if (vTable.version < 6) then begin
FbException.setVersionError(status, 'IStatement', vTable.version, 6);
Result := 0;
end
else begin
Result := StatementVTable(vTable).getMaxInlineBlobSize(Self, status);
end;
FbException.checkException(status);
end;
procedure IStatement.setMaxInlineBlobSize(status: IStatus; size: Cardinal);
begin
if (vTable.version < 6) then begin
FbException.setVersionError(status, 'IStatement', vTable.version, 6);
end
else begin
StatementVTable(vTable).setMaxInlineBlobSize(Self, status, size);
end;
FbException.checkException(status);
end;
procedure IBatch.add(status: IStatus; count: Cardinal; inBuffer: Pointer);
begin
BatchVTable(vTable).add(Self, status, count, inBuffer);
@ -7655,6 +7702,52 @@ begin
FbException.checkException(status);
end;
function IAttachment.getMaxBlobCacheSize(status: IStatus): Cardinal;
begin
if (vTable.version < 6) then begin
FbException.setVersionError(status, 'IAttachment', vTable.version, 6);
Result := 0;
end
else begin
Result := AttachmentVTable(vTable).getMaxBlobCacheSize(Self, status);
end;
FbException.checkException(status);
end;
procedure IAttachment.setMaxBlobCacheSize(status: IStatus; size: Cardinal);
begin
if (vTable.version < 6) then begin
FbException.setVersionError(status, 'IAttachment', vTable.version, 6);
end
else begin
AttachmentVTable(vTable).setMaxBlobCacheSize(Self, status, size);
end;
FbException.checkException(status);
end;
function IAttachment.getMaxInlineBlobSize(status: IStatus): Cardinal;
begin
if (vTable.version < 6) then begin
FbException.setVersionError(status, 'IAttachment', vTable.version, 6);
Result := 0;
end
else begin
Result := AttachmentVTable(vTable).getMaxInlineBlobSize(Self, status);
end;
FbException.checkException(status);
end;
procedure IAttachment.setMaxInlineBlobSize(status: IStatus; size: Cardinal);
begin
if (vTable.version < 6) then begin
FbException.setVersionError(status, 'IAttachment', vTable.version, 6);
end
else begin
AttachmentVTable(vTable).setMaxInlineBlobSize(Self, status, size);
end;
FbException.checkException(status);
end;
procedure IService.deprecatedDetach(status: IStatus);
begin
ServiceVTable(vTable).deprecatedDetach(Self, status);
@ -11577,6 +11670,25 @@ begin
end
end;
function IStatementImpl_getMaxInlineBlobSizeDispatcher(this: IStatement; status: IStatus): Cardinal; cdecl;
begin
Result := 0;
try
Result := IStatementImpl(this).getMaxInlineBlobSize(status);
except
on e: Exception do FbException.catchException(status, e);
end
end;
procedure IStatementImpl_setMaxInlineBlobSizeDispatcher(this: IStatement; status: IStatus; size: Cardinal); cdecl;
begin
try
IStatementImpl(this).setMaxInlineBlobSize(status, size);
except
on e: Exception do FbException.catchException(status, e);
end
end;
var
IStatementImpl_vTable: StatementVTable;
@ -12253,6 +12365,44 @@ begin
end
end;
function IAttachmentImpl_getMaxBlobCacheSizeDispatcher(this: IAttachment; status: IStatus): Cardinal; cdecl;
begin
Result := 0;
try
Result := IAttachmentImpl(this).getMaxBlobCacheSize(status);
except
on e: Exception do FbException.catchException(status, e);
end
end;
procedure IAttachmentImpl_setMaxBlobCacheSizeDispatcher(this: IAttachment; status: IStatus; size: Cardinal); cdecl;
begin
try
IAttachmentImpl(this).setMaxBlobCacheSize(status, size);
except
on e: Exception do FbException.catchException(status, e);
end
end;
function IAttachmentImpl_getMaxInlineBlobSizeDispatcher(this: IAttachment; status: IStatus): Cardinal; cdecl;
begin
Result := 0;
try
Result := IAttachmentImpl(this).getMaxInlineBlobSize(status);
except
on e: Exception do FbException.catchException(status, e);
end
end;
procedure IAttachmentImpl_setMaxInlineBlobSizeDispatcher(this: IAttachment; status: IStatus; size: Cardinal); cdecl;
begin
try
IAttachmentImpl(this).setMaxInlineBlobSize(status, size);
except
on e: Exception do FbException.catchException(status, e);
end
end;
var
IAttachmentImpl_vTable: AttachmentVTable;
@ -17319,7 +17469,7 @@ initialization
IResultSetImpl_vTable.getInfo := @IResultSetImpl_getInfoDispatcher;
IStatementImpl_vTable := StatementVTable.create;
IStatementImpl_vTable.version := 5;
IStatementImpl_vTable.version := 6;
IStatementImpl_vTable.addRef := @IStatementImpl_addRefDispatcher;
IStatementImpl_vTable.release := @IStatementImpl_releaseDispatcher;
IStatementImpl_vTable.getInfo := @IStatementImpl_getInfoDispatcher;
@ -17337,6 +17487,8 @@ initialization
IStatementImpl_vTable.setTimeout := @IStatementImpl_setTimeoutDispatcher;
IStatementImpl_vTable.createBatch := @IStatementImpl_createBatchDispatcher;
IStatementImpl_vTable.free := @IStatementImpl_freeDispatcher;
IStatementImpl_vTable.getMaxInlineBlobSize := @IStatementImpl_getMaxInlineBlobSizeDispatcher;
IStatementImpl_vTable.setMaxInlineBlobSize := @IStatementImpl_setMaxInlineBlobSizeDispatcher;
IBatchImpl_vTable := BatchVTable.create;
IBatchImpl_vTable.version := 4;
@ -17393,7 +17545,7 @@ initialization
IEventsImpl_vTable.cancel := @IEventsImpl_cancelDispatcher;
IAttachmentImpl_vTable := AttachmentVTable.create;
IAttachmentImpl_vTable.version := 5;
IAttachmentImpl_vTable.version := 6;
IAttachmentImpl_vTable.addRef := @IAttachmentImpl_addRefDispatcher;
IAttachmentImpl_vTable.release := @IAttachmentImpl_releaseDispatcher;
IAttachmentImpl_vTable.getInfo := @IAttachmentImpl_getInfoDispatcher;
@ -17422,6 +17574,10 @@ initialization
IAttachmentImpl_vTable.createReplicator := @IAttachmentImpl_createReplicatorDispatcher;
IAttachmentImpl_vTable.detach := @IAttachmentImpl_detachDispatcher;
IAttachmentImpl_vTable.dropDatabase := @IAttachmentImpl_dropDatabaseDispatcher;
IAttachmentImpl_vTable.getMaxBlobCacheSize := @IAttachmentImpl_getMaxBlobCacheSizeDispatcher;
IAttachmentImpl_vTable.setMaxBlobCacheSize := @IAttachmentImpl_setMaxBlobCacheSizeDispatcher;
IAttachmentImpl_vTable.getMaxInlineBlobSize := @IAttachmentImpl_getMaxInlineBlobSizeDispatcher;
IAttachmentImpl_vTable.setMaxInlineBlobSize := @IAttachmentImpl_setMaxInlineBlobSizeDispatcher;
IServiceImpl_vTable := ServiceVTable.create;
IServiceImpl_vTable.version := 5;

View File

@ -307,6 +307,9 @@ public:
JBatch* createBatch(Firebird::CheckStatusWrapper* status, Firebird::IMessageMetadata* inMetadata,
unsigned parLength, const unsigned char* par) override;
unsigned getMaxInlineBlobSize(Firebird::CheckStatusWrapper* status) override;
void setMaxInlineBlobSize(Firebird::CheckStatusWrapper* status, unsigned size) override;
public:
JStatement(DsqlRequest* handle, StableAttachmentPart* sa, Firebird::Array<UCHAR>& meta);
@ -460,6 +463,10 @@ public:
Firebird::IMessageMetadata* inMetadata, unsigned parLength, const unsigned char* par) override;
Firebird::IReplicator* createReplicator(Firebird::CheckStatusWrapper* status) override;
unsigned getMaxBlobCacheSize(Firebird::CheckStatusWrapper* status) override;
void setMaxBlobCacheSize(Firebird::CheckStatusWrapper* status, unsigned size) override;
unsigned getMaxInlineBlobSize(Firebird::CheckStatusWrapper* status) override;
void setMaxInlineBlobSize(Firebird::CheckStatusWrapper* status, unsigned size) override;
public:
explicit JAttachment(StableAttachmentPart* js);

View File

@ -5308,6 +5308,28 @@ IReplicator* JAttachment::createReplicator(CheckStatusWrapper* user_status)
return jr;
}
unsigned JAttachment::getMaxBlobCacheSize(CheckStatusWrapper* status)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
return 0;
}
void JAttachment::setMaxBlobCacheSize(CheckStatusWrapper* status, unsigned size)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
}
unsigned JAttachment::getMaxInlineBlobSize(CheckStatusWrapper* status)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
return 0;
}
void JAttachment::setMaxInlineBlobSize(CheckStatusWrapper* status, unsigned size)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
}
int JResultSet::fetchNext(CheckStatusWrapper* user_status, void* buffer)
{
@ -6090,6 +6112,17 @@ JBatch* JStatement::createBatch(Firebird::CheckStatusWrapper* status, Firebird::
return batch;
}
unsigned JStatement::getMaxInlineBlobSize(CheckStatusWrapper* status)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
return 0;
}
void JStatement::setMaxInlineBlobSize(CheckStatusWrapper* status, unsigned size)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
}
JBatch::JBatch(DsqlBatch* handle, JStatement* aStatement, IMessageMetadata* aMetadata)
: batch(handle),

View File

@ -699,6 +699,26 @@ public:
Batch* createBatch(CheckStatusWrapper* status, IMessageMetadata* inMetadata,
unsigned parLength, const unsigned char* par) override;
unsigned getMaxInlineBlobSize(CheckStatusWrapper* status) override
{
if (statement->rsr_rdb->rdb_port->port_protocol < PROTOCOL_INLINE_BLOB)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
return 0;
}
return statement->rsr_inline_blob_size;
}
void setMaxInlineBlobSize(CheckStatusWrapper* status, unsigned size) override
{
if (statement->rsr_rdb->rdb_port->port_protocol < PROTOCOL_INLINE_BLOB)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
return;
}
statement->rsr_inline_blob_size = size;
}
public:
Statement(Rsr* handle, Attachment* a, unsigned aDialect)
: metadata(getPool(), this, NULL),
@ -909,6 +929,12 @@ public:
Replicator* createReplicator(CheckStatusWrapper* status) override;
unsigned getMaxBlobCacheSize(CheckStatusWrapper* status) override;
void setMaxBlobCacheSize(CheckStatusWrapper* status, unsigned size) override;
unsigned getMaxInlineBlobSize(CheckStatusWrapper* status) override;
void setMaxInlineBlobSize(CheckStatusWrapper* status, unsigned size) override;
public:
Attachment(Rdb* handle, const PathName& path)
: replicator(nullptr), rdb(handle), dbPath(getPool(), path)
@ -2445,6 +2471,50 @@ Batch* Attachment::createBatch(CheckStatusWrapper* status, ITransaction* transac
}
unsigned Attachment::getMaxBlobCacheSize(CheckStatusWrapper* status)
{
if (rdb->rdb_port->port_protocol < PROTOCOL_INLINE_BLOB)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
return 0;
}
return rdb->rdb_blob_cache_size;
}
void Attachment::setMaxBlobCacheSize(CheckStatusWrapper* status, unsigned size)
{
if (rdb->rdb_port->port_protocol < PROTOCOL_INLINE_BLOB)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
return;
}
rdb->rdb_blob_cache_size = size;
}
unsigned Attachment::getMaxInlineBlobSize(CheckStatusWrapper* status)
{
if (rdb->rdb_port->port_protocol < PROTOCOL_INLINE_BLOB)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
return 0;
}
return rdb->rdb_inline_blob_size;
}
void Attachment::setMaxInlineBlobSize(CheckStatusWrapper* status, unsigned size)
{
if (rdb->rdb_port->port_protocol < PROTOCOL_INLINE_BLOB)
{
status->setErrors(Arg::Gds(isc_wish_list).value());
return;
}
rdb->rdb_inline_blob_size = size;
}
Batch* Statement::createBatch(CheckStatusWrapper* status, IMessageMetadata* inMetadata,
unsigned parLength, const unsigned char* par)
{
@ -3573,6 +3643,7 @@ ITransaction* Statement::execute(CheckStatusWrapper* status, ITransaction* apiTr
sqldata->p_sqldata_out_message_number = 0; // out_msg_type
sqldata->p_sqldata_timeout = statement->rsr_timeout;
sqldata->p_sqldata_cursor_flags = 0;
sqldata->p_sqldata_inline_blob_size = statement->rsr_inline_blob_size;
send_packet(port, packet);
@ -3752,6 +3823,7 @@ ResultSet* Statement::openCursor(CheckStatusWrapper* status, ITransaction* apiTr
sqldata->p_sqldata_out_message_number = 0; // out_msg_type
sqldata->p_sqldata_timeout = statement->rsr_timeout;
sqldata->p_sqldata_cursor_flags = flags;
sqldata->p_sqldata_inline_blob_size = statement->rsr_inline_blob_size;
{
Cleanup msgClean([&message] {
@ -3945,6 +4017,8 @@ ITransaction* Attachment::execute(CheckStatusWrapper* status, ITransaction* apiT
ex_now->p_sqlst_out_blr.cstr_length = out_blr_length;
ex_now->p_sqlst_out_blr.cstr_address = const_cast<unsigned char*>(out_blr);
ex_now->p_sqlst_out_message_number = 0; // out_msg_type
ex_now->p_sqlst_inline_blob_size = (packet->p_operation == op_exec_immediate2) ?
rdb->rdb_inline_blob_size : 0;
send_packet(port, packet);
@ -4156,6 +4230,7 @@ Statement* Attachment::createStatement(CheckStatusWrapper* status, unsigned dial
statement->rsr_next = rdb->rdb_sql_requests;
rdb->rdb_sql_requests = statement;
statement->rsr_inline_blob_size = rdb->rdb_inline_blob_size;
Statement* s = FB_NEW Statement(statement, this, dialect);
s->addRef();
@ -9287,7 +9362,10 @@ static void release_blob( Rbl* blob)
Rtr* transaction = blob->rbl_rtr;
Rdb* rdb = blob->rbl_rdb;
if (!blob->isCached())
if (blob->isCached())
// Assume buffer was not resized while blob was cached
rdb->decBlobCache(blob->rbl_buffer_length);
else
rdb->rdb_port->releaseObject(blob->rbl_id);
if (transaction->rtr_blobs.locate(blob->rbl_blob_id))

View File

@ -670,6 +670,8 @@ bool_t xdr_protocol(RemoteXdr* xdrs, PACKET* p)
MAP(xdr_u_long, sqldata->p_sqldata_timeout);
if (port->port_protocol >= PROTOCOL_FETCH_SCROLL)
MAP(xdr_u_long, sqldata->p_sqldata_cursor_flags);
if (port->port_protocol >= PROTOCOL_INLINE_BLOB)
MAP(xdr_u_long, sqldata->p_sqldata_inline_blob_size);
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
@ -691,6 +693,10 @@ bool_t xdr_protocol(RemoteXdr* xdrs, PACKET* p)
return P_FALSE(xdrs, p);
}
MAP(xdr_short, reinterpret_cast<SSHORT&>(prep_stmt->p_sqlst_out_message_number));
if (port->port_protocol >= PROTOCOL_INLINE_BLOB)
MAP(xdr_u_long, prep_stmt->p_sqlst_inline_blob_size);
// Fall into ...
case op_exec_immediate:

View File

@ -630,6 +630,7 @@ typedef struct p_sqlst
CSTRING p_sqlst_out_blr; // blr describing output message
USHORT p_sqlst_out_message_number;
USHORT p_sqlst_flags; // prepare flags
ULONG p_sqlst_inline_blob_size; // maximum size of inlined blob
} P_SQLST;
typedef struct p_sqldata
@ -647,6 +648,7 @@ typedef struct p_sqldata
ULONG p_sqldata_cursor_flags; // cursor flags
P_FETCH p_sqldata_fetch_op; // Fetch operation
SLONG p_sqldata_fetch_pos; // Fetch position
ULONG p_sqldata_inline_blob_size; // maximum size of inlined blob
} P_SQLDATA;
typedef struct p_sqlfree

View File

@ -985,6 +985,13 @@ void Rtr::setupInlineBlob(P_INLINE_BLOB* p_blob)
Rbl* blb = rtr_inline_blob;
rtr_inline_blob = nullptr;
blb->rbl_buffer_length = blb->rbl_data.getCapacity();
if (!rtr_rdb->incBlobCache(blb->rbl_buffer_length))
{
delete blb;
return;
}
blb->rbl_blob_id = p_blob->p_blob_id;
if (!rtr_blobs.add(blb))
{
@ -995,6 +1002,7 @@ void Rtr::setupInlineBlob(P_INLINE_BLOB* p_blob)
fb_assert(blb != old);
delete blb;
rtr_rdb->decBlobCache(blb->rbl_buffer_length);
return;
}

View File

@ -104,6 +104,9 @@ const ULONG MAX_ROWS_PER_BATCH = 1000;
const ULONG MAX_BATCH_CACHE_SIZE = 1024 * 1024; // 1 MB
const ULONG DEFAULT_BLOBS_CACHE_SIZE = 10 * 1024 * 1024; // 10 MB
const ULONG DEFAULT_INLINE_BLOB_SIZE = BLOB_LENGTH;
// fwd. decl.
namespace Firebird {
class Exception;
@ -181,15 +184,44 @@ private:
public:
std::atomic<int> rdb_async_lock; // Atomic to avoid >1 async calls at once
ULONG rdb_inline_blob_size; // default max size of blob that can be transfered inline
ULONG rdb_blob_cache_size; // limit on cached blobs size
ULONG rdb_cached_blobs_size; // actual size of cached blobs
ULONG rdb_cached_blobs_count; // actual count of cached blobs
public:
Rdb() :
rdb_iface(NULL), rdb_port(0),
rdb_transactions(0), rdb_requests(0), rdb_events(0), rdb_sql_requests(0),
rdb_id(0), rdb_async_thread_id(0), rdb_async_lock(0)
rdb_id(0), rdb_async_thread_id(0), rdb_async_lock(0),
rdb_inline_blob_size(DEFAULT_INLINE_BLOB_SIZE), rdb_blob_cache_size(DEFAULT_BLOBS_CACHE_SIZE),
rdb_cached_blobs_size(0), rdb_cached_blobs_count(0)
{
}
static ISC_STATUS badHandle() { return isc_bad_db_handle; }
// Increment blob cache usage.
// Return false if blob cache have not enough space for a blob of given size.
bool incBlobCache(ULONG size)
{
if (rdb_cached_blobs_size + size > rdb_blob_cache_size)
return false;
rdb_cached_blobs_size += size;
rdb_cached_blobs_count++;
return true;
}
// Decrement blob cache usage.
void decBlobCache(ULONG size)
{
fb_assert(rdb_cached_blobs_size >= size);
fb_assert(rdb_cached_blobs_count > 0);
rdb_cached_blobs_size -= size;
rdb_cached_blobs_count--;
}
};
@ -550,6 +582,7 @@ struct Rsr : public Firebird::GlobalStorage, public TypedHandle<rem_type_rsr>
P_FETCH rsr_fetch_operation; // Last performed fetch operation
SLONG rsr_fetch_position; // and position
unsigned int rsr_inline_blob_size; // max size of blob that can be transfered inline
struct BatchStream
{
@ -604,7 +637,7 @@ public:
rsr_rows_pending(0), rsr_msgs_waiting(0), rsr_reorder_level(0), rsr_batch_count(0),
rsr_cursor_name(getPool()), rsr_delayed_format(false), rsr_timeout(0), rsr_self(NULL),
rsr_batch_size(0), rsr_batch_flags(0), rsr_batch_ics(NULL),
rsr_fetch_operation(fetch_next), rsr_fetch_position(0)
rsr_fetch_operation(fetch_next), rsr_fetch_position(0), rsr_inline_blob_size(0)
{ }
~Rsr()
@ -1612,10 +1645,10 @@ public:
private:
bool tryKeyType(const KnownServerKey& srvKey, InternalCryptKey* cryptKey);
void sendInlineBlobs(PACKET*, Rtr* rtr, UCHAR* message, const rem_fmt* format);
void sendInlineBlobs(PACKET*, Rtr* rtr, UCHAR* message, const rem_fmt* format, ULONG maxSize);
// return false if any error retrieving blob happens
bool sendInlineBlob(PACKET*, Rtr* rtr, SQUAD blobId);
bool sendInlineBlob(PACKET*, Rtr* rtr, SQUAD blobId, ULONG maxSize);
};

View File

@ -3512,8 +3512,9 @@ ISC_STATUS rem_port::execute_immediate(P_OP op, P_SQLST * exnow, PACKET* sendL)
{
this->port_statement->rsr_format = this->port_statement->rsr_select_format;
if (out_msg)
sendInlineBlobs(sendL, transaction, out_msg, port_statement->rsr_select_format);
if (out_msg && exnow->p_sqlst_inline_blob_size)
sendInlineBlobs(sendL, transaction, out_msg, port_statement->rsr_select_format,
exnow->p_sqlst_inline_blob_size);
sendL->p_operation = op_sql_response;
sendL->p_sqldata.p_sqldata_messages =
@ -3950,12 +3951,15 @@ ISC_STATUS rem_port::execute_statement(P_OP op, P_SQLDATA* sqldata, PACKET* send
iMsgBuffer.metadata, iMsgBuffer.buffer, oMsgBuffer.metadata, oMsgBuffer.buffer);
}
statement->rsr_inline_blob_size = sqldata->p_sqldata_inline_blob_size;
if (op == op_execute2)
{
this->port_statement->rsr_format = this->port_statement->rsr_select_format;
if (out_msg)
sendInlineBlobs(sendL, transaction, out_msg, port_statement->rsr_select_format);
if (out_msg && statement->rsr_inline_blob_size)
sendInlineBlobs(sendL, transaction, out_msg, port_statement->rsr_select_format,
statement->rsr_inline_blob_size);
sendL->p_operation = op_sql_response;
sendL->p_sqldata.p_sqldata_messages =
@ -4256,12 +4260,12 @@ ISC_STATUS rem_port::fetch(P_SQLDATA * sqldata, PACKET* sendL, bool scroll)
}
// send blob data inline
if (statement->haveBlobs())
if (statement->haveBlobs() && statement->rsr_inline_blob_size)
{
AutoSaveRestore op(&sendL->p_operation);
sendInlineBlobs(sendL, statement->rsr_rtr, message->msg_buffer,
statement->rsr_select_format);
statement->rsr_select_format, statement->rsr_inline_blob_size);
}
// There's a buffer waiting -- send it
@ -5996,7 +6000,8 @@ ISC_STATUS rem_port::seek_blob(P_SEEK* seek, PACKET* sendL)
}
void rem_port::sendInlineBlobs(PACKET* sendL, Rtr* rtr, UCHAR* message, const rem_fmt* format)
void rem_port::sendInlineBlobs(PACKET* sendL, Rtr* rtr, UCHAR* message,
const rem_fmt* format, ULONG maxSize)
{
if (port_protocol < PROTOCOL_INLINE_BLOB || port_type == XNET)
return;
@ -6016,13 +6021,13 @@ void rem_port::sendInlineBlobs(PACKET* sendL, Rtr* rtr, UCHAR* message, const re
if (*blobId == NULL_BLOB)
continue;
if (!sendInlineBlob(sendL, rtr, *blobId))
if (!sendInlineBlob(sendL, rtr, *blobId, maxSize))
break;
}
}
bool rem_port::sendInlineBlob(PACKET* sendL, Rtr* rtr, SQUAD blobId)
bool rem_port::sendInlineBlob(PACKET* sendL, Rtr* rtr, SQUAD blobId, ULONG maxSize)
{
P_INLINE_BLOB* p_blob = &sendL->p_inline_blob;
@ -6039,7 +6044,7 @@ bool rem_port::sendInlineBlob(PACKET* sendL, Rtr* rtr, SQUAD blobId)
return false;
// ask blob info
const UCHAR items[] = {
const UCHAR items[] = {
isc_info_blob_num_segments,
isc_info_blob_max_segment,
isc_info_blob_total_length,
@ -6087,8 +6092,7 @@ bool rem_port::sendInlineBlob(PACKET* sendL, Rtr* rtr, SQUAD blobId)
if (!total_length)
return true;
// todo: set max inline blob size
if (total_length > 16384)
if (total_length > maxSize)
return true;
if (!segmented)

View File

@ -477,6 +477,9 @@ public:
YBatch* createBatch(Firebird::CheckStatusWrapper* status, Firebird::IMessageMetadata* inMetadata,
unsigned parLength, const unsigned char* par);
unsigned getMaxInlineBlobSize(Firebird::CheckStatusWrapper* status) override;
void setMaxInlineBlobSize(Firebird::CheckStatusWrapper* status, unsigned size) override;
public:
AtomicAttPtr attachment;
Firebird::Mutex statementMutex;
@ -579,6 +582,11 @@ public:
Firebird::IMessageMetadata* inMetadata, unsigned parLength, const unsigned char* par);
YReplicator* createReplicator(Firebird::CheckStatusWrapper* status);
unsigned getMaxBlobCacheSize(Firebird::CheckStatusWrapper* status) override;
void setMaxBlobCacheSize(Firebird::CheckStatusWrapper* status, unsigned size) override;
unsigned getMaxInlineBlobSize(Firebird::CheckStatusWrapper* status) override;
void setMaxInlineBlobSize(Firebird::CheckStatusWrapper* status, unsigned size) override;
public:
Firebird::IProvider* provider;
Firebird::PathName dbPath;

View File

@ -4582,6 +4582,36 @@ YBatch* YStatement::createBatch(CheckStatusWrapper* status, IMessageMetadata* in
return NULL;
}
unsigned YStatement::getMaxInlineBlobSize(CheckStatusWrapper* status)
{
try
{
YEntry<YStatement> entry(status, this);
return entry.next()->getMaxInlineBlobSize(status);
}
catch (const Exception& e)
{
e.stuffException(status);
}
return 0;
}
void YStatement::setMaxInlineBlobSize(CheckStatusWrapper* status, unsigned size)
{
try
{
YEntry<YStatement> entry(status, this);
entry.next()->setMaxInlineBlobSize(status, size);
}
catch (const Exception& e)
{
e.stuffException(status);
}
}
//-------------------------------------
IscStatement::~IscStatement()
@ -6220,6 +6250,66 @@ YReplicator* YAttachment::createReplicator(CheckStatusWrapper* status)
}
unsigned YAttachment::getMaxBlobCacheSize(CheckStatusWrapper* status)
{
try
{
YEntry<YAttachment> entry(status, this);
return entry.next()->getMaxBlobCacheSize(status);
}
catch (const Exception& e)
{
e.stuffException(status);
}
return 0;
}
void YAttachment::setMaxBlobCacheSize(CheckStatusWrapper* status, unsigned size)
{
try
{
YEntry<YAttachment> entry(status, this);
entry.next()->setMaxBlobCacheSize(status, size);
}
catch (const Exception& e)
{
e.stuffException(status);
}
}
unsigned YAttachment::getMaxInlineBlobSize(CheckStatusWrapper* status)
{
try
{
YEntry<YAttachment> entry(status, this);
return entry.next()->getMaxInlineBlobSize(status);
}
catch (const Exception& e)
{
e.stuffException(status);
}
return 0;
}
void YAttachment::setMaxInlineBlobSize(CheckStatusWrapper* status, unsigned size)
{
try
{
YEntry<YAttachment> entry(status, this);
entry.next()->setMaxInlineBlobSize(status, size);
}
catch (const Exception& e)
{
e.stuffException(status);
}
}
//-------------------------------------