Skip to content

Commit

Permalink
Fixed #7579: Cannot nbackup a firebird 3.0 database in firebird 4.0 s…
Browse files Browse the repository at this point in the history
…ervice with engine12 setup in Providers
  • Loading branch information
AlexPeshkoff committed Jun 6, 2023
1 parent 244a515 commit 5e77de7
Show file tree
Hide file tree
Showing 12 changed files with 251 additions and 68 deletions.
5 changes: 5 additions & 0 deletions src/common/classes/ClumpletWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ void ClumpletWriter::reset(const UCHAR* buffer, const FB_SIZE_T buffLen)
rewind();
}

void ClumpletWriter::reset(const ClumpletWriter& from)
{
reset(from.getBuffer(), from.getBufferEnd() - from.getBuffer());
}

void ClumpletWriter::size_overflow()
{
fatal_exception::raise("Clumplet buffer size limit reached");
Expand Down
1 change: 1 addition & 0 deletions src/common/classes/ClumpletWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class ClumpletWriter : public ClumpletReader

void reset(UCHAR tag = 0);
void reset(const UCHAR* buffer, const FB_SIZE_T buffLen);
void reset(const ClumpletWriter& from);
void clear();

// Methods to create new clumplet at current position
Expand Down
7 changes: 7 additions & 0 deletions src/include/firebird/FirebirdInterface.idl
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,10 @@ version: // 3.0.9 => 3.0.10, 4.0.1 => 4.0.2

interface Provider : PluginBase
{
const uint PTYPE_ANY = 0;
const uint PTYPE_LOCAL = 1;
const uint PTYPE_NETWORK = 2;

Attachment attachDatabase(Status status, const string fileName,
uint dpbLength, const uchar* dpb);
Attachment createDatabase(Status status, const string fileName,
Expand All @@ -742,6 +746,9 @@ interface Provider : PluginBase
uint spbLength, const uchar* spb);
void shutdown(Status status, uint timeout, const int reason);
void setDbCryptCallback(Status status, CryptKeyCallback cryptCallback);

version: // 3.0.10 => 3.0.11, 4.0.2 => 4.0.3
uint getType(Status status);
}

// Helper to start transaction over >1 attachments (former TEB)
Expand Down
38 changes: 37 additions & 1 deletion src/include/firebird/IdlFbInterfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -2881,7 +2881,7 @@ namespace Firebird
}
};

#define FIREBIRD_IPROVIDER_VERSION 4u
#define FIREBIRD_IPROVIDER_VERSION 5u

class IProvider : public IPluginBase
{
Expand All @@ -2893,6 +2893,7 @@ namespace Firebird
IService* (CLOOP_CARG *attachServiceManager)(IProvider* self, IStatus* status, const char* service, unsigned spbLength, const unsigned char* spb) CLOOP_NOEXCEPT;
void (CLOOP_CARG *shutdown)(IProvider* self, IStatus* status, unsigned timeout, const int reason) CLOOP_NOEXCEPT;
void (CLOOP_CARG *setDbCryptCallback)(IProvider* self, IStatus* status, ICryptKeyCallback* cryptCallback) CLOOP_NOEXCEPT;
unsigned (CLOOP_CARG *getType)(IProvider* self, IStatus* status) CLOOP_NOEXCEPT;
};

protected:
Expand All @@ -2908,6 +2909,10 @@ namespace Firebird
public:
static CLOOP_CONSTEXPR unsigned VERSION = FIREBIRD_IPROVIDER_VERSION;

static CLOOP_CONSTEXPR unsigned PTYPE_ANY = 0;
static CLOOP_CONSTEXPR unsigned PTYPE_LOCAL = 1;
static CLOOP_CONSTEXPR unsigned PTYPE_NETWORK = 2;

template <typename StatusType> IAttachment* attachDatabase(StatusType* status, const char* fileName, unsigned dpbLength, const unsigned char* dpb)
{
StatusType::clearException(status);
Expand Down Expand Up @@ -2945,6 +2950,20 @@ namespace Firebird
static_cast<VTable*>(this->cloopVTable)->setDbCryptCallback(this, status, cryptCallback);
StatusType::checkException(status);
}

template <typename StatusType> unsigned getType(StatusType* status)
{
if (cloopVTable->version < 5)
{
StatusType::setVersionError(status, "IProvider", cloopVTable->version, 5);
StatusType::checkException(status);
return 0;
}
StatusType::clearException(status);
unsigned ret = static_cast<VTable*>(this->cloopVTable)->getType(this, status);
StatusType::checkException(status);
return ret;
}
};

#define FIREBIRD_IDTC_START_VERSION 3u
Expand Down Expand Up @@ -12080,6 +12099,7 @@ namespace Firebird
this->attachServiceManager = &Name::cloopattachServiceManagerDispatcher;
this->shutdown = &Name::cloopshutdownDispatcher;
this->setDbCryptCallback = &Name::cloopsetDbCryptCallbackDispatcher;
this->getType = &Name::cloopgetTypeDispatcher;
}
} vTable;

Expand Down Expand Up @@ -12159,6 +12179,21 @@ namespace Firebird
}
}

static unsigned CLOOP_CARG cloopgetTypeDispatcher(IProvider* self, IStatus* status) CLOOP_NOEXCEPT
{
StatusType status2(status);

try
{
return static_cast<Name*>(self)->Name::getType(&status2);
}
catch (...)
{
StatusType::catchException(&status2);
return static_cast<unsigned>(0);
}
}

static void CLOOP_CARG cloopsetOwnerDispatcher(IPluginBase* self, IReferenceCounted* r) CLOOP_NOEXCEPT
{
try
Expand Down Expand Up @@ -12228,6 +12263,7 @@ namespace Firebird
virtual IService* attachServiceManager(StatusType* status, const char* service, unsigned spbLength, const unsigned char* spb) = 0;
virtual void shutdown(StatusType* status, unsigned timeout, const int reason) = 0;
virtual void setDbCryptCallback(StatusType* status, ICryptKeyCallback* cryptCallback) = 0;
virtual unsigned getType(StatusType* status) = 0;
};

template <typename Name, typename StatusType, typename Base>
Expand Down
5 changes: 5 additions & 0 deletions src/include/firebird/Interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ namespace Firebird
return !hasData();
}

bool isSuccess() const
{
return isEmpty();
}

static void setVersionError(IStatus* status, const char* interfaceName,
unsigned currentVersion, unsigned expectedVersion)
{
Expand Down
34 changes: 32 additions & 2 deletions src/include/gen/Firebird.pas
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ ISC_TIMESTAMP_TZ_EX = record
IProvider_attachServiceManagerPtr = function(this: IProvider; status: IStatus; service: PAnsiChar; spbLength: Cardinal; spb: BytePtr): IService; cdecl;
IProvider_shutdownPtr = procedure(this: IProvider; status: IStatus; timeout: Cardinal; reason: Integer); cdecl;
IProvider_setDbCryptCallbackPtr = procedure(this: IProvider; status: IStatus; cryptCallback: ICryptKeyCallback); cdecl;
IProvider_getTypePtr = function(this: IProvider; status: IStatus): Cardinal; cdecl;
IDtcStart_addAttachmentPtr = procedure(this: IDtcStart; status: IStatus; att: IAttachment); cdecl;
IDtcStart_addWithTpbPtr = procedure(this: IDtcStart; status: IStatus; att: IAttachment; length: Cardinal; tpb: BytePtr); cdecl;
IDtcStart_startPtr = function(this: IDtcStart; status: IStatus): ITransaction; cdecl;
Expand Down Expand Up @@ -1879,16 +1880,21 @@ ProviderVTable = class(PluginBaseVTable)
attachServiceManager: IProvider_attachServiceManagerPtr;
shutdown: IProvider_shutdownPtr;
setDbCryptCallback: IProvider_setDbCryptCallbackPtr;
getType: IProvider_getTypePtr;
end;

IProvider = class(IPluginBase)
const VERSION = 4;
const VERSION = 5;
const PTYPE_ANY = Cardinal(0);
const PTYPE_LOCAL = Cardinal(1);
const PTYPE_NETWORK = Cardinal(2);

function attachDatabase(status: IStatus; fileName: PAnsiChar; dpbLength: Cardinal; dpb: BytePtr): IAttachment;
function createDatabase(status: IStatus; fileName: PAnsiChar; dpbLength: Cardinal; dpb: BytePtr): IAttachment;
function attachServiceManager(status: IStatus; service: PAnsiChar; spbLength: Cardinal; spb: BytePtr): IService;
procedure shutdown(status: IStatus; timeout: Cardinal; reason: Integer);
procedure setDbCryptCallback(status: IStatus; cryptCallback: ICryptKeyCallback);
function getType(status: IStatus): Cardinal;
end;

IProviderImpl = class(IProvider)
Expand All @@ -1903,6 +1909,7 @@ IProviderImpl = class(IProvider)
function attachServiceManager(status: IStatus; service: PAnsiChar; spbLength: Cardinal; spb: BytePtr): IService; virtual; abstract;
procedure shutdown(status: IStatus; timeout: Cardinal; reason: Integer); virtual; abstract;
procedure setDbCryptCallback(status: IStatus; cryptCallback: ICryptKeyCallback); virtual; abstract;
function getType(status: IStatus): Cardinal; virtual; abstract;
end;

DtcStartVTable = class(DisposableVTable)
Expand Down Expand Up @@ -7639,6 +7646,18 @@ procedure IProvider.setDbCryptCallback(status: IStatus; cryptCallback: ICryptKey
FbException.checkException(status);
end;

function IProvider.getType(status: IStatus): Cardinal;
begin
if (vTable.version < 5) then begin
FbException.setVersionError(status, 'IProvider', vTable.version, 5);
Result := 0;
end
else begin
Result := ProviderVTable(vTable).getType(Self, status);
end;
FbException.checkException(status);
end;

procedure IDtcStart.addAttachment(status: IStatus; att: IAttachment);
begin
DtcStartVTable(vTable).addAttachment(Self, status, att);
Expand Down Expand Up @@ -12187,6 +12206,16 @@ procedure IProviderImpl_setDbCryptCallbackDispatcher(this: IProvider; status: IS
end
end;

function IProviderImpl_getTypeDispatcher(this: IProvider; status: IStatus): Cardinal; cdecl;
begin
Result := 0;
try
Result := IProviderImpl(this).getType(status);
except
on e: Exception do FbException.catchException(status, e);
end
end;

var
IProviderImpl_vTable: ProviderVTable;

Expand Down Expand Up @@ -17054,7 +17083,7 @@ initialization
IServiceImpl_vTable.cancel := @IServiceImpl_cancelDispatcher;

IProviderImpl_vTable := ProviderVTable.create;
IProviderImpl_vTable.version := 4;
IProviderImpl_vTable.version := 5;
IProviderImpl_vTable.addRef := @IProviderImpl_addRefDispatcher;
IProviderImpl_vTable.release := @IProviderImpl_releaseDispatcher;
IProviderImpl_vTable.setOwner := @IProviderImpl_setOwnerDispatcher;
Expand All @@ -17064,6 +17093,7 @@ initialization
IProviderImpl_vTable.attachServiceManager := @IProviderImpl_attachServiceManagerDispatcher;
IProviderImpl_vTable.shutdown := @IProviderImpl_shutdownDispatcher;
IProviderImpl_vTable.setDbCryptCallback := @IProviderImpl_setDbCryptCallbackDispatcher;
IProviderImpl_vTable.getType := @IProviderImpl_getTypeDispatcher;

IDtcStartImpl_vTable := DtcStartVTable.create;
IDtcStartImpl_vTable.version := 3;
Expand Down
1 change: 1 addition & 0 deletions src/jrd/EngineInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ class JProvider final :
void shutdown(Firebird::CheckStatusWrapper* status, unsigned int timeout, const int reason);
void setDbCryptCallback(Firebird::CheckStatusWrapper* status,
Firebird::ICryptKeyCallback* cryptCb);
unsigned int getType(Firebird::CheckStatusWrapper* status) override;

private:
JAttachment* internalAttach(Firebird::CheckStatusWrapper* status, const char* const fileName,
Expand Down
6 changes: 6 additions & 0 deletions src/jrd/jrd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4463,6 +4463,12 @@ void JService::start(CheckStatusWrapper* user_status, unsigned int spbLength, co
}


unsigned int JProvider::getType(CheckStatusWrapper* status)
{
return PTYPE_LOCAL;
}


void JRequest::startAndSend(CheckStatusWrapper* user_status, ITransaction* tra, int level,
unsigned int msg_type, unsigned int msg_length, const void* msg)
{
Expand Down
5 changes: 5 additions & 0 deletions src/remote/client/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,11 @@ class RProvider : public StdPlugin<IProviderImpl<RProvider, CheckStatusWrapper>
void shutdown(CheckStatusWrapper* status, unsigned int timeout, const int reason);
void setDbCryptCallback(CheckStatusWrapper* status, ICryptKeyCallback* cryptCallback);

unsigned int getType(CheckStatusWrapper* status) override
{
return PTYPE_NETWORK;
}

protected:
IAttachment* attach(CheckStatusWrapper* status, const char* filename, unsigned int dpb_length,
const unsigned char* dpb, bool loopback);
Expand Down
5 changes: 3 additions & 2 deletions src/utilities/gstat/dba.epp
Original file line number Diff line number Diff line change
Expand Up @@ -618,15 +618,16 @@ int gstat(Firebird::UtilSvc* uSvc)
tddba->page_number = -1;
const header_page* header = (const header_page*) db_read((SLONG) 0);

uSvc->started();

if (!Ods::isSupported(header))
{
const int oversion = (header->hdr_ods_version & ~ODS_FIREBIRD_FLAG);
dba_error(3, SafeArg() << ODS_VERSION << oversion);
// msg 3: Wrong ODS version, expected %d, encountered %d?
}

// it's important for provider auto-select to mark as 'started' after possible network error
uSvc->started();

char file_name[1024];
fileName.copyTo(file_name, sizeof(file_name));
dba_print(false, 6, SafeArg() << file_name); // msg 6: \nDatabase \"@1\"\n
Expand Down
21 changes: 15 additions & 6 deletions src/yvalve/YObjects.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@
#include "../common/classes/alloc.h"
#include "../common/classes/array.h"
#include "../common/MsgMetadata.h"

namespace Firebird
{
class ClumpletWriter;
}
#include "../common/classes/ClumpletWriter.h"

namespace Why
{
Expand All @@ -52,6 +48,7 @@ class YService;
class YStatement;
class IscStatement;
class YTransaction;
class Dispatcher;

class YObject
{
Expand Down Expand Up @@ -600,7 +597,7 @@ class YService final :
public:
static const ISC_STATUS ERROR_CODE = isc_bad_svc_handle;

YService(Firebird::IProvider* aProvider, Firebird::IService* aNext, bool utf8);
YService(Firebird::IProvider* aProvider, Firebird::IService* aNext, bool utf8, Dispatcher* yProvider);
~YService();

void shutdown();
Expand All @@ -625,6 +622,11 @@ class YService final :
private:
Firebird::IProvider* provider;
bool utf8Connection; // Client talks to us using UTF8, else - system default charset

public:
Firebird::RefPtr<IService> alternativeHandle;
Firebird::ClumpletWriter attachSpb;
Firebird::RefPtr<Dispatcher> ownProvider;
};

class Dispatcher final :
Expand All @@ -645,10 +647,17 @@ class Dispatcher final :
void shutdown(Firebird::CheckStatusWrapper* status, unsigned int timeout, const int reason);
void setDbCryptCallback(Firebird::CheckStatusWrapper* status,
Firebird::ICryptKeyCallback* cryptCallback);
unsigned int getType(Firebird::CheckStatusWrapper* status);

void destroy(unsigned)
{ }

public:
Firebird::IService* internalServiceAttach(Firebird::CheckStatusWrapper* status,
const Firebird::PathName& svcName, Firebird::ClumpletReader& spb,
std::function<void(Firebird::CheckStatusWrapper*, Firebird::IService*)> start,
const unsigned pt, Firebird::IProvider** retProvider);

private:
YAttachment* attachOrCreateDatabase(Firebird::CheckStatusWrapper* status, bool createFlag,
const char* filename, unsigned int dpbLength, const unsigned char* dpb);
Expand Down
Loading

0 comments on commit 5e77de7

Please sign in to comment.