mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-28 22:15:49 -04:00
Added sharedDatabaseInterface and oci implementation libraries
This commit is contained in:
@@ -0,0 +1,289 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// OCISession.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "OciSession.h"
|
||||
|
||||
#include "OciQueryImplementation.h"
|
||||
#include "OciServer.h"
|
||||
#include "sharedDatabaseInterface/DbException.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
#include "sharedLog/Log.h"
|
||||
#include "sharedSynchronization/RecursiveMutex.h"
|
||||
|
||||
#include <oci.h>
|
||||
#include <time.h>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace OCISessionNamespace
|
||||
{
|
||||
RecursiveMutex connectLock;
|
||||
}
|
||||
}
|
||||
|
||||
using namespace DB::OCISessionNamespace;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
static dvoid *mallocHook(dvoid *, size_t size)
|
||||
{
|
||||
return reinterpret_cast<dvoid *>(new char[size]);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
static dvoid *reallocHook(dvoid *, dvoid *memptr, size_t newsize)
|
||||
{
|
||||
return reinterpret_cast<dvoid *>(MemoryManager::reallocate(memptr, newsize));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
static void freeHook(dvoid *, dvoid *memptr)
|
||||
{
|
||||
if (memptr)
|
||||
delete [] reinterpret_cast<char *>(memptr);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
DB::OCISession::OCISession(DB::OCIServer *server) :
|
||||
m_server(server),
|
||||
envhp(NULL),
|
||||
errhp(NULL),
|
||||
srvhp(NULL),
|
||||
sesp(NULL),
|
||||
svchp(NULL),
|
||||
autoCommitMode(true),
|
||||
m_resetTime(server->getReconnectTime()==0 ? 0 : time(0) + server->getReconnectTime()),
|
||||
m_okToFetch(true)
|
||||
{
|
||||
}
|
||||
|
||||
DB::OCISession::~OCISession()
|
||||
{
|
||||
if (connected)
|
||||
disconnect();
|
||||
}
|
||||
|
||||
bool DB::OCISession::connect()
|
||||
{
|
||||
connectLock.enter();
|
||||
|
||||
// Create OCI environment. We're creating one environment per session,
|
||||
// so that each session can be used by a different thread concurrently.
|
||||
|
||||
sword result=OCI_ERROR;
|
||||
if (m_server->getUseMemoryManager())
|
||||
{
|
||||
result = OCIEnvCreate(&envhp, // OCIEnv **envhpp,
|
||||
OCI_THREADED | OCI_OBJECT, //ub4 mode, //TODO: do we have to use threaded mode?
|
||||
0, // CONST dvoid *ctxp,
|
||||
&mallocHook, // CONST dvoid *(*malocfp)
|
||||
// (dvoid *ctxp,
|
||||
// size_t size),
|
||||
&reallocHook, // CONST dvoid *(*ralocfp)
|
||||
// (dvoid *ctxp,
|
||||
// dvoid *memptr,
|
||||
// size_t newsize),
|
||||
&freeHook, // CONST void (*mfreefp)
|
||||
// (dvoid *ctxp,
|
||||
// dvoid *memptr))
|
||||
0, //size_t xtramemsz,
|
||||
0 ); //dvoid **usrmempp );
|
||||
}
|
||||
else
|
||||
{
|
||||
result = OCIEnvCreate(&envhp, // OCIEnv **envhpp,
|
||||
OCI_THREADED | OCI_OBJECT, //ub4 mode, //TODO: do we have to use threaded mode?
|
||||
0, // CONST dvoid *ctxp,
|
||||
0, // CONST dvoid *(*malocfp)
|
||||
// (dvoid *ctxp,
|
||||
// size_t size),
|
||||
0, // CONST dvoid *(*ralocfp)
|
||||
// (dvoid *ctxp,
|
||||
// dvoid *memptr,
|
||||
// size_t newsize),
|
||||
0, // CONST void (*mfreefp)
|
||||
// (dvoid *ctxp,
|
||||
// dvoid *memptr))
|
||||
0, //size_t xtramemsz,
|
||||
0 ); //dvoid **usrmempp );
|
||||
|
||||
}
|
||||
FATAL(result != OCI_SUCCESS,("OciEnvCreate failed with error code %hd",result));
|
||||
|
||||
// Create error handle.
|
||||
OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &errhp, OCI_HTYPE_ERROR,
|
||||
(size_t) 0, (dvoid **) 0);
|
||||
|
||||
// Create handle to the server and establish connection
|
||||
OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &srvhp, OCI_HTYPE_SERVER,
|
||||
(size_t) 0, (dvoid **) 0);
|
||||
|
||||
int retryCount = 0;
|
||||
connected = false;
|
||||
while (!connected && retryCount < 5)
|
||||
{
|
||||
LOG("DatabaseConnect", ("calling OCIServerAttach() for OCISession=[%p] with dsn=[%s], uid=[%s], pwd=[%s]", this, m_server->getDSN(), m_server->uid, m_server->pwd));
|
||||
|
||||
connected = DB::OCIServer::checkerr(*this,
|
||||
OCIServerAttach( srvhp, errhp, reinterpret_cast<OraText*>(const_cast<char*>(m_server->getDSN())), strlen(m_server->getDSN()), 0));
|
||||
|
||||
if (! connected)
|
||||
{
|
||||
++retryCount;
|
||||
DEBUG_REPORT_LOG(retryCount<5,("Retrying database connection\n"));
|
||||
Os::sleep(1000);
|
||||
}
|
||||
}
|
||||
if (!connected)
|
||||
{
|
||||
LOG("DatabaseError", ("Database error, Failed to connect to database after 5 tries"));
|
||||
disconnect(); // cleanup
|
||||
connectLock.leave();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a session, set userid & password
|
||||
OCIHandleAlloc(envhp, (void**) &sesp,
|
||||
(ub4) OCI_HTYPE_SESSION, (size_t) 0, (dvoid **) 0);
|
||||
|
||||
OCIAttrSet((dvoid *) sesp, (ub4) OCI_HTYPE_SESSION,
|
||||
(dvoid *) m_server->uid, strlen(m_server->uid),
|
||||
(ub4) OCI_ATTR_USERNAME, errhp);
|
||||
|
||||
OCIAttrSet((dvoid *) sesp, (ub4) OCI_HTYPE_SESSION,
|
||||
(dvoid *) m_server->pwd, strlen(m_server->pwd),
|
||||
(ub4) OCI_ATTR_PASSWORD, errhp);
|
||||
|
||||
// create service context (Wtf is a service context? Don't know, but you gotta have one.)
|
||||
OCIHandleAlloc( envhp, (dvoid **) &svchp, OCI_HTYPE_SVCCTX,
|
||||
(size_t) 0, (dvoid **) 0);
|
||||
|
||||
// Service context has pointers to Server and Session
|
||||
OCIAttrSet( (dvoid *) svchp, OCI_HTYPE_SVCCTX, srvhp,
|
||||
(ub4) 0, OCI_ATTR_SERVER, errhp);
|
||||
|
||||
OCIAttrSet((dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX,
|
||||
(dvoid *) sesp, (ub4) 0,
|
||||
(ub4) OCI_ATTR_SESSION, errhp);
|
||||
|
||||
// Establish session (i.e. check password)
|
||||
if (DB::OCIServer::checkerr(*this, OCISessionBegin ( svchp, errhp, sesp, OCI_CRED_RDBMS, (ub4) OCI_DEFAULT)))
|
||||
{
|
||||
connected=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect(); // cleanup
|
||||
connected=false;
|
||||
}
|
||||
|
||||
connectLock.leave();
|
||||
return connected;
|
||||
}
|
||||
|
||||
bool DB::OCISession::disconnect()
|
||||
{
|
||||
connectLock.enter();
|
||||
|
||||
bool success = true;
|
||||
|
||||
connected=false;
|
||||
|
||||
if (srvhp && errhp && !DB::OCIServer::checkerr(*this,OCIServerDetach( srvhp, errhp, OCI_DEFAULT)))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIDetach returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (svchp && (OCIHandleFree(svchp,OCI_HTYPE_SVCCTX) != OCI_SUCCESS))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIHandleFree OCI_HTYPE_SVCCTX returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (sesp && (OCIHandleFree(sesp,OCI_HTYPE_SESSION) != OCI_SUCCESS))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIHandleFree OCI_HTYPE_SESSION returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (srvhp && (OCIHandleFree(srvhp,OCI_HTYPE_SERVER) != OCI_SUCCESS))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIHandleFree OCI_HTYPE_SERVER returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (errhp && (OCIHandleFree(errhp,OCI_HTYPE_ERROR) != OCI_SUCCESS))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIHandleFree OCI_HTYPE_ERROR returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (envhp && (OCIHandleFree(envhp,OCI_HTYPE_ENV) != OCI_SUCCESS))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIHandleFree OCI_HTYPE_ENV returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
svchp = NULL;
|
||||
sesp = NULL;
|
||||
srvhp = NULL;
|
||||
errhp = NULL;
|
||||
envhp = NULL;
|
||||
|
||||
connectLock.leave();
|
||||
return success;
|
||||
}
|
||||
|
||||
bool DB::OCISession::setAutoCommitMode(bool autocommit)
|
||||
{
|
||||
autoCommitMode=autocommit;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DB::OCISession::commitTransaction()
|
||||
{
|
||||
m_okToFetch = false;
|
||||
return m_server->checkerr(*this, OCITransCommit(svchp, errhp, 0));
|
||||
}
|
||||
|
||||
bool DB::OCISession::rollbackTransaction()
|
||||
{
|
||||
return m_server->checkerr(*this, OCITransRollback(svchp, errhp, 0));
|
||||
}
|
||||
|
||||
bool DB::OCISession::reset()
|
||||
{
|
||||
autoCommitMode = true;
|
||||
if (m_resetTime !=0 && time(0) > m_resetTime)
|
||||
{
|
||||
LOG("Reconnections",("Reconnecting"));
|
||||
commitTransaction(); // just to be safe -- there shouldn't be an oustanding transaction now anyway
|
||||
disconnect();
|
||||
connect();
|
||||
m_resetTime = time(0) + m_server->getReconnectTime();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DB::QueryImpl *DB::OCISession::createQueryImpl(Query *owner) const
|
||||
{
|
||||
return new DB::OCIQueryImpl(owner, autoCommitMode);
|
||||
}
|
||||
|
||||
void DB::OCISession::setOkToFetch()
|
||||
{
|
||||
m_okToFetch = true;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
Reference in New Issue
Block a user