+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: blob.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
-// Subject : IBPP, Blob class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <cstring>\r
-\r
-using namespace ibpp_internals;\r
-\r
-// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
-\r
-void BlobImpl::Open()\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Blob::Open", _("Blob already opened."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Blob::Open", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Blob::Open", _("No Transaction is attached."));\r
- if (! mIdAssigned)\r
- throw LogicExceptionImpl("Blob::Open", _("Blob Id is not assigned."));\r
-\r
- IBS status;\r
- (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Open", _("isc_open_blob2 failed."));\r
- mWriteMode = false;\r
-}\r
-\r
-void BlobImpl::Create()\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Blob::Create", _("Blob already opened."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Blob::Create", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Blob::Create", _("No Transaction is attached."));\r
-\r
- IBS status;\r
- (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Create",\r
- _("isc_create_blob failed."));\r
- mIdAssigned = true;\r
- mWriteMode = true;\r
-}\r
-\r
-void BlobImpl::Close()\r
-{\r
- if (mHandle == 0) return; // Not opened anyway\r
-\r
- IBS status;\r
- (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Close", _("isc_close_blob failed."));\r
- mHandle = 0;\r
-}\r
-\r
-void BlobImpl::Cancel()\r
-{\r
- if (mHandle == 0) return; // Not opened anyway\r
-\r
- if (! mWriteMode)\r
- throw LogicExceptionImpl("Blob::Cancel", _("Can't cancel a Blob opened for read"));\r
-\r
- IBS status;\r
- (*gds.Call()->m_cancel_blob)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Cancel", _("isc_cancel_blob failed."));\r
- mHandle = 0;\r
- mIdAssigned = false;\r
-}\r
-\r
-int BlobImpl::Read(void* buffer, int size)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Blob::Read", _("The Blob is not opened"));\r
- if (mWriteMode)\r
- throw LogicExceptionImpl("Blob::Read", _("Can't read from Blob opened for write"));\r
- if (size < 1 || size > (64*1024-1))\r
- throw LogicExceptionImpl("Blob::Read", _("Invalid segment size (max 64Kb-1)"));\r
-\r
- IBS status;\r
- unsigned short bytesread;\r
- int result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle, &bytesread,\r
- (unsigned short)size, (char*)buffer);\r
- if (result == isc_segstr_eof) return 0; // Fin du blob\r
- if (result != isc_segment && status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Read", _("isc_get_segment failed."));\r
- return (int)bytesread;\r
-}\r
-\r
-void BlobImpl::Write(const void* buffer, int size)\r
-{\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Blob::Write", _("The Blob is not opened"));\r
- if (! mWriteMode)\r
- throw LogicExceptionImpl("Blob::Write", _("Can't write to Blob opened for read"));\r
- if (size < 1 || size > (64*1024-1))\r
- throw LogicExceptionImpl("Blob::Write", _("Invalid segment size (max 64Kb-1)"));\r
-\r
- IBS status;\r
- (*gds.Call()->m_put_segment)(status.Self(), &mHandle,\r
- (unsigned short)size, (char*)buffer);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Write", _("isc_put_segment failed."));\r
-}\r
-\r
-void BlobImpl::Info(int* Size, int* Largest, int* Segments)\r
-{\r
- char items[] = {isc_info_blob_total_length,\r
- isc_info_blob_max_segment,\r
- isc_info_blob_num_segments};\r
-\r
- if (mHandle == 0)\r
- throw LogicExceptionImpl("Blob::GetInfo", _("The Blob is not opened"));\r
-\r
- IBS status;\r
- RB result(100);\r
- (*gds.Call()->m_blob_info)(status.Self(), &mHandle, sizeof(items), items,\r
- (short)result.Size(), result.Self());\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::GetInfo", _("isc_blob_info failed."));\r
-\r
- if (Size != 0) *Size = result.GetValue(isc_info_blob_total_length);\r
- if (Largest != 0) *Largest = result.GetValue(isc_info_blob_max_segment);\r
- if (Segments != 0) *Segments = result.GetValue(isc_info_blob_num_segments);\r
-}\r
-\r
-void BlobImpl::Save(const std::string& data)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Blob::Save", _("Blob already opened."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Blob::Save", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Blob::Save", _("No Transaction is attached."));\r
-\r
- IBS status;\r
- (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Save",\r
- _("isc_create_blob failed."));\r
- mIdAssigned = true;\r
- mWriteMode = true;\r
-\r
- size_t pos = 0;\r
- size_t len = data.size();\r
- while (len != 0)\r
- {\r
- size_t blklen = (len < 32*1024-1) ? len : 32*1024-1;\r
- status.Reset();\r
- (*gds.Call()->m_put_segment)(status.Self(), &mHandle,\r
- (unsigned short)blklen, const_cast<char*>(data.data()+pos));\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Save",\r
- _("isc_put_segment failed."));\r
- pos += blklen;\r
- len -= blklen;\r
- }\r
- \r
- status.Reset();\r
- (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Save", _("isc_close_blob failed."));\r
- mHandle = 0;\r
-}\r
-\r
-void BlobImpl::Load(std::string& data)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("Blob::Load", _("Blob already opened."));\r
- if (mDatabase == 0)\r
- throw LogicExceptionImpl("Blob::Load", _("No Database is attached."));\r
- if (mTransaction == 0)\r
- throw LogicExceptionImpl("Blob::Load", _("No Transaction is attached."));\r
- if (! mIdAssigned)\r
- throw LogicExceptionImpl("Blob::Load", _("Blob Id is not assigned."));\r
-\r
- IBS status;\r
- (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(),\r
- mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Load", _("isc_open_blob2 failed."));\r
- mWriteMode = false;\r
-\r
- size_t blklen = 32*1024-1;\r
- data.resize(blklen);\r
-\r
- size_t size = 0;\r
- size_t pos = 0;\r
- for (;;)\r
- {\r
- status.Reset();\r
- unsigned short bytesread;\r
- int result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle,\r
- &bytesread, (unsigned short)blklen,\r
- const_cast<char*>(data.data()+pos));\r
- if (result == isc_segstr_eof) break; // End of blob\r
- if (result != isc_segment && status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Load", _("isc_get_segment failed."));\r
-\r
- pos += bytesread;\r
- size += bytesread;\r
- data.resize(size + blklen);\r
- }\r
- data.resize(size);\r
- \r
- status.Reset();\r
- (*gds.Call()->m_close_blob)(status.Self(), &mHandle);\r
- if (status.Errors())\r
- throw SQLExceptionImpl(status, "Blob::Load", _("isc_close_blob failed."));\r
- mHandle = 0;\r
-}\r
-\r
-IBPP::Database BlobImpl::DatabasePtr() const\r
-{\r
- if (mDatabase == 0) throw LogicExceptionImpl("Blob::DatabasePtr",\r
- _("No Database is attached."));\r
- return mDatabase;\r
-}\r
-\r
-IBPP::Transaction BlobImpl::TransactionPtr() const\r
-{\r
- if (mTransaction == 0) throw LogicExceptionImpl("Blob::TransactionPtr",\r
- _("No Transaction is attached."));\r
- return mTransaction;\r
-}\r
-\r
-IBPP::IBlob* BlobImpl::AddRef()\r
-{\r
- ASSERTION(mRefCount >= 0);\r
- ++mRefCount;\r
- return this;\r
-}\r
-\r
-void BlobImpl::Release()\r
-{\r
- // Release cannot throw, except in DEBUG builds on assertion\r
- ASSERTION(mRefCount >= 0);\r
- --mRefCount;\r
- try { if (mRefCount <= 0) delete this; }\r
- catch (...) { }\r
-}\r
-\r
-// (((((((( OBJECT INTERNAL METHODS ))))))))\r
-\r
-void BlobImpl::Init()\r
-{\r
- mIdAssigned = false;\r
- mWriteMode = false;\r
- mHandle = 0;\r
- mDatabase = 0;\r
- mTransaction = 0;\r
-}\r
-\r
-void BlobImpl::SetId(ISC_QUAD* quad)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("BlobImpl::SetId", _("Can't set Id on an opened BlobImpl."));\r
- if (quad == 0)\r
- throw LogicExceptionImpl("BlobImpl::SetId", _("Null Id reference detected."));\r
-\r
- memcpy(&mId, quad, sizeof(mId));\r
- mIdAssigned = true;\r
-}\r
-\r
-void BlobImpl::GetId(ISC_QUAD* quad)\r
-{\r
- if (mHandle != 0)\r
- throw LogicExceptionImpl("BlobImpl::GetId", _("Can't get Id on an opened BlobImpl."));\r
- if (! mWriteMode)\r
- throw LogicExceptionImpl("BlobImpl::GetId", _("Can only get Id of a newly created Blob."));\r
- if (quad == 0)\r
- throw LogicExceptionImpl("BlobImpl::GetId", _("Null Id reference detected."));\r
-\r
- memcpy(quad, &mId, sizeof(mId));\r
-}\r
-\r
-void BlobImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
-{\r
- if (database == 0) throw LogicExceptionImpl("Blob::AttachDatabase",\r
- _("Can't attach a NULL Database object."));\r
-\r
- if (mDatabase != 0) mDatabase->DetachBlobImpl(this);\r
- mDatabase = database;\r
- mDatabase->AttachBlobImpl(this);\r
-}\r
-\r
-void BlobImpl::AttachTransactionImpl(TransactionImpl* transaction)\r
-{\r
- if (transaction == 0) throw LogicExceptionImpl("Blob::AttachTransaction",\r
- _("Can't attach a NULL Transaction object."));\r
-\r
- if (mTransaction != 0) mTransaction->DetachBlobImpl(this);\r
- mTransaction = transaction;\r
- mTransaction->AttachBlobImpl(this);\r
-}\r
-\r
-void BlobImpl::DetachDatabaseImpl()\r
-{\r
- if (mDatabase == 0) return;\r
-\r
- mDatabase->DetachBlobImpl(this);\r
- mDatabase = 0;\r
-}\r
-\r
-void BlobImpl::DetachTransactionImpl()\r
-{\r
- if (mTransaction == 0) return;\r
-\r
- mTransaction->DetachBlobImpl(this);\r
- mTransaction = 0;\r
-}\r
-\r
-BlobImpl::BlobImpl(DatabaseImpl* database, TransactionImpl* transaction)\r
- : mRefCount(0)\r
-{\r
- Init();\r
- AttachDatabaseImpl(database);\r
- if (transaction != 0) AttachTransactionImpl(transaction);\r
-}\r
-\r
-BlobImpl::~BlobImpl()\r
-{\r
- try\r
- {\r
- if (mHandle != 0)\r
- {\r
- if (mWriteMode) Cancel();\r
- else Close();\r
- }\r
- }\r
- catch (...) { }\r
- \r
- try { if (mTransaction != 0) mTransaction->DetachBlobImpl(this); }\r
- catch (...) { }\r
- try { if (mDatabase != 0) mDatabase->DetachBlobImpl(this); }\r
- catch (...) { }\r
-}\r
-\r
-//\r
-// EOF\r
-//\r