]> git.stg.codes - stg.git/blobdiff - stglibs/ibpp.lib/events.cpp
Port to CMake, get rid of os_int.h.
[stg.git] / stglibs / ibpp.lib / events.cpp
diff --git a/stglibs/ibpp.lib/events.cpp b/stglibs/ibpp.lib/events.cpp
deleted file mode 100644 (file)
index 14ce1ba..0000000
+++ /dev/null
@@ -1,372 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-//     File    : $Id: events.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $\r
-//     Subject : IBPP, internal EventsImpl 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
-//     SPECIAL WARNING COMMENT (by Olivier Mascia, 2000 Nov 12)\r
-//     The way this source file handles events is not publicly documented, in\r
-//     the ibase.h header file or in the IB 6.0 documentation. This documentation\r
-//     suggests to use the API isc_event_block to construct vectors of events.\r
-//     Unfortunately, this API takes a variable number of parameters to specify\r
-//     the list of event names. In addition, the documentation warn on not using\r
-//     more than 15 names. This is a sad limitation, partly because the maximum\r
-//     number of parameters safely processed in such an API is very compiler\r
-//     dependant and also because isc_event_counts() is designed to return counts\r
-//     through the IB status vector which is a vector of 20 32-bits integers !\r
-//     From reverse engineering of the isc_event_block() API in\r
-//     source file jrd/alt.c (as available on fourceforge.net/project/InterBase as\r
-//     of 2000 Nov 12), it looks like the internal format of those EPB is simple.\r
-//     An EPB starts by a byte with value 1. A version identifier of some sort.\r
-//     Then a small cluster is used for each event name. The cluster starts with\r
-//     a byte for the length of the event name (no final '\0'). Followed by the N\r
-//     characters of the name itself (no final '\0'). The cluster ends with 4 bytes\r
-//     preset to 0.\r
-//\r
-//     SPECIAL CREDIT (July 2004) : this is a complete re-implementation of this\r
-//     class, directly based on work by Val Samko.\r
-//     The whole event handling has then be completely redesigned, based on the old\r
-//     EPB class to bring up the current IBPP::Events implementation.\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
-using namespace ibpp_internals;\r
-\r
-const size_t EventsImpl::MAXEVENTNAMELEN = 127;\r
-\r
-//     (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
-\r
-void EventsImpl::Add(const std::string& eventname, IBPP::EventInterface* objref)\r
-{\r
-       if (eventname.size() == 0)\r
-               throw LogicExceptionImpl("Events::Add", _("Zero length event names not permitted"));\r
-       if (eventname.size() > MAXEVENTNAMELEN)\r
-               throw LogicExceptionImpl("Events::Add", _("Event name is too long"));\r
-       if ((mEventBuffer.size() + eventname.length() + 5) > 32766)     // max signed 16 bits integer minus one\r
-               throw LogicExceptionImpl("Events::Add",\r
-                       _("Can't add this event, the events list would overflow IB/FB limitation"));\r
-\r
-       Cancel();\r
-\r
-       // 1) Alloc or grow the buffers\r
-       size_t prev_buffer_size = mEventBuffer.size();\r
-       size_t needed = ((prev_buffer_size==0) ? 1 : 0) + eventname.length() + 5;\r
-       // Initial alloc will require one more byte, we need 4 more bytes for\r
-       // the count itself, and one byte for the string length prefix\r
-\r
-       mEventBuffer.resize(mEventBuffer.size() + needed);\r
-       mResultsBuffer.resize(mResultsBuffer.size() + needed);\r
-       if (prev_buffer_size == 0)\r
-               mEventBuffer[0] = mResultsBuffer[0] = 1; // First byte is a 'one'. Documentation ??\r
-\r
-       // 2) Update the buffers (append)\r
-       {\r
-               Buffer::iterator it = mEventBuffer.begin() +\r
-                               ((prev_buffer_size==0) ? 1 : prev_buffer_size); // Byte after current content\r
-               *(it++) = static_cast<char>(eventname.length());\r
-               it = std::copy(eventname.begin(), eventname.end(), it);\r
-               // We initialize the counts to (uint32_t)(-1) to initialize properly, see FireActions()\r
-               *(it++) = -1; *(it++) = -1; *(it++) = -1; *it = -1;\r
-       }\r
-\r
-       // copying new event to the results buffer to keep event_buffer_ and results_buffer_ consistant,\r
-       // otherwise we might get a problem in `FireActions`\r
-       // Val Samko, val@digiways.com\r
-       std::copy(mEventBuffer.begin() + prev_buffer_size,\r
-               mEventBuffer.end(), mResultsBuffer.begin() + prev_buffer_size);\r
-\r
-       // 3) Alloc or grow the objref array and update the objref array (append)\r
-       mObjectReferences.push_back(objref);\r
-\r
-       Queue();\r
-}\r
-\r
-void EventsImpl::Drop(const std::string& eventname)\r
-{\r
-       if (eventname.size() == 0)\r
-               throw LogicExceptionImpl("EventsImpl::Drop", _("Zero length event names not permitted"));\r
-       if (eventname.size() > MAXEVENTNAMELEN)\r
-               throw LogicExceptionImpl("EventsImpl::Drop", _("Event name is too long"));\r
-\r
-       if (mEventBuffer.size() <= 1) return;   // Nothing to do, but not an error\r
-\r
-       Cancel();\r
-\r
-       // 1) Find the event in the buffers\r
-       typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
-       EventIterator eit(mEventBuffer.begin()+1);\r
-       EventIterator rit(mResultsBuffer.begin()+1);\r
-\r
-       for (ObjRefs::iterator oit = mObjectReferences.begin();\r
-                       oit != mObjectReferences.end();\r
-                               ++oit, ++eit, ++rit)\r
-       {\r
-               if (eventname != eit.get_name()) continue;\r
-               \r
-               // 2) Event found, remove it\r
-               mEventBuffer.erase(eit.begin(), eit.end());\r
-               mResultsBuffer.erase(rit.begin(), rit.end());\r
-               mObjectReferences.erase(oit);\r
-               break;\r
-       }\r
-\r
-       Queue();\r
-}\r
-\r
-void EventsImpl::List(std::vector<std::string>& events)\r
-{\r
-       events.clear();\r
-       \r
-       if (mEventBuffer.size() <= 1) return;   // Nothing to do, but not an error\r
-\r
-       typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
-       EventIterator eit(mEventBuffer.begin()+1);\r
-\r
-       for (ObjRefs::iterator oit = mObjectReferences.begin();\r
-                       oit != mObjectReferences.end();\r
-                               ++oit, ++eit)\r
-       {\r
-               events.push_back(eit.get_name());\r
-       }\r
-}\r
-\r
-void EventsImpl::Clear()\r
-{\r
-       Cancel();\r
-       \r
-       mObjectReferences.clear();\r
-       mEventBuffer.clear();\r
-       mResultsBuffer.clear();\r
-}\r
-\r
-void EventsImpl::Dispatch()\r
-{\r
-       // If no events registered, nothing to do of course.\r
-       if (mEventBuffer.size() == 0) return;\r
-\r
-       // Let's fire the events actions for all the events which triggered, if any, and requeue.\r
-       FireActions();\r
-       Queue();\r
-}\r
-\r
-IBPP::Database EventsImpl::DatabasePtr() const\r
-{\r
-       if (mDatabase == 0) throw LogicExceptionImpl("Events::DatabasePtr",\r
-                       _("No Database is attached."));\r
-       return mDatabase;\r
-}\r
-\r
-IBPP::IEvents* EventsImpl::AddRef()\r
-{\r
-       ASSERTION(mRefCount >= 0);\r
-       ++mRefCount;\r
-       return this;\r
-}\r
-\r
-void EventsImpl::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 EventsImpl::Queue()\r
-{\r
-       if (! mQueued)\r
-       {\r
-               if (mDatabase->GetHandle() == 0)\r
-                       throw LogicExceptionImpl("EventsImpl::Queue",\r
-                                 _("Database is not connected"));\r
-\r
-               IBS vector;\r
-               mTrapped = false;\r
-               mQueued = true;\r
-               (*gds.Call()->m_que_events)(vector.Self(), mDatabase->GetHandlePtr(), &mId,\r
-                       short(mEventBuffer.size()), &mEventBuffer[0],\r
-                               (isc_callback)EventHandler, (char*)this);\r
-\r
-               if (vector.Errors())\r
-               {\r
-                       mId = 0;        // Should be, but better be safe\r
-                       mQueued = false;\r
-                       throw SQLExceptionImpl(vector, "EventsImpl::Queue",\r
-                               _("isc_que_events failed"));\r
-               }\r
-       }\r
-}\r
-\r
-void EventsImpl::Cancel()\r
-{\r
-       if (mQueued)\r
-       {\r
-               if (mDatabase->GetHandle() == 0) throw LogicExceptionImpl("EventsImpl::Cancel",\r
-                       _("Database is not connected"));\r
-\r
-               IBS vector;\r
-\r
-               // A call to cancel_events will call *once* the handler routine, even\r
-               // though no events had fired. This is why we first set mEventsQueued\r
-               // to false, so that we can be sure to dismiss those unwanted callbacks\r
-               // subsequent to the execution of isc_cancel_events().\r
-               mTrapped = false;\r
-               mQueued = false;\r
-               (*gds.Call()->m_cancel_events)(vector.Self(), mDatabase->GetHandlePtr(), &mId);\r
-\r
-           if (vector.Errors())\r
-               {\r
-                       mQueued = true; // Need to restore this as cancel failed\r
-               throw SQLExceptionImpl(vector, "EventsImpl::Cancel",\r
-                       _("isc_cancel_events failed"));\r
-               }\r
-\r
-               mId = 0;        // Should be, but better be safe\r
-       }\r
-}\r
-\r
-void EventsImpl::FireActions()\r
-{\r
-       if (mTrapped)\r
-       {\r
-               typedef EventBufferIterator<Buffer::iterator> EventIterator;\r
-               EventIterator eit(mEventBuffer.begin()+1);\r
-               EventIterator rit(mResultsBuffer.begin()+1);\r
-\r
-               for (ObjRefs::iterator oit = mObjectReferences.begin();\r
-                        oit != mObjectReferences.end();\r
-                                ++oit, ++eit, ++rit)\r
-               {\r
-                       if (eit == EventIterator(mEventBuffer.end())\r
-                                 || rit == EventIterator(mResultsBuffer.end()))\r
-                               throw LogicExceptionImpl("EventsImpl::FireActions", _("Internal buffer size error"));\r
-                       uint32_t vnew = rit.get_count();\r
-                       uint32_t vold = eit.get_count();\r
-                       if (vnew > vold)\r
-                       {\r
-                               // Fire the action\r
-                               try\r
-                               {\r
-                                       (*oit)->ibppEventHandler(this, eit.get_name(), (int)(vnew - vold));\r
-                               }\r
-                               catch (...)\r
-                               {\r
-                                       std::copy(rit.begin(), rit.end(), eit.begin());\r
-                                       throw;\r
-                               }\r
-                               std::copy(rit.begin(), rit.end(), eit.begin());\r
-                       }\r
-                       // This handles initialization too, where vold == (uint32_t)(-1)\r
-                       // Thanks to M. Hieke for this idea and related initialization to (-1)\r
-                       if (vnew != vold)\r
-                               std::copy(rit.begin(), rit.end(), eit.begin());\r
-               }\r
-       }\r
-}\r
-\r
-// This function must keep this prototype to stay compatible with\r
-// what isc_que_events() expects\r
-\r
-void EventsImpl::EventHandler(const char* object, short size, const char* tmpbuffer)\r
-{\r
-       // >>>>> This method is a STATIC member !! <<<<<\r
-       // Consider this method as a kind of "interrupt handler". It should do as\r
-       // few work as possible as quickly as possible and then return.\r
-       // Never forget: this is called by the Firebird client code, on *some*\r
-       // thread which might not be (and won't probably be) any of your application\r
-       // thread. This function is to be considered as an "interrupt-handler" of a\r
-       // hardware driver.\r
-\r
-       // There can be spurious calls to EventHandler from FB internal. We must\r
-       // dismiss those calls.\r
-       if (object == 0 || size == 0 || tmpbuffer == 0) return;\r
-               \r
-       EventsImpl* evi = (EventsImpl*)object;  // Ugly, but wanted, c-style cast\r
-\r
-       if (evi->mQueued)\r
-       {\r
-               try\r
-               {\r
-                       char* rb = &evi->mResultsBuffer[0];\r
-                       if (evi->mEventBuffer.size() < (unsigned)size) size = (short)evi->mEventBuffer.size();\r
-                       for (int i = 0; i < size; i++)\r
-                               rb[i] = tmpbuffer[i];\r
-                       evi->mTrapped = true;\r
-                       evi->mQueued = false;\r
-               }\r
-               catch (...) { }\r
-       }\r
-}\r
-\r
-void EventsImpl::AttachDatabaseImpl(DatabaseImpl* database)\r
-{\r
-       if (database == 0) throw LogicExceptionImpl("EventsImpl::AttachDatabase",\r
-                       _("Can't attach a null Database object."));\r
-\r
-       if (mDatabase != 0) mDatabase->DetachEventsImpl(this);\r
-       mDatabase = database;\r
-       mDatabase->AttachEventsImpl(this);\r
-}\r
-\r
-void EventsImpl::DetachDatabaseImpl()\r
-{\r
-       if (mDatabase == 0) return;\r
-\r
-       mDatabase->DetachEventsImpl(this);\r
-       mDatabase = 0;\r
-}\r
-\r
-EventsImpl::EventsImpl(DatabaseImpl* database)\r
-       : mRefCount(0)\r
-{\r
-       mDatabase = 0;\r
-       mId = 0;\r
-       mQueued = mTrapped = false;\r
-       AttachDatabaseImpl(database);\r
-}\r
-\r
-EventsImpl::~EventsImpl()\r
-{\r
-       try { Clear(); }\r
-               catch (...) { }\r
-       \r
-       try { if (mDatabase != 0) mDatabase->DetachEventsImpl(this); }\r
-               catch (...) { }\r
-}\r
-\r
-//\r
-//     EOF\r
-//\r