Add atomic reference counting and port DBI (bug 5876 part 3, r=ds).

--HG--
extra : rebase_source : a6defaf477e7a856ce91f92d5f3143f12c141da3
This commit is contained in:
David Anderson
2013-08-23 00:18:13 -07:00
parent dac42ee272
commit 4d43374fde
20 changed files with 235 additions and 143 deletions
@@ -306,7 +306,6 @@ DBResult MyBasicResults::CopyBlob(unsigned int columnId, void *buffer, size_t ma
MyQuery::MyQuery(MyDatabase *db, MYSQL_RES *res)
: m_pParent(db), m_rs(res)
{
m_pParent->IncReferenceCount();
m_InsertID = m_pParent->GetInsertID();
m_AffectedRows = m_pParent->GetAffectedRows();
}
@@ -371,9 +370,6 @@ void MyQuery::Destroy()
mysql_free_result(m_rs.m_pRes);
}
/* Tell our parent we're done */
m_pParent->Close();
/* Self destruct */
delete this;
}
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod MySQL Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -91,7 +91,7 @@ public: // Used by the driver to implement GetInsertIDForQuery()/GetAffectedRows
unsigned int GetInsertID();
unsigned int GetAffectedRows();
private:
MyDatabase *m_pParent;
ke::Ref<MyDatabase> m_pParent;
MyBasicResults m_rs;
unsigned int m_InsertID;
unsigned int m_AffectedRows;
+13 -48
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod MySQL Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -87,7 +87,7 @@ DBType GetOurType(enum_field_types type)
}
MyDatabase::MyDatabase(MYSQL *mysql, const DatabaseInfo *info, bool persistent)
: m_mysql(mysql), m_refcount(1), m_pFullLock(NULL), m_bPersistent(persistent)
: m_mysql(mysql), m_bPersistent(persistent)
{
m_Host.assign(info->host);
m_Database.assign(info->database);
@@ -101,50 +101,24 @@ MyDatabase::MyDatabase(MYSQL *mysql, const DatabaseInfo *info, bool persistent)
m_Info.driver = NULL;
m_Info.maxTimeout = info->maxTimeout;
m_Info.port = info->port;
m_pRefLock = threader->MakeMutex();
}
MyDatabase::~MyDatabase()
{
/* Remove us from the search list */
if (m_bPersistent)
g_MyDriver.RemoveFromList(this, true);
mysql_close(m_mysql);
m_mysql = NULL;
m_pRefLock->DestroyThis();
if (m_pFullLock)
{
m_pFullLock->DestroyThis();
}
}
void MyDatabase::IncReferenceCount()
{
m_pRefLock->Lock();
m_refcount++;
m_pRefLock->Unlock();
AddRef();
}
bool MyDatabase::Close()
{
m_pRefLock->Lock();
if (m_refcount > 1)
{
m_refcount--;
m_pRefLock->Unlock();
return false;
}
m_pRefLock->Unlock();
/* Remove us from the search list */
if (m_bPersistent)
{
g_MyDriver.RemoveFromList(this, true);
}
/* Finally, free our resource(s) */
delete this;
return true;
return !Release();
}
const DatabaseInfo &MyDatabase::GetInfo()
@@ -300,26 +274,17 @@ IPreparedQuery *MyDatabase::PrepareQuery(const char *query, char *error, size_t
bool MyDatabase::LockForFullAtomicOperation()
{
if (!m_pFullLock)
{
m_pFullLock = threader->MakeMutex();
if (!m_pFullLock)
{
return false;
}
}
m_pFullLock->Lock();
if (!m_FullLock)
m_FullLock = new ke::Mutex();
m_FullLock->Lock();
return true;
}
void MyDatabase::UnlockFromFullAtomicOperation()
{
if (m_pFullLock)
{
m_pFullLock->Unlock();
}
if (m_FullLock)
m_FullLock->Unlock();
}
IDBDriver *MyDatabase::GetDriver()
@@ -330,4 +295,4 @@ IDBDriver *MyDatabase::GetDriver()
bool MyDatabase::SetCharacterSet(const char *characterset)
{
return mysql_set_character_set(m_mysql, characterset) == 0 ? true : false;
}
}
+7 -6
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod MySQL Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -32,13 +32,16 @@
#ifndef _INCLUDE_SM_MYSQL_DATABASE_H_
#define _INCLUDE_SM_MYSQL_DATABASE_H_
#include <am-thread-utils.h>
#include <am-refcounting-threadsafe.h>
#include "MyDriver.h"
#include <IThreader.h>
class MyQuery;
class MyStatement;
class MyDatabase : public IDatabase
class MyDatabase
: public IDatabase,
public ke::RefcountedThreadsafe<MyDatabase>
{
friend class MyQuery;
friend class MyStatement;
@@ -67,9 +70,7 @@ public:
const DatabaseInfo &GetInfo();
private:
MYSQL *m_mysql;
unsigned int m_refcount;
IMutex *m_pFullLock;
IMutex *m_pRefLock;
ke::AutoPtr<ke::Mutex> m_FullLock;
/* ---------- */
DatabaseInfo m_Info;
+4 -1
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod MySQL Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -154,6 +154,8 @@ bool CompareField(const char *str1, const char *str2)
IDatabase *MyDriver::Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength)
{
ke::AutoLock lock(&m_Lock);
if (persistent)
{
/* Try to find a matching persistent connection */
@@ -194,6 +196,7 @@ IDatabase *MyDriver::Connect(const DatabaseInfo *info, bool persistent, char *er
void MyDriver::RemoveFromList(MyDatabase *pdb, bool persistent)
{
ke::AutoLock lock(&m_Lock);
if (persistent)
{
m_PermDbs.remove(pdb);
+4 -1
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod MySQL Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -32,6 +32,7 @@
#ifndef _INCLUDE_SM_MYSQL_DRIVER_H_
#define _INCLUDE_SM_MYSQL_DRIVER_H_
#define SOURCEMOD_SQL_DRIVER_CODE
#include <IDBDriver.h>
#include <sm_platform.h>
#if defined PLATFORM_WINDOWS
@@ -46,6 +47,7 @@
#include <sh_string.h>
#include <sh_list.h>
#include <am-thread-utils.h>
using namespace SourceMod;
using namespace SourceHook;
@@ -71,6 +73,7 @@ public:
void Shutdown();
void RemoveFromList(MyDatabase *pdb, bool persistent);
private:
ke::Mutex m_Lock;
Handle_t m_MyHandle;
List<MyDatabase *> m_TempDbs;
List<MyDatabase *> m_PermDbs;
-5
View File
@@ -48,8 +48,6 @@ MyStatement::MyStatement(MyDatabase *db, MYSQL_STMT *stmt)
m_bind = NULL;
}
m_pParent->IncReferenceCount();
m_pRes = mysql_stmt_result_metadata(stmt);
m_Results = false;
}
@@ -75,9 +73,6 @@ MyStatement::~MyStatement()
mysql_free_result(m_pRes);
}
mysql_stmt_close(m_stmt);
/* Tell the parent database that we're done referencing it */
m_pParent->Close();
}
void MyStatement::Destroy()
+2 -2
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod MySQL Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -69,7 +69,7 @@ private:
void *CopyBlob(unsigned int param, const void *blobptr, size_t length);
private:
MYSQL *m_mysql;
MyDatabase *m_pParent;
ke::Ref<MyDatabase> m_pParent;
MYSQL_STMT *m_stmt;
MYSQL_BIND *m_bind;
MYSQL_RES *m_pRes;
+1 -1
View File
@@ -67,6 +67,6 @@
//#define SMEXT_ENABLE_MEMUTILS
//#define SMEXT_ENABLE_GAMEHELPERS
//#define SMEXT_ENABLE_TIMERSYS
#define SMEXT_ENABLE_THREADER
//#define SMEXT_ENABLE_THREADER
#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
+12 -43
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod SQLite Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,47 +34,25 @@
#include "SqQuery.h"
SqDatabase::SqDatabase(sqlite3 *sq3, bool persistent) :
m_sq3(sq3), m_refcount(1), m_pFullLock(NULL), m_Persistent(persistent)
m_sq3(sq3), m_Persistent(persistent)
{
m_pRefLock = threader->MakeMutex();
}
SqDatabase::~SqDatabase()
{
m_pRefLock->DestroyThis();
if (m_pFullLock)
{
m_pFullLock->DestroyThis();
}
if (m_Persistent)
g_SqDriver.RemovePersistent(this);
sqlite3_close(m_sq3);
}
void SqDatabase::IncReferenceCount()
{
m_pRefLock->Lock();
m_refcount++;
m_pRefLock->Unlock();
AddRef();
}
bool SqDatabase::Close()
{
m_pRefLock->Lock();
if (m_refcount > 1)
{
m_refcount--;
m_pRefLock->Unlock();
return false;
}
m_pRefLock->Unlock();
if (m_Persistent)
{
g_SqDriver.RemovePersistent(this);
}
delete this;
return true;
return !Release();
}
const char *SqDatabase::GetError(int *errorCode/* =NULL */)
@@ -84,26 +62,17 @@ const char *SqDatabase::GetError(int *errorCode/* =NULL */)
bool SqDatabase::LockForFullAtomicOperation()
{
if (!m_pFullLock)
{
m_pFullLock = threader->MakeMutex();
if (!m_pFullLock)
{
return false;
}
}
m_pFullLock->Lock();
if (!m_FullLock)
m_FullLock = new ke::Mutex();
m_FullLock->Lock();
return true;
}
void SqDatabase::UnlockFromFullAtomicOperation()
{
if (m_pFullLock)
{
m_pFullLock->Unlock();
}
if (m_FullLock)
m_FullLock->Unlock();
}
IDBDriver *SqDatabase::GetDriver()
@@ -259,4 +228,4 @@ bool SqDatabase::SetCharacterSet(const char *characterset)
{
// sqlite only supports utf8 and utf16 - by the time the database is created. It's too late here.
return false;
}
}
+7 -6
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod SQLite Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -32,10 +32,13 @@
#ifndef _INCLUDE_SQLITE_SOURCEMOD_DATABASE_H_
#define _INCLUDE_SQLITE_SOURCEMOD_DATABASE_H_
#include <IThreader.h>
#include <am-refcounting-threadsafe.h>
#include <am-thread-utils.h>
#include "SqDriver.h"
class SqDatabase : public IDatabase
class SqDatabase
: public IDatabase,
public ke::RefcountedThreadsafe<SqDatabase>
{
public:
SqDatabase(sqlite3 *sq3, bool persistent);
@@ -63,9 +66,7 @@ public:
sqlite3 *GetDb();
private:
sqlite3 *m_sq3;
unsigned int m_refcount;
IMutex *m_pFullLock;
IMutex *m_pRefLock;
ke::AutoPtr<ke::Mutex> m_FullLock;
bool m_Persistent;
String m_LastError;
int m_LastErrorCode;
+4 -16
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod SQLite Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -66,24 +66,16 @@ int busy_handler(void *unused1, int unused2)
SqDriver::SqDriver()
{
m_Handle = BAD_HANDLE;
m_pOpenLock = NULL;
m_bThreadSafe = false;
}
void SqDriver::Initialize()
{
m_pOpenLock = threader->MakeMutex();
InitializeThreadSafety();
}
void SqDriver::Shutdown()
{
if (m_pOpenLock)
{
m_pOpenLock->DestroyThis();
}
if (m_bThreadSafe)
{
sqlite3_enable_shared_cache(0);
@@ -158,8 +150,7 @@ inline bool IsPathSepChar(char c)
IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength)
{
/* We wrap most of the open process in a mutex just to be safe */
m_pOpenLock->Lock();
ke::AutoLock lock(&m_OpenLock);
/* Format our path */
char path[PLATFORM_MAX_PATH];
@@ -189,7 +180,6 @@ IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *er
if (!libsys->CreateFolder(fullpath))
{
strncopy(error, "Could not create or open \"data\" folder\"", maxlength);
m_pOpenLock->Unlock();
return NULL;
}
}
@@ -237,7 +227,6 @@ IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *er
if ((*iter).path.compare(fullpath) == 0)
{
(*iter).db->IncReferenceCount();
m_pOpenLock->Unlock();
return (*iter).db;
}
}
@@ -250,7 +239,6 @@ IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *er
{
strncopy(error, sqlite3_errmsg(sql), maxlength);
sqlite3_close(sql);
m_pOpenLock->Unlock();
return NULL;
}
@@ -266,13 +254,13 @@ IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *er
m_Cache.push_back(pinfo);
}
m_pOpenLock->Unlock();
return pdb;
}
void SqDriver::RemovePersistent(IDatabase *pdb)
{
ke::AutoLock lock(&m_OpenLock);
List<SqDbInfo>::iterator iter;
for (iter = m_Cache.begin(); iter != m_Cache.end(); iter++)
{
+4 -3
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod SQLite Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -32,10 +32,11 @@
#ifndef _INCLUDE_SQLITE_SOURCEMOD_DRIVER_H_
#define _INCLUDE_SQLITE_SOURCEMOD_DRIVER_H_
#define SOURCEMOD_SQL_DRIVER_CODE
#include <IDBDriver.h>
#include <IThreader.h>
#include <sh_list.h>
#include <sh_string.h>
#include <am-thread-utils.h>
#include "sqlite-source/sqlite3.h"
using namespace SourceMod;
@@ -70,7 +71,7 @@ public:
void RemovePersistent(IDatabase *pdb);
private:
Handle_t m_Handle;
IMutex *m_pOpenLock;
ke::Mutex m_OpenLock;
List<SqDbInfo> m_Cache;
bool m_bThreadSafe;
};
-2
View File
@@ -36,14 +36,12 @@ SqQuery::SqQuery(SqDatabase *parent, sqlite3_stmt *stmt) :
{
m_ParamCount = sqlite3_bind_parameter_count(m_pStmt);
m_ColCount = sqlite3_column_count(m_pStmt);
m_pParent->IncReferenceCount();
}
SqQuery::~SqQuery()
{
delete m_pResults;
sqlite3_finalize(m_pStmt);
m_pParent->Close();
}
IResultSet *SqQuery::GetResultSet()
+3 -2
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod SQLite Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -32,6 +32,7 @@
#ifndef _INCLUDE_SQLITE_SOURCEMOD_QUERY_H_
#define _INCLUDE_SQLITE_SOURCEMOD_QUERY_H_
#include <am-refcounting.h>
#include "SqDatabase.h"
#include "SqResults.h"
@@ -81,7 +82,7 @@ public: //IResultRow
public:
sqlite3_stmt *GetStmt();
private:
SqDatabase *m_pParent;
ke::Ref<SqDatabase> m_pParent;
sqlite3_stmt *m_pStmt;
SqResults *m_pResults;
unsigned int m_ParamCount;
+1
View File
@@ -37,6 +37,7 @@
* @brief Sample extension code header.
*/
#define SOURCEMOD_SQL_DRIVER_CODE
#include "smsdk_ext.h"
+1 -1
View File
@@ -67,7 +67,7 @@
//#define SMEXT_ENABLE_MEMUTILS
//#define SMEXT_ENABLE_GAMEHELPERS
//#define SMEXT_ENABLE_TIMERSYS
#define SMEXT_ENABLE_THREADER
//#define SMEXT_ENABLE_THREADER
#define SMEXT_ENABLE_LIBSYS
#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_