* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
- * InspIRCd is copyright (C) 2002-2004 ChatSpike-Dev.
- * E-mail:
- * <brain@chatspike.net>
- * <Craig@chatspike.net>
- *
- * Written by Craig Edwards, Craig McLure, and others.
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
* This program is free but copyrighted software; see
- * the file COPYING for details.
+ * the file COPYING for details.
*
* ---------------------------------------------------
*/
-using namespace std;
-
#include <stdio.h>
#include <string>
#include <mysql.h>
#include "users.h"
#include "channels.h"
#include "modules.h"
-
#include "inspircd.h"
#include "m_sqlv2.h"
/* $ModDesc: SQL Service Provider module for all other m_sql* modules */
/* $CompileFlags: `mysql_config --include` */
/* $LinkerFlags: `mysql_config --libs_r` `perl extra/mysql_rpath.pl` */
+/* $ModDep: m_sqlv2.h */
/* THE NONBLOCKING MYSQL API!
*
typedef std::deque<SQLresult*> ResultQueue;
+/** Represents a mysql query queue
+ */
class QueryQueue : public classbase
{
private:
pthread_mutex_t results_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t logging_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/** Represents a mysql result set
+ */
class MySQLresult : public SQLresult
{
int currentrow;
void NotifyMainThread(SQLConnection* connection_with_new_result);
+/** Represents a connection to a mysql database
+ */
class SQLConnection : public classbase
{
protected:
QueryQueue queue;
ResultQueue rq;
- // This constructor creates an SQLConnection object with the given credentials, and creates the underlying
- // MYSQL struct, but does not connect yet.
- SQLConnection(std::string thishost, std::string thisuser, std::string thispass, std::string thisdb, const std::string &myid)
+ // This constructor creates an SQLConnection object with the given credentials, but does not connect yet.
+ SQLConnection(const std::string &thishost, const std::string &thisuser, const std::string &thispass, const std::string &thisdb, const std::string &myid) : host(thishost), user(thisuser), pass(thispass), db(thisdb), Enabled(true), id(myid)
{
- this->Enabled = true;
- this->host = thishost;
- this->user = thisuser;
- this->pass = thispass;
- this->db = thisdb;
- this->id = myid;
}
// This method connects to the database using the credentials supplied to the constructor, and returns
* Pass them this connection id as what to examine
*/
+ delete[] query;
+
NotifyMainThread(this);
}
for (ConnMap::iterator i = Connections.begin(); i != Connections.end(); i++)
{
i->second->SetEnable(true);
- if (i->second->Connect())
- {
- ServerInstance->Log(DEFAULT,"SQL: Successfully connected database "+i->second->GetHost());
- }
- else
+ if (!i->second->Connect())
{
+ /* XXX: MUTEX */
+ pthread_mutex_lock(&logging_mutex);
ServerInstance->Log(DEFAULT,"SQL: Failed to connect database "+i->second->GetHost()+": Error: "+i->second->GetError());
i->second->SetEnable(false);
+ pthread_mutex_unlock(&logging_mutex);
}
}
}
+void ClearDatabases()
+{
+ ConnMap::iterator i;
+ while ((i = Connections.begin()) != Connections.end())
+ {
+ Connections.erase(i);
+ delete i->second;
+ }
+}
void LoadDatabases(ConfigReader* ThisConf, InspIRCd* ServerInstance)
{
- ServerInstance->Log(DEFAULT,"SQL: Loading database settings");
- Connections.clear();
- ServerInstance->Log(DEBUG,"Cleared connections");
+ ClearDatabases();
for (int j =0; j < ThisConf->Enumerate("database"); j++)
{
std::string db = ThisConf->ReadValue("database","name",j);
std::string pass = ThisConf->ReadValue("database","password",j);
std::string host = ThisConf->ReadValue("database","hostname",j);
std::string id = ThisConf->ReadValue("database","id",j);
- ServerInstance->Log(DEBUG,"Read database settings");
if ((db != "") && (host != "") && (user != "") && (id != "") && (pass != ""))
{
SQLConnection* ThisSQL = new SQLConnection(host,user,pass,db,id);
- ServerInstance->Log(DEFAULT,"Loaded database: "+ThisSQL->GetHost());
Connections[id] = ThisSQL;
- ServerInstance->Log(DEBUG,"Pushed back connection");
}
}
ConnectDatabases(ServerInstance);
void* DispatcherThread(void* arg);
+/** Used by m_mysql to notify one thread when the other has a result
+ */
class Notifier : public InspSocket
{
insp_sockaddr sock_us;
}
};
+/** MySQL module
+ */
class ModuleSQL : public Module
{
public:
pthread_t Dispatcher;
int currid;
+ ModuleSQL(InspIRCd* Me)
+ : Module::Module(Me)
+ {
+ ServerInstance->UseInterface("SQLutils");
+
+ Conf = new ConfigReader(ServerInstance);
+ PublicServerInstance = ServerInstance;
+ currid = 0;
+ SQLModule = this;
+
+ MessagePipe = new Notifier(ServerInstance);
+ ServerInstance->Log(DEBUG,"Bound notifier to 127.0.0.1:%d",MessagePipe->GetPort());
+
+ pthread_attr_t attribs;
+ pthread_attr_init(&attribs);
+ pthread_attr_setdetachstate(&attribs, PTHREAD_CREATE_DETACHED);
+ if (pthread_create(&this->Dispatcher, &attribs, DispatcherThread, (void *)this) != 0)
+ {
+ throw ModuleException("m_mysql: Failed to create dispatcher thread: " + std::string(strerror(errno)));
+ }
+
+ if (!ServerInstance->PublishFeature("SQL", this))
+ {
+ /* Tell worker thread to exit NOW */
+ giveup = true;
+ throw ModuleException("m_mysql: Unable to publish feature 'SQL'");
+ }
+
+ ServerInstance->PublishInterface("SQL", this);
+ }
+
+ virtual ~ModuleSQL()
+ {
+ giveup = true;
+ ClearDatabases();
+ DELETE(Conf);
+ ServerInstance->UnpublishInterface("SQL", this);
+ ServerInstance->DoneWithInterface("SQLutils");
+ }
+
+
void Implements(char* List)
{
List[I_OnRehash] = List[I_OnRequest] = 1;
return NULL;
}
- ModuleSQL(InspIRCd* Me)
- : Module::Module(Me)
- {
-
- Conf = new ConfigReader(ServerInstance);
- PublicServerInstance = ServerInstance;
- currid = 0;
- SQLModule = this;
-
- MessagePipe = new Notifier(ServerInstance);
- ServerInstance->Log(DEBUG,"Bound notifier to 127.0.0.1:%d",MessagePipe->GetPort());
-
- pthread_attr_t attribs;
- pthread_attr_init(&attribs);
- pthread_attr_setdetachstate(&attribs, PTHREAD_CREATE_DETACHED);
- if (pthread_create(&this->Dispatcher, &attribs, DispatcherThread, (void *)this) != 0)
- {
- throw ModuleException("m_mysql: Failed to create dispatcher thread: " + std::string(strerror(errno)));
- }
- if (!ServerInstance->PublishFeature("SQL", this))
- {
- /* Tell worker thread to exit NOW */
- giveup = true;
- throw ModuleException("m_mysql: Unable to publish feature 'SQL'");
- }
- }
-
- virtual ~ModuleSQL()
- {
- DELETE(Conf);
- }
-
virtual void OnRehash(const std::string ¶meter)
{
/* TODO: set rehash bool here, which makes the dispatcher thread rehash at next opportunity */