Ejemplo n.º 1
0
	SQLerror Query(const SQLrequest &req)
	{
		queue.push(req);

		if(!qinprog && queue.totalsize())
		{
			/* There's no query currently in progress, and there's queries in the queue. */
			SQLrequest& query = queue.front();
			return DoQuery(query);
		}
		else
		{
			return SQLerror();
		}
	}
Ejemplo n.º 2
0
void Worker::run()
{
	QueryQueue query_queue;
	QueryPtr follower_query;

	while (working_)
	{
		assert(query_queue.empty());

		{
			std::unique_lock<std::mutex> lock(mutex_);
			if (!follower_query_ && query_queue_.empty())
			{
				cond_.wait(lock);
			}

			if (follower_query_)
			{
				follower_query = follower_query_;
				follower_query_.reset();
			}
			if (!query_queue_.empty())
			{
				query_queue_.swap(query_queue);
			}
		}

		while (!query_queue.empty())
		{
			handle_query(query_queue.front());
			query_queue.pop_front();
		}

		if (follower_query != nullptr)
		{
			handle_query(follower_query);
			follower_query.reset();

			on_query_finished(shared_from_this());
		}
	}
}
Ejemplo n.º 3
0
void Worker::post_to_queue(const QueryPtr& query)
{
	if (!working_) return;

	{
		std::lock_guard<std::mutex> guard(mutex_);
		query_queue_.push_back(query);
	}

	cond_.notify_one();
}
Ejemplo n.º 4
0
	void OnUnloadModule(Module* mod)
	{
		queue.PurgeModule(mod);
	}
Ejemplo n.º 5
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;
		}
	}
Ejemplo n.º 6
0
	void DoLeadingQuery()
	{
		SQLrequest* req = queue.front();
		req->error = Query(req);
	}
Ejemplo n.º 7
0
unsigned int Worker::get_query_queue_size()
{
	std::lock_guard<std::mutex> guard(mutex_);
	return query_queue_.size();
}