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