summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeavey <peavey@e03df62e-2008-0410-955e-edbf42e46eb7>2006-12-30 16:29:04 +0000
committerpeavey <peavey@e03df62e-2008-0410-955e-edbf42e46eb7>2006-12-30 16:29:04 +0000
commitd0147795f8dc4c37c0061638ae6ba57a7c9bd26e (patch)
tree2ca7a6206a3b5d3529818ece568a90deede6dc19
parente5facb2cd00fca595d4b37c4de8ad0938d9eac25 (diff)
Now REHASH checks for same and old connections, same as the DNS resolver. So that the connections are only reset if things were changed. \o/
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@6173 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--src/modules/extra/m_pgsql.cpp130
1 files changed, 95 insertions, 35 deletions
diff --git a/src/modules/extra/m_pgsql.cpp b/src/modules/extra/m_pgsql.cpp
index 50bd6625a..13dc9c3a8 100644
--- a/src/modules/extra/m_pgsql.cpp
+++ b/src/modules/extra/m_pgsql.cpp
@@ -82,16 +82,22 @@ class SQLhost
}
};
+bool operator== (const SQLhost& l, const SQLhost& r)
+{
+ return (l.id == r.id && l.host == r.host && l.port == r.port && l.name == r.name && l.user == l.user && l.pass == r.pass && l.ssl == r.ssl);
+}
+
/** Used to resolve sql server hostnames
*/
class SQLresolver : public Resolver
{
private:
SQLhost host;
+ SQLhost confhost;
Module* mod;
public:
- SQLresolver(Module* m, InspIRCd* Instance, const SQLhost& hi)
- : Resolver(Instance, hi.host, DNS_QUERY_FORWARD, (Module*)m), host(hi), mod(m)
+ SQLresolver(Module* m, InspIRCd* Instance, const SQLhost& hi, const SQLhost& ci)
+ : Resolver(Instance, hi.host, DNS_QUERY_FORWARD, (Module*)m), host(hi), confhost(ci), mod(m)
{
}
@@ -101,7 +107,6 @@ class SQLresolver : public Resolver
{
ServerInstance->Log(DEBUG, "DNS lookup failed (%s), dying horribly", errormessage.c_str());
}
-
};
/** QueryQueue, a queue of queries waiting to be executed.
@@ -447,24 +452,24 @@ public:
class SQLConn : public InspSocket
{
private:
- Module* us; /* Pointer to the SQL provider itself */
- std::string dbhost; /* Database server hostname */
- unsigned int dbport; /* Database server port */
- std::string dbname; /* Database name */
- std::string dbuser; /* Database username */
- std::string dbpass; /* Database password */
- bool ssl; /* If we should require SSL */
- PGconn* sql; /* PgSQL database connection handle */
- SQLstatus status; /* PgSQL database connection status */
- bool qinprog;/* If there is currently a query in progress */
- QueryQueue queue; /* Queue of queries waiting to be executed on this connection */
- time_t idle; /* Time we last heard from the database */
-
+ Module* us; /* Pointer to the SQL provider itself */
+ std::string dbhost; /* Database server hostname */
+ unsigned int dbport; /* Database server port */
+ std::string dbname; /* Database name */
+ std::string dbuser; /* Database username */
+ std::string dbpass; /* Database password */
+ bool ssl; /* If we should require SSL */
+ PGconn* sql; /* PgSQL database connection handle */
+ SQLstatus status; /* PgSQL database connection status */
+ bool qinprog; /* If there is currently a query in progress */
+ QueryQueue queue; /* Queue of queries waiting to be executed on this connection */
+ time_t idle; /* Time we last heard from the database */
+ SQLhost confhost; /* A copy of the config <database> entry for conf checks */
public:
/* This class should only ever be created inside this module, using this constructor, so we don't have to worry about the default ones */
- SQLConn(InspIRCd* SI, Module* self, const SQLhost& hostinfo);
+ SQLConn(InspIRCd* SI, Module* self, const SQLhost& hostinfo, const SQLhost& confinfo);
~SQLConn();
@@ -499,9 +504,11 @@ public:
SQLerror Query(const SQLrequest &req);
void OnUnloadModule(Module* mod);
+
+ const SQLhost GetConfHost();
};
-SQLConn::SQLConn(InspIRCd* SI, Module* self, const SQLhost& hi)
+SQLConn::SQLConn(InspIRCd* SI, Module* self, const SQLhost& hi, const SQLhost& ci)
: InspSocket::InspSocket(SI), us(self), dbhost(hi.host), dbport(hi.port), dbname(hi.name), dbuser(hi.user), dbpass(hi.pass), ssl(hi.ssl), sql(NULL), status(CWRITE), qinprog(false)
{
//ServerInstance->Log(DEBUG, "Creating new PgSQL connection to database %s on %s:%u (%s/%s)", dbname.c_str(), dbhost.c_str(), dbport, dbuser.c_str(), dbpass.c_str());
@@ -509,6 +516,7 @@ SQLConn::SQLConn(InspIRCd* SI, Module* self, const SQLhost& hi)
/* Some of this could be reviewed, unsure if I need to fill 'host' etc...
* just copied this over from the InspSocket constructor.
*/
+ confhost = ci;
strlcpy(this->host, dbhost.c_str(), MAXBUF);
strlcpy(this->IP, dbhost.c_str(), MAXBUF);
this->port = dbport;
@@ -1038,18 +1046,22 @@ void SQLConn::OnUnloadModule(Module* mod)
queue.PurgeModule(mod);
}
+const SQLhost SQLConn::GetConfHost()
+{
+ return confhost;
+}
+
class ModulePgSQL : public Module
{
private:
ConnMap connections;
unsigned long currid;
- bool modloading;
char* sqlsuccess;
public:
ModulePgSQL(InspIRCd* Me)
- : Module::Module(Me), currid(0), modloading(true)
+ : Module::Module(Me), currid(0)
{
ServerInstance->UseInterface("SQLutils");
@@ -1069,12 +1081,12 @@ public:
virtual ~ModulePgSQL()
{
- ClearConnections();
+ ClearAllConnections();
DELETE(sqlsuccess);
ServerInstance->UnpublishInterface("SQL", this);
ServerInstance->UnpublishFeature("SQL");
ServerInstance->DoneWithInterface("SQLutils");
- }
+ }
void Implements(char* List)
{
@@ -1083,20 +1095,42 @@ public:
virtual void OnRehash(const std::string &parameter)
{
- if (modloading)
+ ReadConf();
+ }
+
+ bool HasHost(const SQLhost &host)
+ {
+ for (ConnMap::iterator iter = connections.begin(); iter != connections.end(); iter++)
{
- modloading = false;
- return;
+ if (host == iter->second->GetConfHost())
+ return true;
}
+ return false;
+ }
- ReadConf();
+ bool HostInConf(const SQLhost &h)
+ {
+ ConfigReader conf(ServerInstance);
+ for(int i = 0; i < conf.Enumerate("database"); i++)
+ {
+ SQLhost host;
+ host.id = conf.ReadValue("database", "id", i);
+ host.host = conf.ReadValue("database", "hostname", i);
+ host.port = conf.ReadInteger("database", "port", i, true);
+ host.name = conf.ReadValue("database", "name", i);
+ host.user = conf.ReadValue("database", "username", i);
+ host.pass = conf.ReadValue("database", "password", i);
+ host.ssl = conf.ReadFlag("database", "ssl", i);
+ if (h == host)
+ return true;
+ }
+ return false;
}
void ReadConf()
{
ConfigReader conf(ServerInstance);
- ClearConnections();
for(int i = 0; i < conf.Enumerate("database"); i++)
{
SQLhost host;
@@ -1111,12 +1145,15 @@ public:
host.pass = conf.ReadValue("database", "password", i);
host.ssl = conf.ReadFlag("database", "ssl", i);
+ if (HasHost(host))
+ continue;
+
ipvalid = insp_aton(host.host.c_str(), &blargle);
-
+
if(ipvalid > 0)
{
/* The conversion succeeded, we were given an IP and we can give it straight to SQLConn */
- this->AddConn(host);
+ this->AddConn(host, host);
}
else if(ipvalid == 0)
{
@@ -1125,7 +1162,7 @@ public:
try
{
- resolver = new SQLresolver(this, ServerInstance, host);
+ resolver = new SQLresolver(this, ServerInstance, host, host);
ServerInstance->AddResolver(resolver);
}
@@ -1139,10 +1176,26 @@ public:
/* Invalid address family, die horribly. */
ServerInstance->Log(DEBUG, "insp_aton failed returning -1, oh noes.");
}
- }
+ }
+ ClearOldConnections();
+ }
+
+ void ClearOldConnections()
+ {
+ ConnMap::iterator iter,safei;
+ for (iter = connections.begin(); iter != connections.end(); iter++)
+ {
+ if (!HostInConf(iter->second->GetConfHost()))
+ {
+ DELETE(iter->second);
+ safei = iter;
+ --iter;
+ connections.erase(safei);
+ }
+ }
}
- void ClearConnections()
+ void ClearAllConnections()
{
ConnMap::iterator iter;
while ((iter = connections.begin()) != connections.end())
@@ -1152,12 +1205,18 @@ public:
}
}
- void AddConn(const SQLhost& hi)
+ void AddConn(const SQLhost& hi, const SQLhost& ci)
{
+ if (HasHost(ci))
+ {
+ ServerInstance->Log(DEFAULT, "WARNING: A pgsql connection with id: %s already exists, possible due to DNS delay, aborting.", hi.id.c_str());
+ return;
+ }
+
SQLConn* newconn;
/* The conversion succeeded, we were given an IP and we can give it straight to SQLConn */
- newconn = new SQLConn(ServerInstance, this, hi);
+ newconn = new SQLConn(ServerInstance, this, hi, ci);
connections.insert(std::make_pair(hi.id, newconn));
}
@@ -1225,7 +1284,8 @@ public:
void SQLresolver::OnLookupComplete(const std::string &result)
{
host.host = result;
- ((ModulePgSQL*)mod)->AddConn(host);
+ ((ModulePgSQL*)mod)->AddConn(host, confhost);
+ ((ModulePgSQL*)mod)->ClearOldConnections();
}
class ModulePgSQLFactory : public ModuleFactory