* ---------------------------------------------------
*/
-#include <stdio.h>
-#include <string>
+#include "inspircd.h"
#include <mysql.h>
#include <pthread.h>
#include "users.h"
#include "channels.h"
#include "modules.h"
-#include "inspircd.h"
#include "m_sqlv2.h"
/* VERSION 2 API: With nonblocking (threaded) requests */
ConnectDatabases(ServerInstance);
}
+char FindCharId(const std::string &id)
+{
+ char i = 1;
+ for (ConnMap::iterator iter = Connections.begin(); iter != Connections.end(); ++iter, ++i)
+ {
+ if (iter->first == id)
+ {
+ return i;
+ }
+ }
+ return 0;
+}
+
+ConnMap::iterator GetCharId(char id)
+{
+ char i = 1;
+ for (ConnMap::iterator iter = Connections.begin(); iter != Connections.end(); ++iter, ++i)
+ {
+ if (i == id)
+ return iter;
+ }
+ return Connections.end();
+}
+
void NotifyMainThread(SQLConnection* connection_with_new_result)
{
/* Here we write() to the socket the main thread has open
* thread, we can just use standard connect(), and we can
* block if we like. We just send the connection id of the
* connection back.
+ *
+ * NOTE: We only send a single char down the connection, this
+ * way we know it wont get a partial read at the other end if
+ * the system is especially congested (see bug #263).
+ * The function FindCharId translates a connection name into a
+ * one character id, and GetCharId translates a character id
+ * back into an iterator.
*/
- send(QueueFD, connection_with_new_result->GetID().c_str(), connection_with_new_result->GetID().length()+1, 0);
+ char id = FindCharId(connection_with_new_result->GetID());
+ send(QueueFD, &id, 1, 0);
}
void* DispatcherThread(void* arg);
virtual bool OnDataReady()
{
- char* data = this->Read();
- ConnMap::iterator iter;
-
- if (data && *data)
+ char data = 0;
+ /* NOTE: Only a single character is read so we know we
+ * cant get a partial read. (We've been told that theres
+ * data waiting, so we wont ever get EAGAIN)
+ * The function GetCharId translates a single character
+ * back into an iterator.
+ */
+ if (Instance->SE->Recv(this, &data, 1, 0) > 0)
{
- /* We expect to be sent a null terminated string */
- if((iter = Connections.find(data)) != Connections.end())
+ ConnMap::iterator iter = GetCharId(data);
+ if (iter != Connections.end())
{
/* Lock the mutex, send back the data */
pthread_mutex_lock(&results_mutex);
pthread_mutex_unlock(&results_mutex);
return true;
}
+ /* No error, but unknown id */
+ return true;
}
+ /* Erk, error on descriptor! */
return false;
}
};
ModuleSQL(InspIRCd* Me)
: Module::Module(Me), rehashing(false)
{
- ServerInstance->UseInterface("SQLutils");
+ ServerInstance->Modules->UseInterface("SQLutils");
Conf = new ConfigReader(ServerInstance);
PublicServerInstance = ServerInstance;
throw ModuleException("m_mysql: Failed to create dispatcher thread: " + std::string(strerror(errno)));
}
- if (!ServerInstance->PublishFeature("SQL", this))
+ if (!ServerInstance->Modules->PublishFeature("SQL", this))
{
/* Tell worker thread to exit NOW */
giveup = true;
throw ModuleException("m_mysql: Unable to publish feature 'SQL'");
}
- ServerInstance->PublishInterface("SQL", this);
+ ServerInstance->Modules->PublishInterface("SQL", this);
}
virtual ~ModuleSQL()
{
giveup = true;
ClearAllConnections();
- DELETE(Conf);
- ServerInstance->UnpublishInterface("SQL", this);
- ServerInstance->UnpublishFeature("SQL");
- ServerInstance->DoneWithInterface("SQLutils");
+ delete Conf;
+ ServerInstance->Modules->UnpublishInterface("SQL", this);
+ ServerInstance->Modules->UnpublishFeature("SQL");
+ ServerInstance->Modules->DoneWithInterface("SQLutils");
}
return NULL;
}
-
-// stuff down here is the module-factory stuff. For basic modules you can ignore this.
-
-class ModuleSQLFactory : public ModuleFactory
-{
- public:
- ModuleSQLFactory()
- {
- }
-
- ~ModuleSQLFactory()
- {
- }
-
- virtual Module * CreateModule(InspIRCd* Me)
- {
- return new ModuleSQL(Me);
- }
-
-};
-
-
-extern "C" void * init_module( void )
-{
- return new ModuleSQLFactory;
-}
+MODULE_INIT(ModuleSQL);