void EpollPostgresql::syncReconnect()
{
    if(conn!=NULL)
    {
        std::cerr << "pg already connected" << std::endl;
        return;
    }
    syncConnectInternal(true);
    if(!queriesList.empty())
        sendNextQuery();
}
void GameserverQuerier::onDataReceived(network::UDPSocket* so, const network::Address& from, const char* data, const int len)
{
    (void)so;
    std::stringstream fromaddress;
    fromaddress << from.getIP() << ":" << from.getPort();
    
    const std::string address(from.getIP());
    const uint16_t port(from.getPort());
    
    bool found = false;
    
    for ( unsigned n = 0; n < checking_servers.size(); n++ )
    {
        GameServerInfo * info = checking_servers[n];
        if ( (info->ip == address) && (info->port == port) )
        {
            found = true;
            NPString str;
            str.append(data, len);
            
            parseServerData(info, str);
            
            // *info now owned by ds
            
            checking_servers.erase(n);
            break;
        }
    }
    
    if ( ! found )
    {
        LOGGER.warning("Received answer from unknown server [%s]", fromaddress.str().c_str());
    }
    
    sendNextQuery();
}
void
ServerQueryThread::onDataReceived(network::TCPSocket *s, const char *data, const int len)
{
    string str;
    
    MSInfo * msi = querying_msdata[s];
    msi->touch();
    str = msi->recdata;
    str.append(data,len);
    
    if (str[0] != '\\') {
        delete msi;
        querying_msdata.erase(s);
        s->destroy();
        return; // invalid answer;
    }
    
    string lastpart;
    if (str[str.length()-1] != '\\') {
        // received incomplete
        string::size_type p = str.rfind('\\');
        msi->recdata = str.substr(p);
        str.erase(p);
    } else {
        msi->recdata = "\\";
    }
    
    StringTokenizer tknizer(str,'\\');
    
    string token = tknizer.getNextToken();
    while ( !token.empty()) {
        if ( token == "ip" ) {
            string dirip = tknizer.getNextToken();
            string port;
            if ( dirip.empty() ) { 
                msi->recdata.insert(0,"\\ip\\");
                break;
            }
            
            token = tknizer.getNextToken();
            if ( token.empty() ) {
                msi->recdata.insert(0,dirip.insert(0,"\\ip\\")+"\\");
                break;
            }

            if ( token == "port" ) {
                token = tknizer.getNextToken();
                if (token.empty()) {
                    msi->recdata.insert(0,dirip.insert(0,"\\ip\\")+"\\port\\");
                    break;
                }
                port=token;
                token = tknizer.getNextToken();
            }
            
            LOGGER.warning("Server IP received: [%s:%s]",dirip.c_str(),port.c_str());

            int iport;
            std::stringstream portstr(port);
            portstr >> iport;
            
            bool found=false;
            // check if it is already in list
            std::vector<masterserver::ServerInfo*>::iterator si;
            for ( si = serverlist->begin(); si != serverlist->end(); si++) {
                if ( ((*si)->address == dirip) && ((*si)->port == iport) ) {
                    found=true;
                    break;
                }
            }
            if (found)
                continue;
            ServerInfo * info = new ServerInfo();
            info->address = dirip;
            info->port = iport;
            info->status = ServerInfo::QUERYING;
            serverlist->push_back(info);
            not_queried.push_back(info);
            sendNextQuery(); // XXX first check it is not already in
        } else if ( token == "final") {
bool EpollPostgresql::epollEvent(const uint32_t &events)
{
    if(conn==NULL)
    {
        std::cerr << "epollEvent() conn==NULL" << std::endl;
        return false;
    }

    const ConnStatusType &connStatusType=PQstatus(conn);
    if(connStatusType!=CONNECTION_OK)
    {
        if(connStatusType==CONNECTION_MADE)
        {
            started=true;
            std::cout << "Connexion CONNECTION_MADE" << std::endl;
        }
        else if(connStatusType==CONNECTION_STARTED)
        {
            started=true;
            std::cout << "Connexion CONNECTION_STARTED" << std::endl;
        }
        else if(connStatusType==CONNECTION_AWAITING_RESPONSE)
            std::cout << "Connexion CONNECTION_AWAITING_RESPONSE" << std::endl;
        else
        {
            if(connStatusType==CONNECTION_BAD)
            {
                started=false;
                std::cerr << "Connexion not ok: CONNECTION_BAD" << std::endl;
                //return false;
            }
            else if(connStatusType==CONNECTION_AUTH_OK)
                std::cerr << "Connexion not ok: CONNECTION_AUTH_OK" << std::endl;
            else if(connStatusType==CONNECTION_SETENV)
                std::cerr << "Connexion not ok: CONNECTION_SETENV" << std::endl;
            else if(connStatusType==CONNECTION_SSL_STARTUP)
                std::cerr << "Connexion not ok: CONNECTION_SSL_STARTUP" << std::endl;
            else if(connStatusType==CONNECTION_NEEDED)
                std::cerr << "Connexion not ok: CONNECTION_NEEDED" << std::endl;
            else
                std::cerr << "Connexion not ok: " << connStatusType << std::endl;
        }
    }
    if(connStatusType!=CONNECTION_BAD)
    {
        const PostgresPollingStatusType &postgresPollingStatusType=PQconnectPoll(conn);
        if(postgresPollingStatusType==PGRES_POLLING_FAILED)
        {
            std::cerr << "Connexion status: PGRES_POLLING_FAILED" << std::endl;
            return false;
        }
    }

    if(events & EPOLLIN)
    {
        const int PQconsumeInputVar=PQconsumeInput(conn);
        PGnotify *notify;
        while((notify = PQnotifies(conn)) != NULL)
        {
            std::cerr << "ASYNC NOTIFY of '" << notify->relname << "' received from backend PID " << notify->be_pid << std::endl;
            PQfreemem(notify);
        }
        if(/*PQisBusy(conn)==0, produce blocking, when server is unbusy this this never call*/true)
        {
            if(result!=NULL)
                clear();
            tuleIndex=-1;
            ntuples=0;
            result=PQgetResult(conn);
            if(result==NULL)
                std::cerr << "query async send failed: " << errorMessage() << ", PQgetResult(conn) have returned NULL" << std::endl;
            else
            {
                auto end = std::chrono::high_resolution_clock::now();
                std::chrono::duration<double, std::milli> elapsed = end-start;
                const uint32_t &ms=elapsed.count();
                if(ms>5000)
                {
                    if(queriesList.empty())
                        std::cerr << "query too slow, take " << ms << "ms" << std::endl;
                    else
                        std::cerr << queriesList.front().query << ": query too slow, take " << ms << "ms" << std::endl;
                }
                #ifdef DEBUG_MESSAGE_CLIENT_SQL
                else
                {
                    if(queriesList.empty())
                        std::cout << "query take " << ms << "ms" << std::endl;
                    else
                        std::cout << queriesList.front().query << ": query take " << ms << "ms" << std::endl;
                }
                #endif
                start = std::chrono::high_resolution_clock::now();
                while(result!=NULL)
                {
                    const ExecStatusType &execStatusType=PQresultStatus(result);
                    if(execStatusType!=PGRES_TUPLES_OK && execStatusType!=PGRES_COMMAND_OK)
                    {
                        #ifdef DEBUG_MESSAGE_CLIENT_SQL
                        std::cerr << simplifiedstrCoPG << ", ";
                        #endif
                        if(queriesList.empty())
                            std::cerr << "Query to database failed: " << errorMessage() << std::endl;
                        else
                            std::cerr << "Query to database failed: " << errorMessage() << queriesList.front().query << std::endl;
                        abort();//prevent continue running to prevent data corruption
                        tuleIndex=0;
                    }
                    else
                        ntuples=PQntuples(result);
                    if(!queue.empty())
                    {
                        CallBack callback=queue.front();
                        if(callback.method!=NULL)
                            callback.method(callback.object);
                        queue.erase(queue.cbegin());
                    }
                    if(result!=NULL)
                        clear();
                    if(!queriesList.empty())
                        queriesList.erase(queriesList.cbegin());
                    if(!queriesList.empty())
                        if(!sendNextQuery())
                            return false;
                    result=PQgetResult(conn);
                }
            }
        }
        else
            std::cout << "PostgreSQL events with EPOLLIN: PQisBusy: " << std::to_string(PQconsumeInputVar) << std::endl;
    }
    if(events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR))
    {
        started=false;
        if(events == EPOLLRDHUP)
        {
            std::cerr << "Database disconnected, try reconnect: " << errorMessage() << std::endl;
            syncDisconnect();
            conn=NULL;
            syncReconnect();
        }
    }
    return true;
}