예제 #1
0
	SQLConn(Module* Creator, ConfigTag* tag)
	: SQLProvider(Creator, "SQL/" + tag->getString("id")), conf(tag), sql(NULL), status(CWRITE), qinprog(NULL, "")
	{
		if (!DoConnect())
		{
			ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "WARNING: Could not connect to database " + tag->getString("id"));
			DelayReconnect();
		}
	}
예제 #2
0
	SQLConn(InspIRCd* SI, Module* self, const SQLhost& hi)
	: EventHandler(), ServerInstance(SI), confhost(hi), us(self), sql(NULL), status(CWRITE), qinprog(false)
	{
		idle = this->ServerInstance->Time();
		if(!DoConnect())
		{
			ServerInstance->Logs->Log("m_pgsql",DEFAULT, "WARNING: Could not connect to database with id: " + ConvToStr(hi.id));
			DelayReconnect();
		}
	}
예제 #3
0
	void HandleEvent(EventType et, int errornum)
	{
		switch (et)
		{
			case EVENT_READ:
			case EVENT_WRITE:
				DoEvent();
			break;

			case EVENT_ERROR:
				DelayReconnect();
		}
	}
예제 #4
0
	virtual void HandleEvent(EventType et, int errornum)
	{
		switch (et)
		{
			case EVENT_READ:
				OnDataReady();
			break;

			case EVENT_WRITE:
				OnWriteReady();
			break;

			case EVENT_ERROR:
				DelayReconnect();
			break;

			default:
			break;
		}
	}
예제 #5
0
	void DoConnectedPoll()
	{
restart:
		while (qinprog.q.empty() && !queue.empty())
		{
			/* There's no query currently in progress, and there's queries in the queue. */
			DoQuery(queue.front());
			queue.pop_front();
		}

		if (PQconsumeInput(sql))
		{
			if (PQisBusy(sql))
			{
				/* Nothing happens here */
			}
			else if (qinprog.c)
			{
				/* Fetch the result.. */
				PGresult* result = PQgetResult(sql);

				/* PgSQL would allow a query string to be sent which has multiple
				 * queries in it, this isn't portable across database backends and
				 * we don't want modules doing it. But just in case we make sure we
				 * drain any results there are and just use the last one.
				 * If the module devs are behaving there will only be one result.
				 */
				while (PGresult* temp = PQgetResult(sql))
				{
					PQclear(result);
					result = temp;
				}

				/* ..and the result */
				PgSQLresult reply(result);
				switch(PQresultStatus(result))
				{
					case PGRES_EMPTY_QUERY:
					case PGRES_BAD_RESPONSE:
					case PGRES_FATAL_ERROR:
					{
						SQLerror err(SQL_QREPLY_FAIL, PQresultErrorMessage(result));
						qinprog.c->OnError(err);
						break;
					}
					default:
						/* Other values are not errors */
						qinprog.c->OnResult(reply);
				}

				delete qinprog.c;
				qinprog = QueueItem(NULL, "");
				goto restart;
			}
			else
			{
				qinprog.q.clear();
			}
		}
		else
		{
			/* I think we'll assume this means the server died...it might not,
			 * but I think that any error serious enough we actually get here
			 * deserves to reconnect [/excuse]
			 * Returning true so the core doesn't try and close the connection.
			 */
			DelayReconnect();
		}
	}
예제 #6
0
	bool DoConnectedPoll()
	{
		if(!qinprog && queue.totalsize())
		{
			/* There's no query currently in progress, and there's queries in the queue. */
			SQLrequest& query = queue.front();
			DoQuery(query);
		}

		if(PQconsumeInput(sql))
		{
			/* We just read stuff from the server, that counts as it being alive
			 * so update the idle-since time :p
			 */
			idle = this->ServerInstance->Time();

			if (PQisBusy(sql))
			{
				/* Nothing happens here */
			}
			else if (qinprog)
			{
				/* Grab the request we're processing */
				SQLrequest& query = queue.front();

				/* Get a pointer to the module we're about to return the result to */
				Module* to = query.GetSource();

				/* Fetch the result.. */
				PGresult* result = PQgetResult(sql);

				/* PgSQL would allow a query string to be sent which has multiple
				 * queries in it, this isn't portable across database backends and
				 * we don't want modules doing it. But just in case we make sure we
				 * drain any results there are and just use the last one.
				 * If the module devs are behaving there will only be one result.
				 */
				while (PGresult* temp = PQgetResult(sql))
				{
					PQclear(result);
					result = temp;
				}

				if(to)
				{
					/* ..and the result */
					PgSQLresult reply(us, to, query.id, result);

					/* Fix by brain, make sure the original query gets sent back in the reply */
					reply.query = query.query.q;

					switch(PQresultStatus(result))
					{
						case PGRES_EMPTY_QUERY:
						case PGRES_BAD_RESPONSE:
						case PGRES_FATAL_ERROR:
							reply.error.Id(SQL_QREPLY_FAIL);
							reply.error.Str(PQresultErrorMessage(result));
						default:
							;
							/* No action, other values are not errors */
					}

					reply.Send();

					/* PgSQLresult's destructor will free the PGresult */
				}
				else
				{
					/* If the client module is unloaded partway through a query then the provider will set
					 * the pointer to NULL. We cannot just cancel the query as the result will still come
					 * through at some point...and it could get messy if we play with invalid pointers...
					 */
					PQclear(result);
				}
				qinprog = false;
				queue.pop();
				DoConnectedPoll();
			}
			return true;
		}
		else
		{
			/* I think we'll assume this means the server died...it might not,
			 * but I think that any error serious enough we actually get here
			 * deserves to reconnect [/excuse]
			 * Returning true so the core doesn't try and close the connection.
			 */
			DelayReconnect();
			return true;
		}
	}