Skip to content

Commit f579f81

Browse files
committed
Enhance pool.release() to drop connections known to be unusable
1 parent 1abbbe5 commit f579f81

File tree

11 files changed

+118
-23
lines changed

11 files changed

+118
-23
lines changed

src/dpi/include/dpiConn.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class Conn
6464
virtual void stmtCacheSize(unsigned int stmtCacheSize) = 0;
6565
virtual unsigned int stmtCacheSize() const = 0;
6666
virtual int getByteExpansionRatio () = 0;
67+
virtual void setErrState ( int errNum ) = 0;
6768

6869
virtual void lobPrefetchSize(unsigned int lobPrefetchSize) = 0;
6970
virtual unsigned int lobPrefetchSize() const = 0;

src/dpi/src/dpiConnImpl.cpp

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@
4848

4949
#include <iostream>
5050

51+
// Error numbers to set the drop_sess flag in sessionRelease()
52+
#define DPI_CONNERR_INVALID_SESS 22
53+
#define DPI_CONNERR_SESS_KILLED 28
54+
#define DPI_CONNERR_SESS_MARKED_KILL 31
55+
#define DPI_CONNERR_SESS_TERM_NO_REPLY 45
56+
#define DPI_CONNERR_ORA_NOT_LOGGED_ON 1012
57+
#define DPI_CONNERR_MAX_IDLE_TIMEOUT 2396
58+
5159
using namespace std;
5260

5361

@@ -80,7 +88,7 @@ ConnImpl::ConnImpl(EnvImpl *env, OCIEnv *envh, bool externalAuth,
8088

8189
try : env_(env), pool_(NULL),
8290
envh_(envh), errh_(NULL), auth_(NULL), svch_(NULL), sessh_(NULL),
83-
hasTxn_(false)
91+
hasTxn_(false), srvh_(NULL), dropConn_(false)
8492
{
8593

8694
this->initConnImpl ( false, externalAuth, connClass,
@@ -122,7 +130,7 @@ ConnImpl::ConnImpl(PoolImpl *pool, OCIEnv *envh, bool externalAuth,
122130

123131
try : env_(NULL), pool_(pool),
124132
envh_(envh), errh_(NULL), auth_(NULL),
125-
svch_(NULL), sessh_(NULL), hasTxn_(false)
133+
svch_(NULL), sessh_(NULL), hasTxn_(false), srvh_(NULL), dropConn_(false)
126134
{
127135
this->initConnImpl ( true, externalAuth, connClass, poolName, poolNameLen,
128136
"", "" );
@@ -473,6 +481,46 @@ void ConnImpl::breakExecution()
473481
}
474482
}
475483

484+
/*****************************************************************************/
485+
/*
486+
DESCRIPTION
487+
set the flag if the non-recoverable error happens to connection
488+
489+
PARAMETERS
490+
errNum - Error number
491+
492+
RETURNS:
493+
-NONE_
494+
*/
495+
void ConnImpl::setErrState ( int errNum )
496+
{
497+
/*
498+
* This flag applicable for only Pool, non pooled connection anyway gets
499+
* terminated upon release. This code is NOT thread-safe. But, we are only
500+
* setting the flag to TRUE - multiple threads can try and only will update
501+
* to TRUE only, so it is okay setting this flag.
502+
*/
503+
504+
if ( pool_ )
505+
{
506+
switch ( errNum )
507+
{
508+
// Error numbers to set drop_sess flag
509+
case DPI_CONNERR_INVALID_SESS:
510+
case DPI_CONNERR_SESS_KILLED:
511+
case DPI_CONNERR_SESS_MARKED_KILL:
512+
case DPI_CONNERR_SESS_TERM_NO_REPLY:
513+
case DPI_CONNERR_ORA_NOT_LOGGED_ON:
514+
case DPI_CONNERR_MAX_IDLE_TIMEOUT:
515+
dropConn_ = true;
516+
break;
517+
518+
default:
519+
break;
520+
}
521+
}
522+
}
523+
476524

477525
/*---------------------------------------------------------------------------
478526
PRIVATE METHODS
@@ -499,7 +547,6 @@ void ConnImpl::initConnImpl ( bool pool, bool externalAuth,
499547
const string& connClass, OraText *poolNmRconnStr,
500548
ub4 nameLen, const string &user, const string &password )
501549
{
502-
OCIServer *srvh = NULL;
503550
ub4 mode = OCI_DEFAULT;
504551
ub2 csid = 0;
505552

@@ -551,14 +598,15 @@ void ConnImpl::initConnImpl ( bool pool, bool externalAuth,
551598
OCI_ATTR_SESSION, errh_ ), errh_ );
552599

553600
// Initialize the server handle from service handle
554-
ociCall ( OCIAttrGet ( svch_, OCI_HTYPE_SVCCTX, ( void * ) &srvh, 0,
601+
ociCall ( OCIAttrGet ( svch_, OCI_HTYPE_SVCCTX, ( void * ) &srvh_, 0,
555602
( ub4 ) OCI_ATTR_SERVER, errh_ ), errh_ );
556603

557604
// Get the DBCHARSET from server
558-
ociCall ( OCIAttrGet ( srvh, ( ub4 ) OCI_HTYPE_SERVER, ( void * ) &csid,
605+
ociCall ( OCIAttrGet ( srvh_, ( ub4 ) OCI_HTYPE_SERVER, ( void * ) &csid,
559606
( ub4 * ) 0, ( ub4 ) OCI_ATTR_CHARSET_ID, errh_ ),
560607
errh_ );
561-
csratio_ = getCsRatio ( csid );
608+
609+
csratio_ = getCsRatio ( csid );
562610
}
563611

564612
/*****************************************************************************/
@@ -579,9 +627,25 @@ void ConnImpl::initConnImpl ( bool pool, bool externalAuth,
579627

580628
void ConnImpl::cleanup()
581629
{
630+
ub4 relMode = OCI_DEFAULT;
631+
ub4 serverStatus = OCI_SERVER_NORMAL;
632+
582633
if (svch_)
583634
{
584-
OCISessionRelease(svch_, errh_, NULL, 0, OCI_DEFAULT);
635+
if ( pool_ )
636+
{
637+
// Get the connection status
638+
if ( !dropConn_ )
639+
ociCall ( OCIAttrGet ( ( void * ) srvh_, OCI_HTYPE_SERVER,
640+
( void * ) &serverStatus, ( ub4 * ) 0,
641+
OCI_ATTR_SERVER_STATUS, errh_ ), errh_ );
642+
643+
// Remove the session from pool in case of unusable
644+
if ( dropConn_ || ( serverStatus != OCI_SERVER_NORMAL ) )
645+
relMode |= OCI_SESSRLS_DROPSESS;
646+
}
647+
648+
OCISessionRelease(svch_, errh_, NULL, 0, relMode);
585649
svch_ = NULL;
586650
}
587651

src/dpi/src/dpiConnImpl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ class ConnImpl : public Conn
115115

116116
virtual DpiHandle *getErrh (){return (DpiHandle *)errh_;};
117117

118+
virtual void setErrState ( int errNum );
119+
118120
#if OCI_MAJOR_VERSION < 12
119121
inline void hasTxn(boolean connHasTxn)
120122
{
@@ -133,6 +135,7 @@ class ConnImpl : public Conn
133135
void initConnImpl( bool pool, bool externalAuth, const string& connClass,
134136
OraText *poolNmRconnStr, ub4 nameLen,
135137
const string &user, const string &password );
138+
136139
int getCsRatio ( ub2 csid )
137140
{
138141
return ( csid == DPI_AL32UTF8 ) ? DPI_BESTCASE_CHAR_CONVERSION_RATIO :
@@ -152,6 +155,8 @@ class ConnImpl : public Conn
152155
OCISession *sessh_; // OCI Session handle. Do not free this.
153156
boolean hasTxn_; // set if transaction is in progress
154157
int csratio_; // character expansion ratio
158+
OCIServer *srvh_; // OCI server handle
159+
bool dropConn_; // Set flag in case of unusable connection
155160
};
156161

157162

src/dpi/src/dpiUtils.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,4 @@ void ociCall(sword rc, OCIError *errh);
5050

5151
void ociCallEnv(sword rc, OCIEnv *envh);
5252

53-
void getDriverName ( char *name, unsigned int namelen );
54-
55-
56-
57-
58-
5953
#endif /* DPIUTILS_ORACLE */

src/njs/src/njsConnection.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ NAN_PROPERTY_GETTER(Connection::GetStmtCacheSize)
205205
}
206206
catch(dpi::Exception &e)
207207
{
208+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), njsConn->dpiconn_ );
208209
NJS_SET_EXCEPTION(e.what(), strlen(e.what()));
209210
NanReturnUndefined();
210211
}
@@ -968,6 +969,7 @@ void Connection::Async_Execute (uv_work_t *req)
968969
}
969970
catch (dpi::Exception& e)
970971
{
972+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), executeBaton->dpiconn );
971973
// In Case of DML Returning, if the buffer is small, and if the callback
972974
// is called multiple times, an ORA error 24343 was reported. Converting
973975
// that error to errInsufficientBufferForBinds.
@@ -2410,6 +2412,7 @@ void Connection::Async_Release(uv_work_t *req)
24102412
}
24112413
catch (dpi::Exception& e)
24122414
{
2415+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), releaseBaton->dpiconn );
24132416
releaseBaton->error = std::string(e.what());
24142417
}
24152418
exitAsyncRelease:
@@ -2504,6 +2507,7 @@ void Connection::Async_Commit (uv_work_t *req)
25042507
}
25052508
catch (dpi::Exception& e)
25062509
{
2510+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), commitBaton->dpiconn );
25072511
commitBaton->error = std::string(e.what());
25082512
}
25092513
exitAsyncCommit:
@@ -2596,6 +2600,7 @@ void Connection::Async_Rollback (uv_work_t *req)
25962600
}
25972601
catch (dpi::Exception& e)
25982602
{
2603+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), rollbackBaton->dpiconn );
25992604
rollbackBaton->error = std::string(e.what());
26002605
}
26012606
exitAsyncRollback:
@@ -2691,6 +2696,7 @@ void Connection::Async_Break(uv_work_t *req)
26912696
}
26922697
catch (dpi::Exception& e)
26932698
{
2699+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), breakBaton->dpiconn );
26942700
breakBaton->error = std::string(e.what());
26952701
}
26962702
exitAsyncBreak:

src/njs/src/njsIntLob.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Persistent<FunctionTemplate> ILob::iLobTemplate_s;
8787
*/
8888

8989
ILob::ILob():
90-
lobLocator_(NULL), svch_(NULL), errh_(NULL),
90+
lobLocator_(NULL), dpiconn_(NULL), svch_(NULL), errh_(NULL),
9191
isValid_(false), state_(INACTIVE), buf_(NULL), bufSize_(0), chunkSize_(0),
9292
length_(0), offset_(1), amountRead_(0)
9393
{
@@ -205,6 +205,7 @@ void ILob::setILob(eBaton *executeBaton, ProtoILob *protoILob)
205205

206206
fetchType_ = protoILob->fetchType_;
207207

208+
dpiconn_ = executeBaton->dpiconn;
208209
svch_ = executeBaton->dpiconn->getSvch();
209210

210211
errh_ = protoILob->errh_;
@@ -227,6 +228,7 @@ void ILob::setILob(eBaton *executeBaton, ProtoILob *protoILob)
227228

228229
catch (dpi::Exception &e)
229230
{
231+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), executeBaton->dpiconn );
230232
executeBaton->error = std::string(e.what());
231233
cleanup();
232234
}
@@ -408,6 +410,7 @@ NAN_PROPERTY_GETTER(ILob::GetChunkSize)
408410

409411
catch(dpi::Exception &e)
410412
{
413+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), iLob->dpiconn_ );
411414
NJS_SET_EXCEPTION(e.what(), strlen(e.what()));
412415
NanReturnUndefined();
413416
}
@@ -471,6 +474,7 @@ NAN_PROPERTY_GETTER(ILob::GetLength)
471474

472475
catch(dpi::Exception &e)
473476
{
477+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), iLob->dpiconn_ );
474478
NJS_SET_EXCEPTION(e.what(), strlen(e.what()));
475479
NanReturnUndefined();
476480
}
@@ -532,6 +536,7 @@ NAN_PROPERTY_GETTER(ILob::GetPieceSize)
532536

533537
catch(dpi::Exception &e)
534538
{
539+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), iLob->dpiconn_ );
535540
NJS_SET_EXCEPTION(e.what(), strlen(e.what()));
536541
NanReturnUndefined();
537542
}
@@ -610,6 +615,7 @@ NAN_PROPERTY_GETTER(ILob::GetOffset)
610615

611616
catch(dpi::Exception &e)
612617
{
618+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), iLob->dpiconn_ );
613619
NJS_SET_EXCEPTION(e.what(), strlen(e.what()));
614620
NanReturnUndefined();
615621
}
@@ -732,13 +738,13 @@ NAN_METHOD(ILob::Read)
732738
void ILob::Async_Read(uv_work_t *req)
733739
{
734740
LobBaton *lobBaton = (LobBaton *)req->data;
741+
ILob *iLob = lobBaton->iLob;
735742

736743
if(!(lobBaton->error).empty())
737744
goto exitAsyncRead;
738745

739746
try
740747
{
741-
ILob *iLob = lobBaton->iLob;
742748
unsigned long long byteAmount = (unsigned long int)iLob->bufSize_;
743749
unsigned long long charAmount = 0;
744750

@@ -759,10 +765,10 @@ void ILob::Async_Read(uv_work_t *req)
759765
else
760766
iLob->offset_ += byteAmount;
761767
}
762-
763768
catch (dpi::Exception& e)
764769
{
765-
lobBaton->error = std::string(e.what());
770+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), iLob->dpiconn_ );
771+
lobBaton->error = std::string(e.what());
766772
}
767773

768774
exitAsyncRead:
@@ -917,13 +923,13 @@ NAN_METHOD(ILob::Write)
917923
void ILob::Async_Write(uv_work_t *req)
918924
{
919925
LobBaton *lobBaton = (LobBaton *)req->data;
926+
ILob *iLob = lobBaton->iLob;
920927

921928
if(!(lobBaton->error).empty())
922929
goto exitAsyncWrite;
923930

924931
try
925932
{
926-
ILob *iLob = lobBaton->iLob;
927933
unsigned long long byteAmount = lobBaton->writelen;
928934
unsigned long long charAmount = 0; // interested in byte amount only
929935

@@ -938,10 +944,10 @@ void ILob::Async_Write(uv_work_t *req)
938944
else
939945
iLob->offset_ += byteAmount;
940946
}
941-
942947
catch (dpi::Exception& e)
943948
{
944-
lobBaton->error = std::string(e.what());
949+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), iLob->dpiconn_ );
950+
lobBaton->error = std::string(e.what());
945951
}
946952

947953
exitAsyncWrite:
@@ -1021,9 +1027,9 @@ try : lobLocator_(lobLocator), fetchType_(fetchType), errh_(NULL),
10211027
errh_, lobLocator_);
10221028
length_ = Lob::length(executeBaton->dpiconn->getSvch(), errh_, lobLocator_);
10231029
}
1024-
10251030
catch (dpi::Exception &e)
10261031
{
1032+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), executeBaton->dpiconn );
10271033
executeBaton->error = std::string(e.what());
10281034
cleanup();
10291035
}

src/njs/src/njsIntLob.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ class ILob : public ObjectWrap
198198
Descriptor *lobLocator_;
199199
unsigned short fetchType_;
200200

201+
dpi::Conn *dpiconn_;
201202
DpiHandle *svch_;
202203
DpiHandle *errh_;
203204
bool isValid_;

src/njs/src/njsOracle.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,7 @@ void Oracledb::Async_GetConnection (uv_work_t *req)
712712
}
713713
catch (dpi::Exception& e)
714714
{
715+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), NULL );
715716
connBaton->error = std::string(e.what());
716717
}
717718
exitAsync_GetConnection:
@@ -859,6 +860,7 @@ void Oracledb::Async_CreatePool (uv_work_t *req)
859860
}
860861
catch (dpi::Exception &e)
861862
{
863+
NJS_SET_CONN_ERR_STATUS ( e.errnum(), NULL );
862864
poolBaton->error = std::string (e.what() );
863865
}
864866
exitAsyncCreatePool:

0 commit comments

Comments
 (0)