core/Database.cpp
changeset 868 bdbf922e246f
parent 862 b8636f596080
child 869 caa5587e708a
     1.1 --- a/core/Database.cpp	Thu May 31 21:35:33 2007 +0000
     1.2 +++ b/core/Database.cpp	Fri Jun 01 02:30:29 2007 +0000
     1.3 @@ -16,9 +16,23 @@
     1.4  #include "HandleSys.h"
     1.5  #include "ShareSys.h"
     1.6  #include "sourcemod.h"
     1.7 +#include "sm_stringutil.h"
     1.8 +#include "TextParsers.h"
     1.9 +#include "Logger.h"
    1.10 +#include "ExtensionSys.h"
    1.11 +#include <stdlib.h>
    1.12 +
    1.13 +#define DBPARSE_LEVEL_NONE		0
    1.14 +#define DBPARSE_LEVEL_MAIN		1
    1.15 +#define DBPARSE_LEVEL_DATABASE	2
    1.16  
    1.17  DBManager g_DBMan;
    1.18  
    1.19 +DBManager::DBManager() 
    1.20 +: m_StrTab(512), m_ParseLevel(0), m_ParseState(0), m_pDefault(NULL)
    1.21 +{
    1.22 +}
    1.23 +
    1.24  void DBManager::OnSourceModAllInitialized()
    1.25  {
    1.26  	HandleAccess sec;
    1.27 @@ -31,6 +45,23 @@
    1.28  	m_DatabaseType = g_HandleSys.CreateType("IDatabase", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    1.29  
    1.30  	g_ShareSys.AddInterface(NULL, this);
    1.31 +
    1.32 +	g_SourceMod.BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg");
    1.33 +}
    1.34 +
    1.35 +void DBManager::OnSourceModLevelChange(const char *mapName)
    1.36 +{
    1.37 +	SMCParseError err;
    1.38 +	unsigned int line = 0;
    1.39 +	if ((err = g_TextParser.ParseFile_SMC(m_Filename, this, &line, NULL)) != SMCParse_Okay)
    1.40 +	{
    1.41 +		g_Logger.LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
    1.42 +		if (err != SMCParse_Custom)
    1.43 +		{
    1.44 +			const char *txt = g_TextParser.GetSMCErrorString(err);
    1.45 +			g_Logger.LogError("[SM] Line %d: %s", line, txt);
    1.46 +		}
    1.47 +	}
    1.48  }
    1.49  
    1.50  void DBManager::OnSourceModShutdown()
    1.51 @@ -64,23 +95,173 @@
    1.52  	}
    1.53  }
    1.54  
    1.55 -bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength)
    1.56 +void DBManager::ReadSMC_ParseStart()
    1.57  {
    1.58 -	const DatabaseInfo *pInfo = FindDatabaseConf(name);
    1.59 +	m_confs.clear();
    1.60 +	m_ParseLevel = 0;
    1.61 +	m_ParseState = DBPARSE_LEVEL_NONE;
    1.62 +	m_StrTab.Reset();
    1.63 +	m_DefDriver.clear();
    1.64 +}
    1.65  
    1.66 -	for (size_t i=0; i<m_drivers.size(); i++)
    1.67 +ConfDbInfo s_CurInfo;
    1.68 +SMCParseResult DBManager::ReadSMC_NewSection(const char *name, bool opt_quotes)
    1.69 +{
    1.70 +	if (m_ParseLevel)
    1.71 +	{
    1.72 +		m_ParseLevel++;
    1.73 +		return SMCParse_Continue;
    1.74 +	}
    1.75 +
    1.76 +	if (m_ParseState == DBPARSE_LEVEL_NONE)
    1.77  	{
    1.78 -		if (strcasecmp(pInfo->driver, m_drivers[i]->GetIdentifier()) == 0)
    1.79 +		if (strcmp(name, "Databases") == 0)
    1.80  		{
    1.81 -			*pdr = m_drivers[i];
    1.82 -			*pdb = m_drivers[i]->Connect(pInfo, persistent, error, maxlength);
    1.83 -			return (*pdb == NULL);
    1.84 +			m_ParseState = DBPARSE_LEVEL_MAIN;
    1.85 +		} else {
    1.86 +			m_ParseLevel++;
    1.87 +		}
    1.88 +	} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
    1.89 +		s_CurInfo = ConfDbInfo();
    1.90 +		s_CurInfo.database = m_StrTab.AddString(name);
    1.91 +		m_ParseState = DBPARSE_LEVEL_DATABASE;
    1.92 +	} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
    1.93 +		m_ParseLevel++;
    1.94 +	}
    1.95 +
    1.96 +	return SMCParse_Continue;
    1.97 +}
    1.98 +
    1.99 +SMCParseResult DBManager::ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes)
   1.100 +{
   1.101 +	if (m_ParseLevel)
   1.102 +	{
   1.103 +		return SMCParse_Continue;
   1.104 +	}
   1.105 +
   1.106 +	if (m_ParseState == DBPARSE_LEVEL_MAIN)
   1.107 +	{
   1.108 +		if (strcmp(key, "driver_default") == 0)
   1.109 +		{
   1.110 +			m_DefDriver.assign(value);
   1.111 +		}
   1.112 +	} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
   1.113 +		if (strcmp(key, "driver") == 0)
   1.114 +		{
   1.115 +			if (strcmp(value, "default") != 0)
   1.116 +			{
   1.117 +				s_CurInfo.driver = m_StrTab.AddString(value);
   1.118 +			}
   1.119 +		} else if (strcmp(key, "database") == 0) {
   1.120 +			s_CurInfo.database = m_StrTab.AddString(value);
   1.121 +		} else if (strcmp(key, "host") == 0) {
   1.122 +			s_CurInfo.host = m_StrTab.AddString(value);
   1.123 +		} else if (strcmp(key, "user") == 0) {
   1.124 +			s_CurInfo.user = m_StrTab.AddString(value);
   1.125 +		} else if (strcmp(key, "pass") == 0) {
   1.126 +			s_CurInfo.pass = m_StrTab.AddString(value);
   1.127 +		} else if (strcmp(key, "timeout") == 0) {
   1.128 +			s_CurInfo.info.maxTimeout = atoi(value);
   1.129 +		} else if (strcmp(key, "port") == 0) {
   1.130 +			s_CurInfo.info.port = atoi(value);
   1.131  		}
   1.132  	}
   1.133  
   1.134 -	*pdr = NULL;
   1.135 +	return SMCParse_Continue;
   1.136 +}
   1.137 +
   1.138 +#define ASSIGN_VAR(var) \
   1.139 +	if (s_CurInfo.var == -1) { \
   1.140 +		s_CurInfo.info.var = ""; \
   1.141 +	} else { \
   1.142 +		s_CurInfo.info.var = m_StrTab.GetString(s_CurInfo.var); \
   1.143 +	}
   1.144 +
   1.145 +SMCParseResult DBManager::ReadSMC_LeavingSection()
   1.146 +{
   1.147 +	if (m_ParseLevel)
   1.148 +	{
   1.149 +		m_ParseLevel--;
   1.150 +		return SMCParse_Continue;
   1.151 +	}
   1.152 +
   1.153 +	if (m_ParseState == DBPARSE_LEVEL_DATABASE)
   1.154 +	{
   1.155 +		/* Set all of the info members to either a blank string
   1.156 +		 * or the string pointer from the string table.
   1.157 +		 */
   1.158 +		ASSIGN_VAR(driver);
   1.159 +		ASSIGN_VAR(database);
   1.160 +		ASSIGN_VAR(host);
   1.161 +		ASSIGN_VAR(user);
   1.162 +		ASSIGN_VAR(pass);
   1.163 +		
   1.164 +		/* Save it.. */
   1.165 +		m_confs.push_back(s_CurInfo);
   1.166 +
   1.167 +		/* Go up one level */
   1.168 +		m_ParseState = DBPARSE_LEVEL_MAIN;
   1.169 +	} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
   1.170 +		m_ParseState = DBPARSE_LEVEL_NONE;
   1.171 +		return SMCParse_Halt;
   1.172 +	}
   1.173 +
   1.174 +	return SMCParse_Continue;
   1.175 +}
   1.176 +#undef ASSIGN_VAR
   1.177 +
   1.178 +void DBManager::ReadSMC_ParseEnd(bool halted, bool failed)
   1.179 +{
   1.180 +}
   1.181 +
   1.182 +bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength)
   1.183 +{
   1.184 +	ConfDbInfo *pInfo = GetDatabaseConf(name);
   1.185 +
   1.186 +	if (!pInfo)
   1.187 +	{
   1.188 +		if (pdr)
   1.189 +		{
   1.190 +			*pdr = NULL;
   1.191 +		}
   1.192 +		*pdb = NULL;
   1.193 +		UTIL_Format(error, maxlength, "Configuration \"%s\" not found", name);
   1.194 +		return false;
   1.195 +	}
   1.196 +
   1.197 +	if (!pInfo->realDriver)
   1.198 +	{
   1.199 +		/* Try to assign a real driver pointer */
   1.200 +		if (pInfo->info.driver[0] == '\0')
   1.201 +		{
   1.202 +			if (!m_pDefault && m_DefDriver.size() > 0)
   1.203 +			{
   1.204 +				m_pDefault = FindOrLoadDriver(m_DefDriver.c_str());
   1.205 +			}
   1.206 +			pInfo->realDriver = m_pDefault;
   1.207 +		} else {
   1.208 +			pInfo->realDriver = FindOrLoadDriver(pInfo->info.driver);
   1.209 +		}
   1.210 +	}
   1.211 +
   1.212 +	if (pInfo->realDriver)
   1.213 +	{
   1.214 +		if (pdr)
   1.215 +		{
   1.216 +			*pdr = pInfo->realDriver;
   1.217 +		}
   1.218 +		*pdb = pInfo->realDriver->Connect(&pInfo->info, persistent, error, maxlength);
   1.219 +		return (*pdb != NULL);
   1.220 +	}
   1.221 +
   1.222 +	if (pdr)
   1.223 +	{
   1.224 +		*pdr = NULL;
   1.225 +	}
   1.226  	*pdb = NULL;
   1.227  
   1.228 +	UTIL_Format(error, maxlength, "Driver \"%s\" not found", pInfo->driver);
   1.229 +
   1.230  	return false;
   1.231  }
   1.232  
   1.233 @@ -99,6 +280,27 @@
   1.234  			return;
   1.235  		}
   1.236  	}
   1.237 +
   1.238 +	/* Make sure NOTHING references this! */
   1.239 +	List<ConfDbInfo>::iterator iter;
   1.240 +	for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
   1.241 +	{
   1.242 +		ConfDbInfo &db = (*iter);
   1.243 +		if (db.realDriver == pDriver)
   1.244 +		{
   1.245 +			db.realDriver = NULL;
   1.246 +		}
   1.247 +	}
   1.248 +}
   1.249 +
   1.250 +IDBDriver *DBManager::GetDefaultDriver()
   1.251 +{
   1.252 +	if (!m_pDefault && m_DefDriver.size() > 0)
   1.253 +	{
   1.254 +		m_pDefault = FindOrLoadDriver(m_DefDriver.c_str());
   1.255 +	}
   1.256 +
   1.257 +	return m_pDefault;
   1.258  }
   1.259  
   1.260  Handle_t DBManager::CreateHandle(DBHandleType dtype, void *ptr, IdentityToken_t *pToken)
   1.261 @@ -158,6 +360,58 @@
   1.262  
   1.263  const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
   1.264  {
   1.265 -	/* :TODO: */
   1.266 +	ConfDbInfo *info = GetDatabaseConf(name);
   1.267 +	if (!info)
   1.268 +	{
   1.269 +		return NULL;
   1.270 +	}
   1.271 +
   1.272 +	return &info->info;
   1.273 +}
   1.274 +
   1.275 +ConfDbInfo *DBManager::GetDatabaseConf(const char *name)
   1.276 +{
   1.277 +	List<ConfDbInfo>::iterator iter;
   1.278 +
   1.279 +	for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
   1.280 +	{
   1.281 +		ConfDbInfo &conf = (*iter);
   1.282 +		if (strcmp(m_StrTab.GetString(conf.name), name) == 0)
   1.283 +		{
   1.284 +			return &conf;
   1.285 +		}
   1.286 +	}
   1.287 +
   1.288  	return NULL;
   1.289  }
   1.290 +
   1.291 +IDBDriver *DBManager::FindOrLoadDriver(const char *name)
   1.292 +{
   1.293 +	size_t last_size = m_drivers.size();
   1.294 +	for (size_t i=0; i<last_size; i++)
   1.295 +	{
   1.296 +		if (strcmp(m_drivers[i]->GetIdentifier(), name) == 0)
   1.297 +		{
   1.298 +			return m_drivers[i];
   1.299 +		}
   1.300 +	}
   1.301 +
   1.302 +	char filename[PLATFORM_MAX_PATH];
   1.303 +	UTIL_Format(filename, sizeof(filename), "dbi.%s", name);
   1.304 +
   1.305 +	IExtension *pExt = g_Extensions.LoadAutoExtension(filename);
   1.306 +	if (!pExt || !pExt->IsLoaded() || m_drivers.size() <= last_size)
   1.307 +	{
   1.308 +		return NULL;
   1.309 +	}
   1.310 +
   1.311 +	/* last_size is now gauranteed to be a valid index.
   1.312 +	 * The identifier must match the name.
   1.313 +	 */
   1.314 +	if (strcmp(m_drivers[last_size]->GetIdentifier(), name) == 0)
   1.315 +	{
   1.316 +		return m_drivers[last_size];
   1.317 +	}
   1.318 +
   1.319 +	return NULL;
   1.320 +}