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(); } }
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(); } }
void HandleEvent(EventType et, int errornum) { switch (et) { case EVENT_READ: case EVENT_WRITE: DoEvent(); break; case EVENT_ERROR: DelayReconnect(); } }
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; } }
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(); } }
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; } }