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 +}