/* * GetQueryResult * * Pump the conn till it's dry of results; return false if any are errors. * Note that this will block if the conn is busy. */ static bool GetQueryResult(PGconn *conn, const char *progname) { bool ok = true; PGresult *result; SetCancelConn(conn); while ((result = PQgetResult(conn)) != NULL) { if (!ProcessQueryResult(conn, result, progname)) ok = false; } ResetCancelConn(); return ok; }
SInt64 ApsApnsClientPool::Run() { ApsLogger::Debug("ApsApnsClientPool::Run!"); EventFlags events = this->GetEvents();//we must clear the event mask! if(events&Task::kLcsEvent) { ApsLogger::Debug("Task::kLcsEvent!"); ProcessQueryResult(); } else if(events&Task::kConnectEvent) { //ok, check for connect request now. Go through the whole queue OSMutexLocker locker(&fMutex); //send connection for (OSQueueIter iter(&fQueue); !iter.IsDone(); iter.Next()) { SslTcpClient* theClient = (SslTcpClient*)iter.GetCurrent()->GetEnclosingObject(); //if it's time to time this task out, signal it if(theClient==NULL) { if(fQueue.GetLength() == 0) break; else continue; } if (!theClient->GetConnectStatus()) { //theTimeoutTask->fTask->Signal(Task::kTimeoutEvent); OS_Error theErr = theClient->GetClientSocket().Connect((TCPSocket *)&(theClient->GetClientSocket().fSocket)); if (theErr != OS_NoErr) { ApsLogger::Debug("ssl connect error!"); continue; } else { ApsLogger::Debug("ssl connect sucessful!"); fQueue.Remove(&(theClient->fTaskQueueElem)); theClient->Online(); //设置Task,响应系统的读写事件 theClient->GetClientSocket().SetTask(theClient); theClient->GetClientSocket().SetListener(EV_RE); //尝试发送缓冲中的数据 theClient->NotifySendMsg(); } } else { fQueue.Remove(&(theClient->fTaskQueueElem)); //theClient->Signal(Task::kConnectEvent); } } } else if(events&Task::kTimeoutEvent) { fTimeoutTask.RefreshTimeout(); //feedback connection m_feedbackClient.OnTimeout(); ReInitializeParam(); OS_Error theErr = m_feedbackClient.GetClientSocket().Connect((TCPSocket *)&(m_feedbackClient.GetClientSocket().fSocket)); if (theErr != OS_NoErr) { ApsLogger::Debug("feedback connect error!"); } else { ApsLogger::Debug("feedback connect successful!"); m_feedbackClient.SetConnectStatus(true); //设置Task,响应系统的读写事件 m_feedbackClient.GetClientSocket().SetTask(&m_feedbackClient); m_feedbackClient.GetClientSocket().SetListener(EV_RE); } } OSThread::ThreadYield(); return 0;//don't delete me! }
/* * GetIdleSlot * Return a connection slot that is ready to execute a command. * * We return the first slot we find that is marked isFree, if one is; * otherwise, we loop on select() until one socket becomes available. When * this happens, we read the whole set and mark as free all sockets that become * available. * * If an error occurs, NULL is returned. */ static ParallelSlot * GetIdleSlot(ParallelSlot slots[], int numslots, const char *progname) { int i; int firstFree = -1; /* Any connection already known free? */ for (i = 0; i < numslots; i++) { if (slots[i].isFree) return slots + i; } /* * No free slot found, so wait until one of the connections has finished * its task and return the available slot. */ while (firstFree < 0) { fd_set slotset; int maxFd = 0; bool aborting; /* We must reconstruct the fd_set for each call to select_loop */ FD_ZERO(&slotset); for (i = 0; i < numslots; i++) { int sock = PQsocket(slots[i].connection); /* * We don't really expect any connections to lose their sockets * after startup, but just in case, cope by ignoring them. */ if (sock < 0) continue; FD_SET(sock, &slotset); if (sock > maxFd) maxFd = sock; } SetCancelConn(slots->connection); i = select_loop(maxFd, &slotset, &aborting); ResetCancelConn(); if (aborting) { /* * We set the cancel-receiving connection to the one in the zeroth * slot above, so fetch the error from there. */ GetQueryResult(slots->connection, progname); return NULL; } Assert(i != 0); for (i = 0; i < numslots; i++) { int sock = PQsocket(slots[i].connection); if (sock >= 0 && FD_ISSET(sock, &slotset)) { /* select() says input is available, so consume it */ PQconsumeInput(slots[i].connection); } /* Collect result(s) as long as any are available */ while (!PQisBusy(slots[i].connection)) { PGresult *result = PQgetResult(slots[i].connection); if (result != NULL) { /* Check and discard the command result */ if (!ProcessQueryResult(slots[i].connection, result, progname)) return NULL; } else { /* This connection has become idle */ slots[i].isFree = true; if (firstFree < 0) firstFree = i; break; } } } } return slots + firstFree; }