Subject | RE: [ib-support] Re: Need advise |
---|---|
Author | Wilson, Fred |
Post date | 2002-12-17T19:09:48Z |
Dan, as Sean has already answered, the client is not thread safe, so, *yes*,
you do need to do something about serializing the FB API calls. We do it in
the 3rd layer, as nothing calls the first API wrapper directly.
Best regards,
Fred Wilson
SE, Bell & Howell
fred.wilson@...
-----Original Message-----
From: nitaligavino <Dan.Crea@...> [mailto:Dan.Crea@...]
Sent: Tuesday, December 17, 2002 11:44 AM
To: ib-support@yahoogroups.com
Subject: [ib-support] Re: Need advise
Hi Fred:
First, thank you for all your help!
I'm doing the same thing but without synchronization objects. I have
three classes that wrap the FB API and provide our specific logic,
FBDatabase, FBRecord and FBVariant. Each thread, or client, within
the application creates and destroys it's own object instance of
these wrappers so there is no sharing of these objects across threads
and therefore no need to serialize calls. What is however shared are
the raw FB API calls that I "expect" to be thread safe. For example,
each thread creates their own FBRecord object when it wants to fetch
data. So T1 may be calling Retrieve() at the same time T2 is calling
Retrieve() and so on. To the wrapper that's okay because each thread
has its own instance, but what about to the isc_dsql_fetch() call? (
see snip-it )
AT_LONG FBDatabase::Retrieve(AT_SQL_STATEMENT_HANDLE *hStmt,
AT_SQL_RECORD_SET_DATA *pSqlResults)
{
ISC_LONG lResult = -1;
if(hStmt != 0 && *hStmt != 0 && pSqlResults != 0)
{
// Perform a fetch on this statement handle
ISC_STATUS status[20];
lResult = isc_dsql_fetch(status, hStmt, 1,
pSqlResults);
ErrorHandler("IBDatabase::Fetch", "isc_dsql_fetch",
status);
// EOR, end of record
if(lResult == 100)
lResult = 0;
else
lResult = (ISC_OP_SUCCESS(status) ? 1 : -1);
}
return(lResult);
}
It sounds as if I need to serialize the calls into the FB API. So no
two threads can call a FB API method at the same time. So from the
above, I would need to have a global lock that would lock around the
call to isc_dsql_fetch() so that only 1 thread can call fetch at a
time. Which would also mean that while T1 is in the fetch call, no
other client could call a database method. Is this how your usage
works?
I considered this but it seems that serializing the FB API should not
be required. It should be thread safe itself and if not that's a
bug. Not to mention the performance degradation that will occur.
Dan
--- In ib-support@yahoogroups.com, "Wilson, Fred" <fred.wilson@b...>
wrote:
ib-support-unsubscribe@egroups.com
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
[Non-text portions of this message have been removed]
you do need to do something about serializing the FB API calls. We do it in
the 3rd layer, as nothing calls the first API wrapper directly.
Best regards,
Fred Wilson
SE, Bell & Howell
fred.wilson@...
-----Original Message-----
From: nitaligavino <Dan.Crea@...> [mailto:Dan.Crea@...]
Sent: Tuesday, December 17, 2002 11:44 AM
To: ib-support@yahoogroups.com
Subject: [ib-support] Re: Need advise
Hi Fred:
First, thank you for all your help!
I'm doing the same thing but without synchronization objects. I have
three classes that wrap the FB API and provide our specific logic,
FBDatabase, FBRecord and FBVariant. Each thread, or client, within
the application creates and destroys it's own object instance of
these wrappers so there is no sharing of these objects across threads
and therefore no need to serialize calls. What is however shared are
the raw FB API calls that I "expect" to be thread safe. For example,
each thread creates their own FBRecord object when it wants to fetch
data. So T1 may be calling Retrieve() at the same time T2 is calling
Retrieve() and so on. To the wrapper that's okay because each thread
has its own instance, but what about to the isc_dsql_fetch() call? (
see snip-it )
AT_LONG FBDatabase::Retrieve(AT_SQL_STATEMENT_HANDLE *hStmt,
AT_SQL_RECORD_SET_DATA *pSqlResults)
{
ISC_LONG lResult = -1;
if(hStmt != 0 && *hStmt != 0 && pSqlResults != 0)
{
// Perform a fetch on this statement handle
ISC_STATUS status[20];
lResult = isc_dsql_fetch(status, hStmt, 1,
pSqlResults);
ErrorHandler("IBDatabase::Fetch", "isc_dsql_fetch",
status);
// EOR, end of record
if(lResult == 100)
lResult = 0;
else
lResult = (ISC_OP_SUCCESS(status) ? 1 : -1);
}
return(lResult);
}
It sounds as if I need to serialize the calls into the FB API. So no
two threads can call a FB API method at the same time. So from the
above, I would need to have a global lock that would lock around the
call to isc_dsql_fetch() so that only 1 thread can call fetch at a
time. Which would also mean that while T1 is in the fetch call, no
other client could call a database method. Is this how your usage
works?
I considered this but it seems that serializing the FB API should not
be required. It should be thread safe itself and if not that's a
bug. Not to mention the performance degradation that will occur.
Dan
--- In ib-support@yahoogroups.com, "Wilson, Fred" <fred.wilson@b...>
wrote:
> We do, basically, the same thing.that, which
> We have the FB API calls in a library. There is a layer around
> was some applcaition specific methods (speed related), and lastly,wrapped
> out the outside of all that, is the general database library.individual method
> Within any application (multi-threaded) you need keep the
> calls separate between threads, such that one thread doesn't callone of the
> methods, before another thread has finished.lower). We
> Way early on, in our developement, we figured that out ;)
> Anyway, we're on the Windoze platform, coding in C++ (and C down
> use Critical Sections within the outer library, to control accessinside the
> individual methods. Without something like that, one thread couldcall a
> method within the library, and get some of the database specificbuffers
> setup, or actually be between the individual API calls, and getswapped out
> by another thread, that would then start executing the methodwithin the
> library. That won't work at all.showing our
> Here's a little code snip of one of the outer library methods,
> use of Critical Sections:--------
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> First, one of the constructors and the destructor:
>
> //------------------------------------------------------------------
> -loggingOn)
> IDFSemaphore::IDFSemaphore( BHInterbaseAccess* pIB, const bool
> : mLoggingOn(loggingOn)--------
> {
> InitializeCriticalSection(&mCS);
> mAppName = GetApplicationName();
> mComputerName = GetCompName();
> mpCDKI = new CDKInterface( pIB );
> }
> //------------------------------------------------------------------
> -+ "',
> IDFSemaphore::~IDFSemaphore()
> {
> DeleteCriticalSection(&mCS);
> delete mpCDKI;
> mpCDKI = NULL;
> }
>
> Next, part of one of the method's within the same library (class):
>
>
> errCode IDFSemaphore::OpenExclusive( String& idfname )
> {
> errCode rslt = ERR_NONE;
> String strSQL;
> short actualCC;
> IBColumn colbuf[ 2 ];
> IBColumn ibc;
> ui32 ui32Status;
> ui32 ui32ID;
>
> // Setting up where the returned parameters will be stored
> colbuf[ 0 ].shSize = sizeof( ui32Status ) ;
> colbuf[ 0 ].pData = ( buffer ) &ui32Status;
> colbuf[ 1 ].shSize = sizeof( ui32ID ) ;
> colbuf[ 1 ].pData = ( buffer ) &ui32ID;
> int info;
> ibc.shSize = sizeof( info );
> ibc.pData = (buffer) &info;
>
> EnterCriticalSection(&mCS);
> try
> {
> BHInterbaseAccess* pIB = mpCDKI->GetIBPtr();
>
> if (pIB == NULL)
> {
> LeaveCriticalSection(&mCS);
> return ERR_DATABASE;
> }
>
> try
> {
> pIB->Transaction( BHInterbaseAccess::begin );
>
> if (pIB->Status.GetValue() != ERR_NONE)
> rslt = pIB->Status.GetValue();
> else
> {
> // Check if IDF is fully loaded
> strSQL = String("select * from sp_OpenDS( '") + idfname
> 'PDF')";actualCC );
> pIB->ExecuteAndFetch( strSQL.c_str(), colbuf, 2,
>DB_EXCLUSIVE);
> if (pIB->Status.GetValue() != ERR_NONE)
> rslt = pIB->Status.GetValue();
> else if (ui32Status != ERR_NONE)
> rslt = ERR_NO_DATASET;
>
> <SNIPPED A BUNCH OF OTHER METHOD CALLS >
>
> }
> else if( info == DB_EXCLUSIVE )
> rslt = ERR_LOCKED;
> else if( info == DB_FATAL_ERROR )
> rslt = ERR_DATABASE;
> else if ( info < 0 )
> rslt = ERR_INVALID_CONDITION;
> else
> rslt = ERR_DATASET_INUSE;
> }
> if (rslt == ERR_NONE)
> LogMessage(el_IDFSEMAPHOREEXCLUSIVE, idfname,
> elseapplication), into
> pIB->ErrorCleanUp();
> }
> catch (...)
> {
> pIB->ErrorCleanUp();
> rslt = ERR_DATABASE;
> }
> LeaveCriticalSection(&mCS);
> }
> catch(...)
> {
> LeaveCriticalSection(&mCS);
> }
> return rslt;
> }
>
> You'll have to control thread access (in a multi-threaded
> the FB API calls.this
>
>
> Best regards,
> Fred Wilson
> SE, Bell & Howell
> fred.wilson@b...
>
>
>
> -----Original Message-----
> From: nitaligavino <Dan.Crea@a...> [mailto:Dan.Crea@a...]
> Sent: Monday, December 16, 2002 12:20 PM
> To: ib-support@yahoogroups.com
> Subject: [ib-support] Re: Need advise
>
>
> Hi Fred:
> Direct API access, ibase.h. I'm do my development in c / c++. The
> application is cross-platform, Solaris and Windows. I'm seeing
> issue on W2k. I have not done any extensive testing on Unix so I<fred.wilson@b...>
> don't know if this is platform specific or not.
>
> Dan
>
>
> --- In ib-support@yahoogroups.com, "Wilson, Fred"
> wrote:tool
> > Ok, also, how are you accessing the database, that is with what
> (s)through
> > (IBO, IBX, etc), or are you accessing the database directly
> the APIwork
> > ??
> >
> >
> > Best regards,
> > Fred Wilson
> > SE, Bell & Howell
> > fred.wilson@b...
> >
> >
> >
> > -----Original Message-----
> > From: nitaligavino <Dan.Crea@a...> [mailto:Dan.Crea@a...]
> > Sent: Monday, December 16, 2002 11:46 AM
> > To: ib-support@yahoogroups.com
> > Subject: [ib-support] Re: Need advise
> >
> >
> > Hi Fred:
> > I have a single multithread application. Each thread creates its
> own
> > connection to the database when the thread is started. These
> threads
> > then live thought the application lifecycle. When there is db
> > to be done, an idle thread is woken up and it creates a newconnections
> > transaction. On work completion the transaction is committed or
> > rolledback. Typically, I have at most 12 threads or 12
> > to the database. But this number varies.able
> >
> > This issue is reproducible, but not at will. I have not been
> tofrom
> > create a tester that can produce this on demand. However I run
> into
> > this problem at least 1 time every two days or when the
> applications
> > load increases and all threads are running.
> >
> >
> >
> > --- In ib-support@yahoogroups.com, "Wilson, Fred"
> <fred.wilson@b...>
> > wrote:
> > > How are you executing those two calls "at the same time" ??
> > > Is this from a single application, with multiple threads, or
> > tworight
> > > separate applications ??
> > >
> > > Best regards,
> > > Fred Wilson
> > > SE, Bell & Howell
> > > fred.wilson@b...
> > >
> > >
> > >
> > > -----Original Message-----
> > > From: nitaligavino <Dan.Crea@a...> [mailto:Dan.Crea@a...]
> > > Sent: Monday, December 16, 2002 11:21 AM
> > > To: ib-support@yahoogroups.com
> > > Subject: [ib-support] Need advise
> > >
> > >
> > > Hello:
> > >
> > > I seem to be running into a reoccurring issue I was hopping
> someone
> > > might be able to offer some advise on. It seems, under the
> > > conditions, the FB gds32 becomes stalled and any call into theterminate
> > gds32,
> > > via the gds32 API's, will block indefinitely until you
> > thecalls:
> > > application. I have narrowed it down to the following two
> > >or
> > > isc_dsql_fetch(...)
> > > isc_dsql_execute_immediate(...)
> > >
> > > For some reason, if these two calls occur at the same time the
> > gds32
> > > locks and becomes stalled never to return to the caller again.
> > >
> > > Has anyone else experienced an issue like this?
> > > Can anyone offer some advise on how to work around this issue
> > how0
> > > to figure out what exactly is happing?
> > >
> > > Also, during the stall, I ran iblockpr to see if there was a
> > deadlock
> > > reported. See snip-it. From what I understand of the output,
> > which
> > > is not much, no deadlock occurred.
> > >
> > > P.S Does anyone know how to read this stuff!!
> > >
> > > LOCK_HEADER BLOCK
> > > Version: 114, Active owner: 0, Length: 32768,
> Used:
> > > 24884
> > > Semmask: 0x0, Flags: 0x0001
> > > Enqs: 160067, Converts: 0, Rejects: 21625,
> > Blocks:
> > > 0
> > > Deadlock scans: 13, Deadlocks: 0, Scan
> interval:
> > 10
> > > Acquires: 385444, Acquire blocks: 0, Spin count:
> > > Mutex wait: 0.0%16920
> > > Hash slots: 101, Hash lengths (min/avg/max): 0/
> 0/ 3
> > > Remove node: 0, Insert queue: 0, Insert
> > prior:
> > > 0
> > > Owners (19): forward: 16852, backward: 23968
> > > Free owners (24): forward: 17984, backward:
> > > Free locks (32): forward: 13792, backward:13136
> > > Free requests (67): forward: 23392, backward:23296
> > > Lock Ordering: Enabledhttp://docs.yahoo.com/info/terms/
> > >
> > >
> > >
> > >
> > >
> > > To unsubscribe from this group, send an email to:
> > > ib-support-unsubscribe@egroups.com
> > >
> > >
> > >
> > > Your use of Yahoo! Groups is subject to
> > http://docs.yahoo.com/info/terms/
> > >
> > >
> > >
> > > [Non-text portions of this message have been removed]
> >
> >
> >
> > To unsubscribe from this group, send an email to:
> > ib-support-unsubscribe@egroups.com
> >
> >
> >
> > Your use of Yahoo! Groups is subject to
> http://docs.yahoo.com/info/terms/
> >
> >
> >
> > [Non-text portions of this message have been removed]
>
>
>
> To unsubscribe from this group, send an email to:
> ib-support-unsubscribe@egroups.com
>
>
>
> Your use of Yahoo! Groups is subject to
>To unsubscribe from this group, send an email to:
>
>
> [Non-text portions of this message have been removed]
ib-support-unsubscribe@egroups.com
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
[Non-text portions of this message have been removed]