Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
371 lines (311 sloc) 7.14 KB
/*
* PROGRAM: Firebird interface.
* MODULE: firebird/Interface.h
* DESCRIPTION: Base class for all FB interfaces / plugins.
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Alex Peshkov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2010 Alex Peshkov <peshkoff at mail.ru>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*
*/
#ifndef FB_INTERFACE_H
#define FB_INTERFACE_H
#include "ibase.h"
#include <assert.h>
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#define CLOOP_CARG __cdecl
#endif
struct dsc;
struct PerformanceInfo;
#include "IdlFbInterfaces.h"
namespace Firebird
{
class FbException
{
public:
FbException(IStatus* aStatus, const ISC_STATUS* vector)
{
aStatus->setErrors(vector);
status = aStatus->clone();
}
FbException(IStatus* aStatus)
: status(aStatus->clone())
{
}
FbException(const FbException& copy)
: status(copy.status->clone())
{
}
FbException& operator =(const FbException& copy)
{
status->dispose();
status = copy.status->clone();
return *this;
}
virtual ~FbException()
{
status->dispose();
}
public:
static void check(ISC_STATUS code, IStatus* status, const ISC_STATUS* vector)
{
if (code != 0 && vector[1])
throw FbException(status, vector);
}
public:
IStatus* getStatus() const
{
return status;
}
private:
IStatus* status;
};
template <typename T>
class BaseStatusWrapper : public IStatusImpl<T, T>
{
public:
BaseStatusWrapper(IStatus* aStatus)
: status(aStatus),
dirty(false)
{
}
public:
static void catchException(IStatus* status)
{
if (!status)
return;
try
{
throw;
}
catch (const FbException& e)
{
status->setErrors(e.getStatus()->getErrors());
}
catch (...)
{
ISC_STATUS statusVector[] = {
isc_arg_gds, isc_random,
isc_arg_string, (ISC_STATUS) "Unrecognized C++ exception",
isc_arg_end};
status->setErrors(statusVector);
}
}
static void clearException(BaseStatusWrapper* status)
{
status->clearException();
}
void clearException()
{
if (dirty)
{
dirty = false;
status->init();
}
}
bool isDirty() const
{
return dirty;
}
bool hasData() const
{
return getState() & IStatus::STATE_ERRORS;
}
bool isEmpty() const
{
return !hasData();
}
static void setVersionError(IStatus* status, const char* interfaceName,
unsigned currentVersion, unsigned expectedVersion)
{
intptr_t codes[] = {
isc_arg_gds,
isc_interface_version_too_old,
isc_arg_number,
(intptr_t) expectedVersion,
isc_arg_number,
(intptr_t) currentVersion,
isc_arg_string,
(intptr_t) interfaceName,
isc_arg_end
};
status->setErrors(codes);
}
public:
virtual void dispose()
{
// Disposes only the delegated status. Let the user destroy this instance.
status->dispose();
}
virtual void init()
{
clearException();
}
virtual unsigned getState() const
{
return dirty ? status->getState() : 0;
}
virtual void setErrors2(unsigned length, const intptr_t* value)
{
dirty = true;
status->setErrors2(length, value);
}
virtual void setWarnings2(unsigned length, const intptr_t* value)
{
dirty = true;
status->setWarnings2(length, value);
}
virtual void setErrors(const intptr_t* value)
{
dirty = true;
status->setErrors(value);
}
virtual void setWarnings(const intptr_t* value)
{
dirty = true;
status->setWarnings(value);
}
virtual const intptr_t* getErrors() const
{
return dirty ? status->getErrors() : cleanStatus();
}
virtual const intptr_t* getWarnings() const
{
return dirty ? status->getWarnings() : cleanStatus();
}
virtual IStatus* clone() const
{
return status->clone();
}
protected:
IStatus* status;
bool dirty;
static const intptr_t* cleanStatus()
{
static intptr_t clean[3] = {1, 0, 0};
return clean;
}
};
class CheckStatusWrapper : public BaseStatusWrapper<CheckStatusWrapper>
{
public:
CheckStatusWrapper(IStatus* aStatus)
: BaseStatusWrapper(aStatus)
{
}
public:
static void checkException(CheckStatusWrapper* status)
{
}
};
class ThrowStatusWrapper : public BaseStatusWrapper<ThrowStatusWrapper>
{
public:
ThrowStatusWrapper(IStatus* aStatus)
: BaseStatusWrapper(aStatus)
{
}
public:
static void checkException(ThrowStatusWrapper* status)
{
if (status->dirty && (status->getState() & IStatus::STATE_ERRORS))
throw FbException(status->status);
}
};
#ifdef FB_API_VER // internal hack
class Helper
{
public:
template <typename StatusType>
static isc_db_handle getIscDbHandle(StatusType* status, IAttachment* attachment)
{
if (!attachment)
return 0;
ISC_STATUS_ARRAY statusVector = {0};
isc_db_handle handle = 0;
fb_get_database_handle(statusVector, &handle, attachment);
if (!handle)
{
status->setErrors(statusVector);
StatusType::checkException(status);
}
return handle;
}
template <typename StatusType>
static isc_db_handle getIscDbHandle(StatusType* status, IExternalContext* context)
{
IAttachment* attachment = context->getAttachment(status);
if (!attachment)
return 0;
try
{
isc_db_handle handle = getIscDbHandle(status, attachment);
attachment->release();
return handle;
}
catch (...)
{
attachment->release();
throw;
}
}
template <typename StatusType>
static isc_tr_handle getIscTrHandle(StatusType* status, ITransaction* transaction)
{
if (!transaction)
return 0;
ISC_STATUS_ARRAY statusVector = {0};
isc_tr_handle handle = 0;
fb_get_transaction_handle(statusVector, &handle, transaction);
if (!handle)
{
status->setErrors(statusVector);
StatusType::checkException(status);
}
return handle;
}
template <typename StatusType>
static isc_tr_handle getIscTrHandle(StatusType* status, IExternalContext* context)
{
ITransaction* transaction = context->getTransaction(status);
if (!transaction)
return 0;
try
{
isc_tr_handle handle = getIscTrHandle(status, transaction);
transaction->release();
return handle;
}
catch (...)
{
transaction->release();
throw;
}
}
};
#endif // FB_API_VER
// Additional API function.
// Should be used only in non-plugin modules.
// All plugins including providers should use passed at init time interface instead.
extern "C" IMaster* ISC_EXPORT fb_get_master_interface();
} // namespace Firebird
#define FB_PLUGIN_ENTRY_POINT firebird_plugin
#define FB_UDR_PLUGIN_ENTRY_POINT firebird_udr_plugin
#endif // FB_INTERFACE_H
You can’t perform that action at this time.